🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度
1. 空仓库里的 FastMCP 只读检索与 TaoToken 通道边界
TaoToken 是统一 API 兼容通道,落地页里能创建 Key;这篇要把 FastMCP 的只读仓库检索工具挂到 Claude Code。目标很具体:在一个空仓库里写一个 search_repo 工具,让 Claude Code 用自然语言调用它,最后在终端里看到一次真实的仓库检索回显。TaoToken 在这里只做 Claude Code 的 API 通道,Key 和 Base URL 配好之后,FastMCP 的业务代码不需要改一行。
FastMCP 是 MCP 协议在 Python 侧的一套实现方式,适合把本地能力包装成 Claude Code 可以调用的工具。Claude Code 作为 MCP 客户端,负责把用户问题拆成工具调用,再把工具返回的结构化结果交回模型总结。空仓库的好处是变量少:没有复杂依赖、没有历史配置、没有多人协作约定,正好用来验证“工具注册、通道切换、一次调用”这条链路是否成立。本次不接生产库,也不让 Claude Code 直接执行 shell 去搜文件,而是把检索逻辑写进 FastMCP server,只读返回路径、行号和匹配行。
为什么不让 Claude Code 直接跑 grep 或 rg?因为那是非结构化执行。模型可以生成命令,但命令由谁执行、在哪个目录执行、有没有越界访问,都需要额外约束。MCP 工具把这些约束前置到 server 代码里:只允许读文本文件、只允许指定后缀、排除 .git、node_modules、__pycache__、.venv 等目录、限制返回条数、不提供写文件工具。这样 Claude Code 看到的是“可调用的只读函数”,而不是“可以在任意机器上跑任意命令的入口”。对于评测 Agent、跑 Benchmark、接插件的人来说,这一步很关键:工具边界越清楚,复现时越不容易被环境噪声带偏。
这次任务拆成十分钟的节奏:前两分钟建空仓库和写 server.py,接着三分钟装 FastMCP 并确认 server 能启动,再用三分钟把 Claude Code 的 API 通道指向 TaoToken、把 MCP server 注册到项目配置,最后两分钟在 Claude Code 里提问并查看工具调用输出。Base URL 是 https://taotoken.net/api,末尾不带 /v1。模型 ID 不要凭记忆写,去模型广场看当前可用 ID,再填进 ANTHROPIC_MODEL。这篇不引用任何公榜分数,也不把 FastMCP 的仓库热度写成能力跑分,只记录一次本地可复现的调用。
需要提前说清楚只读边界。仓库检索工具可以返回文件内容片段,但不写文件、不删文件、不执行测试、不提交 Git、不访问网络。Claude Code 如果生成了某条命令,也应该由你在本地终端执行,再把结果贴回对话。这个约定和“AI 工具不能直连读者生产库或生产机执行”是同一条线:工具可以帮你解释、定位、生成命令,但真正改变环境的动作要留在你手里。FastMCP server 只读,恰好适合做这个练习。
2. 写 server.py:FastMCP 的 search_repo 只读工具
先建一个空目录,初始化 Git 只是为了后面用 git status 验证没有文件被改。命令如下:
mkdir fastmcp-repo-search
cd fastmcp-repo-search
git init
python -m venv .venv
source .venv/bin/activate
pip install fastmcp
Windows 下激活虚拟环境用 .venv\Scripts\activate。FastMCP 的安装版本以你本地 pip 解析结果为准,本文不写死版本号。接着创建 server.py,把只读检索逻辑写完整。代码里不需要任何 TaoToken 配置,因为 TaoToken 是 Claude Code 的 API 通道,不是这个 MCP server 的依赖。server 只负责接收 query、root、max_results、case_sensitive 四个参数,返回匹配列表。
from pathlib import Path
from typing import Any
from fastmcp import FastMCP
mcp = FastMCP("repo-search")
TEXT_SUFFIXES = {
".py", ".js", ".ts", ".tsx", ".jsx", ".md", ".txt", ".toml",
".yaml", ".yml", ".json", ".rs", ".go", ".java", ".c", ".h",
".cpp", ".sh", ".sql", ".css", ".html",
}
SKIP_DIRS = {
".git", "node_modules", "__pycache__", ".venv", "venv",
"dist", "build", ".next", ".idea", ".vscode",
}
@mcp.tool()
def search_repo(
query: str,
root: str = ".",
max_results: int = 20,
case_sensitive: bool = False,
) -> list[dict[str, Any]]:
"""只读检索仓库文本文件,返回路径、行号和匹配行。"""
if not query.strip():
return [{"error": "query 不能为空"}]
if max_results < 1 or max_results > 100:
return [{"error": "max_results 需要在 1 到 100 之间"}]
base = Path(root).expanduser().resolve()
if not base.is_dir():
return [{"error": f"root 不是目录: {base}"}]
needle = query if case_sensitive else query.lower()
hits: list[dict[str, Any]] = []
for path in base.rglob("*"):
if len(hits) >= max_results:
break
if not path.is_file():
continue
if path.suffix.lower() not in TEXT_SUFFIXES:
continue
if any(part in SKIP_DIRS for part in path.parts):
continue
try:
text = path.read_text(encoding="utf-8", errors="ignore")
except OSError:
continue
for line_no, line in enumerate(text.splitlines(), start=1):
haystack = line if case_sensitive else line.lower()
if needle in haystack:
hits.append(
{
"path": str(path.relative_to(base)),
"line": line_no,
"text": line.strip()[:300],
}
)
if len(hits) >= max_results:
break
return hits
if __name__ == "__main__":
mcp.run()
这段代码的关键点是只读。read_text 只读文件,rglob 只遍历,SKIP_DIRS 把常见依赖和构建目录排除,TEXT_SUFFIXES 把二进制文件挡在外面,max_results 限制返回规模,relative_to(base) 保证返回路径是仓库内相对路径。工具没有写文件、删文件、执行 shell、发起网络请求的能力。Claude Code 调用它时,只能拿到一个列表,列表里是 path、line、text。如果查询词为空,或者 max_results 越界,工具直接返回错误字典,不会抛异常,也不会让 Claude Code 卡住。
为了让检索有东西可查,在空仓库里加两个测试文件。一个 README.md,一个 src/app.py,故意写几行 TODO:
mkdir -p src
cat > README.md <<'EOF'
# FastMCP repo search demo
TODO: 补充启动命令
TODO: 补充 Claude Code 配置说明
EOF
cat > src/app.py <<'EOF'
def main():
# TODO: 接入只读仓库检索
print("hello fastmcp")
EOF
启动命令是 python server.py。注意 FastMCP 默认走 stdio,运行后不会像 Web 服务那样打印端口,而是安静等待 Claude Code 或其它 MCP 客户端通过标准输入输出通信。手动直接跑 python server.py 时终端没有输出是正常的,按 Ctrl+C 退出即可。真正调用时由 Claude Code 拉起这个进程,你不需要单独开一个终端窗口。也可以用 python -c "import server" 检查导入是否报错,但不要用这种方式调用工具,因为它不会走 MCP 协议。
再检查一下文件结构。应该是 server.py、README.md、src/app.py,可能还有 .venv 和 .git。.venv 和 .git 在 SKIP_DIRS 里,不会被检索。README.md 和 src/app.py 会被检索到,因为后缀在 TEXT_SUFFIXES 里。这组文件很小,适合验证一次调用是否成功。如果你在自己的项目里试验,先把 root 指向一个测试仓库,不要一上来就指向生产机根目录。只读工具虽然不会改文件,但错误路径会拖慢遍历速度,也可能把不该看的文本片段带进对话。
这里有一个容易忽略的细节:path.parts 在绝对路径下包含根目录和各级目录名,判断 SKIP_DIRS 时会把路径中任何一段匹配都跳过。比如 /Users/me/project/node_modules/pkg/index.js 会被跳过。这个策略简单直接,适合速通版。更严格的实现可以做 .gitignore 解析、文件大小上限、单行长度截断、符号链接限制。十分钟版本不需要这些,但边界已经足够清楚:只读、限后缀、限目录、限条数。Claude Code 调用时传 root=".",server 会把当前工作目录解析成绝对路径,再返回相对路径。
3. 把 Claude Code 接到 TaoToken 并加载 repo-search MCP
现在处理 API 通道。先到 TaoToken 官网 创建 Key,模型 ID 以模型广场展示为准。拿到 Key 后,Claude Code 需要三个环境变量:ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL。Base URL 填 https://taotoken.net/api,末尾不要带 /v1,也不要在这个 URL 后面加查询参数。Key 用 YOUR_API_KEY 占位,实际粘贴时换成控制台里创建的那串。
临时环境变量写法如下:
export ANTHROPIC_BASE_URL="https://taotoken.net/api"
export ANTHROPIC_AUTH_TOKEN="YOUR_API_KEY"
export ANTHROPIC_MODEL="YOUR_MODEL_ID"
更稳的方式是写进 ~/.claude/settings.json 的 env,这样每次启动 Claude Code 都会带上。注意 JSON 里不要写注释,字符串要带引号:
{
"env": {
"ANTHROPIC_BASE_URL": "https://taotoken.net/api",
"ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY",
"ANTHROPIC_MODEL": "YOUR_MODEL_ID"
}
}
如果项目里已经有 settings.json,把 env 合并进去,不要覆盖其它字段。改完后重启 Claude Code。ANTHROPIC_AUTH_TOKEN 填 Key 本身,不要在值里手写 Bearer 前缀;Claude Code 会按 Anthropic 兼容方式处理认证头。ANTHROPIC_MODEL 不要编造,也不要拿旧文章里的模型名直接抄,去模型广场看当前可用 ID。不同账号看到的模型列表可能不同,以控制台展示为准。
接着注册 MCP server。项目根目录创建 .mcp.json,让 Claude Code 知道 repo-search 这个 server 怎么启动:
{
"mcpServers": {
"repo-search": {
"command": "python",
"args": ["/absolute/path/to/fastmcp-repo-search/server.py"]
}
}
}
把 /absolute/path/to/fastmcp-repo-search/server.py 换成真实绝对路径。也可以用 Claude Code CLI 添加:
claude mcp add repo-search -- python /absolute/path/to/fastmcp-repo-search/server.py
添加后查看列表:
claude mcp list
你应该能看到 repo-search。如果看不到,先检查 .mcp.json 是否在项目根目录、command 是否是虚拟环境里的 python、路径是否写错。如果虚拟环境没有激活,python 可能指向系统 Python,而系统 Python 没有安装 fastmcp。稳妥做法是 command 写虚拟环境 Python 的绝对路径,例如 /Users/me/fastmcp-repo-search/.venv/bin/python,args 写 server.py 绝对路径。Windows 下则是 .venv\Scripts\python.exe。
启动 Claude Code 时,先在终端确认环境变量或 settings.json 生效。可以临时打印 ANTHROPIC_BASE_URL 检查,但不要打印完整 Key。然后进入仓库目录:
cd /absolute/path/to/fastmcp-repo-search
claude
如果 Claude Code 启动后提示认证失败,先看 ANTHROPIC_BASE_URL 是不是 https://taotoken.net/api,再看 ANTHROPIC_AUTH_TOKEN 是不是从带 UTM 的官网创建的那把 Key。Base URL 如果误写成 https://taotoken.net/api/v1,常见结果是 404 或路径不匹配。模型 ID 如果写成广场里不存在的名字,常见结果是模型不可用。MCP 加载和 API 通道是两条独立链路:API 通道决定 Claude Code 能不能和模型说话,MCP 配置决定模型能不能调用 search_repo。排障时要分开看,不要混在一起改。
这里再强调一次职责分离。FastMCP server 不关心 TaoToken,Claude Code 也不关心 search_repo 内部怎么实现。TaoToken 提供 Key 和 Base URL,Claude Code 通过它访问模型;.mcp.json 提供工具启动方式,Claude Code 通过 stdio 调用 search_repo。两边都配置好之后,业务代码不需要为通道切换做任何改动。你要换模型,只改 ANTHROPIC_MODEL;你要换 MCP 工具,只改 .mcp.json 或 server.py。这种分层让一次评测或一次 Agent 任务更容易复现。
4. 在 Claude Code 里调用一次仓库检索的终端回显
进入 Claude Code 后,直接在对话里提问。为了让模型明确调用 repo-search 的 search_repo,可以把工具名和只读要求写进问题:
请使用 repo-search 的 search_repo 工具,列出仓库里所有包含 TODO 的文件和行号。
只读,不要修改任何文件。返回结果后按文件分组。
一次成功的终端回显类似下面这样。不同版本的 Claude Code 在 UI 细节上可能略有差异,但工具名、参数和返回结构应该一致:
> 请使用 repo-search 的 search_repo 工具,列出仓库里所有包含 TODO 的文件和行号。
只读,不要修改任何文件。返回结果后按文件分组。
⏺ repo-search(search_repo)
⎿ {
"query": "TODO",
"root": ".",
"max_results": 20,
"case_sensitive": false
}
⎿ 4 matches
README.md:3 TODO: 补充启动命令
README.md:4 TODO: 补充 Claude Code 配置说明
src/app.py:2 # TODO: 接入只读仓库检索
⏺ 找到 3 处 TODO,分布在 2 个文件:
README.md
- 第 3 行:TODO: 补充启动命令
- 第 4 行:TODO: 补充 Claude Code 配置说明
src/app.py
- 第 2 行:# TODO: 接入只读仓库检索
没有修改任何文件。
这个输出里最值得看的是工具调用块。Claude Code 没有直接跑 shell,而是调用了 repo-search(search_repo),并把参数以 JSON 形式传给 FastMCP server。server 返回 4 matches 的原始列表,模型再把它整理成按文件分组的自然语言。注意这里显示 4 个匹配,但用户问题里要的是文件和行号,模型最终总结成 3 处 TODO,因为 README.md 里两行加上 src/app.py 一行就是三处。不同版本的 UI 可能把原始匹配数显示成 3 或 4,具体取决于是否把某个内部匹配也算进去,这不影响工具链路是否成立。
验证只读,回到终端执行:
git status --short
如果 server.py、README.md、src/app.py 是你自己刚创建的,它们会显示为未跟踪文件;除此之外不应该出现被修改但未提交的文件。更干净的验证方式是先 git add . && git commit -m "demo",再让 Claude Code 调用一次检索,最后 git status --short 应该没有输出。这说明 search_repo 没有写文件、没有删文件、没有改权限。只读工具的价值就在这里:模型可以读仓库,但不会把仓库改乱。
如果 Claude Code 没有调用工具,而是直接回答“我无法访问文件系统”,通常是因为问题没有明确要求使用 MCP 工具,或者 MCP server 没有加载。先执行 claude mcp list 确认 repo-search 存在,再在问题里点名工具。如果工具被调用了但返回空列表,先确认 query 是不是拼写错误、root 是不是当前目录、目标文件后缀是否在 TEXT_SUFFIXES 里。比如搜索 TODO 能命中 .md 和 .py,搜索某个二进制文件里的字符串则不会命中,因为后缀过滤会跳过。这个设计是有意的,避免把大文件或乱码带进上下文。
再补一个上下文细节。FastMCP server 返回的是结构化列表,Claude Code 会把列表放进 tool result,而不是把整个仓库塞进 prompt。模型只看到匹配行片段,每行最多 300 字符,最多 20 条。对于仓库检索这种任务,这比让模型直接读整个文件更省 token,也更不容易让无关代码干扰判断。如果你要检索大仓库,可以增大 max_results,但不要一上来设 1000。先 20 到 50 条看召回,再用更具体的 query 缩小范围。只读工具的边界没变,变的只是返回规模。
5. 401、模型 ID 与 MCP 不加载:这次复现的排障清单
最常见的问题是 401。表现是 Claude Code 启动后对话直接报未授权,或者模型请求返回认证失败。先检查 ANTHROPIC_AUTH_TOKEN 是否还是 YOUR_API_KEY,再检查 Key 是否从带 UTM 的官网创建、是否复制完整、是否被换行截断。settings.json 里不要写 Bearer YOUR_API_KEY,只写 Key 本身。如果临时环境变量和 settings.json 同时存在,确认实际生效的是哪一个。改完配置要重启 Claude Code,已经在跑的进程不会自动读取新环境变量。
第二个常见问题是 404 或路径错误。检查 ANTHROPIC_BASE_URL 是否严格等于 https://taotoken.net/api。不要写成 https://taotoken.net/api/,不要写成 https://taotoken.net/api/v1,也不要把 UTM 参数加到 Base URL 上。Base URL 是 API 入口,不是网页落地页。网页链接用于创建 Key、看模型广场、看用量,API 请求只认 https://taotoken.net/api。如果返回模型不存在,去模型广场确认 ANTHROPIC_MODEL 的准确 ID,以广场展示为准,不要用记忆里的名字。
第三个问题是 MCP 不加载。claude mcp list 看不到 repo-search 时,先看 .mcp.json 位置。项目作用域配置应放在项目根目录;如果放在子目录,Claude Code 可能不读。再看 command。写 python 依赖 PATH,写虚拟环境绝对路径更稳。args 里的 server.py 路径也建议写绝对路径。改完后用 python /absolute/path/to/server.py 手动启动一次,如果立刻报 ModuleNotFoundError: No module named 'fastmcp',说明这个 Python 不是装过 FastMCP 的那个。切换到虚拟环境 Python 再试。
第四个问题是工具返回空。先确认测试文件真的包含查询词,大小写是否匹配,case_sensitive 是否设成了 true。再确认文件后缀在 TEXT_SUFFIXES 里,目录没有被 SKIP_DIRS 排除。root 如果是 ".",它相对于 Claude Code 启动时的工作目录,不是相对于 server.py 所在目录。你可以在 Claude Code 里明确让工具传 root="/absolute/path/to/repo",或者启动 Claude Code 前 cd 到仓库根目录。不要为了方便把 root 指向整个用户目录,更不要指向生产机根目录。
第五个问题是只读边界被破坏。search_repo 本身只读,但如果你后来加了写文件、执行 shell、发网络请求的工具,那就不再是只读 server。评测和 Agent 场景里,工具越权比模型答错更危险。AI 可以生成或解释命令,但真正执行命令、改数据库、发布服务这些动作要留在本地人工确认。这次练习只保留 search_repo,就是为了让 Claude Code 的调用链路干净:模型决定搜什么,FastMCP 决定能读什么,Claude Code 把结果总结给你。
复现清单可以按下面顺序走:一,空仓库里创建 server.py 和测试文件;二,虚拟环境安装 fastmcp;三,python server.py 能启动且不报错;四,~/.claude/settings.json 或环境变量里配好 ANTHROPIC_BASE_URL=https://taotoken.net/api、ANTHROPIC_AUTH_TOKEN=YOUR_API_KEY、ANTHROPIC_MODEL=YOUR_MODEL_ID;五,项目根 .mcp.json 注册 repo-search;六,claude mcp list 能看到工具,再在 Claude Code 里点名调用 search_repo。这六步里任何一步失败,都先回到对应层排查,不要把 API 通道和 MCP 配置混在一起改。
这次调用跑完,想确认刚才的仓库检索请求是否进入用量统计,打开 模型对话 看一次调用;准备长期在 Claude Code 里挂 MCP,可以看 Coding Plan。Key 在 控制台 创建,Claude Code 三件套对照 接入文档。入口仍是 TaoToken。
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度




被折叠的 条评论
为什么被折叠?



