MCP语义路由工具

OmniMCP是一个语义路由工具,用于在多MCP服务器环境中发现和执行工具,避免上下文膨胀问题。

  • by milkymap
  • Python
  • 本地部署
  • 30 星标
  • 更新于
在 GitHub 查看 milkymap/omnimcp

使用说明

OmniMCP

MCP生态系统的语义路由器

跨多个MCP服务器发现和执行工具,而不会造成上下文膨胀



问题

MCP工具定义消耗令牌很快。典型设置:

服务器 工具 令牌
GitHub 35 ~26K
松弛 11 ~21K
文件系统 8 ~5K
数据库 12 ~8K

那是 60K+代币 在谈话开始之前。添加更多服务器,您将与实际环境竞争。

为什么这很重要

上下文膨胀会降低性能。 当工具定义消耗50-100K令牌时,您用于实际对话、文档和推理的空间有限。该模型将注意力放在工具模式上,而不是你的任务上。

更多的工具=更多的幻觉。 使用50多种类似工具(如 notification-send-user 对比 notification-send-channel),模型选择了错误的工具并产生了幻觉参数。工具选择精度随着工具集的增长而下降。

动态工具加载会中断缓存。 在推理过程中按需加载工具似乎很聪明,但它会使提示缓存无效。在对话中添加的每一个新工具都意味着重新处理整个上下文。你的“优化”变成了一种绩效税。

工具结果也会使上下文膨胀。 一次文件读取可以返回50K个令牌。图像采用1K+令牌base64编码。这些在对话历史中堆积起来,推翻了早期的背景。

解决方案

OmniMCP公开了 单 semantic_router 工具 作为您整个MCP生态系统的唯一入口点。LLM从不看到单独的工具定义,只看到一个统一的接口。

Traditional: 58 tools → 55K tokens in tool definitions
OmniMCP:      1 tool   → ~500 tokens (semantic_router)

它是如何工作的:

  1. 语义搜索 → 按意图而非名称查找相关工具。工具通过嵌入预先索引,在运行时搜索,作为文本结果返回(不是工具定义)
  2. 延迟服务器加载 → 服务器仅在需要时启动,完成后关闭
  3. 渐进式架构加载 → 仅在执行前获取完整的JSON模式,在对话中以文本形式返回
  4. 内容卸载 → 将大结果分块,描述图像,存储以供检索

关键见解: 工具模式出现在对话文本中,而不是工具定义中。这意味着:

  • 快速缓存保持不变(工具定义永远不会改变)
  • 只有相关模式才能进入上下文(通过搜索结果)
  • 没有类似工具名称的幻觉(型号看到3-5个工具,而不是50个以上)

从约60K代币到约3K。获取一切,几乎无需任何成本。

架构:元工具模式

OmniMCP使用 元工具模式,类似于克劳德·科德的代理技能系统。它没有公开数十个单独的工具,而是公开了一个 semantic_router 元工具,充当整个MCP生态系统的门户。

渐进式披露工作流程

架构和请求流

运作原理

传统MCP方法:

tools: [
  {name: "github_create_issue", description: "..."},
  {name: "github_create_pr", description: "..."},
  {name: "filesystem_read", description: "..."},
  // ... 50+ more tools
]

❌ 问题:上下文膨胀、工具幻觉、没有缓存

OmniMCP的元工具方法:

{
  "tools": [
    {
      "name": "semantic_router",
      "description": "Universal gateway to MCP ecosystem...\n
        OPERATIONS: search_tools, get_server_info, execute_tool...\n
        LIST OF INDEXED SERVERS:\n
        filesystem: 8 tools (file operations, read/write)\n
        github: 35 tools (issues, PRs, repos)\n
        ...",
      "input_schema": {
        "operation": "search_tools | execute_tool | ..."
      }
    }
  ]
}

✅ 优点:单一工具定义、描述中的服务器列表、动态发现

与克劳德技能平行

Claude Skills和OmniMCP有着相同的架构见解:

