mcp-go Go搭建MCP服务的实现示例

 更新时间:2025年05月25日 10:37:12   作者:NPE~  
本文主要介绍了mcp-go Go搭建MCP服务的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

介绍

目前Go 生态圈有两个知名的开发 MCP 的库,一个是mark3labs/mcp-go,另一个是metoro-io/mcp-golang。

在介绍常用库之前,先来简单介绍一下mcp协议:

MCP全称Model Context Protocol 模型上下文协议,MCP 是一个开放协议,它为应用程序向 LLM 提供上下文的方式进行了标准化。你可以将 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供了标准化的方式一样,MCP 为 AI 模型连接各种数据源和工具提供了标准化的接口。

相比之前各大AI厂商各自为战,接口以及协议之间不通用,导致开发者针对同一个功能为了适配多个AI模型,需要开发多套。现在有了MCP,各大模型厂商和开发者只需遵循MCP协议,即可实现一次编写,多模型适用。

MCP与大模型调用之间原理图:

在这里插入图片描述

MCP架构主要包含一下几个模块:

  • MCP Hosts: 如 Claude Desktop、IDE 、DeepChat或 AI 工具,希望通过 MCP 访问数据的程序
  • MCP Clients: 维护与服务器一对一连接的协议客户端
  • MCP Servers: 轻量级程序,通过标准的 Model Context Protocol 提供特定能力
  • 本地数据源: MCP 服务器可安全访问的计算机文件、数据库和服务
  • 远程服务: MCP 服务器可连接的互联网上的外部系统(如通过 APIs)

安装

go get "github.com/mark3labs/mcp-go"

API介绍

1. server.NewMCPServer:新建一个mcp server

目前MCP 支持 SSE 和Stdio两种类型。

stdio:standard input output,标准输入输出,适用于mcp client和mcp server部署在同一个机器上,不涉及跨机器。

sse:Server-Sent Events,服务器发送事件,是一个基于HTTP的协议。适用于mcp client与mcp server不在同一个机器中的场景,涉及网络传输。

这里我们以新建一个基于Stdio协议的mcp server为例:

//新建mcp 服务
mcpServer := server.NewMCPServer("ziyi Mcp Server", "1.0.0")
//对外提供 stdio mcp server服务
if err := server.ServeStdio(mcpServer); err != nil {
	panic(err)
}

2. mcp.NewResource:对外提供资源

资源是你向 LLMs 暴露数据的方式。它们可以是任何东西:文件、API 响应、数据库查询、系统信息等。资源可以是:

  • 静态资源(固定 URI)
  • 动态资源(使用 URI 模板)
//新增一个mcp server对外暴露的静态资源(固定URI),比如:对外暴露项目的操作手册以及部署方式等,就可以通过静态资源README文件的方式来告诉大模型
resource := mcp.NewResource(
	"docs://readme",
	"项目的README文件",
	mcp.WithResourceDescription("这是一个项目的README文件"),
	mcp.WithMIMEType("text/markdown"),
)
// 添加对静态资源的处理器
mcpServer.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
})

3. mcp.NewTool:对外提供工具

工具让 LLM 通过你的服务器执行操作。与资源不同,工具预期会进行计算并产生副作用。它们类似于 REST API 中的 POST 端点。 下面是一个算术运算的工具示例:

工具可以用于任何种类的计算:

Database queries 数据库查询

File operations 文件操作

External API calls 外部 API 调用

Calculations 计算

System operations 系统操作

每个工具应该:

有清晰的描述

验证输入

优雅处理错误

返回结构化的响应

使用适当的结果类型

//给该mcp server添加计算能力(Tools)
// 1. 描述该工具,以及调用该工具调用的参数机器含义
calculatorTool := mcp.NewTool("calculate",
	mcp.WithDescription("进行基础的数学运算"),
	mcp.WithString("operation",
		mcp.Required(),
		mcp.Description("The arithmetic operation to perform"),
		mcp.Enum("add", "subtract", "multiply", "divide"),
	),
	mcp.WithNumber("x",
		mcp.Required(),
		mcp.Description("First number"),
	),
	mcp.WithNumber("y",
		mcp.Required(),
		mcp.Description("Second number"),
	),
)
// 2. 实现工具的具体处理逻辑,类比大模型function_calling中的func部分
mcpServer.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 "add":
		result = x + y
	case "subtract":
		result = x - y
	case "multiply":
		result = x * y
	case "divide":
		if y == 0 {
			return nil, errors.New("Division by zero is not allowed")
		}
		result = x / y
	}

	return mcp.FormatNumberResult(result), nil
})

4. s.AddPrompt:添加提示词

下面是一个简单的提示词示例,它需要一个名称参数,然后返回一个问候提示词:

// 给mcpServer添加提示词模版
mcpServer.AddPrompt(mcp.NewPrompt("打招呼",
	mcp.WithPromptDescription("A friendly greeting prompt"),
	mcp.WithArgument("name",
		mcp.ArgumentDescription("Name of the person to greet"),
	),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
	name := request.Params.Arguments["name"]
	if name == "" {
		name = "friend"
	}

	return mcp.NewGetPromptResult(
		"A friendly greeting",
		[]mcp.PromptMessage{
			mcp.NewPromptMessage(
				mcp.RoleAssistant,
				mcp.NewTextContent(fmt.Sprintf("Hello, %s! How can I help you today?", name)),
			),
		},
	), nil
})

实战使用

1. 编写mcp server

