Skip to content

fix(opencode): exclude denied MCP tools from provider requests - #38060

Closed
IbrahimKhan12 wants to merge 1 commit into
anomalyco:devfrom
IbrahimKhan12:mcp-tools-visibility
Closed

fix(opencode): exclude denied MCP tools from provider requests#38060
IbrahimKhan12 wants to merge 1 commit into
anomalyco:devfrom
IbrahimKhan12:mcp-tools-visibility

Conversation

@IbrahimKhan12

Copy link
Copy Markdown

Issue for this PR

Closes #37675

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The global tools key is documented so that { "mymcp_*": false } (equivalent to { "*": "deny" }) disables all of an MCP server's tools. But SessionTools.resolve added every mcp.tools() entry to the tool list sent to the provider regardless of permission. So a wholly-denied MCP tool was still advertised, and when its schema is one the provider rejects (the Moonshot 400 in the report) the whole session fails.

Permission.visibleTools already drops wholly-denied tools, and the experimental code-mode path already applies it to mcp.tools(). This applies the same filter in the normal path. Only tools denied with resource pattern * are hidden; ask and resource-scoped rules leave the tool advertised, so nothing else changes.

How did you verify your code works?

Added packages/opencode/test/session/tools.test.ts, which drives SessionTools.resolve with mocked MCP tools and a permission ruleset:

  • a "postman*" deny rule excludes postman_search but keeps github_list
  • no matching rule keeps the tool
  • a resource-scoped deny (pattern != "*") keeps the tool
  • an exact-match deny hides only that tool, not siblings under the same prefix

The deny-glob test fails before the change and passes after. Also ran bun typecheck and the related suites (test/session/prompt.test.ts, test/permission/next.test.ts, test/tool/code-mode.test.ts, test/tool/registry.test.ts, test/mcp/), all passing.

Screenshots / recordings

N/A, not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

The global `tools` config (e.g. `{ "mymcp_*": false }`, documented as
equivalent to `{ "*": "deny" }`) is meant to disable all of an MCP
server's tools, but SessionTools.resolve advertised every `mcp.tools()`
entry to the provider regardless of permission. A wholly-denied MCP tool
whose schema the provider rejects then fails the whole session with a 400.

Apply the existing `Permission.visibleTools` filter to `mcp.tools()` in the
normal path, matching the experimental code-mode path which already does
this. Only wholly-denied tools (resource pattern `*`) are hidden; `ask`
and resource-scoped rules leave the tool advertised.

Fixes anomalyco#37675
@IbrahimKhan12

Copy link
Copy Markdown
Author

Fixed by #6319, with the current provider-bound filtering path retained by #28560: LLMRequestPrep.resolveTools already removes hard-denied tools before either provider runtime receives prepared.tools. This PR repeats the same predicate earlier in SessionTools.resolve, and its tests stop before request preparation, so it does not change the reported behavior. The remaining Moonshot schema compatibility issue is separate. Closing PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global tools globs don't exclude MCP tools from provider requests

1 participant