MCP Tool-Retrieval Gateway
This server is a semantic proxy/gateway for Model Context Protocol (MCP) tools, sitting between MCP clients and multiple upstream MCP servers. It exposes only the tools relevant to a natural-language query instead of loading every tool from every server.
Find tools:
find_tools(query, top_k)searches all connected upstream MCP servers and returns the most relevant tool definitions (name, description, input schema). This significantly reduces context overhead—e.g., 18 tools can be reduced to 3 relevant ones.Invoke tools:
call_tool(name, arguments)invokes a discovered tool by name, automatically routing the call to the correct upstream MCP server and returning its real result.Semantic understanding: Queries like "schedule a meeting" can match tools like "create a calendar event."
Deployment options: Works as a standard MCP server over stdio (e.g., for Claude Desktop) and as an HTTP JSON-RPC server with
tools/list(query support),tools/call, and/statsendpoints.Configuration: Configure upstream MCP servers via YAML/JSON; supports
stdio(real subprocess) andmock(inline tool definitions) transports.Embedding strategies: Choose semantic (
sentence-transformers) or offline/deterministichashingembedders.Caching: Optional query-to-tool-set caching with TTL + LRU, including cache hit/miss stats.
Extensibility: Implements pluggable
RetrieverandEmbedderinterfaces for custom retrieval/embedding logic.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Tool-Retrieval Gatewayconvert 100 USD to EUR"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Tool-Retrieval Gateway
A self-hostable MCP proxy that exposes only the top-k semantically relevant tools per query — instead of every tool from every server.
v0.5 — a retrieval evaluation harness: measure retrieval quality on a labeled set with the standard IR metrics — recall@k, precision@k, and MRR. Ships a small deterministic smoke dataset and a
python -m mcp_router.evalCLI. See v0.5: retrieval evaluation.v0.4 — hybrid retrieval: blends the semantic (embedding cosine) score with a lexical token-overlap score so a query that names a tool or its keywords surfaces it even when embedding similarity is only moderate. Configurable
alpha, default on. See v0.4: hybrid retrieval.v0.3 — a query→tool-set cache (TTL + LRU) so repeated queries skip re-embedding and vector search, with hit/miss stats on
/stats. See v0.3: query caching.v0.2 — real MCP transport over the official
mcpSDK (the gateway is now a real MCP client and a real MCP server), and a real local semantic embedder by default. See what's verified vs roadmap.
The problem
The Model Context Protocol (MCP) lets an LLM-based client connect to many tool servers — filesystem, GitHub, a database, a browser, your internal APIs. But there is a cost that grows with every server you add:
An MCP client loads the full tool definitions from every connected server into the context window on every request — names, descriptions, and complete JSON input schemas — before the user has typed a single word.
A handful of servers can easily contribute 50–100+ tool definitions. Rich JSON schemas are verbose, and in practice this commonly burns ~20–40% of the context window as fixed overhead on every turn. That overhead is:
Paid on every request, whether or not any of those tools are relevant.
Mostly wasted — a typical query needs 1–3 tools, not 80.
Money and latency — more prompt tokens on every call, and a larger prompt the model must attend to.
For a single query like "convert 100 USD to EUR", the model does not need the weather tools, the calendar tools, or the git tools. It needs one.
Related MCP server: context-saver
The solution
This gateway sits between the client and the upstream MCP servers as a proxy. It:
Connects to each upstream MCP server and discovers its real tools.
Embeds every tool definition once, at startup, into a vector store.
Per query, returns only the top-k tools whose embeddings are most similar — not the whole catalogue.
On a call, routes the invocation back to the upstream server that actually owns that tool and returns its real result.
The client sees a small, query-relevant tool list. The context overhead drops from "all tools, always" to "k tools, on demand."
Real end-to-end run (v0.2)
Connected to two real MCP servers over stdio — the bundled example server plus the official @modelcontextprotocol/server-filesystem via npx — using the default sentence-transformers embedder:
$ python examples/real_mcp_demo.py
Upstream MCP servers : 2 (real, live over stdio)
Real tools discovered: 18 (a naive client would load all of these)
Exposed per query : 3 (top-k relevant)
Reduction : 18 -> 3 (~83% fewer)
query: 'read the contents of a text file'
1. read_text_file [filesystem] score=0.711
2. read_file [filesystem] score=0.674
3. read_multiple_files [filesystem] score=0.496
query: 'add two numbers together'
1. add_numbers [example ] score=0.784
2. move_file [filesystem] score=0.111
3. reverse_text [example ] score=0.092
----------------------------------------------------------------------
tools/call reverse_text('gateway') -> [example] yawetagThose tools were fetched live from the real servers, and the final line is a real call proxied to the upstream that owns reverse_text — its actual output, yawetag, returned back.
Architecture
MCP Tool-Retrieval Gateway
┌────────────────────────────────────────────┐
MCP host │ │ Upstream MCP servers
(Claude Desktop)│ MCP server (stdio, mcp SDK) │ (real, over stdio)
┌──────────┐ │ ┌────────────────────────┐ │ ┌────────────────────┐
│find_tools│──────▶│ find_tools(query,k) │ top-k │ │ example (SDK) │
│ │◀──────│ │◀──────┐ │┌─▶│ filesystem (npx) │
│call_tool │──────▶│ call_tool(name,args) │ │ ││ │ ...your servers... │
└──────────┘ │ └───────────┬────────────┘ │ ││ └────────────────────┘
│ │ ┌────────┴─────┐ ││
HTTP client │ FastAPI ▼ │ ToolRegistry │ ││
┌──────────┐ │ ┌────────────────────┐ │ Retriever │ ││
│tools/list│──────▶│ POST / (JSON-RPC) │──▶│ embedder │ ││
│ (query) │◀──────│ tools/list+query │ │ vectorstore │ ││
│tools/call│──────▶│ tools/call │───┼─ routes call ─┼──┘│
└──────────┘ │ └────────────────────┘ │ Upstream ───┼───┘
│ └──────────────┘ (MockUpstream | StdioUpstream)
└────────────────────────────────────────────┘
index (startup): connect upstream ─▶ discover tools ─▶ embed() ─▶ VectorStore.add()
query: text ─▶ embed() ─▶ VectorStore.search(k) ─▶ ToolDefs
call: name ─▶ owning Upstream.call() ─▶ real resultTwo front doors, one core:
MCP server (stdio) — what a standard MCP host (Claude Desktop) connects to. See Run as an MCP server.
HTTP JSON-RPC — a convenient HTTP surface whose
tools/listtakes an extraqueryparam. See Run as an HTTP server.
Module map
Module | Responsibility |
| Parse the YAML/JSON config: which upstreams ( |
|
|
| Pluggable embedders: real |
| In-memory NumPy cosine-similarity store. |
|
|
|
|
| Ties it together; discovers tools from upstreams, owns retrieval + routing. |
| The gateway as a real MCP server ( |
| FastAPI app exposing MCP-shaped JSON-RPC over HTTP. |
Requirements
Python 3.11+
fastapi,uvicorn,numpy,pyyaml,mcp(seerequirements.txt)Optional:
sentence-transformersfor the default semantic embedder; Node/npxonly if you point at npx-launched upstream servers.
Quick start
# 1. Install (lean runtime + the real MCP SDK)
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# 2a. Semantic default: install the embedder (downloads ~80MB on first use)
pip install sentence-transformers
# 2b. ...or run fully offline/deterministic instead:
export MCP_ROUTER_EMBEDDER=hashing
# 3. See the reduction against REAL MCP servers, end to end
python examples/real_mcp_demo.pyexamples/demo.py is the original offline demo over inline mock tools; examples/real_mcp_demo.py (above) connects to real MCP servers over stdio.
Run as an MCP server (Claude Desktop)
The gateway serves the real MCP protocol over stdio. Because a vanilla tools/list has nowhere to put a query, it exposes the reduction through progressive disclosure — just two meta-tools, so a host loads 2 tool definitions instead of N:
find_tools(query, k)— semantic search across every upstream; returns the top-k matching tool definitions.call_tool(name, arguments)— proxies a call to whichever upstream owns the tool and returns its real result.
Run it standalone:
MCP_ROUTER_CONFIG=config.stdio.example.yaml python -m mcp_router.mcp_serverAdd it to Claude Desktop's claude_desktop_config.json:
{
"mcpServers": {
"tool-router": {
"command": "python",
"args": ["-m", "mcp_router.mcp_server"],
"env": {
"MCP_ROUTER_CONFIG": "/absolute/path/to/config.stdio.example.yaml",
"MCP_ROUTER_EMBEDDER": "sentence-transformers"
}
}
}
}The host then loads two tools; the model calls find_tools("…") to discover what it needs, then call_tool(...) to run it — keeping context overhead constant no matter how many upstream servers you connect.
Run as an HTTP server
export MCP_ROUTER_CONFIG=config.example.yaml
uvicorn mcp_router.server:app_from_env --factory --port 8000# tools/list with a query -> only the top-k relevant tools
curl -s localhost:8000/ -H 'content-type: application/json' -d '{
"jsonrpc": "2.0", "id": 1, "method": "tools/list",
"params": {"query": "convert dollars to euros", "k": 3}
}'
# tools/call -> routed to the upstream that owns the tool
curl -s localhost:8000/ -H 'content-type: application/json' -d '{
"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": {"name": "convert_currency", "arguments": {"amount": 100}}
}'Omit query from tools/list and the gateway returns all tools — behaving as a transparent proxy.
With Docker
The image is lean and defaults to the offline hashing embedder (instant start, no download):
docker build -t mcp-tool-router .
docker run -p 8000:8000 mcp-tool-router
# point it at your own config:
docker run -p 8000:8000 -e MCP_ROUTER_CONFIG=/app/my.yaml -v $PWD/my.yaml:/app/my.yaml mcp-tool-routerConfiguration
Each server has a name and a transport.
stdio — a real MCP server launched as a subprocess (config.stdio.example.yaml):
servers:
- name: filesystem
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
env: {}
- name: example
transport: stdio
command: python
args: ["examples/example_upstream_server.py"]mock — offline; tools listed inline, calls echoed (config.example.yaml):
servers:
- name: finance
transport: mock
tools:
- name: convert_currency
description: Convert a monetary amount from one currency to another.
inputSchema:
type: object
properties:
amount: { type: number }v0.5: retrieval evaluation
Retrieval quality is the product. Up to v0.4 it was asserted only by crafted unit tests; v0.5 makes it a number you can track across changes to the embedder, the hybrid blend, or alpha. The harness (mcp_router/eval.py) scores the retriever's top-k results against a labeled dataset — each example is a query plus the set of tool names that should come back — using three standard IR metrics:
metric | definition | rewards |
recall@k | ` | relevant ∩ retrieved_k |
precision@k | ` | relevant ∩ retrieved_k |
MRR | mean of | putting a relevant tool near the top |
The harness never reimplements retrieval — evaluate(retriever, dataset, k) calls the real retriever.retrieve(query, k) (a Retriever or a ToolRegistry) and scores the names it returns, so you measure the exact code path the gateway serves.
python -m mcp_router.eval # k=3 by default
python -m mcp_router.eval --k 5query recall@k prec@k RR
--------------------------------------------------------------
current temperature and condit... 1.000 0.333 1.000
...
MEAN 1.000 0.333 1.000The bundled dataset (mcp_router/eval_data.py) is a small, deterministic smoke set — a handful of tools and a few queries with known-relevant tools — that runs offline on the hashing embedder. It exists to make the harness runnable out of the box and to guard against regressions; it is not a benchmark or a quality claim. Point evaluate() at your own labeled set to measure a real catalogue.
v0.4: hybrid retrieval
Pure-embedding retrieval scores meaning, which is what you want for "schedule a meeting" → create_event. But it has a blind spot: an exact tool-name or keyword hit can score only moderately when the surrounding words differ, so a semantically-fuzzy distractor can edge out the tool the user literally named. v0.4 blends in a lexical signal to fix that.
What it does
Computes a lexical score — normalized token overlap between the query and the tool's text (name + description + parameter names): of the meaningful tokens in the query, what fraction appear in the tool? Bounded to
[0, 1], stopword-aware, no heavy dependency.Blends it with the semantic cosine score by a weight
alpha:final = alpha * semantic + (1 - alpha) * lexicalBecause a strong keyword match may sit outside the semantic top-k, the hybrid path scores the whole catalogue before taking the top-k — affordable since a gateway fronts only tens-to-hundreds of tools.
alpha = 1.0reproduces the v0.3 pure-semantic behaviour;alpha = 0.0is pure lexical. The default0.5is an even blend.
Why it helps — consider the query "delete_user account" against two tools, delete_user ("Remove an account permanently") and user_account. On pure cosine the shorter user_account scores higher (0.82 vs 0.77) and wins — the exact-name match loses. Blending in lexical coverage (the query fully covers delete_user) flips the ranking so the tool the user named comes first. This exact case is pinned in the test suite.
Config — a top-level retrieval: block (all optional; defaults shown):
retrieval:
hybrid: true # false -> pure-semantic (v0.3 behaviour)
alpha: 0.5 # 1.0 = all semantic, 0.0 = all lexicalThe active mode is reported on GET /stats (retrieval.hybrid, retrieval.alpha) alongside the cache counters.
v0.3: query caching
Retrieval is the expensive part of every request — embedding the query and searching the vector store. Real traffic is repetitive (the same phrasings recur, clients retry), so redoing that work for an identical query is pure waste. v0.3 adds a small cache in front of the retriever that memoizes the top-k tool set per query.
What it does
Keys each entry by a normalized query (lowercased + trimmed) plus
k. A repeated query returns the cached tool set without re-embedding or re-searching.TTL expiry — every entry has a lifetime; a hit past its TTL is recomputed, so results can't go stale indefinitely.
LRU eviction — the cache holds at most
max_entries; inserting beyond that drops the least-recently-used entry, capping memory.Auto-invalidation — when the tool catalogue changes (
ToolRegistry.refresh()— upstreams reconnect / tools refresh), the whole cache is cleared so a tool set computed against the old catalogue is never served.Hit/miss stats — exposed on the HTTP
GET /statsendpoint (andToolRegistry.stats()).
Perf rationale: the win is skipping the embed + vector-search on repeated queries. With the semantic embedder that avoids a model forward-pass per repeat; a cache hit is a dict lookup.
Config — a top-level cache: block (all optional; defaults shown):
cache:
enabled: true # set false to bypass the cache entirely
ttl_seconds: 300 # how long a cached tool set stays fresh
max_entries: 512 # LRU cap on distinct cached (query, k) pairs# hit/miss counters, hit rate, cached-entry count, evictions, invalidations
curl -s localhost:8000/statsEmbedders
The embedder is selected by MCP_ROUTER_EMBEDDER:
Value | What it is | When |
| Real local model | Production / real semantic retrieval. Downloads ~80MB once, then cached. |
| Dependency-free, deterministic hashing-trick embedder. Lexical overlap only. | Tests, CI, air-gapped runs. No download. |
export MCP_ROUTER_EMBEDDER=sentence-transformers # default
export MCP_ROUTER_ST_MODEL=all-MiniLM-L6-v2 # optional; this is the default
# or, fully offline:
export MCP_ROUTER_EMBEDDER=hashingTo wire in a hosted embedding API, implement the Embedder interface (one method, embed(texts) -> np.ndarray) and return it from get_embedder(). Everything downstream depends only on that interface.
Running the tests
pip install -r requirements.txt
pytestThe suite is offline and deterministic by design: it forces MCP_ROUTER_EMBEDDER=hashing and never downloads a model. It includes real MCP-transport integration tests that launch the bundled example server as a subprocess and speak the actual protocol to it (both the gateway-as-client and gateway-as-server paths).
74 passing, 1 skipped locally. The skipped test connects to the official
@modelcontextprotocol/server-filesystemvianpx(needs Node + network); enable it withMCP_ROUTER_RUN_NPX_TESTS=1 pytest.
What's verified vs roadmap
Honest status for v0.2.
Verified end-to-end (implemented + tested):
Real MCP client transport.
StdioUpstreamlaunches a real MCP server and speaks JSON-RPC over stdio via the officialmcpSDK; tools are discovered live and calls are proxied to the real server. Exercised against the bundled example server (offline, in CI) and against the officialnpxfilesystem server (opt-in test, and in the demo above).Real MCP server transport.
mcp_router.mcp_serverruns as a real MCP server over stdio (find_tools+call_tool); a real SDKClientdrives the full loop in tests — including a launched-subprocess run that mirrors how Claude Desktop connects.Real semantic embedder by default (
sentence-transformers,all-MiniLM-L6-v2), with the offline hashing embedder as the deterministic fallback.Config-driven registry (YAML/JSON), NumPy cosine top-k retrieval, upstream routing, HTTP JSON-RPC surface, Docker image.
Not yet exercised by an external host: connecting the actual Claude Desktop app is documented (config snippet above) and the stdio server it would launch is verified with the SDK's own client, but the end-to-end run inside the Claude Desktop UI has not been performed here.
Deferred (next milestones):
Approximate vector index (FAISS/hnswlib) for very large tool catalogues — exact search is the right choice for tens–hundreds of tools.
SSE / streamable-HTTP MCP transports (only stdio upstreams today).
Resources / prompts passthrough. (Query→tool-set caching shipped in v0.3; hybrid lexical + semantic retrieval shipped in v0.4; a labeled-set evaluation harness with recall@k / precision@k / MRR shipped in v0.5.)
License
MIT — see LICENSE.
Available Tools
2 toolscall_toolA
Invoke a tool by name (as returned by find_tools) on whichever upstream server owns it, forwarding the given arguments, and return that server's result.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| arguments | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the core behavior of forwarding arguments and returning the server's result, but does not mention potential side effects (since invoking arbitrary tools may cause mutations), error handling, or permissions. The generic nature limits deeper transparency, but the forwarding and return behavior is clearly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no fluff. Every part adds value: invocation, name source, routing, argument forwarding, and return behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter proxy with an output schema, the description covers the key aspects: what it invokes, how to get the name, where it routes, and what it returns. It omits edge-case details like errors or timeouts, which is acceptable given the tool's simplicity and the presence of an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does specify that the 'name' parameter comes from find_tools and that 'arguments' are forwarded, adding some meaning beyond the schema. However, it does not elaborate on argument structure or provide examples, leaving partial compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool invokes a named tool, explicitly references find_tools for name discovery, and distinguishes itself from the sibling by focusing on invocation rather than discovery. The verb 'Invoke' and resource 'tool by name' make the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description ties usage to find_tools output ('as returned by find_tools'), providing clear context on when to use this tool. It lacks explicit exclusions or 'when not to use' guidance, but the reference to the sibling is strong contextual guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_toolsA
Search all connected MCP servers for the tools most relevant to a natural-language query. Returns up to k tool definitions (name, description, input schema) as JSON. Call this first to discover which tool to use, then invoke it with call_tool.
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses that the tool searches across all connected MCP servers and returns a bounded number of tool definitions, which covers the core behavioral traits. However, it does not mention potential latency, network dependency, or failure modes, so it is not fully exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences long, front-loaded with the core function, and contains no fluff. Every clause adds value: what it does, what it returns, and how to use it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's modest complexity (2 parameters, no annotations), the description fully covers the essential context: it explains the output schema content (name, description, input schema), the role in the workflow, and the parameters. It is a complete description for a discovery tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description must compensate. It does so implicitly: 'natural-language query' explains the query parameter, and 'up to k' explains the k parameter. This provides meaningful semantics beyond the raw schema, though it lacks detailed constraints or edge cases.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search all connected MCP servers for the tools most relevant to a natural-language query.' It also specifies the return format ('Returns up to k tool definitions... as JSON') and distinguishes itself from the sibling tool call_tool by positioning itself as the discovery step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: 'Call this first to discover which tool to use, then invoke it with call_tool.' This clearly states when to use this tool and how it relates to the alternative, call_tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.2.0- First observed
call_tool - First observed
find_tools
TDQS
Scored across 2 tools
The two tools are entirely distinct: find_tools is for discovery/searching across upstream servers, while call_tool is for execution. There is no functional overlap or ambiguity.
Both tools follow the verb_noun pattern (find_tools, call_tool) with lowercase and underscores, making the naming predictable and consistent.
As a gateway that dynamically exposes tools from many upstream servers, two meta-tools (discover and invoke) are exactly the right scope. Each tool earns its place, and adding more would be redundant.
The tool surface fully covers the domain of a retrieval/calling gateway: discover which tool to use (find_tools) and then invoke it (call_tool). There are no obvious missing operations for this purpose.
Maintenance
Related MCP Connectors
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
Security & DLP proxy for MCP: tool-poisoning scans, PII redaction on tool args/results. Beta.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
- WauldoOAuthcom.wauldo
Stateless agentic tools over MCP: concept extraction, long-context, knowledge graph, planning.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceA proxy server that wraps existing MCP servers to significantly reduce token consumption by compressing tool descriptions into a two-step interface. It enables users to integrate extensive toolsets without exceeding context limits or incurring high API costs.118Apache 2.0
- AlicenseNot gradedqualityDmaintenanceMCP proxy that reduces context usage through semantic tool routing, enabling on-demand discovery and routing of relevant tools.MIT
- -licenseNot gradedqualityNot gradedmaintenanceMCP proxy server with semantic tool search for LLM coding agents. It reduces context window usage by activating only relevant tools based on user queries.-
- AlicenseNot gradedqualityCmaintenanceIntelligent MCP proxy server that reduces context bloat by serving only the tools your AI actually needs through semantic search and a fixed two-tool surface.12MIT