mcp-router

mcp-router

Enables efficient tool routing and context budgeting for AI agents handling hundreds of MCP tools, with circuit breaker, RBAC, and federation for reliable serving.

Category
访问服务器

README

mcp-router

수백 개 MCP tool을 다루는 AX 에이전트 백엔드에서 tool routing·context budgeting·서빙 신뢰성을 end-to-end로 다룬 프로젝트. 오프라인 벤치(M3)로 라우팅 전략을 계측하고, 같은 라우팅 코어를 실제 게이트웨이(M1)로 서빙한다. 순수 stdlib로 결정적으로 돌아가며(오프라인 기본), 실제 임베딩·Claude· MCP SDK는 opt-in 어댑터다.

한 줄 요약. 강한 주장을 세우고 실측으로 스스로 반증했다. ① 약한 렉시컬 유사도(mock)에선 semantic top-k가 tool을 놓치는 recall cliff가 가팔랐다(recall@1 0.70→0.13). ② 실제 임베딩 (bge-small)에선 훨씬 완만했다(0.89→0.70), hybrid 이점도 marginal. ③ 실제 MCP 서버 22곳의 tool 247개를 재보니 근접 중복은 실재하나(70%가 코사인 0.80+ 이웃) 합성이 실제보다 과하게 붐볐다 (중앙값 0.94 vs 0.84). 결론: 문제는 진짜지만 초기 헤드라인은 과장 — 어느 상황에서 라우팅이 실제로 중요한지를 재는 도구다.


실무에서 마주친 깊은 문제와 해결

문제 (production) 핵심 고민 해결
Tool sprawl / context budgeting — tool이 수백 개면 스키마가 컨텍스트를 잠식하고 top-k가 정답 tool을 누락 토큰을 아끼면서 recall을 지키는 지점은? 4개 라우팅 전략을 recall@k로 계측, hybrid(벡터+렉시컬)로 recall 회복. "전량 노출 대비 3-of-N 토큰"의 트레이드오프를 수치화
벤치 외적 타당성 — 합성 데이터가 문제를 과장하지 않았나 mock 결론이 실제로도 성립하나 실제 임베딩(bge-small)·실제 tool 코퍼스(22서버/247)로 자기 검증 → 초기 주장 하향 보정
가짜 엄밀성 — 약한 신호 위 통계 남발 지표가 라우팅 품질을 실제로 구분하나 fractional recall@k, gold-cluster bootstrap(클러스터 의존성), McNemar+Benjamini-Hochberg, phi로 task_success↔recall 탈-폐회로 입증
서빙 신뢰성 — 업스트림 장애 전파·권한·중복 한 서버 장애가 전체를 멈추지 않게 per-upstream circuit breaker(closed/open/half-open, 스레드 안전·단일 프로브), RBAC(테넌트 allow/deny·deny 우선·fnmatchcase로 결정적), federation(server.tool 네임스페이싱)
async↔sync 통합 — 비동기 MCP SDK를 동기 게이트웨이에 세션을 안전하게 오래 유지 업스트림별 전용 event-loop 스레드 브리지 + send_ping 헬스체크·지수 백오프 자동 재연결
미인증 캐시 증식(DoS) — X-Tenant 원문 키잉 공격자 제어 입력이 메모리를 무한 점유 캐시 키를 유효 정책 아이덴티티로 축약 + 상한
결정성/재현성 같은 seed면 같은 결과인가 순수 stdlib·주입 clock·seed 봉투 → 벤치 수치 바이트 단위 재현
과설계 회피 안 쓸 인프라를 넣지 않기 pgvector/OTel/latency 파이프라인 절단, 실제 어댑터는 .[extra] opt-in

각 항목은 적대적 리뷰(총 7회)로 검증했다 — 라우팅 폐회로, breaker 썬더링 허드, readonly RBAC 우회, 캐시 DoS, MCP 세션 누수 등 실제 결함을 매번 잡아 고쳤다.


시스템 아키텍처

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Pretendard, Segoe UI, sans-serif","primaryColor":"#F0EEE6","primaryTextColor":"#29261B","primaryBorderColor":"#C6714F","lineColor":"#B5654A","clusterBkg":"#FAF9F5","clusterBorder":"#DED7C9"}}}%%
flowchart TB
    CLIENT["MCP 클라이언트 / 에이전트"]

    subgraph M1["M1 · 서빙 게이트웨이 (gateway/)"]
        TR["Transport<br/>MCP stdio(SDK) · HTTP JSON-RPC"]
        RB["RBAC<br/>테넌트 allow/deny · deny 우선"]
        CB["Circuit Breaker<br/>closed · open · half-open"]
        FD["Federation<br/>server.tool 네임스페이싱"]
        UP["MCP 업스트림<br/>stdio/HTTP · 헬스체크 · 자동 재연결"]
    end

    subgraph CORE["공유 라우팅 코어 (routing/ · providers/)"]
        EM["Embedder → Vector Index<br/>bge-small · mock · exact cosine"]
        RT["Router<br/>passthrough · semantic_topk<br/>hierarchical · hybrid"]
    end

    subgraph M3["M3 · 오프라인 평가 (bench/)"]
        CAT["카탈로그<br/>합성 staircase + 실제 tool 247"]
        MET["Metrics<br/>recall@k · cluster bootstrap<br/>McNemar+BH · phi"]
        RPT["Report<br/>md · csv · svg · traces"]
    end

    CLIENT --> TR --> RB --> RT
    RT --> CB --> FD --> UP
    EM --> RT
    CAT --> RT --> MET --> RPT

    classDef m1 fill:#C6714F,stroke:#A8543A,color:#FCF9F3;
    classDef core fill:#D9A883,stroke:#BE7C57,color:#2B2013;
    classDef m3 fill:#EADFCB,stroke:#CBB897,color:#29261B;
    class TR,RB,CB,FD,UP m1;
    class EM,RT core;
    class CAT,MET,RPT m3;

