如何编写一个MCP服务
Table of Contents
使用 Python MCP SDK 以及 mcp-go ,来学习 MCP 服务的开发流程。
什么是 MCP
MCP(Model Context Protocol),即模型上下文协议,是一种开放协议,它标准化了应用程序如何为 LLM 提供上下文。将 MCP 想象成 AI 应用程序的 USB-C 端口。正如 USB-C 提供了一种将设备连接到各种外围设备和配件的标准化方式一样,MCP 也提供了一种将 AI 模型连接到不同数据源和工具的标准化方式。
MCP 官方提供了多种编程语言的 SDK,方便开发者进行 MCP 服务的开发。
由于 MCP 协议是公开的,因此社区中也有不少开发者自行开发了其他编程语言的 MCP 服务 SDK,比如 Go 语言版本 MCP 工具:mark3labs/mcp-go。
下面的笔记将使用 Python MCP SDK 以及 Go MCP SDK ,来学习 MCP 服务的开发流程。
Python MCP 服务
MCP 官方推荐使用 uv 来管理 Python 的 MCP 项目,因此需要先安装 uv,uv 的安装和使用具体可以参考我之前写的笔记:Python项目环境管理工具:uv。
先使用 uv 创建一个 MCP 项目文件夹:
uv init mcp-server-demo
cd mcp-server-demo
再添加 MCP 服务所需要的 Python 依赖包:
uv add "mcp[cli]"
# 等同于
pip install "mcp[cli]"
接着就可以在项目文件夹中的 main.py
中编写相关的 MCP 代码。比如下面一个简单的加法工具例子:
# server.py
from mcp.server.fastmcp import FastMCP
# Create an MCP server
mcp = FastMCP("Demo")
# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""Get a personalized greeting"""
return f"Hello, {name}!"
其中有两处关键点。
一是 @mcp.tool()
向 LLM 添加一个工具,即 LLM 可以使用这个工具完成这个函数指定的功能,那么 LLM 是怎么知道这个函数具体的功能以及什么时候可以调用呢?
这就是该功能函数下面的 """Add two numbers"""
多行注释的作用,通过它可以告诉 LLM 这个功能函数有什么作用,也可以再具体申明功能函数的参数和返回值的意义和类型。
二是 @mcp.resource()
向 LLM 公开一些资源数据,它类似于 REST API 中的 GET 请求处理,LLM 向 MCP 服务请求它时,它只向 LLM 提供一些只读数据,而不做其他操作。
同样,该函数下面的多行注释,也是向 LLM 说明这个函数提供的数据有什么意义,是什么数据,有哪些类型,有什么作用,方便 LLM 理解并在合适的时机读取它。
最后就是启动这个 MCP 服务。
if __name__ == "__main__":
mcp.run()
启动这个 MCP 服务有三种方式:
stdio
标准输入输出sse
服务器发送事件(逐渐被streamable-http
替代)streamable-http
可流式传输的 HTTP
可以通过 mcp.run(transport="模式")
指定,比如:
if __name__ == "__main__":
mcp.run(transport="stdio")
其中 sse
与 streamable-http
类似,都是启动一个服务器,通过暴露调用地址和端口,供 LLM 调用,因此可以部署在云端服务器中,实现远程调用。而 stdio
则是通过系统的标准输入输出通道与 LLM 进行通信,这种方式不需要启动服务程序,只需要向 MCP 客户端提供程序的路径或使用命令即可。
因为 Cherry Studio 这个 AI 客户端中集成了 MCP 客户端并且拥有友好的配置界面,因此接下来尝试在其中配置 MCP 服务,让 LLM 可以调用自己编写的 MCP 服务。
打开 Cherry Studio 的设置,找到 MCP 服务器,先点击上方的红色感叹号,先安装 Cherry Studio 内置的 uv 和 bun。安装成功重启后,红色感叹号变为绿色对勾则安装成功。
选择添加服务器(快速创建),类型选择 标准输入/输出stdio
,命令使用 uv,参数中填入:
--directory
D:\Desktop\mcp-server-demo
run
main.py
D:\Desktop\mcp-server-demo
是 MCP 项目的本地路径,main.py
是 MCP 的程序名。
其他选项默认即可。
接下来就可以在模型对话界面使用 MCP 服务进行对话,比如我问它一个加法问题,它会自行调用 MCP 服务完成这个功能,并回答。
Go MCP 服务
学习了如何使用 Python 编写一个 MCP 服务,那么 Go 语言也是类似的流程。Go 语言版本的 MCP 服务基于第三方的 mark3labs/mcp-go 库。
同样首先创建一个 mcp-server-demo
项目文件夹,并在其中初始化 Go 项目。
mkdir mcp-server-demo
cd mcp-server-demo
go mod init mcpserverdemo
go get github.com/mark3labs/mcp-go
创建一个 main.go
文件,并在其中编写 MCP 服务。
package main
import (
"context"
"errors"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// Create a new MCP server
s := server.NewMCPServer(
"MCP Server Demo",
"1.0.0",
server.WithToolCapabilities(false),
)
// Add an addition tool
tool := mcp.NewTool(
"Add two numbers",
mcp.WithDescription("This tool adds two int numbers together"),
mcp.WithNumber("x",
mcp.Required(),
mcp.Description("The first int number to add"),
),
mcp.WithNumber("y",
mcp.Required(),
mcp.Description("The second int number to add"),
),
)
// Add tool handler
s.AddTool(tool, addHandler)
// Start the stdio server
if err := server.ServeStdio(s); err != nil {
fmt.Printf("Server error: %v\n", err)
}
}
这里同样使用了 stdio
模式,如果要使用其他模式,则可以使用 server.ServeSSE
和 server.ServeHTTP
(需要指定端口)
以上就向 LLM 注册了两个整数相加的工具,而这个工具实现的功能则编写在 addHandler
函数中。
func addHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
x, err := request.RequireInt("x")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
y, err := request.RequireInt("y")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
result := x + y
return mcp.NewToolResultText(fmt.Sprintf("%d", result)), nil
}
编写完完整代码后,整理 Go Mod。最后使用 go install
将编写好的 MCP 程序编译成可执行文件(mcpserverdemo.exe
)。
go mod tidy
go install .
这里不使用
go build
的原因在于,go install
会将编译后的可执行文件直接放入GOPATH/bin
文件夹中,由于GOPATH
配置了系统环境变量,因此可以在任何地方使用这个工具,方便 MCP 客户端调用这个工具。可以使用
go clean -i
来清除go install
生成的可执行文件。
同样使用 Cherry Studio 作为 MCP 客户端。配置方式与 Python 几乎一致,只不过命令填入 mcpserverdemo.exe
(编译后的可执行文件名),参数不用填。
同样在模型对话界面问模型一个两个整数相加问题,它自动调用了 MCP 服务。
以上便完成了 Go 语言版本的 MCP 服务开发。
当然以上 Python 和 Go 版本都只是实现了一个很简单的整数加法 MCP 功能,实际上 MCP 能够实现的功能十分强大。因为它可以调用编程语言提供的工具,理论上来说 AI 可以通过 MCP 服务完成所有编程语言可以完成的功能。
学习了如何编写一个 MCP 服务,也可以尝试自己编写一些工具,比如爬虫服务:让 AI 自行爬取你所需要的数据。又或者是操作本地电脑:让 AI 可以通过编程语言操作本地电脑的 Shell 命令行,完成本地电脑的所有操作,比如办公自动化,系统设置等等,让 AI 真正能够操作你的电脑。
AI + MCP,一切皆有可能。