首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >proto直接生成MCP-server:protoc-gen-go-mcp(3)

proto直接生成MCP-server:protoc-gen-go-mcp(3)

作者头像
golangLeetcode
发布2026-03-18 17:44:46
发布2026-03-18 17:44:46
1900
举报

在介绍完生成MCP server的三种使用方法后,发现介绍的都是STDIO协议的版本,要向使用SSE版本的MCP可以行吗?当然,使用过程中核心逻辑不变,只是入口改为NEWSSEServer即可,具体源码如下

代码语言:javascript
复制
package main
import (
    example "learn/langchain/protoc_gen_mcp/exp1/server"
    "github.com/mark3labs/mcp-go/server"
)
func main() {
    s := server.NewMCPServer(
        "My Server", // Server 名称
        "1.0.0",     // 版本号
    )
    example.RegisterExampleService(s, &example.Server{})
    // 创建基于 SSE 的服务器实例
    sseServer := server.NewSSEServer(s)
    // 启动服务器,监听指定端口(如 :8080)
    err := sseServer.Start(":8083")
    if err != nil {
        panic(err)
    }
}

定义完成后我们可以使用工具mcpinspector测试下是否成功

代码语言:javascript
复制
nvm use v18.14.0
npx @modelcontextprotocol/inspector

启动后界面如下:

在tools/list下面我们可以看到我们定义的mcp工具

代码语言:javascript
复制
example_ExampleService_GetPerson

call tool后返回如下

代码语言:javascript
复制
{
person:
  {
    name:
    "hello"
    id:
    123
    email:
    "example@example.com"
  }
}

当然也可以使用stdio协议,不过要配置对应的二机制文件路径。在使用的最后,我们分析下生成的.pb.mcp.go文件的源码

代码语言:javascript
复制
// Code generated by protoc-gen-mcp-go. DO NOT EDIT.
// source: example_service.proto
package example_service_v1mcp
import (
    example_service_v1 "learn/langchain/protoc_gen_mcp/exp1/example.service.v1"
)
import (
    "context"
    "github.com/mark3labs/mcp-go/mcp"
    mcpserver "github.com/mark3labs/mcp-go/server"
    "encoding/json"
    "google.golang.org/protobuf/encoding/protojson"
    "connectrpc.com/connect"
    grpc "google.golang.org/grpc"
)
var (
    ExampleService_GetPersonTool = mcp.Tool{Name: "example_ExampleService_GetPerson", Description: "", InputSchema: mcp.ToolInputSchema{Type: "", Properties: map[string]interface{}(nil), Required: []string(nil)}, RawInputSchema: json.RawMessage{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x7d}}
)
// ExampleServiceServer is compatible with the grpc-go server interface.
type ExampleServiceServer interface {
    GetPerson(ctx context.Context, req *example_service_v1.PersonRequest) (*example_service_v1.PersonResponse, error)
}
func RegisterExampleServiceHandler(s *mcpserver.MCPServer, srv ExampleServiceServer) {
    s.AddTool(ExampleService_GetPersonTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        marshaled, err := json.Marshal(request.Params.Arguments)
        if err != nil {
            return nil, err
        }
        var req example_service_v1.PersonRequest
        if err := (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(marshaled, &req); err != nil {
            return nil, err
        }
        resp, err := srv.GetPerson(ctx, &req)
        if err != nil {
            return nil, err
        }
        marshaled, err = (protojson.MarshalOptions{UseProtoNames: true, EmitDefaultValues: true}).Marshal(resp)
        if err != nil {
            return nil, err
        }
        return mcp.NewToolResultText(string(marshaled)), nil
    })
}
// ExampleServiceClient is compatible with the grpc-go client interface.
type ExampleServiceClient interface {
    GetPerson(ctx context.Context, req *example_service_v1.PersonRequest, opts ...grpc.CallOption) (*example_service_v1.PersonResponse, error)
}
// ConnectExampleServiceClient is compatible with the connectrpc-go client interface.
type ConnectExampleServiceClient interface {
    GetPerson(ctx context.Context, req *connect.Request[example_service_v1.PersonRequest]) (*connect.Response[example_service_v1.PersonResponse], error)
}
// ForwardToConnectExampleServiceClient registers a connectrpc client, to forward MCP calls to it.
func ForwardToConnectExampleServiceClient(s *mcpserver.MCPServer, client ConnectExampleServiceClient) {
    s.AddTool(ExampleService_GetPersonTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        marshaled, err := json.Marshal(request.Params.Arguments)
        if err != nil {
            return nil, err
        }
        var req example_service_v1.PersonRequest
        if err := (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(marshaled, &req); err != nil {
            return nil, err
        }
        resp, err := client.GetPerson(ctx, connect.NewRequest(&req))
        if err != nil {
            return nil, err
        }
        marshaled, err = (protojson.MarshalOptions{UseProtoNames: true, EmitDefaultValues: true}).Marshal(resp.Msg)
        if err != nil {
            return nil, err
        }
        return mcp.NewToolResultText(string(marshaled)), nil
    })
}
// ForwardToExampleServiceClient registers a gRPC client, to forward MCP calls to it.
func ForwardToExampleServiceClient(s *mcpserver.MCPServer, client ExampleServiceClient) {
    s.AddTool(ExampleService_GetPersonTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        marshaled, err := json.Marshal(request.Params.Arguments)
        if err != nil {
            return nil, err
        }
        var req example_service_v1.PersonRequest
        if err := (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(marshaled, &req); err != nil {
            return nil, err
        }
        resp, err := client.GetPerson(ctx, &req)
        if err != nil {
            return nil, err
        }
        marshaled, err = (protojson.MarshalOptions{UseProtoNames: true, EmitDefaultValues: true}).Marshal(resp)
        if err != nil {
            return nil, err
        }
        return mcp.NewToolResultText(string(marshaled)), nil
    })
}

可以看到,它核心有三个方法,分别对应的是本地实现MCP server,代理到connectrpc Server 和代理到grpc server

代码语言:javascript
复制
RegisterExampleServiceHandler
ForwardToConnectExampleServiceClient
ForwardToExampleServiceClient

三者实现的流程都是使用的AddTool添加MCP tool,然后将MCP的jsonrpc协议序列化为json,然后再反序列化为pb

代码语言:javascript
复制
 s.AddTool(ExampleService_GetPersonTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        marshaled, err := json.Marshal(request.Params.Arguments)
        if err != nil {
            return nil, err
        }
        var req example_service_v1.PersonRequest
        if err := (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(marshaled, &req); err != nil {
            return nil, err
        }

最后分别调用本地的server实现的方法或者使用connecrrpc的客户端转发请求,或者grpc的客户端转发请求。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档