方面 克劳德技能 OmniMCP
元工具 Skill 工具 semantic_router 工具
发现 工具描述中的技能描述 服务器列表+工具描述中提示
调用 Skill(command="skill-name") semantic_router(operation="execute_tool", server_name=...)
上下文注入 调用时加载技能说明 按需获取工具模式,以文本形式返回
缓存友好 工具定义永远不会改变 工具定义永远不变
动态列表 <available_skills> 部分 LIST OF INDEXED SERVERS 部分
行为暗示 技能描述指南LLM 服务器 hints 现场指南LLM

关键见解: 两个系统都通过以下方式注入指令 迅速扩张 而不是传统的函数调用。工具描述成为LLM读取和推理的动态目录,而实际执行细节则延迟加载。

行为指导示例:

克劳德技能:

<available_skills>
  skill-creator: "When user wants to create a new skill..."
  internal-comms: "When user wants to write internal communications..."
</available_skills>

OmniMCP hints:

{
  "elevenlabs": {
    "hints": [
      "When the user requests audio generation (speech or music), always execute in background mode",
      "Proactively offer to play audio using the ElevenLabs tool when contextually relevant"
    ]
  }
}

两者都注射 行为指示 这决定了LLM如何使用这些工具,而不仅仅是它们做什么。

真实世界示例

多服务器编排正在进行中:

Claude Code使用OmniMCP(以前是脉冲星mcp)来协调多个mcp服务器,从而生成了一个视频。

过程:

  1. Exa(背景模式) -并行网络搜索以收集最新消息
  2. 模态沙盒 -根据新闻数据计算和生成视频
  3. 文件系统 -从Modal的输出中检索到视频文件
  4. FFmpeg -将视频转换为GIF格式

工作流程:

search_tools("web search news")
  → execute_tool(exa, search, in_background=True) × 3 parallel calls
  → poll_task_result() → aggregate results
  → execute_tool(modal-sandbox, generate_video, data)
  → execute_tool(filesystem, read_file, video_path)
  → execute_tool(modal-sandbox, ffmpeg_convert, video_to_gif)

这表明:

  • 语义发现 -在不知道确切名称的情况下跨服务器查找正确的工具
  • 后台执行 -并行考试搜索而不阻止对话
  • 跨服务器协调 模态→ 文件系统→ 具有自动状态管理的模态管道
  • 接口 -所有操作通过一个 semantic_router 工具

没有OmniMCP:50多个工具定义、复杂的编排、上下文溢出。 使用OmniMCP:探索→ 执行→ 协调。无缝。

安装

uv pip install omnimcp // or uv add omnimcp 

配置

环境变量

OmniMCP需要几个环境变量才能运行。您必须在运行之前配置这些 index 或 serve 命令。

所需变量:

变量 描述 示例
OPENAI_API_KEY 用于嵌入和描述的OpenAI API密钥 sk-proj-...
TOOL_OFFLOADED_DATA_PATH 存储卸载内容(大结果、图像)的路径 /path/to/tool_offloaded_data

Qdrant连接(选择一种模式):

模式 变量 描述
本地文件 QDRANT_DATA_PATH=/path/to/data 嵌入式Qdrant,持久到磁盘
在存储器中 QDRANT_DATA_PATH=:memory: 嵌入式Qdrant,无持久性(测试)
远程服务器 QDRANT_URL=http://localhost:6333 Docker或自托管Qdrant
Qdrant云 QDRANT_URL=https://xxx.qdrant.io
QDRANT_API_KEY=your-api-key
管理Qdrant云

可选变量(默认值):

变量 默认值 描述
EMBEDDING_MODEL_NAME text-embedding-3-small OpenAI嵌入模型
DESCRIPTOR_MODEL_NAME gpt-4.1-mini 生成工具描述的模型
VISION_MODEL_NAME gpt-4.1-mini 图像描述模型
MAX_RESULT_TOKENS 5000 大结果的块阈值
DESCRIBE_IMAGES true 用视觉来描述图像
DIMENSIONS 1024 嵌入尺寸

设置方法:

选项1:本地文件存储(最简单)

export OPENAI_API_KEY="sk-proj-..."
export QDRANT_DATA_PATH="/path/to/qdrant_data"
export TOOL_OFFLOADED_DATA_PATH="/path/to/tool_offloaded_data"

