一文弄懂用Go实现MCP服务的示例代码

Written by

in

文章目录
  • 在过去,如果想要让AI处理特定的数据,通常只能依赖于预训练数据或者手动上传数据,这既麻烦又低效。即便对于强大的AI模型而言,也存在数据隔离的问题,无法直接访问新的数据源,每次更新数据都需要重新训练或上传。现在,MCP解决了这个问题,它使得AI不再局限于静态知识库,而是能够像人类一样调用搜索引擎、访问本地文件、连接API服务等,极大提升了AI的动态交互能力。
  • MCP的核心是“客户端-服务器”架构,其中MCP客户端可以连接到多个服务器。客户端是指希望通过MCP访问数据的应用程序,如CLI工具、IDE插件或AI应用。
  • 要开始使用Go语言构建MCP项目,首先需要安装mcp-go库,这是Go语言实现的Model Context Protocol库,支持LLM应用与外部数据源和工具之间的无缝集成。 go get github.com/mark3labs/mcp-go
  • 接下来,我们将演示如何使用mcp-go提供的server模块来构建一个通过stdio方式连接的MCP服务器。 创建Server对象 s := server.NewMCPServer(“My Server”, “1.0.0”) 添加工具(Tools) 例如,我们可以创建一个简单的计算器工具,这次我们实现乘法和除法功能: calculatorTool := mcp.NewTool(“calculate”, mcp.WithDescription(“执行基本的算术运算”), mcp.WithString(“operation”, mcp.Required(), mcp.Description(“要执行的算术运算类型”), mcp.Enum(“multiply”, “divide”), // 修改为仅支持乘法和除法 ), mcp.WithNumber(“x”, mcp.Required(), mcp.Description(“第一个数字”), ), mcp.WithNumber(“y”, mcp.Required(), mcp.Description(“第二个数字”), ), ) s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { op := request.Params.Arguments[“operation”].(string) x := request.Params.Arguments[“x”].(float64) y := request.Params.Arguments[“y”].(float64) var result float64 switch op { case “multiply”: result = x * y case “divide”: if y == 0 { return nil, errors.New(“不允许除以零”) } result = x / y } return mcp.FormatNumberResult(result), nil }) 添加资源(Resources) 同样地,我们也可以注册一些静态资源,比如README.md文件的内容: resource := mcp.NewResource( “docs://readme”, “项目说明文档”, mcp.WithResourceDescription(“项目的 README 文件”), mcp.WithMIMEType(“text/markdown”), ) s.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) { content, err := os.ReadFile(“README.md”) if err != nil { return nil, err } return []mcp.ResourceContents{ mcp.TextResourceContents{ URI: “docs://readme”, MIMEType: “text/markdown”, Text: string(content), }, }, nil }) 启动基于stdio传输类型的服务器 if err := server.ServeStdio(s); err != nil { fmt.Printf(“Server error: %vn”, err) } 以上步骤完成后,我们就成功搭建了一个基础的MCP服务器。
  • 接着,我们将展示如何使用mcp-go提供的client模块构建一个连接至上述MCP服务器的客户端。 创建MCP客户端 mcpClient, err := client.NewStdioMCPClient(“./client/server”, []string{}) if err != nil { panic(err) } defer mcpClient.Close() 初始化客户端连接 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() initRequest := mcp.InitializeRequest{} initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION initRequest.Params.ClientInfo = mcp.Implementation{ Name: “Client Demo”, Version: “1.0.0”, } initResult, err := mcpClient.Initialize(ctx, initRequest) if err != nil { panic(err) } fmt.Printf(“初始化成功,服务器信息: %s %sn”, initResult.ServerInfo.Name, initResult.ServerInfo.Version) 调用远程工具 最后,我们可以通过构造CallToolRequest来调用服务器上的工具,如下所示: toolRequest := mcp.CallToolRequest{ Request: mcp.Request{ Method: “tools/call”, }, } toolRequest.Params.Name = “calculate” toolRequest.Params.Arguments = map[string]any{ “operation”: “multiply”, // 调用乘法 “x”: 2, “y”: 3, } result, err := mcpClient.CallTool(ctx, toolRequest) if err != nil { panic(err) } fmt.Println(“调用工具结果:”, result.Content[0].(mcp.TextContent).Text)
  • 以下是完整的代码示例,包括服务端和客户端的实现: 服务端代码: package main import ( “context” “errors” “fmt” “os” “github.com/mark3labs/mcp-go/mcp” “github.com/mark3labs/mcp-go/server” ) func main() { s := server.NewMCPServer(“Server Demo”, “1.0.0”) // 添加工具 calculatorTool := mcp.NewTool(“calculate”, mcp.WithDescription(“执行基本的算术运算”), mcp.WithString(“operation”, mcp.Required(), mcp.Description(“要执行的算术运算类型”), mcp.Enum(“multiply”, “divide”), ), mcp.WithNumber(“x”, mcp.Required(), mcp.Description(“第一个数字”), ), mcp.WithNumber(“y”, mcp.Required(), mcp.Description(“第二个数字”), ), ) s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { op := request.Params.Arguments[“operation”].(string) x := request.Params.Arguments[“x”].(float64) y := request.Params.Arguments[“y”].(float64) var result float64 switch op { case “multiply”: result = x * y case “divide”: if y == 0 { return nil, errors.New(“不允许除以零”) } result = x / y } return mcp.FormatNumberResult(result), nil }) // 启动基于 stdio 的服务器 if err := server.ServeStdio(s); err != nil { fmt.Printf(“Server error: %vn”, err) } } 客户端代码: package main import ( “context” “fmt” “time” “github.com/mark3labs/mcp-go/client” “github.com/mark3labs/mcp-go/mcp” ) func main() { mcpClient, err := client.NewStdioMCPClient(“./client/server”, []string{}) if err != nil { panic(err) } defer mcpClient.Close() ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() initRequest := mcp.InitializeRequest{} initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION initRequest.Params.ClientInfo = mcp.Implementation{ Name: “Client Demo”, Version: “1.0.0”, } initResult, err := mcpClient.Initialize(ctx, initRequest) if err != nil { panic(err) } fmt.Printf(“初始化成功,服务器信息: %s %sn”, initResult.ServerInfo.Name, initResult.ServerInfo.Version) // 调用工具 toolRequest := mcp.CallToolRequest{ Request: mcp.Request{ Method: “tools/call”, }, } toolRequest.Params.Name = “calculate” toolRequest.Params.Arguments = map[string]any{ “operation”: “multiply”, “x”: 2, “y”: 3, } result, err := mcpClient.CallTool(ctx, toolRequest) if err != nil { panic(err) } fmt.Println(“调用工具结果:”, result.Content[0].(mcp.TextContent).Text) } 希望这篇文章能帮助你快速入门Go语言下的MCP开发! 到此这篇关于一文弄懂用Go实现MCP服务的示例代码的文章就介绍到这了,更多相关Go MCP服务内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: 一文带你学会使用Go语言实现自己的MCP服务端
  • 目录
    • 为什么MCP如此重要?
    • MCP总体架构
    • 使用mcp-go构建MCP服务端与客户端
    • 构建MCP服务端
    • 构建MCP客户端
    • 完整代码示例

    最近这段时间,AI领域里有一个非常热门的概念——MCP(模型上下文协议)。Anthropic推出的这一开放标准旨在为大型语言模型和AI助手提供统一的接口,使其能够轻松操作外部工具并完成更复杂的任务。

    本文将带你速览MCP的核心概念,并以Go语言为例,介绍如何开发MCP服务端和客户端

    在过去,如果想要让AI处理特定的数据,通常只能依赖于预训练数据或者手动上传数据,这既麻烦又低效。即便对于强大的AI模型而言,也存在数据隔离的问题,无法直接访问新的数据源,每次更新数据都需要重新训练或上传。现在,MCP解决了这个问题,它使得AI不再局限于静态知识库,而是能够像人类一样调用搜索引擎、访问本地文件、连接API服务等,极大提升了AI的动态交互能力

    MCP的核心是“客户端-服务器”架构,其中MCP客户端可以连接到多个服务器。客户端是指希望通过MCP访问数据的应用程序,如CLI工具、IDE插件或AI应用。

    要开始使用Go语言构建MCP项目,首先需要安装mcp-go库,这是Go语言实现的Model Context Protocol库,支持LLM应用与外部数据源和工具之间的无缝集成。

    go get github.com/mark3labs/mcp-go
    

    接下来,我们将演示如何使用mcp-go提供的server模块来构建一个通过stdio方式连接的MCP服务器。

    创建Server对象

    s := server.NewMCPServer("My Server", "1.0.0")
    

    添加工具(Tools)

    例如,我们可以创建一个简单的计算器工具,这次我们实现乘法和除法功能:

    calculatorTool := mcp.NewTool("calculate",
        mcp.WithDescription("执行基本的算术运算"),
        mcp.WithString("operation",
            mcp.Required(),
            mcp.Description("要执行的算术运算类型"),
            mcp.Enum("multiply", "divide"), // 修改为仅支持乘法和除法
        ),
        mcp.WithNumber("x",
            mcp.Required(),
            mcp.Description("第一个数字"),
        ),
        mcp.WithNumber("y",
            mcp.Required(),
            mcp.Description("第二个数字"),
        ),
    )
    
    s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        op := request.Params.Arguments["operation"].(string)
        x := request.Params.Arguments["x"].(float64)
        y := request.Params.Arguments["y"].(float64)
    
        var result float64
        switch op {
        case "multiply":
            result = x * y
        case "divide":
            if y == 0 {
                return nil, errors.New("不允许除以零")
            }
            result = x / y
        }
    
        return mcp.FormatNumberResult(result), nil
    })
    
    • 添加资源(Resources)

    同样地,我们也可以注册一些静态资源,比如README.md文件的内容:

    resource := mcp.NewResource(
        "docs://readme",
        "项目说明文档",
        mcp.WithResourceDescription("项目的 README 文件"),
        mcp.WithMIMEType("text/markdown"),
    )
    
    s.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
        content, err := os.ReadFile("README.md")
        if err != nil {
            return nil, err
        }
    
        return []mcp.ResourceContents{
            mcp.TextResourceContents{
                URI:      "docs://readme",
                MIMEType: "text/markdown",
                Text:     string(content),
            },
        }, nil
    })
    
    • 启动基于stdio传输类型的服务器
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("Server error: %vn", err)
    }
    

    以上步骤完成后,我们就成功搭建了一个基础的MCP服务器。

    接着,我们将展示如何使用mcp-go提供的client模块构建一个连接至上述MCP服务器的客户端。

    • 创建MCP客户端
    mcpClient, err := client.NewStdioMCPClient("./client/server", []string{})
    if err != nil {
        panic(err)
    }
    defer mcpClient.Close()
    
    • 初始化客户端连接
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    
    initRequest := mcp.InitializeRequest{}
    initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
    initRequest.Params.ClientInfo = mcp.Implementation{
        Name:    "Client Demo",
        Version: "1.0.0",
    }
    
    initResult, err := mcpClient.Initialize(ctx, initRequest)
    if err != nil {
        panic(err)
    }
    fmt.Printf("初始化成功,服务器信息: %s %sn", initResult.ServerInfo.Name, initResult.ServerInfo.Version)
    
    • 调用远程工具

    最后,我们可以通过构造CallToolRequest来调用服务器上的工具,如下所示:

    toolRequest := mcp.CallToolRequest{
        Request: mcp.Request{
            Method: "tools/call",
        },
    }
    toolRequest.Params.Name = "calculate"
    toolRequest.Params.Arguments = map[string]any{
        "operation": "multiply", // 调用乘法
        "x":         2,
        "y":         3,
    }
    
    result, err := mcpClient.CallTool(ctx, toolRequest)
    if err != nil {
        panic(err)
    }
    fmt.Println("调用工具结果:", result.Content[0].(mcp.TextContent).Text)
    

    以下是完整的代码示例,包括服务端和客户端的实现:

    服务端代码:

    package main
    
    import (
        "context"
        "errors"
        "fmt"
        "os"
    
        "github.com/mark3labs/mcp-go/mcp"
        "github.com/mark3labs/mcp-go/server"
    )
    
    func main() {
        s := server.NewMCPServer("Server Demo", "1.0.0")
    
        // 添加工具
        calculatorTool := mcp.NewTool("calculate",
            mcp.WithDescription("执行基本的算术运算"),
            mcp.WithString("operation",
                mcp.Required(),
                mcp.Description("要执行的算术运算类型"),
                mcp.Enum("multiply", "divide"),
            ),
            mcp.WithNumber("x",
                mcp.Required(),
                mcp.Description("第一个数字"),
            ),
            mcp.WithNumber("y",
                mcp.Required(),
                mcp.Description("第二个数字"),
            ),
        )
    
        s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
            op := request.Params.Arguments["operation"].(string)
            x := request.Params.Arguments["x"].(float64)
            y := request.Params.Arguments["y"].(float64)
    
            var result float64
            switch op {
            case "multiply":
                result = x * y
            case "divide":
                if y == 0 {
                    return nil, errors.New("不允许除以零")
                }
                result = x / y
            }
    
            return mcp.FormatNumberResult(result), nil
        })
    
        // 启动基于 stdio 的服务器
        if err := server.ServeStdio(s); err != nil {
            fmt.Printf("Server error: %vn", err)
        }
    }
    

    客户端代码:

    package main
    
    import (
        "context"
        "fmt"
        "time"
    
        "github.com/mark3labs/mcp-go/client"
        "github.com/mark3labs/mcp-go/mcp"
    )
    
    func main() {
        mcpClient, err := client.NewStdioMCPClient("./client/server", []string{})
        if err != nil {
            panic(err)
        }
        defer mcpClient.Close()
    
        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        defer cancel()
    
        initRequest := mcp.InitializeRequest{}
        initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
        initRequest.Params.ClientInfo = mcp.Implementation{
            Name:    "Client Demo",
            Version: "1.0.0",
        }
    
        initResult, err := mcpClient.Initialize(ctx, initRequest)
        if err != nil {
            panic(err)
        }
        fmt.Printf("初始化成功,服务器信息: %s %sn", initResult.ServerInfo.Name, initResult.ServerInfo.Version)
    
        // 调用工具
        toolRequest := mcp.CallToolRequest{
            Request: mcp.Request{
                Method: "tools/call",
            },
        }
        toolRequest.Params.Name = "calculate"
        toolRequest.Params.Arguments = map[string]any{
            "operation": "multiply",
            "x":         2,
            "y":         3,
        }
    
        result, err := mcpClient.CallTool(ctx, toolRequest)
        if err != nil {
            panic(err)
        }
        fmt.Println("调用工具结果:", result.Content[0].(mcp.TextContent).Text)
    }
    

    希望这篇文章能帮助你快速入门Go语言下的MCP开发!

    到此这篇关于一文弄懂用Go实现MCP服务的示例代码的文章就介绍到这了,更多相关Go MCP服务内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • 一文带你学会使用Go语言实现自己的MCP服务端

    站内搜索