grpc-mcp网关
gRPC ↔ MCP Bridge — Generate MCP servers directly from protobufs
enabling seamless AI-native interfaces for existing services
概述
grpc-mcp网关 是一个 protoc 插件和运行时自动 将您的gRPC服务转换为MCP兼容的服务器。
gRPC → MCP代理生成器遵循 MCP规范.
您可以公开现有的API,而不是为AI系统重写API gRPC基础设施如下:
- 工具 → 代理的可调用函数
- 提示 → 结构化交互模板
- 资源 → 可检索上下文/数据
- 引出 → 动态输入流
用a建造 规范优先法,它确保完全符合 模型上下文协议,同时保持系统的强类型性和可扩展性。
开源由 Machani机器人,该项目将传统后端系统与AI原生平台连接起来。
A. protoc 插件和运行时,将任何gRPC服务转换为完全符合规范的服务 模型上下文协议 服务器——工具、提示、资源和启发——在Go、Python、Rust和C++中。
特性
- 多语言 --从单个文件生成Go、Python、Rust和C++的MCP服务器代码
.proto文件 - 工具 --每个一元RPC都成为一个MCP工具,其JSON模式源自protobuf请求消息
- 提示 --通过以下方式将提示模板附加到具有模式验证参数的RPC
(mcp.protobuf.prompt) - 字段描述 --添加
(mcp.protobuf.field) = { description: "..." }到用于模式描述的消息字段 - 枚举说明 --添加
(mcp.protobuf.enum)和(mcp.protobuf.enum_value)用于架构中的枚举级别和每个值的描述 - 进展 --使用gRPC服务器流
mcp.protobuf.MCPProgress用于长时间运行的工具上的MCP进度通知 - 资源 --自动检测来自的MCP资源
google.api.resource注释 - 引出 --在工具执行之前,通过以下方式生成确认对话框
(mcp.protobuf.elicitation) - 运输 --stdio、SSE和流式http——在单个进程中并发运行多个
- gRPC网关 --将MCP工具调用转发到远程gRPC服务器(Go)
- 已发布的原型 --从导入注释
buf.build/machanirobotics/grpc-mcp-gateway,或从安装预编译类型 PyPI / 克拉特斯.io
| 语言 | 生成的文件 | 示例 |
|---|---|---|
| 去 | *_service.pb.mcp.go | examples/go |
| python | *_service_pb2_mcp.py | examples/python |
| 锈 | *_service.mcp.rs | examples/rust |
| C | *_service.mcp.h/cc +铁锈桥 | examples/cpp |
建筑
graph LR
Proto[".proto + MCP annotations"] -->|buf generate| GenGo["Go MCP stubs"]
Proto -->|buf generate| GenPy["Python MCP stubs"]
Proto -->|buf generate| GenRs["Rust MCP stubs"]
Proto -->|buf generate| GenCpp["C++ MCP bridge"]
GenGo --> GoSrv["Go Server"]
GenPy --> PySrv["Python Server"]
GenRs --> RsSrv["Rust Server"]
GenCpp --> CppSrv["C++ Server"]
GoSrv -->|stdio / SSE / streamable-http| Client["MCP Client / LLM"]
PySrv -->|stdio / SSE / streamable-http| Client
RsSrv -->|stdio / SSE / streamable-http| Client
CppSrv -->|stdio / streamable-http| Client运作原理
sequenceDiagram
participant LLM as LLM / MCP Client
participant MCP as MCP Server (generated)
participant gRPC as gRPC Service (your impl)
LLM->>MCP: tools/list
MCP-->>LLM: [{name, description, inputSchema}, ...]
LLM->>MCP: tools/call (tool_name, args)
Note over MCP: elicitation (if configured)
MCP->>gRPC: RPC method(request)
gRPC-->>MCP: response
MCP-->>LLM: tool result (JSON)- 注释 你的
.proto具有MCP选项(工具、提示、资源、启发)的服务。 - 生成 MCP服务器代码
buf generate使用protoc-gen-mcp. - 实施 您的gRPC服务逻辑与往常一样。
- 服务 --生成的代码在您选择的传输上启动MCP服务器。
- 连接 --MCP客户端(Claude Desktop、MCP Inspector、自定义LLM代理)发现并调用您的工具。
安装
插件
go install github.com/machanirobotics/grpc-mcp-gateway/plugin/cmd/protoc-gen-mcp@latest或者从以下网址下载二进制文件 .
预编译原型
MCP注释类型(mcp.protobuf.*)作为预编译库发布,因此生成的代码可以在运行时解析其导入,就像 googleapis-common-protos 用于Google API类型。
| 语言 | 软件包 | 安装 |
|---|---|---|
| 去 | mcp/protobuf/mcppb | go get github.com/machanirobotics/grpc-mcp-gateway/mcp/protobuf/mcppb |
| python | grpc-mcp-gateway-protos | pip install grpc-mcp-gateway-protos==1.5.3 |
| 锈 | mcp-protobuf | cargo add mcp-protobuf@1.5.3 |
python (PyPI)--添加到您的项目并导入以注册原型扩展:
# Required for MCP-annotated protos
import mcp.protobuf.annotations_pb2 # noqa: F401[dependencies]
mcp-protobuf = "1.5.62" # or cargo add mcp-protobuf for latest快速开始
1.添加原型依赖
# buf.yaml
version: v2
deps:
- buf.build/googleapis/googleapis
- buf.build/machanirobotics/grpc-mcp-gatewaybuf dep update2.为原型添加注释
syntax = "proto3";
package todo.v1;
import "mcp/protobuf/annotations.proto";
service TodoService {
option (mcp.protobuf.service) = {
app: {
name: "Todo App"
version: "1.0.0"
description: "A simple todo management application"
}
};
rpc CreateTodo(CreateTodoRequest) returns (Todo) {
option (mcp.protobuf.tool) = {
description: "Creates a new todo item."
};
option (mcp.protobuf.elicitation) = {
message: "Please confirm the todo details before creating."
schema: "todo.v1.CreateTodoConfirmation"
};
}
rpc GetTodo(GetTodoRequest) returns (Todo) {
option (mcp.protobuf.tool) = {
description: "Retrieves a todo by resource name."
};
option (mcp.protobuf.prompt) = {
name: "summarize_todos"
description: "Summarize all pending todo items for a user"
schema: "todo.v1.SummarizeTodosArgs"
};
}
}
// Enum with descriptions for MCP tool schema
enum Priority {
option (mcp.protobuf.enum) = { description: "Priority level for a todo item." };
PRIORITY_UNSPECIFIED = 0 [(mcp.protobuf.enum_value) = { description: "Unspecified; use default priority." }];
PRIORITY_LOW = 1 [(mcp.protobuf.enum_value) = { description: "Low priority; can be done when convenient." }];
PRIORITY_MEDIUM = 2 [(mcp.protobuf.enum_value) = { description: "Normal priority; default for most todos." }];
PRIORITY_HIGH = 3 [(mcp.protobuf.enum_value) = { description: "High priority; should be done soon." }];
PRIORITY_URGENT = 4 [(mcp.protobuf.enum_value) = { description: "Urgent; do first." }];
}3.生成代码
# buf.gen.yaml
version: v2
plugins:
# --- Go ---
- local: protoc-gen-go
out: generated/go
opt: [module=example/generated/go]
- local: protoc-gen-mcp
out: generated/go
opt: [lang=go, module=example/generated/go]
# --- Python ---
- remote: buf.build/protocolbuffers/python
out: generated/python
- local: protoc-gen-mcp
out: generated/python
opt: [lang=python, paths=source_relative]
# --- Rust ---
- remote: buf.build/community/neoeinstein-prost
out: generated/rust
- local: protoc-gen-mcp
out: generated/rust
opt: [lang=rust, paths=source_relative]
# --- C++ (Rust bridge + C++ gRPC client) ---
- local: protoc-gen-mcp
out: generated/cpp
opt: [lang=cpp, paths=source_relative]buf generate4.使用MCP检查器运行
# Go
cd examples/go/stdio && go run .
npx @modelcontextprotocol/inspector -- go run .
# Python
cd examples/python
npx @modelcontextprotocol/inspector -- uv run python stdio/main.py
# Rust
cd examples/rust && cargo build --bin stdio
npx @modelcontextprotocol/inspector -- ./target/debug/stdio
# C++
cd examples/cpp && make
MCP_TRANSPORT=stdio npx @modelcontextprotocol/inspector -- ./serverMCP注释
所有注释都是从导入的 mcp/protobuf/annotations.proto (BSR).
服务水平: mcp.protobuf.service
定义MCP服务器的应用元数据:
option (mcp.protobuf.service) = {
app: { name: "My App" version: "1.0.0" description: "..." }
};工具: mcp.protobuf.tool
覆盖自动生成的工具名称或描述:
rpc CreateItem(CreateItemRequest) returns (Item) {
option (mcp.protobuf.tool) = {
name: "custom_tool_name"
description: "Custom description for LLMs."
};
}提示: mcp.protobuf.prompt
将提示模板附加到RPC。这 schema 引用一个原型消息,其字段成为提示参数:
rpc GetItem(GetItemRequest) returns (Item) {
option (mcp.protobuf.prompt) = {
name: "summarize_items"
description: "Summarize all items"
schema: "mypackage.SummarizeItemsArgs"
};
}引语: mcp.protobuf.elicitation
在执行工具之前请求用户确认。这 schema 引用一个原型消息,其字段成为确认表单:
rpc DeleteItem(DeleteItemRequest) returns (google.protobuf.Empty) {
option (mcp.protobuf.elicitation) = {
message: "Are you sure you want to delete this item?"
schema: "mypackage.DeleteConfirmation"
};
}所有三种语言都支持启发式,并且可以优雅地降级——如果客户端不支持启发式,该工具将在没有确认的情况下继续运行。
字段: mcp.protobuf.field
将JSON模式元数据添加到MCP工具inputSchema的消息字段中:
message User {
string name = 1 [
(google.api.field_behavior) = IDENTIFIER,
(mcp.protobuf.field) = {
description: "The resource name of the user. You can parse the user id from the resource name."
examples: "users/alice"
examples: "users/bob"
format: "uri" // optional: override format (uri, email, uuid, etc.)
deprecated: false // optional: mark field as deprecated
}
];
}- 描述 --人类可读的描述(建议用于LLM)
- 例子 --指导LLM的示例值(重复)
- 已弃用 --在架构中将该字段标记为已弃用
- 格式 --JSON模式格式覆盖(例如。
uri,email,uuid)
枚举: mcp.protobuf.enum 和 mcp.protobuf.enum_value
为MCP工具inputSchema的枚举类型和单个枚举值添加描述:
enum Priority {
option (mcp.protobuf.enum) = { description: "Priority level for a todo item." };
PRIORITY_UNSPECIFIED = 0 [(mcp.protobuf.enum_value) = { description: "Unspecified; use default priority." }];
PRIORITY_LOW = 1 [(mcp.protobuf.enum_value) = { description: "Low priority; can be done when convenient." }];
PRIORITY_MEDIUM = 2 [(mcp.protobuf.enum_value) = { description: "Normal priority; default for most todos." }];
PRIORITY_HIGH = 3 [(mcp.protobuf.enum_value) = { description: "High priority; should be done soon." }];
PRIORITY_URGENT = 4 [(mcp.protobuf.enum_value) = { description: "Urgent; do first." }];
}该架构包括:
- 描述 --枚举级别和每个值的组合描述
- 枚举描述 --值名称映射→ 结构化访问描述
对于枚举字段,枚举描述优先于 (mcp.protobuf.field) 当两者都存在时的描述。
进度(服务器流)
对于长时间运行的操作,使用gRPC服务器流 mcp.protobuf.MCPProgress 向MCP客户端发送进度通知。使用以下之一定义流响应:
import "mcp/protobuf/progress.proto";
message CreateTodoStreamChunk {
oneof payload {
mcp.protobuf.MCPProgress progress = 1;
Todo result = 2;
}
}
rpc CreateTodo(CreateTodoRequest) returns (stream CreateTodoStreamChunk);插件自动生成发送MCP的工具处理程序 notifications/progress 对于每个进度块,返回最终结果。使用时支持进度 ForwardTo*MCPClient (gRPC转发)。客户通过以下方式请求进度 progressToken 在 params._meta.
进度和超时:发送进度的长时间运行的请求不得超时。网关使用 ReadTimeout: 0 和 WriteTimeout: 0 默认情况下,流媒体进程永远不会中断。如果你设置 WriteTimeout 在 MCPServerConfig,使用 0 或者对于支持进度的工具来说具有很高的价值。MCP客户端(如Inspector)可能有自己的超时;在可用时启用进度超时重置(MCP_REQUEST_TIMEOUT_RESET_ON_PROGRESS).如果你看到 “MCP错误-32001:超过最大总超时时间”,客户端对总请求时间有一个硬上限(检查器默认值:60秒)。增加它,例如。 MCP_REQUEST_MAX_TOTAL_TIMEOUT=300000 (5分钟,单位为毫秒)。
资源
从以下位置自动检测资源 google.api.resource 原始消息的注释。不需要额外的MCP注释。
项目结构
grpc-mcp-gateway/
├── go.mod # Single Go module
├── go.work # Workspace (root + examples)
├── proto/ # Publishable buf module (BSR)
│ └── mcp/protobuf/ # MCP annotation .proto source files
├── mcp/protobuf/ # Pre-compiled proto libraries
│ ├── mcppb/ # Go (.pb.go) — see [mcp/protobuf/README.md](mcp/protobuf/README.md)
│ ├── python/ # Python (PyPI: grpc-mcp-gateway-protos)
│ └── rust/ # Rust (crates.io: mcp-protobuf)
├── runtime/ # Go runtime — [README](runtime/README.md)
├── plugin/
│ ├── cmd/protoc-gen-mcp/ # Plugin binary (go install target)
│ └── generator/ # Code generation (Go, Python, Rust, C++)
│ └── templates/ # go.tpl, python.tpl, rust.tpl, cpp/*.tpl
├── examples/ # Separate module with replace directive
│ ├── proto/ # TodoService + CounterService definitions
│ ├── go/ # Go examples (http, stdio, sse, grpc-gateway, counter)
│ ├── python/ # Python examples (http, stdio, sse)
│ ├── rust/ # Rust examples (http, stdio, sse)
│ └── cpp/ # C++ example (Make, gRPC + MCP via Rust bridge)
└── .github/workflows/ # CI + release pipelines插件选项
| 选项 | 值 | 描述 |
|---|---|---|
lang | go, python, rust, cpp | 生成代码的目标语言 |
module | Go模块路径 | 输出路径解析的Go模块前缀 |
package_suffix | 任意字符串(仅限Go) | 生成的子包后缀 .pb.mcp.go 文件 |
paths | source_relative | 相对于原型源代码(Python、Rust)放置输出 |
生成的代码
对于每个原型服务,插件都会生成:
| 特性 | Go | Python | Rust | C++ |
|---|---|---|---|---|
| 工具 (按RPC) | s.AddTool(...) | @server.call_tool() | ServerHandler::call_tool() | TodoServiceMcpImpl (Cxx FFI) |
| 提示 | s.AddPrompt(...) | @server.get_prompt() | ServerHandler::get_prompt() | — |
| 资源 | s.AddResource(...) / s.AddResourceTemplate(...) | @server.list_resources() | ServerHandler::list_resources() | — |
| 引出 | runtime.RunElicitation(...) | session.elicit(...) | peer.create_elicitation(...) | — |
| 服务功能 | ServeTodoServiceMCP() | serve_todo_service_mcp() | serve_todo_service_mcp() | start_*_mcp_http / _stdio |
| gRPC转发 | ForwardToTodoServiceMCPClient() | forward_to_todo_service_mcp_client() | -- | 正在处理中(C++gRPC服务器) |
| 界面/特性 | TodoServiceMCPServer | TodoServiceMCPServer (协议) | TodoServiceMcpServer (性状) | TodoServiceMcpImpl (C++类) |
JSON模式推导
工具的 inputSchema 源自protobuf请求消息:
- 字段类型→ JSON模式类型
google.api.field_behavior必需→ JSON 模式requiredbuf.validate约束→minLength,maxLength,pattern,minimum,maximum等等。- 众所周知的类型(时间戳、持续时间、字段掩码、结构、任意、包装器)→ 适当的JSON模式
- 原蟾蜍
oneof→ JSON 模式oneOf/anyOf - 枚举→ JSON 模式
enum具有字符串值;(mcp.protobuf.enum)/(mcp.protobuf.enum_value)→description和enumDescriptions
运输配置
支持的传输
| 传输 | 值 | 协议 | 用例 |
|---|---|---|---|
| stdio | stdio | stdin/stdout管道 | 本地工具,IDE集成 |
| SSE(传统) | sse | HTTP+服务器发送事件 | 浏览器客户端、传统MCP客户端 |
| 流式HTTP | streamable-http | HTTP+双向JSON-RPC | 生产部署,现代SDK |
多个传输
使用逗号分隔的值同时运行多个传输:
MCP_TRANSPORT=stdio,streamable-http go run .
MCP_TRANSPORT=stdio,streamable-http uv run python http/main.py
MCP_TRANSPORT=stdio,streamable-http cargo run --bin http环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
MCP_TRANSPORT | 每个示例 | 逗号分隔: stdio, sse, streamable-http |
MCP_HOST | 0.0.0.0 | HTTP传输的绑定地址 |
MCP_PORT | 8082 | HTTP传输的侦听端口 |
GRPC_PORT | 50051 | gRPC服务器侦听端口 |
Go运行时配置
import "github.com/machanirobotics/grpc-mcp-gateway/runtime"
cfg := &runtime.MCPServerConfig{
Name: "my-service",
Version: "1.0.0",
Transports: []runtime.Transport{runtime.TransportStdio, runtime.TransportStreamableHTTP},
Addr: ":8082",
BasePath: "/todo/v1/todoservice/mcp",
}
todopbv1.ServeTodoServiceMCP(ctx, server, cfg)Python配置
from todo.v1.todo_service_pb2_mcp import serve_todo_service_mcp
serve_todo_service_mcp(impl, transport="streamable-http", host="0.0.0.0", port=8082)Rust配置
let config = TodoServiceMcpTransportConfig {
transport: "streamable-http".into(),
host: "0.0.0.0".into(),
port: 8082,
..Default::default()
};
serve_todo_service_mcp(server, config).await?;示例
这 examples/ 目录包含 TodoService (CRUD、提示、启发)和 柜台服务 (进度流)实现:
| 服务 | 原型 | 描述 |
|---|---|---|
| TodoService | proto/todo/v1/ | CRUD、提示、启发、资源 |
| 柜台服务 | proto/counter/v1/ | 带有MCP进度通知的服务器流式传输 |
| 语言 | 目录 | 传输 | 测试 |
|---|---|---|---|
| 去吧 | examples/go/ | http、stdio、sse、grpc网关、计数器 | go test ./examples/go/... |
python examples/python/ | http、stdio、sse | uv run python -m pytest smoke_test.py | |
| 生锈 | examples/rust/ | http、stdio、sse | cargo check |
C examples/cpp/ | 可流式传输http、stdio | make |
有关详细的设置和运行说明,请参阅每种语言的README。
MCP检验员测试
# stdio (Inspector spawns the process)
npx @modelcontextprotocol/inspector --
# HTTP (start server first, then open Inspector)
npx @modelcontextprotocol/inspector
# Enter URL, e.g. http://localhost:8082/todo/v1/todoservice/mcp or http://localhost:8083/counter/v1/counterservice/mcp对于有进度的长时间运行的工具,增加检查器的最大总超时时间(默认60秒):
MCP_REQUEST_MAX_TOTAL_TIMEOUT=300000 npx @modelcontextprotocol/inspector许可证
根据 Apache许可证,版本2.0.
