fix: downgrade MCP "Unexpected content type" log spam from ERROR to DEBUG#1315
fix: downgrade MCP "Unexpected content type" log spam from ERROR to DEBUG#1315opspawn wants to merge 5 commits intokagent-dev:mainfrom
Conversation
…EBUG The observability-agent (and any agent using the MCP streamable-HTTP client) logs "Unexpected content type:" at ERROR level every 30 seconds when connected to the kagent-tools MCP server. This happens because the Go mcp-go library returns 200 OK without a Content-Type header when it handles heartbeat ping-responses, and the Python MCP SDK treats any non-JSON/SSE Content-Type as an error. These messages are benign -- actual MCP tool calls work correctly -- but they spam the logs and obscure real problems. This commit installs a logging filter on the `mcp.client.streamable_http` logger that downgrades matching ERROR records to DEBUG. The messages are still emitted when DEBUG logging is enabled, but they no longer pollute the default log output. Fixes kagent-dev#1200 Signed-off-by: opspawn <agent@opspawn.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses noisy log spam from the MCP Python SDK client by implementing a logging filter that downgrades "Unexpected content type" ERROR messages to DEBUG level. The issue occurs because the Go-based kagent-tools MCP server doesn't set a Content-Type header on heartbeat ping responses, causing the Python MCP client to log errors every 30 seconds. While these errors are benign (actual tool calls work correctly), they obscure real problems in the logs.
Changes:
- Adds a new
_logging.pymodule with a filter that downgrades specific MCP client ERROR messages to DEBUG level - Installs the filter automatically at package import time in
__init__.py - Provides comprehensive unit tests (8 tests) covering filter behavior, idempotency, and end-to-end integration
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
python/packages/kagent-adk/src/kagent/adk/_logging.py |
New module implementing the _UnexpectedContentTypeFilter that downgrades "Unexpected content type" ERROR logs to DEBUG, plus an idempotent installation function |
python/packages/kagent-adk/src/kagent/adk/__init__.py |
Imports and installs the filter at module initialization time so it's active for all kagent agents |
python/packages/kagent-adk/tests/unittests/test_logging_filter.py |
New comprehensive test suite covering filter behavior, edge cases, idempotency, and end-to-end integration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -1,8 +1,18 @@ | |||
| import importlib.metadata | |||
| import logging | |||
There was a problem hiding this comment.
The logging module is imported but never used in this file. Since install_mcp_content_type_filter() doesn't require the logging module to be imported in the calling code, this import can be removed.
| import logging |
Signed-off-by: opspawn <agent@opspawn.com>
a7754fd to
f12b482
Compare
Signed-off-by: opspawn <agent@opspawn.com>
Signed-off-by: opspawn <agent@opspawn.com>
bb74bdd to
a982c24
Compare
…t CRD race condition, unrelated to Python logging filter) Signed-off-by: opspawn <agent@opspawn.com>
f74c5e0 to
8baec6b
Compare
Summary
Fixes #1200
The observability-agent logs
mcp.client.streamable_http - ERROR - Unexpected content type:every 30 seconds when connected to the kagent-tools MCP server. This happens because the Gomcp-golibrary returns200 OKwithout aContent-Typeheader for heartbeat ping-responses, and the Python MCP SDK treats any unexpected Content-Type as an error.These errors are benign -- actual MCP tool calls work correctly -- but they spam the logs and obscure real problems.
Changes
python/packages/kagent-adk/src/kagent/adk/_logging.py(new): Logging filter that downgrades "Unexpected content type" ERROR records frommcp.client.streamable_httpto DEBUG level. The messages remain visible when DEBUG logging is enabled.python/packages/kagent-adk/src/kagent/adk/__init__.py: Installs the filter at import time so it takes effect for all kagent agents automatically.python/packages/kagent-adk/tests/unittests/test_logging_filter.py(new): 8 unit tests covering filter behavior, idempotent installation, and end-to-end integration.Root cause note
The upstream root cause is in kagent-dev/tools (and transitively in
mark3labs/mcp-go), where theisPingResponsehandler inStreamableHTTPServer.handlePostdoes a barereturnwithout settingContent-Type: application/jsonon the response. A complementary fix there would fully resolve the issue at the source. This PR addresses the symptom on the Python client side within this repo.Test plan
ruff checkpasses on all changed files