it编程 > 前端脚本 > Golang

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

3人参与 2025-04-24 Golang

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

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

为什么mcp如此重要?

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

mcp总体架构

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

使用mcp-go构建mcp服务端与客户端

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

go get github.com/mark3labs/mcp-go

构建mcp服务端

接下来,我们将演示如何使用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
})

同样地,我们也可以注册一些静态资源,比如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
})
if err := server.servestdio(s); err != nil {
    fmt.printf("server error: %v\n", err)
}

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

构建mcp客户端

接着,我们将展示如何使用mcp-go提供的client模块构建一个连接至上述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 %s\n", 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: %v\n", 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 %s\n", 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服务内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

golang实现读取excel数据并导入数据库

04-24

Go语言实现优雅关机和重启的示例详解

04-24

Go实现一个轻量级并发任务调度器(支持限速)

04-24

Go语言实现Viper配置管理笔记

04-24

Go 跨域中间件解决CORS问题

04-24

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

04-24

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论