Skip to main content

MCP Proxy

The MCP proxy sits between an MCP client and one or more backend MCP servers. It builds a searchable graph over backend tools and exposes a smaller, filtered tool surface to the client.

Use a proxy when the client would otherwise see too many tools or when several backend servers need to be searched as one catalog.

Run The Proxy

graph-tool-call proxy \
--config .mcp.json \
--top-k 10 \
--passthrough-threshold 30

--passthrough-threshold keeps small catalogs simple. If a backend exposes fewer tools than the threshold, the proxy may pass them through without aggressive filtering.

The proxy has two operating modes:

ModeTriggerClient SeesUse It For
gatewaycatalog size is above --passthrough-thresholdsearch_tools, get_tool_schema, call_backend_tool, then matched backend toolslarge or multi-server catalogs
passthroughcatalog size is below the thresholdbackend tools directlysmall catalogs where filtering would add friction

HTTP Transport

graph-tool-call proxy \
--config proxy-config.json \
--transport streamable-http \
--host 127.0.0.1 \
--port 8000

Config Inputs

The proxy can read a normal .mcp.json style file or a graph-tool-call proxy config. Keep backend credentials in your runtime secret manager where possible.

{
"mcpServers": {
"orders": {
"command": "python",
"args": ["orders_server.py"]
}
}
}

When multiple backends expose the same tool name, the proxy keeps names callable by prefixing duplicates with the backend name. That avoids silent collisions while preserving direct tool calls after search.

Retrieval Behavior

The proxy uses graph-tool-call to:

  • ingest backend tool schemas
  • normalize descriptions and annotations
  • search with keyword and optional embedding signals
  • return a compact candidate set
  • preserve evidence for debugging

Gateway Workflow

In gateway mode, the client should search before calling a backend tool.

tools/list
-> search_tools({"query": "create a customer refund", "top_k": 8})
-> tools/list refresh exposes matched backend tools
-> get_tool_schema({"tool_name": "orders.create_refund"})
-> call matched backend tool directly

call_backend_tool is a fallback for clients that cannot call dynamically injected backend tools. Prefer direct calls when the client supports them.

Tuning

OptionEffectPractical Guidance
--top-kdefault number of tools returned by search_toolskeep this small enough for the client context window
--embeddingenables optional embedding signalsuse when descriptions are rich enough to justify the cost
--cachepersists backend tool metadata and retrieval stateuse for slower backend startup
--passthrough-thresholdswitches between passthrough and gateway modelower it when clients struggle with many tools

When Not To Use It

Do not add a proxy when:

  • the backend exposes only a handful of tools
  • the client needs complete raw backend capability discovery
  • product policy must be enforced inside a dedicated backend adapter
  • latency is more important than tool catalog reduction

Failure Modes

SymptomLikely CauseCheck
only meta-tools appeargateway mode is active and no search has been run yetcall search_tools and refresh tools/list
direct backend tool is missingmatched tools were not injected or client cached tools/listcall get_tool_schema or call_backend_tool as fallback
duplicate-looking namesmultiple backends exposed the same tool nameinspect backend-prefixed names in search results
poor rankingbackend descriptions are thin or genericadd annotations or ingest richer metadata
startup is slowevery backend is queried on process startenable --cache or reduce backend scope

Validate The Integration

poetry run pytest tests/test_mcp_proxy.py -q

For a manual smoke test, run the proxy with a small fixture backend, confirm gateway versus passthrough mode, search for one task, and verify that the matched tool can be called either directly or through call_backend_tool.