Skip to content

MCP: a tool with a non-ECMAScript JSON-Schema pattern fails the whole server connection (shown as "Authentication failed" for OAuth servers) #35624

Description

@verkadabambam

Summary

If any tool returned by tools/list has an input/output JSON Schema pattern that isn't a valid ECMAScript (ECMA-262) regex, Client.listTools() throws while compiling schema validators, and OpenCode tears down the entire MCP server connection — even though the connection and every other tool are fine.

Worse: for OAuth servers authenticated via opencode mcp auth, the OAuth token exchange has already succeeded and been persisted by the time this happens, yet the CLI reports "Authentication failed". A purely schema-side problem is misattributed to authentication, so users re-authenticate in a loop that can never succeed.

Environment

  • opencode 1.17.14
  • @modelcontextprotocol/sdk 1.29.0
  • Reproduced on both Bun and Node runtimes.

Root cause

  1. listTools() calls cacheToolMetadata(), which compiles a validator for each tool's schema. A pattern that is invalid in ECMA-262 makes new RegExp(pattern) throw, so the whole listTools() call throws.
  2. create() in packages/opencode/src/mcp/index.ts runs McpCatalog.defs() (i.e. listTools) after the transport has already connected successfully. The throw is caught by create()'s outer handler and returned as status: "failed" with message "Failed to get tools" — failing the whole server, not just the one tool.
  3. In the OAuth path, finishAuth() calls provider.commit() (persist tokens) before createAndStore() (which runs the failing listTools). So valid tokens are already written to mcp-auth.json.
  4. opencode mcp auth (packages/opencode/src/cli/cmd/mcp.ts) maps status: "failed" to the message "Authentication failed" followed by the underlying "Failed to get tools".

Net effect: OAuth actually succeeded, the token works, but the user sees "Authentication failed" and re-auths repeatedly.

Reproduction

Connect to a remote MCP server that returns a tool whose schema pattern uses a Python-style named group (?P<name>...), which is invalid in ECMA-262.

Concrete example (Tracecat): tools get_workflow_execution, run_published_workflow, run_draft_workflow, list_workflow_executions, run_case_task emit:

(?P<workflow_id>wf-[0-9a-f]{32}|wf_[0-9a-zA-Z]+)[:/](?P<execution_id>...)
new RegExp("(?P<workflow_id>wf-[0-9a-f]{32})[:/](?P<execution_id>.*)")
// -> SyntaxError: Invalid regular expression: Invalid group   (Node and Bun)

Result: opencode mcp auth <server> shows Authentication failed / Failed to get tools, and the server never reaches connected, despite a valid token being persisted.

Suggested fix

  • In cacheToolMetadata, wrap the per-tool validator compilation in try/catch so one un-compilable pattern degrades that tool's output validation instead of throwing out of listTools() and failing the whole connection.
  • Don't surface a post-authentication tool-listing failure as an authentication failure — distinguish "connected but tool-listing failed" from "auth failed" in create()/cmd/mcp.ts.

(The server also shouldn't emit non-ECMA-262 patterns — that's a server-side bug being fixed separately — but a single malformed tool schema shouldn't take down an otherwise-healthy MCP connection.)

Metadata

Metadata

Assignees

Labels

No labels
No labels

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