选项2:Docker Qdrant服务器

# Start Qdrant in Docker
docker run -p 6333:6333 -p 6334:6334 qdrant/qdrant

# Configure OmniMCP
export OPENAI_API_KEY="sk-proj-..."
export QDRANT_URL="http://localhost:6333"
export TOOL_OFFLOADED_DATA_PATH="/path/to/tool_offloaded_data"

选项3:Qdrant Cloud

export OPENAI_API_KEY="sk-proj-..."
export QDRANT_URL="https://your-cluster.qdrant.io"
export QDRANT_API_KEY="your-qdrant-api-key"
export TOOL_OFFLOADED_DATA_PATH="/path/to/tool_offloaded_data"

选项4:创建 .env 文件

# .env
OPENAI_API_KEY=sk-proj-...
QDRANT_DATA_PATH=/path/to/qdrant_data
# OR for remote: QDRANT_URL=http://localhost:6333
TOOL_OFFLOADED_DATA_PATH=/path/to/tool_offloaded_data

然后使用 --env-file 运行命令时标记:

uvx --env-file .env omnimcp index --config-path mcp-servers.json

注: 寻找环境变量(例如。, source .env)不能可靠地工作 uvx。始终使用 --env-file 或者直接导出变量。

注: 对于stdio传输,环境变量也必须包含在MCP客户端配置中(请参阅 stdio运输段 在......下面

快速开始

1.创建MCP服务器配置 (mcp-servers.json):

这是Claude Desktop MCP配置的增强模式,带有额外的OmniMCP特定字段。OmniMCP支持 两种运输方式 用于连接到MCP服务器:

服务器传输类型

stdio运输(本地子流程)

使用 command + args 生成本地MCP服务器作为子进程。这是Claude Desktop、Cursor等使用的标准MCP方法。

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/directory"],
      "env": {},
      "timeout": 30.0
    }
  }
}

HTTP传输(远程服务器)

使用 url 通过Streamable HTTP连接到远程MCP服务器。这消除了对 mcp-remote 或 mcp-proxy 桥接器——只需直接提供URL。

{
  "mcpServers": {
    "remote-api": {
      "url": "https://mcp.example.com/api",
      "headers": {"Authorization": "Bearer your-token"},
      "timeout": 60.0
    }
  }
}

何时使用HTTP传输:

  • 远程MCP服务器(云API、共享服务)
  • 服务器已作为HTTP端点运行
  • 避免为每台服务器生成子流程
  • 无需直接连接 mcp-remote 高架桥

混合配置示例

您可以在一个配置中混合使用这两种传输类型:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/directory"],
      "env": {},
      "timeout": 30.0,
      "hints": ["file operations", "read write files"],
      "blocked_tools": [],
      "ignore": false,
      "overwrite": false
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {"GITHUB_TOKEN": "..."},
      "blocked_tools": ["delete_repository", "fork_repository"]
    },
    "elevenlabs": {
      "command": "uvx",
      "args": ["elevenlabs-mcp"],
      "env": {"ELEVENLABS_API_KEY": "..."},
      "hints": [
        "When the user requests audio generation (speech or music), always execute in background mode",
        "Proactively offer to play audio using the ElevenLabs tool when contextually relevant"
      ]
    },
    "exa-direct": {
      "url": "https://mcp.exa.ai/mcp",
      "headers": {"Authorization": "Bearer your-exa-api-key"},
      "timeout": 60.0,
      "hints": [
        "Always execute web searches in background mode to avoid blocking the conversation",
        "Multiple Exa tool calls can be fired in parallel to efficiently gather information from different sources"
      ]
    },
    "company-internal-api": {
      "url": "http://internal-mcp.company.com:8080/mcp",
      "headers": {"X-API-Key": "internal-key"},
      "timeout": 120.0,
      "hints": ["Internal company data access", "Use for employee and project queries"]
    }
  }
}

配置字段参考

特定于运输的字段(选择一个):

