Skip to content

Cherry pick MCP logging, instructions, and schema fixes to release/2.0#3512

Open
anushakolan wants to merge 6 commits intorelease/2.0from
dev/anushakolan/release-2.0-bugfixes
Open

Cherry pick MCP logging, instructions, and schema fixes to release/2.0#3512
anushakolan wants to merge 6 commits intorelease/2.0from
dev/anushakolan/release-2.0-bugfixes

Conversation

@anushakolan
Copy link
Copy Markdown
Contributor

@anushakolan anushakolan commented May 6, 2026

Why make this change?

This backport ports a set of MCP-related and schema-related bug fixes from main to release/2.0 so the 2.0 release line includes:

  • Correct MCP initialize instructions field on the HTTP/SSE transport (was missing despite runtime.mcp.description being configured).
  • Schema validation of runtime.mcp.description (was supported in code but missing from dab.draft.schema.json, causing valid configs to fail validation).
  • Schema default for runtime.host.authentication.provider aligned with the documented/CLI default of Unauthenticated (was incorrectly AppService).
  • MCP logging/setLevel JSON-RPC method support, dynamic log-level updates, and clean stdout for MCP stdio mode.
  • Consistent CLI log labels matching ASP.NET Core's default console formatter (prerequisite for the MCP log-level work).

What is this change?

Cherry-picked PRs (chronological order on main):

  1. Make CLI Log Labels consistent with ASP.NET Core and use appropriate label on startup #3307 — included as a prerequisite for Implemented MCP Set Log Level #3419 (introduces the shared abbreviated-label dictionary).
  2. Added server description to dab.draft.schema #3405
  3. Changed default authentication provider to "Unauthenticated" in dab.draft.schema.json #3424
  4. Added changes to set McpServerOptions.Instructions in HTTPS/SSE mode #3423
  5. Implemented MCP Set Log Level #3419
  6. Upgrade OpenTelemetry.Exporter.OpenTelemetryProtocol from 1.13.0 to 1.15.3 #3488 — required to unblock CI on release/2.0 (fixes CVE-2026-42191 / GHSA-4625-4j76-fww9, which dotnet format --verify-no-changes promotes to an error via NU1902).

How was this tested?

  1. Existing and newly added unit/integration tests from each source PR (e.g., DynamicLogLevelProviderTests, TestMcpInitializeIncludesInstructionsFromRuntimeDescription, CustomLoggerTests, McpRuntimeOptionsSerializationTests).
  2. dotnet build of src/Cli, src/Service, and src/Cli.Tests on the cherry-pick branch — succeeded with 0 warnings, 0 errors.
  3. Manual verification on main was performed in each original PR; no additional manual verification was added for the backport.

Sample Request(s)

N/A — these are bug fixes; no new public API.

anushakolan and others added 5 commits May 5, 2026 18:28
## Why make this change?

Closes #3282

The issue is that runtime MCP server description exists in code
(`McpRuntimeOptions.Description`) but was missing from the JSON schema,
so valid config using `runtime.mcp.description` could fail schema
validation. This change adds the missing schema entry, so config and
schema stay aligned.

## What is this change?

Added `runtime.mcp.description` to `schemas/dab.draft.schema.json` under
the `mcp` runtime properties:

- `type: "string"`
- description clarifying it is exposed as the MCP `instructions` field
in initialize response

No runtime/CLI code changes were needed because support already exists
in config model, converter, CLI configure option, and MCP server
response wiring.

## How was this tested?

- [ ] Integration Tests
- [x] Unit Tests

Ran:

- `dotnet test
src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj --filter
"FullyQualifiedName~McpRuntimeOptionsSerializationTests" -v minimal`

## Sample Request(s)

CLI example:

```bash
dab configure --runtime.mcp.description "Use this MCP for product and inventory questions."
```

Config example:

