Repository navigation
Description
#297 stops validation errors from echoing what they
rejected. A value that passes validation, such as a token put in the
wrong string field, is still echoed wherever a handler looks it up,
refuses it or reports on it. Most of these are also returned in a
structured output field by design. Sites on 7680445:
- routing names:
server.py:359(Gateway tool blocked by policy: {name});server.py:380/:444(Unknown tool: {name}, response only since
Validation errors echo argument values (pydantic input_value, jsonschema type/pattern) into responses and logs #297);server.py:582/:609/:613/:683(resources/read/prompts/get
unknown or blocked URI/name, which the SDK also logs with a
traceback:mcp/shared/jsonrpc_dispatcher.py:754);client/manager.py:1277(Unknown server, when lazy).
- lookups / policy refusals:
handlers.py:1341/:1359(describe,detailsonly);:1510/:1543/:1569(make_error(tool_id=...)inerrors);:2426/:2541/:3010/:3083/:3192(Server '{server_name}' ..., and
into the auditerrorvia_lifecycle_output:2898-2908);:3888/:4044,:5585(Job '{job_id}' not found);tasks_*blocked-by-policy:5938/:6021/:6065/:6157;client/manager.py:3847/:3896(Task not found: {server}::{task_id}).
- format / allowlist refusals of a schema-valid string:
handlers.py:4549/:4558(Env var '{env_var}' is not permitted);:4567-4581viaenv_store.py:23({name!r});:5410(unsafe package identifier {package!r});:5427-5433(disallowedenv_vars,operator_safe);client/manager.py:4208/:4217(Invalid request_id format: {request_id},Invalid local_id);config/loader.py:778-780/:854(the policypath).
- free text echoed by design:
refreshreason(handlers.py:1857, INFO log);request_capabilityquery(:3860log,:3866/:3869output);search_registryquery(:5384);submit_feedbacktitle/description (:4681-4682).
- invoke's own log lines name
tool_id(:1657/:1688/:1734/:1817).
Proposed class fix: give identifier fields a pattern so token-shaped input
fails validation (and is then described without its value by #297). For
example tool_id can reuse scoped_advisor_audit._TOOL_ID_PATTERN; add
patterns for server_name, task_id, job_id, request_id and
env_var. Then route the routing-name log lines through a fixed text as
#297 did for Unknown tool. This changes advertised schemas, so it
belongs with, or after, piece B of #236.
- N5,
resources/read/prompts/get: this is part of the follow-up
above, not this plan. It is a lookup echo, not a validation error. The
SDK writes the traceback for any exception a request handler raises, so
silencing it means raisingMCPError, which changes the wire error code. - N4, the SDK's malformed-envelope echo (
streamable_http.py:550):
Source: the non-goals of the plan for #297 (#314); line numbers are on 7680445.
🤖 Generated with Claude Code
Activity
ViperJuice commentedon Sep 29, 2026
One more site, found in review of #314:
client/manager.py:2037-2041logs a rejected downstream pagination cursor verbatim (unusable cursor ({raw_cursor!r})). This is not an exception path, so it belongs on this list rather than in #297.🤖 Generated with Claude Code
docs(plan): rev 3 -- malformed downstream frames on every transport, …
ViperJuice commentedon Sep 29, 2026
Two more sites, found in review of #314. Neither is a validation-error path:
acceptheader.🤖 Generated with Claude Code
docs(plan): rev 5 -- install the log scrubber on import pmcp, so ever…
ViperJuice commentedon Sep 30, 2026
Two more pre-existing, operator/config-side echoes, found by the claude seat in round 7 of the #314 panel (the #297 plan). Recorded here rather than in #297 because they are accepted-config or launch-environment values, not tool-argument validation:
src/pmcp/config/loader.py:494logs a rejectedallowPrivateRegistryvalue with%r. Triggered by a call togateway.search_registry. Repro:~/.mcp.jsonwith"allowPrivateRegistry": "SENT…"gives a WARNING containing the value. Fix: log only the value's type.PMCP_PORT(and three other environment variables) go through a bareint():PMCP_PORT=SENT… python -m pmcpprintsFatal error: invalid literal for int() … 'SENT…'to stderr (not togateway.log). Two warnings insrc/pmcp/client/manager.pydo the same with%r. Visible only to whoever launches the process. Fix: fixed-text messages naming the variable, not its value.docs(plan): rev 8 - describe every rejected stdio frame; static rule …
docs(plan): rev 9 - stdio output decided by where JSON can start; out…
ViperJuice commentedon Oct 1, 2026
Update from the round-9 panel on #314 (the #297 plan): the mcp SDK's DEBUG logging of JSON-RPC message payloads (incoming accepted frames, and outgoing client messages with the caller's arguments) is moving INTO #297's revision 10. A downstream payload that pmcp later rejects (e.g. a task
ttl) was logged by the SDK before validation, so it breaks #297's own guarantee. The fix replaces every SDK record that renders a message payload with a structural description, which also removes the accepted-value traffic-logging part of this issue. The lookup-mismatch and config echoes listed above stay here.docs(plan): rev 10 - SDK traffic logging shows message structure; han…
ViperJuice commentedon Oct 1, 2026
Scope note from round 10 of the #314 panel: on the serving side,
sse_starlettelogs every outbound SSE chunk at DEBUG — the full body of each response pmcp sends its caller, including proxied downstream results. It never carries a value pmcp rejected, so it is outside #297 and stays here with the other accepted-value echoes. (#297 rev 10 covers the mcp SDK's own message-object rendering on the client side.)docs(plan): rev 11 - stdio describe mode ends only on a valid frame; …
ViperJuice commentedon Oct 1, 2026
Correction from round 11 of the #314 panel: the
_fetch_listing_pagescursor log (tools/list returned an unusable cursor (…), renderingraw_cursor!rat WARNING), which an earlier comment on this issue listed, echoes a value pmcp REJECTS (a non-string cursor), so it moves into #297's revision 12 together with a sweep for every other hand-written rejection log that renders the rejected value. It is no longer tracked here.docs(plan): rev 12 - non-protocol stdout lines get a fixed record; ha…
docs(plan): rev 21 - every except binding is an exception name; templ…