How to Filter Exposed MCP Tools for Token-Constrained Environments

Reduce LLM token consumption by exposing only specific MCP tools using the --tools CLI flag or CRG_TOOLS environment variable.

The Code Review Graph (CRG) server provides a rich set of Model Context Protocol (MCP) tools for graph-based code analysis, but full tool exposure can overwhelm token-limited LLMs. This guide explains how to filter exposed MCP tools for token-constrained environments using the built-in _apply_tool_filter mechanism in CRG's FastMCP implementation.

How the Tool Filter Works

CRG implements tool filtering in code_review_graph/main.py through the _apply_tool_filter helper, invoked during server startup. The mechanism prunes the MCP tool inventory before any client connection occurs.

Filter Execution Flow

  • Step 1: Resolve allow‑list — The filter reads --tools from CLI arguments or the CRG_TOOLS environment variable, normalizing the comma-separated list (whitespace stripped, empty entries removed). Source: code_review_graph/main.py lines 381‑386.

  • Step 2: Iterate registered tools — CRG loops through every tool registered on the FastMCP instance (mcp).

  • Step 3: Prune non-matching tools — Tools not in the allow‑list are removed via mcp.remove_tool(name), eliminating their descriptions from the MCP tool inventory entirely.

  • Step 4: Preserve async semantics — The underlying coroutine implementations remain intact; only the registration is dropped.

  • Step 5: Default to full exposure — If no filter is provided, all tools remain available.

This approach is token‑efficient by design: shrinking the tool inventory reduces the initial payload size, directly lowering token consumption for constrained LLMs.

Filtering Methods

CLI Flag: --tools

Pass a comma-separated list of tool names to keep:

code-review-graph serve --tools query_graph_tool,semantic_search_nodes

Only query_graph_tool and semantic_search_nodes remain exposed; all others are pruned from the MCP inventory.

Environment Variable: CRG_TOOLS

Ideal for containerized deployments or CI pipelines:

export CRG_TOOLS="embed_graph_tool,get_review_context_tool"
code-review-graph serve

The server reads CRG_TOOLS and applies identical filtering logic before accepting connections.

Programmatic Filtering

For embedded server scenarios, invoke the filter directly:

from code_review_graph.main import crg_main

# Retain minimal tool set before client connections

crg_main._apply_tool_filter("list_graph_stats,visualize")

This manipulates the FastMCP instance in-process, ensuring filtered tool exposure for all subsequent clients.

Verifying Filtered Tool Exposure

After server startup, connected MCP clients receive only the pruned tool list:

client = mcp_client.connect()   # platform-specific connection

print(client.list_tools())

# Output: ['query_graph_tool', 'semantic_search_nodes']

The filtered inventory persists for the server's lifetime; restart with different parameters to adjust exposure.

Implementation Details

Component Location Purpose
_apply_tool_filter code_review_graph/main.py lines 381‑386 Core filtering logic
CLI argument parsing code_review_graph/cli.py Bridges --tools to internal filter
Test coverage tests/test_main.py lines 418‑442 Validates filter behavior across input methods

The filter integrates into the serve command initialization, ensuring trimmed tool exposure from the first client handshake regardless of transport (stdio or HTTP).

Test Coverage

The test suite confirms three critical scenarios in tests/test_main.py:

  • test_no_filter_keeps_all_tools (lines 418‑425): Verifies full tool retention when crg_main._apply_tool_filter(None) is called.

  • test_filter_via_argument (lines 426‑432): Confirms CLI-based filtering with crg_main._apply_tool_filter("query_graph_tool").

  • test_filter_via_env_var (lines 434‑442): Validates CRG_TOOLS environment variable behavior using monkeypatch.setenv.

Summary

  • Use --tools for ad-hoc filtering via command line
  • Set CRG_TOOLS for environment-based configuration in containers
  • Call _apply_tool_filter programmatically for embedded deployments
  • Target code_review_graph/main.py for source-level understanding of the filter mechanism

Frequently Asked Questions

What happens if I specify a tool name that doesn't exist?

The filter silently ignores non-existent names. Only matching registered tools are retained; unknown names simply result in no tools being exposed if no valid names remain in the allow‑list.

Can I change the filter without restarting the server?

No. The _apply_tool_filter runs once during server initialization. Changing exposed tools requires a server restart with new --tools or CRG_TOOLS values.

Does filtering affect tool execution performance?

No. Performance characteristics remain unchanged—the filter only removes registration metadata, not the underlying tool implementations. Async semantics for long-running tools are preserved.

How do I discover available tool names for filtering?

Check the source code in code_review_graph/main.py where tools are registered via decorators like @mcp.tool(), or run the server without filtering and query client.list_tools() to see the full inventory.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →