Repository navigation
Description
Describe the bug
A misspelled name gets one of three different outcomes, depending on which option it is in:
| input | result |
|---|---|
--tools=not_a_tool |
startup fails: unknown tools specified in WithTools: not_a_tool |
--toolsets=not_a_toolset (or Repos, case-sensitive) |
WARN unrecognized toolsets ignored, then the server runs with 0 tools |
--exclude-tools=delete_fil |
no log line; delete_file stays enabled (46 tools) |
--features=not_a_feature |
no log line |
A misspelled --exclude-tools entry gives no signal, so the tool stays enabled. An operator who misspells a tool they meant to disable is not told, and the model can still call it.
Ignoring unknown toolsets is deliberate (PR #1202, docs PR #1398), and so is erroring on unknown tools (PR #1776). Open PR #2184 adds an opt-in strict mode for toolsets. This issue is about the two options that give no signal at all. ResolveFeatureFlags documents this as intentional for request input; the ask here is only a startup log line for the --features CLI flag.
Code (main 99d6d65, unchanged since v2.1.0):
pkg/inventory/builder.go:154-175:WithExcludeTools/CreateExcludeToolsFilternever check names against the inventory. Compare:247-249forWithTools.pkg/github/feature_flags.go:105-125:ResolveFeatureFlagsdrops names outsideAllowedFeatureFlagswithout logging.pkg/github/server.go:114: the toolset warning.
Affected version
v2.1.0 (image sha256:f6056fc1…0f8a, commit 4bcdcdf) and main nightly (image sha256:48bc16d0…338f, revision 99d6d65). stdio.
Steps to reproduce the behavior
Each step is docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN <image> stdio <flags>, then initialize + tools/list (a dummy token is enough, since no API call is needed):
- no flags: 46 tools, including
delete_file --exclude-tools=delete_file: 45, nodelete_file--exclude-tools=delete_fil: 46,delete_filepresent, and stderr has no warning about the unknown name (only the token-scope WARN from the dummy token)--features=not_a_feature: 46, and stderr has no warning about the unknown name (only the token-scope WARN from the dummy token)--toolsets=not_a_toolset: 0 tools, and stderr haslevel=WARN msg="Warning: unrecognized toolsets ignored" toolsets=not_a_toolset--tools=not_a_tool: the process exits withfailed to create MCP server: failed to build inventory: unknown tools specified in WithTools: not_a_tool
Expected vs actual behavior
Expected: unknown names in --exclude-tools and --features are at least logged, as unknown toolsets are. For --exclude-tools, an error would match --tools, since a typo there leaves enabled a tool the operator meant to disable.
Actual: silent.
Suggested fix: in WithExcludeTools, collect names not present in the inventory (including deprecated aliases) and warn or error. In ResolveFeatureFlags (CLI path), warn on names outside AllowedFeatureFlags.
Logs
--exclude-tools=delete_fil -> 46 tools, delete_file listed; stderr: only the token-scope WARN
--features=not_a_feature -> 46 tools; stderr: only the token-scope WARN
--toolsets=not_a_toolset -> 0 tools; WARN "Warning: unrecognized toolsets ignored" toolsets=not_a_toolset
--tools=not_a_tool -> exit; "unknown tools specified in WithTools: not_a_tool"
Same on v2.1.0 and main.
Found during an independent audit of v2.1.0 on a throwaway org and private test repo. Prepared with AI assistance (Claude Code); reproduced by two independent test runs before filing.
Activity