Skip to main content

Intelligent MCP tool routing — reduce context bloat by serving only relevant tools

Project description

smartmcp

PyPI version Python 3.10+ License: MIT

Without smartmcp vs With smartmcp

PyPI package: smartmcp-router (CLI: smartmcp)

Intelligent MCP tool routing that reduces context bloat by serving only the tools your AI actually needs.

In my own setup with 8 MCP servers and 224 tools, every AI request was loading ~66,000 tokens of tool schemas before the model even started thinking. With smartmcp, that dropped to ~1,600 tokens. A 97% reduction on every request.

Without smartmcp With smartmcp
Tools in context All 224 1 (search_tools) + 5 matched
Tokens per request ~66,000 ~1,600
Scales with Every tool you add (O(n)) Always top-k (O(1))

Token counts estimated at ~4 characters per token. Actual counts vary by model tokenizer.

Most MCP setups expose every tool from every server to the AI at once. With 5+ servers, that's 50–200+ tool schemas crammed into the context window before the AI even starts thinking. smartmcp fixes this.

smartmcp is a proxy MCP server that sits between your AI client and your upstream MCP servers. It indexes all available tools using semantic embeddings, then exposes a single search_tools tool. When the AI describes what it wants to do, smartmcp finds the most relevant tools and dynamically surfaces their full schemas so the AI can see their parameters and call them directly.

How it works

AI Client (Claude Desktop / Cursor / your agent)
    ↕  stdio
smartmcp (proxy server)
    ↕  stdio (one connection per server)
[github] [filesystem] [google-workspace] [git] [memory] [puppeteer] ...

smartmcp uses a two-phase flow: discover, then call.

Phase 1: Discovery

  1. On startup, smartmcp connects to all your configured MCP servers, collects every tool schema, and builds a FAISS vector index using sentence-transformer embeddings.
  2. The AI sees only one tool: search_tools. It calls it with a natural language query, for example search_tools({ "query": "create a GitHub issue" }).
  3. smartmcp runs semantic search across all indexed tools and finds the top-k matches.
  4. The full schemas of those matching tools (name, description, parameters, types) are dynamically added to the tool list. smartmcp sends a tool_list_changed notification so the AI client re-fetches and sees them.

Phase 2: Calling

  1. The AI now sees the surfaced tool schemas with their complete inputSchema. It picks the right tool, constructs the correct arguments itself, and calls it.
  2. smartmcp parses the namespaced tool name (e.g. github__create_issue), routes the call to the correct upstream server, and returns the result.

The intelligence is in the discovery step. The AI still does its own parameter construction based on the exposed schemas. smartmcp just narrows down which tools it sees.

Installation

pip install smartmcp-router

Requires Python 3.10+.

Quick start

1. Create a config file

Create a smartmcp.json with your upstream MCP servers (same format as Claude Desktop / Cursor config):

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_your_token_here"
      }
    },
    "slack": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-slack"],
      "env": {
        "SLACK_BOT_TOKEN": "xoxb-your-token-here"
      }
    }
  },
  "top_k": 5,
  "embedding_model": "all-MiniLM-L6-v2"
}

2. Add smartmcp to your AI client

Add smartmcp as your single MCP server entry. It now manages all your upstream servers defined in smartmcp.json.

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "smartmcp": {
      "command": "smartmcp",
      "args": ["--config", "/path/to/smartmcp.json"]
    }
  }
}

Cursor

Add to your .cursor/mcp.json:

{
  "mcpServers": {
    "smartmcp": {
      "command": "smartmcp",
      "args": ["--config", "/path/to/smartmcp.json"]
    }
  }
}

Custom agents

Point your MCP client at smartmcp the same way you would any stdio MCP server:

smartmcp --config /path/to/smartmcp.json

3. Use it

Your AI now sees a single search_tools tool. When it needs to do something, it searches:

AI calls: search_tools({ "query": "read files from disk" })

smartmcp returns: 3 matching tools from the filesystem server. Their full schemas are now exposed.

AI sees: The complete parameter definitions for filesystem__read_file, filesystem__list_directory, etc. It picks the right one, fills in the arguments, and calls it.

smartmcp proxies the call to the filesystem server and returns the result.

Configuration reference

Field Type Default Description
mcpServers object (required) Map of server names to MCP server configs
mcpServers.<name>.command string (required) Command to spawn the server
mcpServers.<name>.args string[] [] Arguments for the command
mcpServers.<name>.env object {} Environment variables for the server
top_k integer 5 Default number of tools returned per search
embedding_model string "all-MiniLM-L6-v2" Sentence-transformers model for embeddings

Why smartmcp?

  • Less context waste: Instead of 100 tool schemas in every request, the AI sees 1 tool plus only the few it actually needs.
  • Better tool selection: Semantic search finds the right tools even when the AI doesn't know the exact name.
  • Full schema exposure: Surfaced tools include their complete parameter definitions, so the AI constructs calls correctly.
  • Works with any MCP server: If it speaks MCP over stdio, smartmcp can proxy it.
  • Drop-in replacement: Replace your list of MCP servers with one smartmcp entry. No code changes needed.
  • Graceful degradation: If some upstream servers fail to connect, smartmcp continues with whatever is available.

Contributing

smartmcp is early-stage and actively improving. Contributions are welcome, especially around search accuracy, embedding strategies, and support for new transports.

If you have ideas, find bugs, or want to add features, open an issue or submit a PR on GitHub.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smartmcp_router-0.2.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smartmcp_router-0.2.0-py3-none-any.whl (11.9 kB view details)

Uploaded Python 3

File details

Details for the file smartmcp_router-0.2.0.tar.gz.

File metadata

  • Download URL: smartmcp_router-0.2.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for smartmcp_router-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d8923f918366593d29a1bb4a1431e2c74564e4c28ec796272f5614c12f52ab61
MD5 2a47e307b6515c5e5968d6751a7533c7
BLAKE2b-256 36017941732ddd4826196cea96f92bb22907e913f2957aeadb193d4730842fd4

See more details on using hashes here.

File details

Details for the file smartmcp_router-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for smartmcp_router-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6de3302fd02a3553012aa54aee212d4981e85bf9de7b0205e5b01bdb924d871d
MD5 a626d2e3dfeeb017df8ddb2b51e7b018
BLAKE2b-256 81de9787a233ea389c546f5bf7d4785b49b5f20bdaea58c348a467b9d10f19e6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page