
This page is part of our MCP specification reference, a plain-English guide to the Model Context Protocol spec (version 2026-07-28), within The MCP Guide. Building a server? See MCP development.
Status in the 2026-07-28 spec: deprecated (still functional; eligible for removal in the first spec released on or after 28 July 2027)
The MCP logging utility is a feature that lets a server send structured log messages to the AI app (the client) while it works. Each message has a severity level, an optional logger name and any JSON data.
The 2026-07-28 MCP specification deprecated it. The spec's migration advice is to "log to stderr (stdio) or use OpenTelemetry instead of Logging." It also removed the logging/setLevel method and made log levels a per-request setting. This page covers what still works, what is gone and what to do.
One clarification up front: this page is about the protocol's logging messages. Your own audit logs of who called which tool are a separate and still essential practice. See MCP audit logging.
Key Takeaways
- The logging utility lets servers send
notifications/messagelog entries to clients. - It is deprecated in 2026-07-28 and becomes eligible for removal in the first spec released on or after 28 July 2027.
logging/setLevelwas removed. A client now asks for logs per request withio.modelcontextprotocol/logLevelin_meta.- Servers must not send log messages for requests that did not ask for them.
- Replace it with
stderrfor local servers and OpenTelemetry for observability.
Why the logging utility existed
When an MCP server misbehaves, developers want to see why. Early MCP gave servers a standard way to stream debug and error messages to the client, which could show them in a console or log panel. It has been in the spec since the first version, 2024-11-05.
Log levels follow the eight syslog severities from RFC 5424: debug, info, notice, warning, error, critical, alert and emergency.
How it works in 2026-07-28
The Logging page of the spec describes the current rules. They are stricter than before.
- A server that sends log messages declares the
loggingcapability. - A client that wants logs for a specific request adds
io.modelcontextprotocol/logLevelto that request's_meta, for example"info". - The server may then send
notifications/messageentries at or above that level, on the response stream for that request, before the final response. - If the request did not include the field, the server "MUST NOT emit
notifications/message."
Log messages are request-scoped. The spec says the server must not deliver them on a subscriptions/listen stream or any other stream. An unrecognized log level should be rejected with JSON-RPC error -32602 (Invalid params).
Here is a log message from the spec:
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": { "host": "localhost", "port": 5432 }
}
}
}
What changed across spec versions
| Version | Logging change |
|---|---|
| 2024-11-05 | Introduced; clients set a session-wide minimum with logging/setLevel |
| 2025-11-25 | Clarified that stdio servers may use stderr for all types of logging (changelog) |
| 2026-07-28 | logging/setLevel removed; per-request logLevel in _meta; feature deprecated |
In 2025-11-25, a client sent logging/setLevel once and the setting applied for the session. The 2026-07-28 release removed sessions, so a session-wide setting no longer fits. The log level now travels with each request. Read why MCP became stateless for the bigger picture.
The deprecation timeline
The deprecated features registry records:
| Item | Detail |
|---|---|
| Deprecated in | 2026-07-28 (SEP-2577) |
| Migration path | Log to stderr for stdio transports; use OpenTelemetry for observability |
| Earliest removal | First spec revision released on or after 2027-07-28 |
As with all deprecations under the feature lifecycle policy, the feature stays functional during the window. Core Maintainers decide the actual removal date.
What to use instead
Local servers: stderr
Local servers run over the stdio transport, where stdout carries MCP messages. Write your logs to stderr instead. The stdio transport page says a server "MAY write UTF-8 strings to stderr for any logging purposes," and the client may capture, forward or ignore it. Our guide to the MCP stdio transport explains the split.
Remote servers: OpenTelemetry
OpenTelemetry is an open standard for traces, metrics and logs. It works with most monitoring tools. The 2026-07-28 changelog also documents how to pass OpenTelemetry trace context (traceparent, tracestate, baggage) in _meta. That lets one trace follow a request from the client through the server.
Your own audit trail
Neither of these replaces business audit logs. Record who called which tool, with what arguments and result, in your own systems. MCP governance for IT leaders covers what to keep.
Common mistakes
- Still calling
logging/setLevel. It no longer exists in 2026-07-28. - Sending log messages nobody asked for. Without
logLevelin the request's_meta, the server must stay silent. - Logging secrets. The spec says log messages "MUST NOT contain" credentials, secrets, personal information or internal details that could aid attacks.
- Writing logs to stdout on a stdio server. That corrupts the protocol stream. Use
stderr. - Treating protocol logs as an audit trail. They are optional, client-requested debug output.
Next step
The logging utility often travels with progress updates on the same response stream. Read MCP progress notifications next, or browse the MCP specification reference.
Frequently asked questions
Is MCP logging removed?
Not yet. As of October 2026, the logging utility is deprecated but still in the 2026-07-28 spec. It becomes eligible for removal in the first spec revision released on or after 28 July 2027.
What replaced logging/setLevel?
A per-request field. The client adds io.modelcontextprotocol/logLevel to a request's _meta, and the server may send log messages at or above that level for that request only.
Where should an MCP server write its logs now?
Local stdio servers should write to stderr. Remote servers should use OpenTelemetry or another observability stack. Keep separate audit logs for security and compliance.
Can log messages include user data?
They should not. The spec says log messages must not contain credentials, secrets or personal identifying information, and implementations should monitor for sensitive content.
Does this change affect business users?
Rarely. It mainly affects developers and the monitoring setup of teams that run their own servers. Ask your vendors whether their servers still depend on the deprecated utility.











