春江暮客

春江暮客的个人学习分享网站

2026 实战:用 Python 快速搭建第一个 MCP Server

2026-05-29 技术

AI Agent 越来越常见以后,一个实际问题会很快出现:模型不能只会聊天,还要能安全地调用你的本地脚本、项目文件、数据库或内部 API。

MCP,也就是 Model Context Protocol,正是为这个场景准备的。它把“模型如何连接工具和上下文”这件事做成统一接口。本文不讲太多概念,目标只有一个:用 Python 写一个可以运行、可以调试、可以接入客户端的 MCP Server。

完成后,你会得到:

  1. 一个本地 server.py
  2. 两个可被 AI 调用的工具
  3. 一个可读取的资源
  4. 一套验证和排错命令

什么场景适合先学 MCP

如果你正在做下面这些事情,MCP 很值得先跑通一个最小版本:

  1. 想让 AI 助手读取项目里的 Markdown、日志或配置文件
  2. 想把现有 Python 脚本包装成 AI 可调用工具
  3. 想让不同 AI 客户端复用同一套本地能力
  4. 想做面向开发、运维、内容自动化的 Agent 工作流

最好的入门方式不是先设计复杂平台,而是先把一个本地工具暴露出来,并确认客户端能正常调用。

方法 1:创建一个本地 stdio MCP Server

stdio 是本地 MCP Server 最常见的启动方式。客户端启动你的脚本,然后通过标准输入和标准输出通信。它适合本地文件、命令行工具和开发环境集成。

1. 准备环境

推荐用 uv 管理 Python 项目。如果你已经安装过 uv,直接执行:

mkdir mcp-local-tools
cd mcp-local-tools
uv init
uv add "mcp[cli]"

如果你暂时不用 uv,也可以用 pip

python3 -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]"

先确认命令可用:

uv run mcp --help

如果能看到 devinstall 等子命令,说明开发工具已经安装完成。

2. 编写 server.py

新建 server.py

from __future__ import annotations

from datetime import datetime
from pathlib import Path

from mcp.server.fastmcp import FastMCP


mcp = FastMCP("Local Tools")
PROJECT_ROOT = Path.cwd().resolve()


@mcp.tool()
def word_count(text: str) -> dict[str, int]:
    """Count characters, words, and lines in a text block."""
    words = [word for word in text.split() if word]
    return {
        "characters": len(text),
        "words": len(words),
        "lines": len(text.splitlines()),
    }


@mcp.tool()
def list_md_files(directory: str = ".") -> list[str]:
    """List Markdown files under the project directory."""
    target = (PROJECT_ROOT / directory).resolve()

    if target != PROJECT_ROOT and PROJECT_ROOT not in target.parents:
        raise ValueError("directory must stay inside the project")

    if not target.exists() or not target.is_dir():
        raise ValueError("directory does not exist or is not a directory")

    files = sorted(target.rglob("*.md"))
    return [str(path.relative_to(PROJECT_ROOT)) for path in files[:50]]


@mcp.resource("time://now")
def current_time() -> str:
    """Return current local time."""
    return datetime.now().isoformat(timespec="seconds")


if __name__ == "__main__":
    mcp.run()

这个例子故意保持很小:

  1. word_count 用来测试普通文本参数
  2. list_md_files 用来测试读取本地项目文件
  3. time://now 用来测试 MCP resource

list_md_files 里加了目录限制,避免客户端随意读取项目目录之外的文件。真实项目里如果要访问数据库、私有目录或线上 API,也应该先加权限边界。

方法 2:用 MCP Inspector 调试

MCP Server 不是普通 Web 服务,直接运行时通常会等待客户端通过 stdio 通信。因此调试时建议先用官方开发工具:

uv run mcp dev server.py

正常情况下,它会启动 MCP Inspector。打开页面后可以检查:

  1. Server 是否成功连接
  2. word_countlist_md_files 是否出现在 tools 列表里
  3. time://now 是否出现在 resources 列表里
  4. 调用工具后返回值是否符合预期

可以先用这个输入测试 word_count

{
  "text": "hello MCP\nhello Python"
}

预期返回类似:

{
  "characters": 22,
  "words": 4,
  "lines": 2
}

再测试 list_md_files

{
  "directory": "."
}

如果当前目录里有 Markdown 文件,会返回类似:

[
  "README.md",
  "docs/usage.md"
]

接入支持 MCP 的客户端

调试通过后,可以把这个 Server 配到支持 MCP 的 AI 客户端里。不同客户端配置界面不一样,但核心信息通常都是这三项:

  1. 命令:uv
  2. 参数:进入项目目录并运行 python server.py
  3. 工作目录:你的 mcp-local-tools 绝对路径

通用 JSON 配置可以参考:

{
  "mcpServers": {
    "local-tools": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/mcp-local-tools",
        "run",
        "python",
        "server.py"
      ]
    }
  }
}

/absolute/path/mcp-local-tools 换成你的真实路径。例如:

pwd

如果你使用的客户端支持直接安装本地 MCP Server,也可以尝试:

uv run mcp install server.py --name "Local Tools"

安装后重启客户端,再让 AI 调用 word_countlist_md_files 做一次实际测试。

验证清单

上线或接入客户端前,建议按这个顺序检查:

# 1. 检查 Python 语法
uv run python -m py_compile server.py

# 2. 检查 MCP CLI 是否可用
uv run mcp --help

# 3. 启动 Inspector 调试
uv run mcp dev server.py

如果这三步都通过,再接入 AI 客户端会更稳。

常见问题

1. 找不到 mcp 命令

通常是依赖没有安装到当前项目里。重新执行:

uv add "mcp[cli]"
uv run mcp --help

如果你用的是 pip,确认已经激活虚拟环境:

source .venv/bin/activate
python -m pip show mcp

2. 直接运行 server.py 没有输出

这是正常现象。stdio MCP Server 会等待客户端连接,不是启动后打印 HTTP 地址的 Web 服务。

用 Inspector 调试:

uv run mcp dev server.py

3. 客户端连接后看不到工具

优先检查三件事:

  1. server.py 是否有 @mcp.tool() 装饰器
  2. 客户端配置里的项目路径是否是绝对路径
  3. 客户端重启后是否重新加载了 MCP 配置

也可以先运行语法检查:

uv run python -m py_compile server.py

4. 读取文件时报权限错误

本文示例只允许读取项目目录内的 Markdown 文件。如果你传入 ../ 或系统目录,会被主动拒绝。

建议不要直接放开全盘读取,而是把可访问目录做成明确配置,例如:

ALLOWED_ROOT = Path("/home/user/my-project").resolve()

然后所有文件访问都先检查是否仍在 ALLOWED_ROOT 内。

参考资料

  • Model Context Protocol 文档:https://modelcontextprotocol.io/docs
  • MCP Python SDK:https://github.com/modelcontextprotocol/python-sdk

总结

MCP 的价值不在于概念新,而在于它把 AI 调用工具这件事变成了可复用接口。对个人开发者和站长来说,最实用的切入点就是把已有 Python 脚本、内容目录和自动化命令包装成 MCP Server。

先从本文这种小工具开始:能调通、能限制权限、能被客户端调用。等这个闭环跑顺以后,再接数据库、搜索、部署脚本或站点内容管理工具,会更容易控制风险。

友情链接

其它