字段 类型 描述
command 字符串 stdio传输: 可执行文件(npx、uvx、docker、python等)
args 阵列 stdio传输: 传递给可执行文件的命令行参数
env 对象 stdio传输: 此MCP服务器的环境变量
url 字符串 HTTP传输: 远程MCP服务器端点的URL
headers 对象 HTTP传输: HTTP头(例如授权、API密钥)

共享字段(适用于两种传输方式):

字段 类型 描述
timeout number 等待服务器启动/连接的秒数(默认值:30.0)
hints 阵列 强大! 指导LLM如何使用此服务器。用于发现和执行指令。示例:“始终在后台模式下执行”,“可以并行发起多个调用”,“在上下文相关时主动提供”
blocked_tools array 将被索引但被阻止执行的工具名称
ignore boolean 如果为true,则完全跳过对此服务器的索引(默认值:false)
overwrite boolean 如果为true,即使已经索引,也强制重新索引(默认值:false)

注: 您必须指定 command (stdio)或 url (HTTP),但不是两者都有。根据存在的字段自动检测传输类型。

2.设置环境变量:

export OPENAI_API_KEY="sk-..."
export QDRANT_DATA_PATH="/path/to/qdrant_data"
export TOOL_OFFLOADED_DATA_PATH="/path/to/tool_offloaded_data"

3.为服务器建立索引 (食用前推荐):

uvx --env-file .env omnimcp index --config-path mcp-servers.json

4.运行服务器:

# Default: HTTP transport (recommended)
uvx --env-file .env omnimcp serve --config-path mcp-servers.json --transport http --host 0.0.0.0 --port 8000

# stdio transport (for local MCP clients - requires pre-indexing)
uvx --env-file .env omnimcp serve --config-path mcp-servers.json --transport stdio

或者,直接使用CLI选项:

# With local Qdrant storage
uvx omnimcp serve \
  --config-path mcp-servers.json \
  --openai-api-key "sk-..." \
  --qdrant-data-path /path/to/qdrant_data \
  --tool-offloaded-data-path /path/to/tool_offloaded_data

# With remote Qdrant (Docker or Cloud)
uvx omnimcp serve \
  --config-path mcp-servers.json \
  --openai-api-key "sk-..." \
  --qdrant-url "http://localhost:6333" \
  --qdrant-api-key "optional-api-key" \
  --tool-offloaded-data-path /path/to/tool_offloaded_data

运输方式

OmniMCP支持两种传输协议,每种协议都针对不同的部署场景进行了优化:

HTTP传输(默认-推荐)

最适合大多数用例:远程访问、web集成或与 mcp-remote 或 mcp-proxy.

uvx omnimcp serve --config-path mcp-servers.json --transport http --host 0.0.0.0 --port 8000

使用案例:

  • 远程访问 -在服务器上为OmniMCP提供服务,随时随地连接
  • 多个客户端 -跨多个代理共享一个OmniMCP实例
  • Web集成 -REST API访问MCP生态系统
  • mcp远程/mcp代理 -通过MCP代理层公开OmniMCP

示例 mcp遥控器:

npm install mcp-remote
{
  "mcpServers": {
    "omnimcp-remote": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://your-server:port/mcp"]
    }
  }
}

HTTP模式优势:

  • 索引在服务器启动时发生一次
  • 多个客户端共享相同的索引数据

stdio运输

最适合通过标准输入/输出(Claude Desktop、Cline等)进行通信的本地MCP客户端。

⚠️ 重要提示:你必须跑步 uvx omnimcp index 在使用stdio模式之前,避免启动时间缓慢。

uvx omnimcp serve --config-path mcp-servers.json --transport stdio

推荐工作流程:

  1. 索引优先 -快跑 omnimcp index 在添加到MCP客户端配置之前
  2. 然后安装 -将OmniMCP添加到客户的MCP配置中
  3. 开始服务 -客户端通过stdio自动启动OmniMCP

客户端配置示例 (claude_desktop_config.json):

