Skip to content

fix(amazonq): derive MCP tool name mapping from enabled tools - #2904

Draft
dungdong-aws wants to merge 1 commit into
Amazon-Q-Developer:feature/mcp-security-enchancefrom
dungdong-aws:fix/mcp-tool-mapping-enabled-set
Draft

dungdong-aws wants to merge 1 commit into
Amazon-Q-Developer:feature/mcp-security-enchancefrom
dungdong-aws:fix/mcp-tool-mapping-enabled-set

Conversation

@dungdong-aws

Copy link
Copy Markdown
Contributor

Summary

Two code paths compute MCP tool names independently with createNamespacedToolName, which assigns bare names by set occupancy, first come first served:

  • toolServer.registerServerTools builds names from getEnabledTools(). This is the name a tool is registered under in the runtime.
  • agenticChatController.#getTools built names from getAllTools(), which includes disabled tools. This is the name the model is offered, and #getTools also writes the result into the manager via setToolNameMapping, which is what getOriginalToolNames reads at dispatch.

When two servers advertise the same tool name and one of them is disabled, the two sides disagree. toolServer sees only the enabled tool and registers it under the bare name. #getTools sees both, lets the disabled tool claim the bare name first, and pushes the enabled tool to its server___tool form. The model is offered a name the runtime has not registered, and the mapping resolves the bare name to a tool the user turned off.

#getTools now derives the mapping from getEnabledTools(), the same set toolServer registers from.

Relationship to #2903

Independent. #2903 reserves built-in tool names so a server-advertised name cannot select built-in dispatch. This change makes the two MCP name-assignment sites agree with each other. Neither depends on the other, they touch different lines of #getTools, and both call createNamespacedToolName in forms that merge in either order. This was split out of #2903 to keep that change scoped to the built-in collision.

Intentional behavior changes

  • Disabled MCP tools no longer participate in bare-name assignment. An enabled tool that shares a name only with disabled tools keeps its bare name.
  • mcpToolSpecNames, which feeds the read-only-mode tool filter, no longer includes disabled tools. Disabled tools are not registered, so they were never present in the list being filtered; this changes nothing observable there.

Tests and verification

Adds a processToolUses case where two servers advertise search and only one is enabled, asserting the written mapping resolves search to the enabled server, does not contain the namespaced form for it, and contains no entry for the disabled server. The shared McpManager test stub gains getEnabledTools.

Prettier passed on both changed files. ESLint reported no errors; the remaining warnings are pre-existing import/no-nodejs-modules.

Verification limits

Compilation and the unit suite were not run locally. The authoring host enforces memory-capped build invocation through a cgroup scope that the sandboxed session could not create, so tsc and Mocha were refused rather than run uncapped. CI is the first execution of the added test.

Not verified in a running IDE. The scenario requires two MCP servers sharing a tool name with one disabled.

toolServer registers MCP tools from getEnabledTools(), while
agenticChatController.#getTools built the tool name mapping from
getAllTools(). createNamespacedToolName assigns bare names by set
occupancy, so a disabled tool could claim a bare name first and push an
enabled tool with the same name to its namespaced form. The model was
then offered a name the runtime had not registered, and the mapping
written by setToolNameMapping resolved the bare name to the disabled
tool.

#getTools now derives the mapping from getEnabledTools(), the same set
toolServer registers from. The test stubs gain getEnabledTools, and a
test pins that a disabled tool does not appear in the mapping and does
not displace an enabled tool's bare name.
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.

1 participant