Skip to content

feat(serve): add --tools flag and CRG_TOOLS env var for MCP tool filtering#301

Closed
sdeonvacation wants to merge 1 commit into
tirth8205:mainfrom
sdeonvacation:feat/tool-filtering
Closed

feat(serve): add --tools flag and CRG_TOOLS env var for MCP tool filtering#301
sdeonvacation wants to merge 1 commit into
tirth8205:mainfrom
sdeonvacation:feat/tool-filtering

Conversation

@sdeonvacation
Copy link
Copy Markdown
Contributor

Summary

  • Add --tools CLI flag to serve subcommand and CRG_TOOLS env var fallback for filtering which MCP tools are exposed
  • When set, unlisted tools are removed via FastMCP.remove_tool() before the server starts
  • When neither is set, all tools remain available (no breaking change)

Motivation

CRG exposes 28 MCP tools by default, adding ~8k description tokens per LLM turn. In token-constrained environments (e.g. agentic coding tools calling CRG via MCP), this overhead can exceed the savings from graph queries — especially when only 5-10 tools are actually needed.

Filtering to a working set reduces per-turn overhead by 70-85%, making CRG net-positive on tokens from the first few queries.

Usage

# Via CLI flag (highest precedence)
code-review-graph serve --tools query_graph_tool,semantic_search_nodes_tool,detect_changes_tool

# Via environment variable (fallback)
CRG_TOOLS=query_graph_tool,semantic_search_nodes_tool code-review-graph serve

MCP client config example:

{
  "mcpServers": {
    "code-review-graph": {
      "command": "code-review-graph",
      "args": ["serve", "--tools", "query_graph_tool,semantic_search_nodes_tool,detect_changes_tool"]
    }
  }
}

Changes

File Change
code_review_graph/main.py Add _apply_tool_filter() + update main() signature
code_review_graph/cli.py Add --tools arg to serve subparser, pass to main()
tests/test_main.py 7 async tests: noop, arg filter, env var, precedence, empty string, whitespace
README.md Tool Filtering section in Configuration

Testing

All 794 existing tests pass. 7 new tests added:

  • test_no_filter_keeps_all_tools — noop when unset
  • test_filter_via_argument — keeps only listed tools
  • test_filter_via_env_varCRG_TOOLS env var works
  • test_argument_takes_precedence_over_env — CLI wins over env
  • test_empty_string_is_noop — empty string doesn't remove all tools
  • test_whitespace_handling — spaces around names are stripped
uv run pytest tests/test_main.py -v   # 13 passed
uv run pytest tests/ -q               # 794 passed, 1 skipped, 2 xpassed
uv run ruff check                     # All checks passed

…ering

CRG exposes 28 MCP tools by default, adding ~8k description tokens
per LLM turn. In token-constrained environments this overhead can
exceed the savings from graph queries.

Add _apply_tool_filter() that accepts a comma-separated allow-list
of tool names. Unlisted tools are removed via FastMCP.remove_tool()
before the server starts. The allow-list can be provided via:

  1. --tools CLI flag (highest precedence)
  2. CRG_TOOLS environment variable (fallback)

When neither is set, all tools remain available (no breaking change).

Filtering to 5-10 tools reduces per-turn overhead by 70-85%.

Includes 7 async tests covering: no-filter noop, argument-based
filtering, env var fallback, argument precedence over env, empty
string noop, and whitespace handling.
@tirth8205
Copy link
Copy Markdown
Owner

This PR now has merge conflicts with main after recent merges. Could you rebase on the latest main? The feature looks good.

tirth8205 added a commit that referenced this pull request Apr 18, 2026
Kept --tools flag / CRG_TOOLS env var (PR #301) alongside --http/--host/--port
Streamable HTTP transport flags added by origin/main; merged both sets of
changes in cli.py, main.py, README.md, and tests/test_main.py.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tirth8205
Copy link
Copy Markdown
Owner

Closed: changes merged directly into main as commit a3a043b (feat(serve): add --tools flag and CRG_TOOLS env var for MCP tool filtering). Conflicts with --http/--host/--port HTTP transport flags were resolved by keeping both features.

@tirth8205 tirth8205 closed this Apr 18, 2026
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.

2 participants