Skip to content

Implemented MCP Set Log Level#3419

Open
anushakolan wants to merge 2 commits intomainfrom
dev/anushakolan/set-log-level
Open

Implemented MCP Set Log Level#3419
anushakolan wants to merge 2 commits intomainfrom
dev/anushakolan/set-log-level

Conversation

@anushakolan
Copy link
Copy Markdown
Contributor

@anushakolan anushakolan commented Apr 8, 2026

Why make this change?

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

What is this change?

  • Added handler for logging/setLevel JSON-RPC method in McpStdioServer.cs
  • Implemented ILogLevelController interface to allow MCP to update log levels dynamically
  • Added IsConfigOverridden property to enforce precedence rules

Precedence (highest to lowest):

  1. CLI --LogLevel flag - cannot be changed
  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

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

How was this tested?

  • Unit Tests
  • 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, debug message shows "Log level changed to: info"

Manual Test 2: CLI override (MCP blocked)

  1. Start MCP server with --LogLevel None
  2. MCP sends logging/setLevel with level: info
  3. Result: Log level stays at None, debug message shows "Log level not changed (CLI override active)"

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
  4. Result: Log level stays at Warning, debug message shows "Log level not changed (Config override active)"

Sample Request(s)

MCP client sends:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "logging/setLevel",
  "params": {
    "level": "info"
  }
}

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

@anushakolan
Copy link
Copy Markdown
Contributor Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

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 PR addresses MCP stdio clients receiving Method not found: logging/setLevel by adding support for the logging/setLevel JSON-RPC method and wiring it to DAB’s dynamic log-level infrastructure with explicit precedence rules (CLI > config > MCP).

Changes:

  • Added logging/setLevel dispatch + handler in McpStdioServer to accept the standard MCP request and (when allowed) update runtime log level.
  • Introduced ILogLevelController and implemented it in DynamicLogLevelProvider, including CLI/config precedence tracking.
  • Updated CLI engine-launch argument construction to only pass --LogLevel when explicitly provided, plus added unit tests for MCP log-level updates.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Service/Telemetry/DynamicLogLevelProvider.cs Implements ILogLevelController, adds MCP level mapping and precedence handling (CLI/config/MCP).
src/Service/Program.cs Registers ILogLevelController in DI so MCP can resolve the controller.
src/Service.Tests/UnitTests/DynamicLogLevelProviderTests.cs Adds unit tests for MCP-driven log-level changes and override behavior.
src/Core/Telemetry/ILogLevelController.cs New interface to decouple MCP from the concrete log-level provider.
src/Cli/ConfigGenerator.cs Only forwards --LogLevel when explicitly set by the user (to avoid treating defaults as CLI overrides).
src/Azure.DataApiBuilder.Mcp/Core/McpStdioServer.cs Adds logging/setLevel handler that calls into ILogLevelController.

Comment on lines 46 to +52
if (!IsCliOverridden)
{
CurrentLogLevel = runtimeConfig.GetConfiguredLogLevel();

// Track if config explicitly set a log level (not just using defaults)
IsConfigOverridden = !runtimeConfig.IsLogLevelNull();
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

IsConfigOverridden is derived from !runtimeConfig.IsLogLevelNull(), but the schema allows runtime.telemetry.log-level values to be null (meaning “use host-mode defaults”). In that case IsLogLevelNull() returns false (because the dictionary exists), causing MCP logging/setLevel to be blocked even though config did not actually pin a log level. Consider treating config as “overridden” only when at least one configured log-level value is non-null (e.g., any entry value != null), or add a dedicated RuntimeConfig helper for this distinction.

Copilot uses AI. Check for mistakes.
minimumLogLevel = deserializedRuntimeConfig.GetConfiguredLogLevel();
HostMode hostModeType = deserializedRuntimeConfig.IsDevelopmentMode() ? HostMode.Development : HostMode.Production;

_logger.LogInformation($"Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType);
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

In the default log-level branch, _logger.LogInformation($"Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType); uses an interpolated string while also passing structured args—those args won’t be captured as structured fields. Use a message template without $"..." (or remove the extra args) so logging behaves as intended.

Suggested change
_logger.LogInformation($"Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType);
_logger.LogInformation("Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType);

Copilot uses AI. Check for mistakes.
Comment on lines 2585 to +2616
@@ -2597,17 +2598,22 @@ public static bool TryStartEngineWithOptions(StartOptions options, FileSystemRun

minimumLogLevel = (LogLevel)options.LogLevel;
_logger.LogInformation("Setting minimum LogLevel: {minimumLogLevel}.", minimumLogLevel);

// Only add --LogLevel when user explicitly specified it via CLI.
// This allows MCP logging/setLevel to work when no CLI override is present.
args.Add("--LogLevel");
args.Add(minimumLogLevel.ToString());
}
else
{
minimumLogLevel = deserializedRuntimeConfig.GetConfiguredLogLevel();
HostMode hostModeType = deserializedRuntimeConfig.IsDevelopmentMode() ? HostMode.Development : HostMode.Production;

_logger.LogInformation($"Setting default minimum LogLevel: {minimumLogLevel} for {hostModeType} mode.", minimumLogLevel, hostModeType);
}

args.Add("--LogLevel");
args.Add(minimumLogLevel.ToString());
// Don't add --LogLevel arg since user didn't explicitly set it.
// Service will determine default log level based on config or host mode.
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

After this change, when options.LogLevel is not provided the CLI no longer passes --LogLevel to the engine. The Service defaults to LogLevel.Error when --LogLevel is absent (Program.GetLogLevelFromCommandLineArgs), so early startup logs will be suppressed even in Development until DynamicLogLevelProvider.UpdateFromRuntimeConfig(...) runs. If the intent is to keep the existing “Debug in Development / Error in Production” default behavior while still allowing MCP to change the level, consider setting the initial log level from the loaded config earlier in host construction (or introducing a non-override mechanism distinct from the CLI override flag).

Copilot uses AI. Check for mistakes.
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.

[Bug]: when using --mcp-stdio failure with "logging/setlevel"

4 participants