随着大模型和各类 AI 应用的普及,越来越多用户遇到产品使用问题时,第一反应已经从“去官网查手册”变成了“向 AI 提问”。
然而,通用 AI 的训练数据往往缺乏你家产品最新、最准确的操作指南或使用规则。无论你是 SaaS 厂商、智能硬件企业,还是任何对外提供产品文档的团队,如何让你的客户在使用 AI 时直接精准读取你提供的官方文档呢?
今天我们就来聊一个简单的方案:基于 MCP(Model Context Protocol) 协议、用 FastMCP 框架,几十行代码搭一个带鉴权的 Markdown 知识库 MCP Server。
1. FastMCP 是什么?
如果说 MCP 是 AI 与外部数据源之间的通用语言,那 FastMCP 就是让你用几行 Python 就能“开口说”这门语言的工具包。
MCP 是 Anthropic 在 2024 年提出的标准化协议,用于在 AI 模型和外部数据源(或工具)之间建立安全连接。
而 FastMCP 让你不必直接处理 MCP 规范里的底层通信和 JSON Schema 描述:你只需要写普通的 Python 函数,加一个 @mcp.tool() 装饰器,它就会把这个函数自动包装成任意 MCP 客户端都能直接调用的标准接口。
如果你想先把 MCP 和它周围的 Agent、SKILL、RAG 这几个概念一次理清楚,可以先读这篇:《上菜啦!大龙虾、SKILL、Agent、MCP、RAG…》。
2. 适用场景
基于 FastMCP 的极简特性,它非常适合产品和服务提供商打造“智能文档引擎”:
- 📚 产品官方知识引擎(本文实践):让客户的 AI 工具直接搜索、读取你家产品的最新 Markdown 使用手册,降低 AI 在回答 API 对接、设备联网等具体问题时产生幻觉的概率。
- 🛠 内部研发知识库:把内部架构设计、运维规范、Code Review 清单暴露给团队成员 IDE 里的 Copilot/Cursor,避免新人到处问、老人重复回答。
- 🔐 分级/私域数据访问:通过轻量级鉴权对不同客户开放不同范围的文档,例如对合作伙伴开放高级集成指南,对普通用户只暴露公开 FAQ。
3. 官方文档服务极简架构设计
为了让提供商维护文档最简单,同时对外部调用有一定的权限隔离和控制,我们设计了如下极简架构:
核心思路:
- 文档维护:纯 Markdown 文件管理,产品经理或技术写作者通过 Git 仓库更新产品手册,无需搭建复杂的数据库。之所以选 Markdown,是因为它对 AI 最友好——这一点在 《Markdown - AI 时代的万能转换器》 里展开讲过。
- 服务提供:FastMCP 启动 HTTP 服务,对外暴露三个核心 Tool(目录浏览、全文搜索、原文读取)。
- 客户端鉴权:通过 FastMCP 中间件(Middleware)校验客户或合作方专属的 API Key,确保接口资源不被滥用。
架构图
graph LR
subgraph "用户侧 AI 客户端"
A[VS Code Copilot / Cursor]
B[ChatGPT / Claude Desktop]
C[第三方聚合平台内置 Agent]
end
subgraph "提供商侧 FastMCP Server"
MW[中间件层<br/>身份鉴权与限流]
T1[list_docs<br/>目录浏览]
T2[search_docs<br/>文档检索]
T3[get_doc<br/>读取长文]
end
subgraph "存储层"
GIT[Git 仓库<br/>产品 Markdown 知识库]
end
A & B & C -- 携带 API Key 请求 --> MW
MW --> T1 & T2 & T3
T1 & T2 & T3 --> GIT
核心代码一览
下面是一个能跑起来的最小骨架,演示如何用 FastMCP 同时实现三个核心 Tool + 一个最简的 API Key 鉴权中间件:
from fastmcp import FastMCP
from fastmcp.server.middleware import Middleware, MiddlewareContext
from mcp.types import ToolAnnotations
VALID_KEYS = {"customer-key-001", "partner-key-002"}
class CustomerApiAuthMiddleware(Middleware):
"""校验请求头中的 X-API-Key,校验失败直接抛出异常拒绝调用。"""
async def on_request(self, context: MiddlewareContext, call_next):
headers = context.fastmcp_context.get_http_request().headers
if headers.get("x-api-key") not in VALID_KEYS:
raise PermissionError("invalid or missing X-API-Key")
return await call_next(context)
# mask_error_details 防止把服务端的绝对路径等敏感错误泄露给外部调用者
mcp = FastMCP(name="VendorOfficialDocs", mask_error_details=True)
mcp.add_middleware(CustomerApiAuthMiddleware())
@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
def list_docs(category: str | None = None) -> list[str]:
"""列出指定分类下的所有文档路径,不传则返回全部。"""
...
@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
def search_docs(query: str, category: str | None = None) -> list[dict]:
"""全文搜索官方手册,返回匹配的文件名和上下文片段。"""
# 文档量小可直接遍历 Markdown 文件做关键词匹配;
# 文档量大可换成 ripgrep、SQLite FTS5 或本地向量库。
...
@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
def get_doc(path: str) -> str:
"""按路径返回完整 Markdown 原文,供 AI 引用上下文。"""
...
if __name__ == "__main__":
mcp.run(transport="http", host="0.0.0.0", port=8000)
只要参数加上了类型注解(如 query: str),FastMCP 就会自动生成任意 MCP 客户端都能读懂的调用说明(JSON Schema)。
关于检索实现:文档量不大时,直接在
search_docs里遍历 Markdown 文件做关键词匹配就够用;文档多到上千篇再考虑接 ripgrep 子进程、SQLite FTS5 或本地向量库。
4. 你的用户如何接入这套服务?
一旦你的服务部署上线(例如提供在 https://docs-mcp.your-product.com/mcp),并为企业或个人用户发放了专属 API Key,他们只需要在日常使用的 AI 工具里加几行配置即可。
开发者用户:在 Cursor / Claude Code 中对接
开发者客户如果正在对接你的 API 服务,只需要在编辑器的 MCP 配置中添加你的远程服务(Cursor、Claude Code 格式如下):
{
"mcpServers": {
"YourProduct 官方知识库": {
"url": "https://docs-mcp.your-product.com/mcp",
"headers": {
"X-API-Key": "提供商发放的密钥"
}
}
}
}
VS Code 的 .vscode/mcp.json 字段名略有不同(顶层 key 是 servers,且需要显式声明 "type": "http"),具体以官方文档为准。配置完成后,客户写代码时如果忘了参数名,IDE 中的 AI 会自动调用这台服务器抓取最新对接指南。
普通终端用户:在 Claude Desktop 中对接
Claude Desktop 目前还不支持直接配置远程 HTTP MCP,需要借助 mcp-remote 这类桥接器把远程服务包装成本地 STDIO Server,再写入本地配置文件。配置完成后,当用户在 Claude 中询问“怎么设置这款智能设备的夜间模式”时,大模型就能直接阅读你提供的手册文件。
合作方用于自己的 AI 工作流
如果合作方希望把你的产品规范、服务指南整合进他们自己的自动化客服系统(如通过 LangChain 等框架调用):
import asyncio
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport
async def main():
transport = StreamableHttpTransport(
'https://docs-mcp.your-product.com/mcp',
headers={'X-API-Key': '提供商发放的密钥'}
)
async with Client(transport) as client:
# 合作方的 Agent 遇到无法解答的问题自动向你查询
result = await client.call_tool('search_docs', {'query': '退换货具体政策'})
print(result)
asyncio.run(main())
5. 总结
在 AI 时代,文档的目标读者正在从“人”悄悄变成“人 + 模型”。以前我们关心的是文档库的搜索结果准不准、页面好不好看;现在还要关心 “用户的 AI 能不能在一次对话里,准确理解并回答关于你产品的问题”。
通过 FastMCP,我们可以用很少的代码把原本写给人看的 Markdown 文档库,包装成面向大模型的 MCP 服务。再配合 API Key 鉴权和 Git 版本管理,文档作者只需照常 git push,下一次 AI 调用工具时就能读到最新内容。