MCP服务器+RPC工具Monrepo
一个完整的端到端演示系统,展示 Cloudflare Workers+Hono+MCP(模型上下文协议) 作为使用PNPM工作区的单仓库。
现场演示
在此处尝试实时Streamlit客户端: https://mcp-server-rpc-tools-gzlapy2fedh6ff2wohnnhl.streamlit.app/
在此处尝试实时CopilotKit客户端: https://mcp-server-rpc-tools-mcp-client-cop.vercel.app/
建筑
- mcp网关工作器:MCP服务器入口点,通过安全RPC将工具调用路由到域工作者
- 域工具工人:RPC端点公开域A工具(你好,列出顶级客户)
- 域b-to-ols-worker:RPC端点公开域B工具(求和、规范化文本)
- mcp客户端流式传输:用于测试MCP网关的Python UI
- mcp客户端拷贝套件:Next.js CopilotKit用户界面,用于通过聊天测试MCP工具
快速开始
先决条件
- Node.js 18+
- PNPM 8+
- 牧马人CLI:
npm install -g wrangler - Python 3.9+(用于Streamlit应用程序)
设置顺序
1.安装依赖项
pnpm install2.首先部署域工作者
配置和部署domain-a-tools-worker:
cd apps/domain-a-tools-worker
wrangler secret put DOMAIN_SHARED_SECRET
# Enter a shared secret (e.g., "dev-secret-123")部署:
pnpm deploy:domain-a然后是域b到ols-worker:
cd ../domain-b-tools-worker
wrangler secret put DOMAIN_SHARED_SECRET
# Use same secret
pnpm deploy:domain-b3.获取已部署的URL
成功部署后,请注意以下URL:
- 域A:
https://domain-a-.workers.dev - 域B:
https://domain-b-.workers.dev
4.配置和部署网关
更新 apps/mcp-gateway-worker/wrangler.toml:
[env.production]
vars = { DOMAIN_A_URL = "https://domain-a-.workers.dev", DOMAIN_B_URL = "https://domain-b-.workers.dev", ALLOWED_ORIGINS = "localhost:3000,localhost:8501" }部署网关:
cd apps/mcp-gateway-worker
wrangler secret put DOMAIN_SHARED_SECRET
# Use same secret
pnpm deploy:gateway网关URL: https://mcp-gateway-.workers.dev
5.运行Streamlit客户端
cd apps/mcp-client-streamlit
pip install -r requirements.txt
streamlit run app.py打开浏览器 http://localhost:8501,将MCP URL设置为网关URL+ /mcp.
本地开发
所有三个Workers都可以在本地开发模式下同时运行:
# Terminal 1
pnpm dev:domain-a
# Terminal 2
pnpm dev:domain-b
# Terminal 3
pnpm dev:gateway
# Terminal 4 (after Workers are running)
cd apps/mcp-client-streamlit
streamlit run app.py默认本地URL:
- 域A:http://localhost:8001
- 域B:http://localhost:8002
- 网关:http://localhost:8000
- 流光灯:http://localhost:8501
项目结构
repo-root/
├── apps/
│ ├── mcp-gateway-worker/ # MCP server endpoint
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ ├── registry.ts
│ │ │ └── types.ts
│ │ ├── package.json
│ │ ├── wrangler.toml
│ │ └── tsconfig.json
│ ├── domain-a-tools-worker/ # Domain A RPC tools
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── package.json
│ │ ├── wrangler.toml
│ │ └── tsconfig.json
│ ├── domain-b-tools-worker/ # Domain B RPC tools
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── package.json
│ │ ├── wrangler.toml
│ │ └── tsconfig.json
│ └── mcp-client-streamlit/ # Python Streamlit client
│ ├── app.py
│ └── requirements.txt
├── pnpm-workspace.yaml
├── package.json
└── README.md测试检查表
部署后,验证系统:
- \[ \] 工具/列表:返回所有4个工具(域A 2个,域B 2个)
- \[ \] 你好:接受
{ name: string },返回问候消息 - \[ \] 列出顶级客户:接受
{ limit: number },返回模拟客户数据 - \[ \] 总和:接受
{ a: number, b: number },返回总和结果 - \[ \] 规范化文本:接受
{ text, mode: "lower"|"upper"|"title" },返回规范化文本 - \[ \] 范围验证:请求缺失
customers:read列表顶级客户的标题失败 - \[ \] 原产地验证:来自未列出来源的请求被阻止
- \[ \] 令牌验证:没有正确网关令牌的RPC调用返回403
可用脚本
# Development
pnpm dev:gateway # Start gateway in local dev mode
pnpm dev:domain-a # Start domain A in local dev mode
pnpm dev:domain-b # Start domain B in local dev mode
pnpm dev:all # Start all Workers in parallel
# Production Deployment
pnpm deploy:gateway # Deploy gateway to Cloudflare
pnpm deploy:domain-a # Deploy domain A to Cloudflare
pnpm deploy:domain-b # Deploy domain B to Cloudflare
pnpm deploy:all # Deploy all (domains first, then gateway)
# Build
pnpm build # Build all projects安全说明
- 共享的秘密:
DOMAIN_SHARED_SECRET是网关和域工作者之间的简单共享令牌(不是生产级;在生产中使用mTLS) - 原产地允许清单:通过配置
ALLOWED_ORIGINS在网关争吵中。toml - 范围执行:传入
x-scopes根据工具要求验证收割台 - 秘密管理:永远不要泄露秘密;使用
wrangler secret储存它们
MCP规范
网关在以下位置公开了一个标准MCP 1.0服务器 /mcp 使用流式HTTP传输。
两种主要的RPC方法:
- 工具/列表:发现可用工具
- 工具/调用:执行具有输入验证和范围检查的工具
有关详细的集成示例,请参阅各个应用程序的自述文件。
故障排除
“DOMAIN_A_URL未配置”
- 使用已部署的域URL更新mcp网关worker中的wrangler.toml
- 重新部署网关:
pnpm deploy:gateway
401未经授权的域内工作者
- 验证
DOMAIN_SHARED_SECRET所有工人的设置都是相同的 - 检查
x-gateway-token标头包含在网关中→ 域RPC调用
Streamlit的CORS错误
- 确保网关URL位于
ALLOWED_ORIGINS在争吵中 - 在使用Streamlit之前,先用curl进行测试
范围拒绝错误
- 通过
x-scopes: customers:read,data:readStreamlit UI中的标题 - 检查注册表中的工具定义以了解所需的作用域
许可证
麻省理工学院
