Skip to content

Structured request and tool logging #373

Description

@gbrlcustodio

Part of the hosted on-behalf-of MCP server proposal (#297).

Scope

Emit structured (JSON) logs to stdout for the hosted profile: one line per HTTP request and one line per tool call, so operators can attribute activity and latency without standing up a separate APM. This is the logging half of #309; per-user quota accounting stays in #309.

Request line: method, path, status, duration, client IP, session id, a request id, and the authenticated caller's subject and client id. The subject and client id come from the request auth context (request-scoped identity, #302), not from re-decoding the bearer.

Tool line: tool name, outcome (ok or error, from the call result's error flag), duration, the argument keys only, and the same request id as the HTTP request that carried it, for correlation.

The per-request logger must be pure-ASGI middleware, not Starlette BaseHTTPMiddleware. BaseHTTPMiddleware buffers the response body and breaks the long-lived streamable-HTTP / SSE stream; a pure-ASGI middleware only reads the response-start status and headers as they pass through. The tool logger wraps the low-level CallToolRequest handler on the shared server.

Privacy: never log the bearer token, and never log tool argument values, only their keys. Caller identity is limited to subject and client id.

Acceptance criteria

  • Each HTTP request emits one structured JSON line with the fields above, and the streamable-HTTP / SSE stream is unaffected (no buffering; time-to-first-byte on a streamed response is unchanged).
  • Each tool call emits one structured JSON line carrying the same request id as its HTTP request.
  • Logs are JSON on stdout and the level is configurable.
  • No bearer token and no tool argument values appear in any log line; argument keys and the caller's subject and client id do.
  • Verifiable locally without an authorization server: boot the server, exercise a request and a tool call, and assert the log shape.

Dependencies

Builds on request-scoped identity (#302, closed) for the caller subject and client id. This is the logging half of #309; per-user quotas remain there.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requesthosted-mcpHosted, multi-user, on-behalf-of MCP server profile

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions