Repository navigation
mcp-client: one unsupported tool inputSchema keyword rejects the entire MCP server (Playwright MCP registers zero tools) #7401
Replies: 5 comments
|
Confirmed, and one part of the mechanism is different in a way that matters for the fix.
The enforced subset is the twelve fields of Where the all-or-nothing happens is the correction. It is not the swap phase.
That distinction is what makes the cheap fix cheap: the failure is per-tool and happens before any registration, so skipping the offending tool - or degrading only its schema to the unconstrained node - is a local change inside the Phase 1 loop. No rollback machinery is involved, and no registry state needs unwinding. One thing from your report worth repeating for whoever hits this next: the practical symptom is that every browser tool vanishes silently while the agent falls back to launching its own Chromium from bash, which reads as an authentication or IP problem rather than a tool-registration one. That misdirection is the expensive part of this bug, not the missing tools. Boundary: read from the committed tree at |
|
这条缺陷在 0.2.0-rc.2 上仍然复现,而且能打死整台服务器的关键字不止 版本: 病例:阿里云百炼 Harness 的 7 台 Streamable HTTP MCP 服务器,共 11 个工具。它们的工具 schema 长这样: {"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":500}},"required":["query"]}把宿主自己的
离线复现(不需要 MCP 服务器,直接用宿主自己的校验函数): # <TREE> 指本机运行树里 @deepseek-ai/dsh 的目录;出厂形状回 rejected,降级之后回 accepted
DSH_TOOLS=<TREE>/../dsh-tools/lib/index.js node -e '
const t = require(process.env.DSH_TOOLS);
try { t.assertSupportedJsonSchema({ type:"object", properties:{ query:{ type:"string", minLength:1, maxLength:500 } }, required:["query"] }); console.log("accepted"); }
catch (e) { console.log("rejected:", e.message); }'
# 出厂形状(0.2.0-rc.2)实测输出:
# rejected: unsupported JSON schema: schema.properties.query.minLength is not a supported keyword
# (subset: type/oneOf/properties/required/additionalProperties/items/enum/const + annotations);
# schema.properties.query.maxLength is not a supported keyword (subset: ...)这条链上多出来的误导:可见的错误不在注册侧,而在调用侧 —— 就地降级这条路本机走过一遍:只在 Phase 1 降级该工具的 schema(把不支持的键剥掉而不是拒绝), |
|
One thing nobody in this thread has said yet: the MCP spec explicitly allows this, so the server is sending valid tool schemas. From the spec's JSON Schema usage section (2025-11-25):
So the server isn't at fault here: Playwright's On the fix, building on @PerryLink's point that the throw happens in Phase 1, before anything is registered:
Until a fix lands, @astread777-collab's stdio bridge above is the working fix. Per @PerryLink's trace, the zero-tools result happens only on the first sync. A re-sync keeps the previous generation, which explains why it can look intermittent. |
你引的规范条款把这条从"体验问题"变成"合规问题"——这一点很关键1. 你引的三条我都收下,并把它们的要求明确到"必须"你引 MCP 规范(2025-11-25
⇒ 关键在于最后一条是 MUST。于是本条的性质是:
建议把这一句放在报告最前面——"违反规范 MUST 条款"与"我认为应该更宽容"在优先级上完全不同。 2. 与
|
|
规范那条我收下,顺序按你说的改:先把「客户端遇到不支持的输入 schema 关键字,规范要求的是优雅报错(指明关键字/方言),这里是整条链路拒掉」放在最前,再讲现象与复现。 版本补上,顺便钉成两版对照 —— 今天把两个版本的出厂 tarball 各解一份,用同一段 schema 各跑一次宿主自己的断言函数,命令是 两版都拒,说明这条跨 0.2.0-rc.2 → 0.2.1-alpha.1 存活。你问的两样,我们这例的答案是:关键字是
|
Uh oh!
There was an error while loading. Please reload this page.
Summary
When an MCP server advertises even one tool whose
inputSchemauses a JSON Schema keyword outside the enforced subset,dsh-mcp-clientends up registering zero tools from that server. The all-or-nothing swap insyncToolsrolls back the whole generation because a single schema failsassertSupportedJsonSchema.In practice this makes Playwright MCP completely unusable through DSH: every one of its 26 tool schemas carries
"inputSchema": { "$schema": "https://json-schema.org/draft/2020-12/schema", ... }, so the entire browser server is dropped. Sessions then have nomcp__browser__*tools at all, and agents typically fall back to launching their own headless Chromium from bash — which sites such as Google risk-block — producing confusing downstream failures that look like an IP or login problem instead of a tool-registration one.Reproduction
cordis.patch.yml:mcp__browser__*tools exist in the tool catalog (verified on 0.1.5-rc.2 and 0.1.6-alpha.2; other streamable-http servers in the same profile register fine).Current behavior
Running
assertSupportedJsonSchema(from@deepseek-ai/dsh-tools) against each of the 26 Playwright MCP tool schemas:In
packages/mcp/mcp-client/src/tools.ts,syncToolsbuilds the full next generation in phase 1 and registers it in phase 2. The ToolRuntime registration validatesparametersagainst the enforced subset; when one tool's schema throws, the catch block disposes everything already registered for that server:Result: zero tools from the server — not 25 of 26. The only trace is a single error log line; the session otherwise looks healthy.
Note the asymmetry in the same file:
supportedOutputSchema()already degrades gracefully for unsupported output schemas (try/catch →undefinedfallback), while an unsupported input schema takes down the whole server.Expected behavior
One tool with an out-of-subset schema should not disable an entire MCP server. Suggested options, in order of preference:
inputSchemas (they are advisory to the model anyway; the subset engine cannot validate them) and log a warning per affected tool. This preserves the full server and keeps registration total.$schemaas an annotation (it is a pure annotation in JSON Schema 2020-12) — though this alone would not fix Playwright MCP (propertyNames,minimum/maximum, object-valuedadditionalPropertieswould still fail).Environment
ddefc45fbc— same code path inpackages/mcp/mcp-client/src/tools.tsWorkaround (running in production)
A stdio proxy in front of the HTTP server that sanitizes
tools/listschemas to the supported subset and forwards everything else verbatim. Wired into DSH as atransport: stdioentry pointing at the script below; verified end-to-end (all 26 tools registered, real browsing works). ~180 lines, pure Node, zero dependencies:browser-bridge.mjs
Per CONTRIBUTING.md I understand external PRs are not currently accepted; on request I can share a working patch implementing option 1 (sanitize + warn in
syncTools) or the full prototype above for internal use.All reactions