Skip to content

Config typos are handled inconsistently: a misspelled --exclude-tools or --features entry is silently ignored #3761

Open

Description

@rafe-walker

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 / CreateExcludeToolsFilter never check names against the inventory. Compare :247-249 for WithTools.
  • pkg/github/feature_flags.go:105-125: ResolveFeatureFlags drops names outside AllowedFeatureFlags without 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):

  1. no flags: 46 tools, including delete_file
  2. --exclude-tools=delete_file: 45, no delete_file
  3. --exclude-tools=delete_fil: 46, delete_file present, and stderr has no warning about the unknown name (only the token-scope WARN from the dummy token)
  4. --features=not_a_feature: 46, and stderr has no warning about the unknown name (only the token-scope WARN from the dummy token)
  5. --toolsets=not_a_toolset: 0 tools, and stderr has level=WARN msg="Warning: unrecognized toolsets ignored" toolsets=not_a_toolset
  6. --tools=not_a_tool: the process exits with failed 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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions