实际使用别人写好的 MCP
项目来源
```python
https://github.com/Nihilantropy/godot-mcp-docs/tree/main?tab=readme-ov-file
```
首先在根文件夹下使用 `uv sync`安装Python虚拟环境. [ 不是使用requirements.txt 而是使用 **`pyproject.toml`**文件 ]
- 详细:
这是一个非常敏锐的问题!如果工程里没有 `requirements.txt`,`uv sync` 依然能工作,是因为它并不依赖 `requirements.txt`。
**uv sync 的核心权威来源是:****`pyproject.toml`**。
在现代 Python 打包标准(PEP 517/518/621)中,`pyproject.toml` 才是真正的“项目身份证”,而 `requirements.txt` 只是一个传统的、被逐渐边缘化的依赖列表。
### 1. `uv sync` 的工作机制
当你运行 `uv sync` 时,它会按照以下优先级寻找依赖:
1. **首选:****`pyproject.toml`**
它会去读取这个文件里的 `[project.dependencies]` 部分。
```toml
# pyproject.toml
[project]
name = "godot-mcp-docs"
dependencies = [
"mcp>=0.1.0",
"requests",
"beautifulsoup4"
]
```
- **你的情况**:你 clone 的这个 `godot-mcp-docs` 项目根目录下一定有一个 `pyproject.toml` 文件。uv 就是读了它,才知道需要安装 `fastmcp`, `httpx` 等包的。
2. **次选:****`uv.lock`** **(锁定文件)**
如果目录下已经有一个 `uv.lock` 文件(类似 Node.js 的 `package-lock.json` 或 Rust 的 `Cargo.lock`),`uv sync` 会**无脑执行**这个锁文件里的版本,确保大家环境绝对一致。
- 即使 `pyproject.toml` 里写的是 `requests>=2.0`,如果 lock 文件里写死是 `2.28.1`,sync 就会装 `2.28.1`。
3. **如果都没有?**
如果既没有 `pyproject.toml` 也没有 `uv.lock`,`uv sync` 可能会报错或者初始化一个空环境(取决于版本和上下文,通常它是为项目设计的,所以必须有项目配置)。
### 2. 为什么不用 `requirements.txt` 了?
`requirements.txt` 有几个重大缺陷,导致新一代工具(uv, poetry, pdm)都弃用它作为核心元数据:
- **扁平化**:你没法区分哪些是“生产依赖”,哪些是“开发依赖”(测试工具、文档生成器)。虽然可以分多个文件,但管理麻烦。
- **信息丢失**:它只记录了“要装什么”,没记录“为什么要装它”(是直接依赖还是间接依赖?)。
- **冲突地狱**:没有锁文件机制,今天装和明天装,得到的子依赖版本可能不同,导致“在我机器上能跑”的经典 Bug。
### 3. uv 是怎么偷懒的?
如果你的项目里确实只有 `requirements.txt`(旧项目),uv 也有办法:
- 你需要显式告诉它:`uv pip install -r requirements.txt` (这是模拟 pip 的行为)。
- 但 `uv sync` 命令本身,是专门为**基于 pyproject.toml 的现代项目**设计的。
**总结**:
你去看看项目目录下的 `pyproject.toml`,你会发现所有神奇的“必需包”都白纸黑字写在那里面呢。
这样会创建好一个虚拟环境

创建好文档就要用当前虚拟环境来下载文档和进行处理:
`uv run python .\godot_docs_converter.py`
转换好之后的docs文件夹移动到根目录下, 并且进入到docs文件夹中, 执行tree命令查看文件树
处理好的文档还需要输出文件树
`tree /f > docs_tree.txt`
- 详细 追加写入或者覆盖写入 还有编码问题 中文乱码解决.
在 PowerShell 中,有几种常用方法可以将指令输出保存到 `.txt` 文件:
### 1. 使用 `>` 或 `>>` 符号 (最简单)
这是最常用的方式,和 Linux/CMD 类似。
- **覆盖写入** (如果文件存在,内容会被清空):
```powershell
ls > list.txt
```
- **追加写入** (保留原有内容,加在后面):
```powershell
ls >> list.txt
```
### 2. 使用 `Out-File` (推荐,可控制编码)
如果你遇到**中文乱码**问题,或者需要指定特定的文件编码(如 UTF8),请使用此方法。
```powershell
# 默认为 utf-16le,可能导致乱码
ls | Out-File output.txt
# 强制使用 UTF8 编码 (推荐)
ls | Out-File -FilePath output.txt -Encoding utf8
```
### 3. 使用 `Tee-Object` (同时看和存)
如果你既想在**屏幕上看到输出**,又想**保存到文件**:
```powershell
ls | Tee-Object -FilePath log.txt
```
### 示例:将你的 python 命令输出保存
如果你想保存刚才那个转换脚本的输出日志:
```powershell
uv run python .\godot_docs_converter.py | Out-File -Encoding utf8 conversion_log.txt
```
- 调试不能直接用LLM调, 用官方的调试器: `npx @modelcontextprotocol/inspector uv run python main.py` 直接运行一个Web端点击进行测试.
调试 FastMCP 服务主要有三种方式:**CLI 交互调试**(最快)、**HTTP 请求调试**(最直观)、以及 **MCP Inspector**(官方推荐的 GUI 工具)。
## 方式一:FastMCP 内置 Dev UI (最推荐)
FastMCP 自带了一个非常漂亮的调试界面(基于 Swagger UI 的变体)。
1. **启动服务 (SSE 模式)**
假设你的入口文件是 `main.py`,确保它以 SSE 模式启动(或者直接用 `uv run fastmcp dev main.py`)。
```
# 使用 dev 模式启动,这会自动开启调试界面
uv run fastmcp dev main.py
```
2. **访问调试界面**
启动成功后,控制台会输出一个 URL,通常是:
`http://127.0.0.1:8000` (或者其他端口)
打开浏览器访问这个地址,你可以看到:
- 列出了所有的 **Tools** (工具) 和 **Resources** (资源)。
- 你可以直接在网页上填参数,点击 **"Execute"** ,查看 JSON 输出。
## 方式二:HTTP API 调试 (Postman / Curl)
如果你的 Server 是以 SSE 模式运行的,它其实就是一个标准的 Web Server。虽然 MCP 协议比较复杂(JSON-RPC),但你可以直接发 POST 请求来模拟。
**Endpoint**: `/message` (这是 FastMCP 处理请求的端点)
**Request (POST)** :
```
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "search_godot_docs", // 你的工具名
"arguments": {
"query": "DisplayServer" // 工具参数
}
},
"id": 1
}
```
**用 Curl 测试**:
```
curl -X POST http://localhost:8000/message `
-H "Content-Type: application/json" `
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": { "name": "search_godot_docs", "arguments": { "query": "DisplayServer" } },
"id": 1
}'
```
## 方式三:使用 MCP Inspector (官方调试器)
这是 Anthropic 官方提供的 MCP 协议调试器,它是 Web 版的,可以直接连接你的本地服务。
1. 你需要先安装 `npx` (Node.js)。
2. 运行 Inspector 并指向你的 Python 脚本:
```
npx @modelcontextprotocol/inspector uv run python main.py
```
3. 它会在浏览器打开 `http://localhost:5173`。
在这个界面里,你可以像 LLM 一样,看到所有的工具定义,并手动点击调用它们,查看完整的请求和响应日志。
**总结建议:**
- **随手测测**:直接用 **`fastmcp dev`**,浏览器点点就行,无需安装额外工具。
- **集成测试**:用 **Curl / Python requests** 写脚本批量测。
- **协议级调试**:用 **MCP Inspector**。
- 官方调试器使用 `npx @modelcontextprotocol/inspector uv run python main.py` 直接打开前端调试器
- 详细
## 使用 MCP Inspector (官方调试器)
这是 Anthropic 官方提供的 MCP 协议调试器,它是 Web 版的,可以直接连接你的本地服务。
1. 你需要先安装 `npx` (Node.js)。
2. 运行 Inspector 并指向你的 Python 脚本:
```
npx @modelcontextprotocol/inspector uv run python main.py
```
3. 它会在浏览器打开 `http://localhost:5173`。
在这个界面里,你可以像 LLM 一样,看到所有的工具定义,并手动点击调用它们,查看完整的请求和响应日志。
**总结建议:**
- **随手测测**:直接用 **`fastmcp dev`**,浏览器点点就行,无需安装额外工具。
- **集成测试**:用 **Curl / Python requests** 写脚本批量测。
- **协议级调试**:用 **MCP Inspector**。
不需要自己再运行`uv run python main.py`
在根目录下直接跑命令

在浏览器界面中选择tool测试即可, 可以得知Python会返回转码失败的提示.

- Python代码: `DOCS_DIR = Path("docs").resolve()`的解析 -> 只跟运行Python文件时 Powershell 所在的位置有关, 运行Python之后会进入到Python的Shell中, 这个shell的上一层就是Powershell, 所以路径在 运行 python main.py时就确定了. 这就是 **当前工作目录” (Current Working Directory, CWD)** .
1. **`Path("docs")`** :
这创建了一个 `pathlib.Path` 对象,指向当前工作目录(CWD)下的 `docs` 文件夹。这是一个**相对路径**。
- *问题*: 相对路径很危险。如果你的程序在 `D:\Codes\16_MCP\` 运行,它指向 `D:\Codes\16_MCP\docs`;但如果你换个目录运行,它就指向别处了。
2. **`.resolve()`** :
这个方法做了三件大事:
- **绝对化 (Make Absolute)** : 获取当前工作目录(CWD),把它和 `"docs"` 拼起来,变成 `D:\Codes\16_MCP\godot-mcp-docs\docs` 这样的完整路径。
- **标准化 (Normalize)** : 消除路径中的冗余,比如 `.` (当前目录) 和 `..` (上级目录)。如果你的路径是 `docs/../img`,它会直接变成 `img` 的绝对路径。
- **解析软链接 (Follow Symlinks)** : 如果 `docs` 是一个快捷方式(Windows)或者软链接(Linux),`.resolve()` 会直接返回它**真正指向**的那个文件夹的物理路径。
这是初学者最容易混淆的概念,一针见血的答案是:
**“当前工作目录” (Current Working Directory, CWD) 指的是你在终端里敲命令时所在的那个文件夹,跟你运行的** **`.py`** **脚本文件放在哪里完全没关系。**
## 直观演示
假设你的目录结构如下:
```
D:\Codes\16_MCP\ <-- 根目录
├── main.py <-- 你的启动脚本
├── docs\ <-- 你想找的文档目录
└── srcs\
└── util\
└── docs_utils.py <-- 你的工具代码 (里面写了 Path("docs"))
```
## 情况 A:你在根目录运行
你打开终端,`cd D:\Codes\16_MCP`,然后输入:
`python main.py`
- **当前工作目录**: `D:\Codes\16_MCP`
- `Path("docs")` 解析结果: `D:\Codes\16_MCP\docs`
- **结果**: **成功**。因为根目录下确实有 `docs`。
## 情况 B:你在子目录运行 (常见错误)
你打开终端,进到了 `srcs` 目录,`cd D:\Codes\16_MCP\srcs`,然后输入:
`python ../main.py` (或者 `python D:\Codes\16_MCP\main.py`)
- **当前工作目录**: `D:\Codes\16_MCP\srcs`
- `Path("docs")` 解析结果: `D:\Codes\16_MCP\srcs\docs`
- **结果**: **失败**。`srcs` 里面没有 `docs` 文件夹。
## 为什么会这样?
`Path("docs")` 是一个**相对路径**。
相对路径永远是相对于 **“你人现在在哪” (CWD)** ,而不是相对于“代码文件在哪”。
## 最佳实践:如何让它永远指向正确的 `docs`?
如果你想让 `docs_utils.py` 永远指向项目根目录下的 `docs`,不管你在哪里运行命令,你应该使用 **基于** **`__file__`** **的绝对定位**。
**修改** **`docs_utils.py`** **的写法:**
```
from pathlib import Path
# 1. 获取当前脚本文件 (docs_utils.py) 的绝对路径
CURRENT_SCRIPT_DIR = Path(__file__).resolve().parent
# 2. 根据目录结构往上找根目录
# docs_utils.py 在 src/util/,所以根目录是它的 "爷爷" (parent.parent)
PROJECT_ROOT = CURRENT_SCRIPT_DIR.parent.parent
# 3. 定位 docs 目录
DOCS_DIR = (PROJECT_ROOT / "docs").resolve()
```
这样写之后,无论你在 D 盘根目录、C 盘还是任何奇怪的地方运行 Python,`DOCS_DIR` 永远都会精准锁定在 `D:\Codes\16_MCP\docs`。