从零开始搭建一个MCP服务器

背景

MCP(Model Context Protocol)来自于2024年Anthropic发布的文章:Introducing the Model Context Protocol,是一种用于和LLM Model 交互的标准化协议,允许模型拓展自己的能力。在最近的Manus爆火之后,关注度更是上升,我也是在这之后才了解到这个协议的。在我看来,这个协议是一个里程碑式的节点,统一了模型和应用之间的通信标准,在未来会有更加广阔的应用场景,现在也有不少应用厂家接入了MCP协议,比如国内的百度地图。

v2-9fe7fb51f264338a079a444eefa041b1_1440w

借用下面这篇文章的图片,这张图一目了然地展示了MCP的作用。对于MCP感兴趣但是还不是很了解的读者,推荐去阅读一下下面这篇文章。

https://zhuanlan.zhihu.com/p/29001189476

本文既是我摸索搭建一个MCP学习记录,也是一个简单的流程分享。受限于个人技术,本文并不涉及到一些较为成熟的开发范式,更多是对整体流程做一个记录和梳理,希望能对想要着手开发MCP服务器的读者有所帮助。这篇文章会以Python为编程语言进行实践。

我搭建的服务器:一个用于帮助大模型访问wiki网站的服务器,欢迎大伙Star!

https://github.com/shiquda/mediawiki-mcp-server

这个项目的灵感源于我最近玩的一款游戏Noita,对于我这个新手来说,需要经常查询游戏wiki。于是我就为了这点醋,包了这碗饺子,打算利用MCP技术,让大模型帮我阅读和总结wiki。于是就有了这篇文章😄

先决条件

在阅读并实践之前,笔者假设读者拥有以下能力:

  1. 熟悉Python编程语言
  2. 拥有能稳定使用、支持Tool Call的大模型提供商,以及一个支持MCP协议的客户端
  3. 熟悉Git与GitHub的基本使用
  4. 拥有良好的网络环境

对于第2点,若读者还没有合适的,笔者进行以下推荐:

  1. 火山引擎-云上增长新动力:字节提供的稳定性好、价格优惠的平台,使用其中的DeepSeek模型,支持tool-call。
  2. Cherry Studio 官方网站 - 全能的AI助手:一个开源免费的、支持多个LLM提供商的桌面端大模型对话软件,现在支持MCP协议。(笔者参与了该项目的贡献,算是打个小小的广告:))

对于上述二者的申请与配置,相信对读者应该不成问题,烦请读者自行查找攻略进行配置。

正文

环境配置

使用Python进行MCP服务器的开发,目前主流使用的是uv,这是一个使用Rust编写的高效的包管理器,支持虚拟环境管理、运行和安装Python应用、项目管理、项目构建等多个功能。想进一步了解,可以阅读官方文档

请读者自行安装与配置uv。可以参考这篇文章:

Python包管理不再头疼:uv工具快速上手 - wang_yb - 博客园

我们还需要用到node环境,用于服务器的测试。

初始化

使用uv进行项目的初始化。

1
2
uv init <项目名>
cd <项目名>

创建虚拟环境:

1
uv venv

并使用你所在平台的方式进行激活。

使用uv添加依赖:

1
uv add "mcp[cli]" httpx

对于克隆来的其他mcp项目,我们可以使用下面的命令来进行依赖的安装:

1
uv sync

项目结构

下面是一个最简单的项目结构,省略了部分文件,供读者参考。

1
2
3
4
5
6
7
mediawiki-mcp-server
├── pyproject.toml
├── README.md
├── src
│ ├── mediawiki_mcp_server
│ │ ├── main.py
├── uv.lock

pyproject.toml是整个项目的配置文件,我们需要对其进行相应的修改。

除了已有的项目名称、版本号等,我们还需要添加下面几行,用于项目的运行和构建:

1
2
3
4
5
6
7
8
9
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project.scripts]
mediawiki-mcp-server = "<包的名称>.main:main"

[tool.hatch.build.targets.wheel]
packages = ["src/<包的名称>"]

然后就是开始编写一个简单的MCP服务器啦!想要更详细地查看,可以参考下面这些来源:

For Server Developers - Model Context Protocol

modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients

我们在/src/<name>创建一个main.py 文件,用于写MCP服务器的主要逻辑。

对于一个最简单的服务器,可以参考下面的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("<name>") # 创建服务器实例