这里我们演示一个查询IP的mcp server。大模型传入ip,mcp server返回地址信息。

ip mcp server全部代码:

package main

import (
	"context"
	"errors"
	"fmt"
	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
	"io"
	"net"
	"net/http"
)

func main() {
	// Create MCP server
	s := server.NewMCPServer(
		"ip-mcp",
		"1.0.0",
	)

	// Add tool
	tool := mcp.NewTool("ip_query",
		mcp.WithDescription("query geo location of an IP address"),
		mcp.WithString("ip",
			mcp.Required(),
			mcp.Description("IP address to query"),
		),
	)

	// Add tool handler
	s.AddTool(tool, ipQueryHandler)

	// Start the stdio server
	if err := server.ServeStdio(s); err != nil {
		fmt.Printf("Server error: %v\n", err)
	}
}

func ipQueryHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	ip, ok := request.Params.Arguments["ip"].(string)
	if !ok {
		return nil, errors.New("ip must be a string")
	}

	parsedIP := net.ParseIP(ip)
	if parsedIP == nil {
		return nil, errors.New("invalid IP address")
	}

	resp, err := http.Get("https://ip.rpcx.io/api/ip?ip=" + ip)
	if err != nil {
		return nil, fmt.Errorf("Error fetching IP information: %v", err)
	}
	defer resp.Body.Close()

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("Error reading response body: %v", err)
	}
	fmt.Printf("call ip: %s  Response body: %s\n", ip, string(data))
	return mcp.NewToolResultText(string(data)), nil
}

然后我们编译代码:

# 执行命令编译mcp server
go build -o mcp-ip main.go

在这里插入图片描述

2. 桌面版调用mcp server插件

这里使用桌面版的deepchat来演示大模型调用mcp server。

deepchat下载地址:https://deepchat.thinkinai.xyz/#/download

  • 下载后配置本地大模型(通过ollama方式搭建等)或者直接配置远程模型地址

远程模型这里我使用openrouter的免费deepseek-r1版本:https://openrouter.ai/deepseek/deepseek-r1:free

选择模型,配置URL以及Token后,点击校验

在这里插入图片描述

点击下一步,然后就可以与大模型对话了

在这里插入图片描述

tips:

可修改页面文字为中文

在这里插入图片描述

可修改对话模型

在这里插入图片描述

下面我们配置mcp server

在这里插入图片描述

跳过json方式配置,转为手动配置

在这里插入图片描述

填写mcp server配置参数,然后点击提交

在这里插入图片描述

启用mcp server

在这里插入图片描述

  • 输入问题,查看效果

如:帮我查询39.156.66.10 IP信息

在这里插入图片描述

参考文章:
https://mcp-docs.cn/introduction
https://mp.weixin.qq.com/s/UgdXztu3SKYMs56DqiX3Sg
https://www.junki.cn/archives/Zqgi7fzK

到此这篇关于mcp-go Go搭建MCP服务的实现示例的文章就介绍到这了,更多相关mcp-go Go搭建MCP服务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Go语言实现LRU缓存的代码详解

    使用Go语言实现LRU缓存的代码详解

    在日常开发中,缓存是提高系统性能的重要手段,LRU缓存是一种基于“最近最少使用”策略的缓存系统,其目的是在空间受限的情况下保留最新、最常用的数据,本文将详细讲解如何使用 Go 语言实现一个 LRU 缓存,需要的朋友可以参考下
    2024-11-11
  • Golang测试框架goconvey进行单元测试流程介绍

    Golang测试框架goconvey进行单元测试流程介绍

    goconvey是一款针对Golang的测试框架,可以管理和运行测试用例,同时提供了丰富的断言函数,并支持很多Web界面特性,这篇文章主要介绍了使用goconvey进行单元测试流程,感兴趣的同学可以参考下文
    2023-05-05
  • golang爬虫colly 发送post请求

    golang爬虫colly 发送post请求

    本文主要介绍了golang爬虫colly 发送post请求实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Go开发环境搭建详细介绍

    Go开发环境搭建详细介绍

    由于目前网上Go的开发环境搭建文章很多,有些比较老旧,都是基于 GOPATH的,给新入门的同学造成困扰。以下为2023 版 Go 开发环境搭建,可参照此教程搭建Go开发环境,有需要的朋友可以参考阅读
    2023-04-04
  • 深入了解Golang中的Slice底层实现

    深入了解Golang中的Slice底层实现

    本文主要为大家详细介绍了Golang中slice的底层实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2023-02-02
  • Go基于雪花算法生成随机id

    Go基于雪花算法生成随机id

    雪花算法是twitter开源的由64位整数组成的分布式ID,本文主要介绍了Go基于雪花算法生成随机id,具有一定的参考价值,感兴趣的可以了解一下
    2024-05-05
  • 总结Golang四种不同的参数配置方式

    总结Golang四种不同的参数配置方式

    这篇文章主要介绍了总结Golang四种不同的参数配置方式,文章围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • golang实现微信支付v3版本的方法

    golang实现微信支付v3版本的方法

    这篇文章主要介绍了golang实现微信支付v3版本的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 详解go语言中sort如何排序

    详解go语言中sort如何排序

    我们的代码业务中很多地方需要我们自己进行排序操作,本文主要介绍了详解go语言中sort如何排序,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Golang logrus 日志包及日志切割的实现

    Golang logrus 日志包及日志切割的实现

    这篇文章主要介绍了Golang logrus 日志包及日志切割的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02

最新评论