
在介绍完生成MCP server的三种使用方法后,发现介绍的都是STDIO协议的版本,要向使用SSE版本的MCP可以行吗?当然,使用过程中核心逻辑不变,只是入口改为NEWSSEServer即可,具体源码如下
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测试下是否成功
nvm use v18.14.0
npx @modelcontextprotocol/inspector启动后界面如下:

在tools/list下面我们可以看到我们定义的mcp工具
example_ExampleService_GetPersoncall tool后返回如下
{
person:
{
name:
"hello"
id:
123
email:
"example@example.com"
}
}当然也可以使用stdio协议,不过要配置对应的二机制文件路径。在使用的最后,我们分析下生成的.pb.mcp.go文件的源码
// 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
RegisterExampleServiceHandler
ForwardToConnectExampleServiceClient
ForwardToExampleServiceClient三者实现的流程都是使用的AddTool添加MCP tool,然后将MCP的jsonrpc协议序列化为json,然后再反序列化为pb
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的客户端转发请求。
本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!