@mcp.tool() # 这个装饰器表示下面的函数是一个可被LLM调用的Tool
async def get_page(title: str): # 参数会被自动处理,写在下面的docstring可以被识别作为给大模型的“工具使用说明书”
"""Get a page from mediawiki.org
Args:
title: The title of the page to get, which can be found in title field of the search results
Returns:
The page content
"""
path = f"page/{title}"
response = await make_request(path, {}) # 实现略
return response

def main():
mcp.run(transport="stdio") # 使用stdio本地模式

if __name__ == "__main__":
main()

简单来说,只要专注于实现一个Tool的接口就行了,对于暴露给模型调用的,使用@mcp.tool()进行修饰,调用参数即为函数的传入参数,而使用方法写在函数的注释里面即可。

下面我们从用户的角度考虑一下。用户使用你的服务器,主要可以配置三个部分:

PixPin_2025-04-04_23-06-25

  1. 命令。主要使用的有uvx/uvnpxdocker 。我们使用的是python,因此这里一般是填uvx/uv。
  2. 参数。这一部分会通过命令行参数传给服务器,因此我们需要考虑在mcp.run启动前处理这些命令行参数。
  3. 环境变量。我们在启动前也需要检查需要的环境变量。

因此,我们需要使用参数或者环境变量来达到自定义服务器和读取数据的目的。例如,对于一些需要鉴权的服务,我们可以让用户在环境变量部分配置他们的凭证;一些自定义的参数,可以放在命令行参数来传入。

测试

编写完逻辑之后,需要进行测试。

第一步,先使用MCP官方提供的测试工具进行测试,使用起来非常简单:

1
npx @modelcontextprotocol/inspector uv run <name>

运行之后,在浏览器打开提示的地址,即可进行调试。

PixPin_2025-04-04_23-04-22

对于我们这个简单的项目,主要测试的是Tool的功能。

PixPin_2025-04-04_23-16-32

第二步,测试完成后,我们就可以对接到客户端进行进一步测试了。这一步主要是检查功能是否符合预期,LLM能否按照预期调用,以及会不会出一些没考虑到的问题。

对于本地开发调试,需要注意的地方是,由于我们现在还没有将成品打包到pypi,因此需要添加命令行参数来进行本地调试。可以参考下面的写法:

命令:uv

参数:

1
2
3
4
5
6
7
"args": [
"run",
"--directory",
"path/to/project/src/<name(下划线)>",
"<name>",
"<...其他参数>"
],

构建

测试完毕后,我们可以考虑发布到pypi,让其他用户能够更方便的下载使用。

在本文中,我们使用uv,利用Github Actions来进行自动化构建,但在正式构建之前,本地需要进行测试:

1
uv build

如果正常的话,在项目的/dist 应该会有相应的构建产物。

一切正常后,我们先去 https://pypi.org/ 进行相应的设置。如果没有账号,可以先注册一个。

pypi现在支持通过“受信任”的发布者进行自动化构建。我们这里使用Github平台进行配置。

进入 Trusted Publisher Management · PyPI,找到Add a new pending publisher

PixPin_2025-04-04_23-26-55
添加之后,我们在项目中添加.github/workflows/publish.yml。注意yml的文件名需要和上一步的对得上。

工作流文件,可以参考下面的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
name: Publish Python Package to PyPI when a Release is Created

on:
release:
types: [created]

jobs:
pypi-publish:
name: Publish release to PyPI
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/<name> # 改成前一步设置的项目名称
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.13" # 改成需要的版本号
- name: Install dependencies
run: |
pip install uv
- name: Build package
run: |
uv sync
uv build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

这里设置的是在Github上创建Release时触发构建,所以构建时,需要去项目的Release中手动创建一下。工作流也可以更改为检测到tag推送后触发,读者可以自行更改。

成功推送到pypi上后,你就可以使用下面的方式在客户端中调用了:

1
2
3
4
"command": "uvx",
"args": [
"<name>",
],

分享

想要把你的MCP服务器推荐给别人?我整理了几个常见的mcp检索平台,在这些地方上提交你的服务器,可以让更多用户发现并体验你的服务器。

  1. https://glama.ai/mcp/servers ,和 punkpeye/awesome-mcp-servers: A collection of MCP servers. 相关
  2. https://mcp.so/

参考

Introduction - Model Context Protocol

PyPI · The Python Package Index

Publishing a Python Package from GitHub to PyPI in 2024

https://pypi.org/manage/account/publishing/

https://github.com/punkpeye/awesome-mcp-servers

ChatGPT alternative for power users

Building and publishing a package | uv