{
  "mcpServers": {
    "omnimcp": {
      "command": "uvx",
      "args": ["omnimcp", "serve"],
      "env": {
        "CONFIG_PATH": "/path/mcp/config/file",
        "TRANSPORT": "stdio|http",
        "OPENAI_API_KEY": "sk-...",
        "QDRANT_DATA_PATH": "/path/to/qdrant_data",
        "TOOL_OFFLOADED_DATA_PATH": "/path/to/tool_offloaded_data"
        // add other env keys
      }
    }
  }
}

为什么要在挂载前进行索引? 对许多服务器进行索引可能需要时间。预索引确保您的MCP客户端启动OmniMCP时立即启动。

故障排除 uvx 问题

错误: spawn uvx ENOENT 或 command not found: uvx

这意味着 uv 未安装或不在您的PATH中。 详细的故障排除指南 • MCP官方文件.

快速修复:

  1. 安装uv (如果未安装):

    # macOS/Linux
    brew install uv
    
    # or official installer
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
  2. 确保紫外线在路径中 (macOS/Linux):

    # Check if installed
    which uvx
    
    # If not found, add to PATH (add to ~/.zshrc or ~/.bashrc)
    export PATH="$HOME/.local/bin:$PATH"
    
    # Or create symlink
    sudo ln -s ~/.local/bin/uvx /usr/local/bin/uvx
    
  3. 使用绝对路径 在配置中(使用查找 which uvx):

    "command": "/Users/you/.local/bin/uvx"  // macOS
    "command": "C:\\Users\\you\\.local\\bin\\uvx.exe"  // Windows
    

替代方案:使用mcp-remote进行HTTP模式

如果 uvx 问题仍然存在,请通过HTTP运行OmniMCP并通过 mcp-remote:

# Terminal 1: Run OmniMCP HTTP server
uvx omnimcp serve --config-path mcp-servers.json --transport http --port 8000
// Claude Desktop config
{
  "mcpServers": {
    "omnimcp": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost:8000/mcp"]
    }
  }
}

这绕过了stdio问题,并在跨平台上可靠地工作。

运作原理

OmniMCP公开了一个 semantic_router 作为通往整个MCP生态系统的门户的工具:

search_tools("read CSV files and analyze data")
    → Returns: filesystem.read_file, database.query (ranked by relevance)

get_tool_details("filesystem", "read_file")
    → Returns: Full JSON schema with parameters

manage_server("filesystem", "start")
    → Launches the server process

execute_tool("filesystem", "read_file", {"path": "/data/sales.csv"})
    → Returns: File content (chunked if large)

运营

操作 说明
search_tools 跨所有索引工具的语义搜索
get_server_info 查看服务器功能和限制
list_server_tools 浏览特定服务器上的工具
get_tool_details 执行前获取完整架构
manage_server 启动或关闭服务器实例
list_running_servers 显示活动服务器
execute_tool 使用可选后台模式运行工具
poll_task_result 检查后台任务状态
get_content 通过引用检索卸载的内容

内容管理

自动处理大型工具结果:

  • 文本 >5000个代币→ 分块,预览返回参考ID
  • 图像 → 卸载,用GPT-4视觉描述,返回参考
  • 音频 → 卸载,返回引用

使用检索完整内容 get_content(ref_id, chunk_index).

后台执行

对于长时间运行的工具:

# Queue for background execution
execute_tool("server", "slow_tool", args, in_background=True, priority=1)
# Returns: task_id

# Check status
poll_task_result(task_id)
# Returns: status, result when done

码头工人

OmniMCP可以在Docker容器中运行,并完全支持两者 npx (Node.js MCP服务器)和 uvx (Python MCP服务器)。

从Docker Hub拉取

docker pull milkymap/omnimcp:latest

本地构建(可选)

docker build -t omnimcp:latest -f Dockerfile .

跑

使用本地Qdrant存储:

docker run --rm -it \
  -v /path/to/qdrant_data:/data/qdrant \
  -v /path/to/tool_offloaded_data:/data/tool_offloaded_data \
  -v /path/to/mcp-servers.json:/app/config/mcp-servers.json:ro \
  --env-file .env.docker \
  -p 8000:8000 \
  milkymap/omnimcp:latest serve

使用远程Qdrant(云或Docker):