게이트웨이 요청 흐름 (tools/call)

%%{init: {"theme":"base","themeVariables":{"fontFamily":"Pretendard, Segoe UI, sans-serif","primaryColor":"#F0EEE6","primaryTextColor":"#29261B","primaryBorderColor":"#C6714F","lineColor":"#B5654A"}}}%%
flowchart LR
    Q(["tools/call<br/>tenant · name · args"]) --> P{"RBAC 허용?"}
    P -->|deny| D["거부<br/>-32001"]
    P -->|allow| B{"breaker 상태"}
    B -->|open| F["fast-fail<br/>-32002"]
    B -->|closed / half-open| C["업스트림 호출"]
    C -->|성공| OK(["결과"])
    C -->|실패| T["실패 집계 → 임계 초과 시 open"]
    H["헬스 프로브<br/>send_ping"] -.->|사망 감지| RC["백오프 재연결"]

    classDef n fill:#F6F3EA,stroke:#DED7C9,color:#29261B;
    classDef hot fill:#C6714F,stroke:#A8543A,color:#FCF9F3;
    class P,B,C,OK,T,H,RC n;
    class D,F hot;

핵심 결과: mock(BoW) vs 실제(bge-small)

카탈로그 300 · semantic_topk의 fractional recall@1 낙폭, 그리고 전략별 recall@k:

mock r@1 (100→300) bge r@1 (100→300) 300에서 recall@3 (mock / bge)
semantic_topk 0.70 → 0.13 0.89 → 0.70 0.62 / 0.90
hybrid — — 0.92 / 0.93
passthrough 1.00 (tokens ~31k) 1.00 1.00 / 1.00
  • 방향은 둘 다 성립(카탈로그↑ → recall↓, hybrid는 큰 k에서 도움). 크기는 실제 임베딩에서 훨씬 작다.
  • 전량 노출은 토큰 ~100배(≈31k vs ≈316@k=3). 괜찮은 임베딩 + k≥3이면 그 recall을 거의 따라잡는다.

recall cliff

증거는 docs/에 커밋(mock/bge 차트, 리포트/CSV, 실제 tool 유사도 분석). make bench / make bench-real / make similarity로 재현.


실행

make bench          # 오프라인·순수 stdlib·같은 seed면 바이트 단위 재현
make test           # 41 unittest (cliff·에이전트·게이트웨이·재연결·실제 MCP 왕복)
make gateway-demo   # 게이트웨이 walk-through: federation → RBAC → routing → breaker 트립/복구
make bench-real     # bge-small 실제 임베딩 (pip install .[local])
make similarity     # 실제 MCP tool 코퍼스 pairwise 유사도

# 실제 MCP 연결 (pip install .[mcp])
python -m mcp_router gateway serve --transport mcp-stdio         # 게이트웨이를 MCP 서버로 서빙
python -m mcp_router gateway serve --config deploy/gateway.mcp.config.json   # 실제 stdio/HTTP 업스트림

무엇이 실제고 무엇이 mock인가

  • 실행 검증: bge-small 임베딩, 실제 MCP SDK 양방향 stdio 왕복(업스트림 연결 + 게이트웨이 서빙), 실제 tool 코퍼스 유사도.
  • mock(기본): hashed BoW/char-trigram 임베딩, Jaccard 선택 에이전트, in-process 업스트림.
  • 미실행(로드맵): Claude tool-use 에이전트(cassette), 실제 토크나이저 토큰 계측.
  • task_success는 약한 보조 지표(정답 개수 미고지) — phi≈0.29로 recall과 독립임을 명시. 라벨 리포트는 사람 검증이 아닌 self-consistency(κ≈0.40).

구조

src/mcp_router/
  catalog/     합성 staircase(키워드 충돌 distractor) + 쿼리 생성 + Spec
  routing/     4 전략 + RoutingContext            providers/  임베딩(mock/mock_char/bge) + llm(mock/claude)
  vectorstore/ exact cosine index                labeling/   self-consistency 라벨러 + kappa
  bench/       선택 에이전트 · metrics · runner · report
  gateway/     federation · rbac · breaker · server · transport(HTTP)
               mcp_upstream(SDK client·재연결) · mcp_server(SDK stdio) · factory
tests/         41 unittest (.[mcp] 없으면 실제-MCP만 skip)

로드맵

streamable-HTTP 멀티테넌트 서버, cassette 커밋한 Claude 에이전트 실행, 실제 토크나이저 토큰 계측, 더 넓은 tool 표본.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选