```json
{
  "runtime": {
    "mcp": {
      "enabled": true,
      "path": "/mcp",
      "description": "Use this MCP for product and inventory questions."
    }
  }
}
```
…raft.schema.json. (#3424)

## Why make this change?

Closes #3392.

The JSON schema default for runtime.host.authentication.provider was set
to AppService, while CLI help text and docs indicate the default should
be Unauthenticated. This mismatch can confuse users and tooling.

## What is this change?

- Updated the schema default in schemas/dab.draft.schema.json:
  - runtime.host.authentication.provider: AppService -> Unauthenticated
- No runtime behavior changes were introduced beyond aligning the schema
default value.

## How was this tested?

- [ ] Integration Tests
- [x] Unit Tests

Ran:

- dotnet test
src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj --framework
net8.0 --filter
"FullyQualifiedName~CorsUnitTests.TestCorsConfigReadCorrectly"

## Sample Request(s)

CLI example:

- dab configure --runtime.host.authentication.provider AppService
- This demonstrates overriding the default.

Config example:

- Omit runtime.host.authentication.provider from config.
- Schema default resolves it to Unauthenticated.

Co-authored-by: Souvik Ghosh <souvikofficial04@gmail.com>
…#3423)

## Why make this change?

Closes #3283

`runtime.mcp.description` was configured, but MCP HTTP/SSE initialize
did not return it as `instructions`. This made the engine behavior
inconsistent with expected MCP initialization output.

Related discussion:
#3282

## What is this change?

- Wired runtime MCP description into MCP server options for HTTP/SSE
initialization:
  - `runtime.mcp.description` -> `ServerInstructions`
  - Files updated:
- `src/Azure.DataApiBuilder.Mcp/Core/McpServiceCollectionExtensions.cs`
    - `src/Azure.DataApiBuilder.Mcp/Core/McpServerConfiguration.cs`

- Added/updated regression coverage for initialize response
instructions:
  - `src/Service.Tests/Configuration/ConfigurationTests.cs`
  - Test: `TestMcpInitializeIncludesInstructionsFromRuntimeDescription`

How the bug was simulated:
- Reverted the MCP wiring changes and called MCP `initialize`;
`result.instructions` was missing.

How it was verified after fix:
- Re-applied the wiring, called MCP `initialize` again, and confirmed
`result.instructions` is present.

## How was this tested?

- [x] Integration Tests
- [ ] Unit Tests

Ran:

- `dotnet test
src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj --filter
"FullyQualifiedName~ConfigurationTests.TestMcpInitializeIncludesInstructionsFromRuntimeDescription"
-v minimal`

## Sample Request(s)

MCP initialize request (HTTP):

```bash
curl -i -X POST http://localhost:5000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"initialize",
    "params":{
      "protocolVersion":"2025-03-26",
      "capabilities":{},
      "clientInfo":{"name":"manual-test","version":"1.0.0"}
    }
  }'
```

Expected response snippet after fix:

```json
{
  "result": {
    "instructions": "Use SQL tools to query the database."
  }
}
```
…label on startup (#3307)

## Why make this change?

Closes #3269

## What is this change?

Align the CLI logger labels with the labels used in ASP.Net Core.
Downgraded internal plumbing message from `Information` to `Debug`

Add a test case to cover the changed behavior.

## How was this tested?

Added a test case to validate the new behavior.
## Why make this change?

Closes #3274 - MCP Server returns "Method not found: logging/setLevel"
error when clients send the standard MCP logging/setLevel request.

Closes #3275 - Control output in MCP stdio mode (default to
`LogLevel.None`, redirect/suppress console output).

## What is this change?

### MCP `logging/setLevel` Handler
- Added handler for `logging/setLevel` JSON-RPC method in
`McpStdioServer.cs`
- Implemented `DynamicLogLevelProvider` with `ILogLevelController`
interface to allow MCP to update log levels dynamically
- Added `IsCliOverridden` and `IsConfigOverridden` properties to enforce
precedence rules

### Log Level Precedence System
**Precedence (highest to lowest):**
1. **CLI `--LogLevel` flag** - cannot be changed by MCP
2. **Config `runtime.telemetry.log-level`** - cannot be changed by MCP  
3. **MCP `logging/setLevel`** - only works if neither CLI nor config set
a level
4.  Default (LogLevel.None for MCP stdio mode)

If CLI or config set a level, MCP requests are accepted but silently
ignored (no error returned per MCP spec).

### Early Config Reading for MCP Mode
- Added `TryGetLogLevelFromConfig()` in `Program.cs` to read config file
early (before host build)
- This ensures config log level is detected before Console redirect
decision
- Console redirect for MCP stdio mode now respects config log level

### CLI Log Level Handling
- Added `Utils.CliLogLevel` property to track the parsed `--LogLevel`
value
- CLI's `CustomLoggerProvider` now respects the `--LogLevel` value for
its own logging

### Config Helpers
- Added `HasExplicitLogLevel()` helper to `RuntimeConfig` to correctly
detect when config actually pins a log level
- This properly handles null values in telemetry section (null values
don't count as explicit override)

## How was this tested?

- [x] Unit Tests (`DynamicLogLevelProviderTests` - 5 tests)
- [x] Manual Testing

### Manual Test 1: No override (MCP can change level)
1. Start MCP server without `--LogLevel` and without config `log-level`
2. MCP sends `logging/setLevel` with `level: info`
3. Result: Log level changes to info

### Manual Test 2: CLI override (MCP blocked)
1. Start MCP server with `--LogLevel Warning`
2. MCP sends `logging/setLevel` with `level: info`
3. Result: Log level stays at Warning, MCP request accepted silently

### Manual Test 3: Config override (MCP blocked)
1. Add `"telemetry": { "log-level": { "default": "Warning" } }` to
config
2. Start MCP server without `--LogLevel`
3. MCP sends `logging/setLevel` with `level: info`
5. Result: Log level stays at Warning, MCP request accepted silently

### Manual Test 4: Config with null values (MCP can change level)
1. Add `"telemetry": { "log-level": { "default": null } }` to config
2. Start MCP server without `--LogLevel`
3. MCP sends `logging/setLevel` with `level: info`
4. Result: Log level changes to info (null values don't count as
override)

## Sample Request(s)

MCP client sends:
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "logging/setLevel",
  "params": {
    "level": "info"
  }
}
```

Server responds with empty result (success per MCP spec) and updates log
level if no CLI/config override is active.

---------

Co-authored-by: RubenCerna2079 <32799214+RubenCerna2079@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 6, 2026 01:32
@anushakolan anushakolan changed the title Dev/anushakolan/release 2.0 bugfixes Cherry pick MCP logging, instructions, and schema fixes to release/2.0 May 6, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This backport brings MCP initialization/schema fixes and MCP-focused logging improvements from main into the release/2.0 line, aiming to align runtime behavior, CLI logging, and JSON schema validation for MCP-related configuration.

Changes:

  • Add MCP server description support in the JSON schema and wire it through to MCP initialize instructions (HTTP/SSE and stdio paths).
  • Introduce dynamic log-level control for MCP stdio via logging/setLevel, including CLI/config precedence and cleaner stdio output behavior.
  • Align schema defaults and logging output labels with documented/expected defaults and ASP.NET Core conventions.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Service/Telemetry/DynamicLogLevelProvider.cs Adds MCP log-level mapping and dynamic update path via ILogLevelController.
src/Service/Startup.cs Downgrades response-compression message to Debug for less noisy startup logs.
src/Service/Program.cs Initializes log level earlier, adds MCP stdio console redirection, and config-based log-level detection.
src/Service.Tests/UnitTests/DynamicLogLevelProviderTests.cs Adds unit coverage for MCP logging/setLevel behavior and precedence.
src/Service.Tests/Configuration/ConfigurationTests.cs Adds regression test ensuring MCP initialize includes instructions; extends MCP helpers to capture/parse response bodies (JSON/SSE).
src/Core/Telemetry/ILogLevelController.cs Introduces an abstraction for runtime log-level control without tight coupling.
src/Core/Services/RequestValidator.cs Fixes a garbled character in a comment (em dash).
src/Config/ObjectModel/RuntimeConfig.cs Adds HasExplicitLogLevel() to detect when config truly pins a non-null log level.
src/Config/Converters/EntityCacheOptionsConverterFactory.cs Fixes a garbled character in a comment (em dash).
src/Cli/Utils.cs Adds flags/state used to suppress CLI stdout in MCP stdio mode and track CLI --LogLevel.
src/Cli/Program.cs Adds early arg scanning so MCP/log-level flags affect logger creation.
src/Cli/CustomLoggerProvider.cs Changes CLI log labels to ASP.NET Core abbreviations and routes MCP-stdio logs to stderr/suppresses output by default.
src/Cli/ConfigGenerator.cs Only forwards --LogLevel to the engine when explicitly specified, enabling MCP dynamic changes otherwise.
src/Cli.Tests/CustomLoggerTests.cs Adds tests for abbreviated CLI log labels.
src/Azure.DataApiBuilder.Mcp/Core/McpStdioServer.cs Adds logging/setLevel JSON-RPC handler and removes stray debug stderr output; refines initialize payload.
src/Azure.DataApiBuilder.Mcp/Core/McpServiceCollectionExtensions.cs Propagates runtime MCP description into server configuration.
src/Azure.DataApiBuilder.Mcp/Core/McpServerConfiguration.cs Sets MCP server instructions (ServerInstructions) based on runtime description.
schemas/dab.draft.schema.json Adds runtime.mcp.description and updates runtime.host.authentication.provider default to Unauthenticated.

Comment thread src/Service/Program.cs
Comment thread src/Service/Program.cs
Comment thread src/Service/Program.cs
Comment thread src/Service/Telemetry/DynamicLogLevelProvider.cs
Comment thread src/Azure.DataApiBuilder.Mcp/Core/McpStdioServer.cs
Comment thread src/Cli/CustomLoggerProvider.cs
Comment thread src/Service/Program.cs
….15.3 (#3488)

## Why make this change?

Bump `OpenTelemetry.Exporter.OpenTelemetryProtocol` to pick up patch
fixes from 1.15.3.

## What is this change?

- Updated `OpenTelemetry.Exporter.OpenTelemetryProtocol` from `1.13.0` →
`1.15.3` in `src/Directory.Packages.props` (centrally managed versions)

## How was this tested?

- [ ] Integration Tests
- [ ] Unit Tests

## Sample Request(s)

N/A — dependency version bump only.

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `www.nuget.org`
> - Triggering command:
`/home/REDACTED/work/_temp/ghcca-node/node/bin/node
/home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps
/home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js`
(dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/Azure/data-api-builder/settings/copilot/coding_agent)
(admins only)
>
> </details>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RubenCerna2079 <32799214+RubenCerna2079@users.noreply.github.com>
Co-authored-by: Ruben Cerna <rcernaserna@microsoft.com>
@anushakolan anushakolan linked an issue May 6, 2026 that may be closed by this pull request
@anushakolan anushakolan enabled auto-merge (squash) May 6, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cherry pick PRs

7 participants