docker run --rm -it \
  -v /path/to/tool_offloaded_data:/data/tool_offloaded_data \
  -v /path/to/mcp-servers.json:/app/config/mcp-servers.json:ro \
  --env-file .env.docker \
  -p 8000:8000 \
  milkymap/omnimcp:latest serve

环境文件 (.env.docker)-选择一个Qdrant模式:

OPENAI_API_KEY=sk-proj-...
CONFIG_PATH=/app/config/mcp-servers.json
TOOL_OFFLOADED_DATA_PATH=/data/tool_offloaded_data
TRANSPORT=http
HOST=0.0.0.0
PORT=8000

# Option 1: Local Qdrant storage
QDRANT_DATA_PATH=/data/qdrant

# Option 2: Remote Qdrant (comment out QDRANT_DATA_PATH above)
# QDRANT_URL=https://your-cluster.qdrant.io
# QDRANT_API_KEY=your-api-key

可用命令:

# Show help
docker run --rm milkymap/omnimcp:latest --help

# Index servers
docker run --rm \
  -v /path/to/mcp-servers.json:/app/config/mcp-servers.json:ro \
  --env-file .env.docker \
  milkymap/omnimcp:latest index

# Serve (HTTP mode)
docker run --rm -d \
  -v /path/to/mcp-servers.json:/app/config/mcp-servers.json:ro \
  --env-file .env.docker \
  -p 8000:8000 \
  --name omnimcp \
  milkymap/omnimcp:latest serve

发展

git clone https://github.com/milkymap/omnimcp.git
cd omnimcp
uv sync
uv run pytest

相关研究

OmniMCP建立在LLM代理可扩展工具选择的新兴研究之上:

ScaleMCP:动态和自动同步模型上下文协议工具

Lumer等人(2025年) 介绍 ScaleMCP,大规模解决MCP工具选择中的类似挑战。他们的方法强调:

  • 动态刀具检索 -赋予代理在多回合交互中发现和添加工具的自主权
  • 自动同步存储 -通过CRUD操作使用MCP服务器作为唯一的事实来源
  • 工具文档加权平均值(TDWA) -有选择地强调关键工具文档组件的新型嵌入策略

他们在5000个财务指标服务器上的评估表明,工具检索和代理调用性能有了显著提高,验证了语义搜索在MCP生态系统中的重要性。

关键洞察:OmniMCP和ScaleMCP都认识到传统的单片工具库无法扩展。未来需要动态的、语义优先的工具发现方法。

Anthropic的高级工具使用

Anthropic的工具搜索功能 (2025)引入了三种与OmniMCP架构相一致的功能:

  • 工具搜索工具 -在不占用上下文窗口的情况下发现数千种工具
  • 程序化工具调用 -在代码执行环境中调用工具以减少上下文影响
  • 工具使用示例 -学习JSON模式定义之外的正确使用模式

引自Anthropic: “在代理读取请求之前,工具结果和定义有时会消耗50000多个令牌。代理应按需发现和加载工具,只保留与当前任务相关的内容。”

这反映了OmniMCP的核心理念:预先暴露最小的接口(单个 semantic_router 工具),从语义上发现工具,逐步加载模式。

趋同进化

这些独立的努力都遵循类似的原则:

  1. 语义发现 过于详尽的列举
  2. 又称渐进负重 超过前期工具定义
  3. 代理人自主权 查询和重新查询工具库
  4. 上下文效率 作为一流的设计约束

OmniMCP通过语义路由、延迟服务器加载和内容卸载来实现这些原则,使大规模MCP生态系统在今天变得实用。

许可证

MIT许可证-请参阅 许可证 了解详情。


经过几个月的研究和开发

多个架构迭代•真实世界的代理部署•在不同的MCP生态系统中进行广泛的测试

OmniMCP源于解决传统方法失败的生产代理系统中的实际问题。从语义路由到后台执行再到内容卸载,每个功能都经过了战斗测试,以应对将MCP生态系统扩展到玩具示例之外的挑战。

我们希望OmniMCP在构建更强大、更高效的代理系统方面对社区有用。