【小智AI】本地化知识库:MCP服务链路,让云端AI安全读取极空间本地txt

周店瑟谷 5 阅读 AI 工具与智能体

‌​​​​‍​‌‌​​​‍​​⁠‌⁠​​​​⁠‌‬​‬​‬​‬​​‬​​​​⁠‍‬​​‌小智AI配置MCP接入点使用说明(官方) - 飞书云文档
https://my.feishu.cn/wiki/HiPEwZ37XiitnwktX13cEM5KnSb?from=from_copylink

这三个文件共同构成了一个完整的 MCP(Model Context Protocol)服务链路,核心目的是让云端的小智 AI 能够跨越网络,安全地读取你极空间本地的 txt 文本资料。


它们的协同工作流程如下:

  • knowledge_server.py:knowledge_server.py(核心工具库)


    • 功能:这是整个服务的“大脑”或“执行者”。

    • 解析:它基于 FastMCP 框架编写,向外暴露了一个名为 search_local_knowledge 的工具。当小智判断需要查阅你的私人资料时,就会调用这个工具。该脚本会遍历读取容器内 /data 目录下的所有 .txt 文件,并将内容打包成提示词返回给小智。它默认通过最基础的标准输入/输出(stdio)来接收和发送数据。

  • mcp_pipe.py :mcp_pipe.py(网络通信桥梁)


    • 功能:这是一个“翻译官”兼“快递员”。

    • 解析:因为 knowledge_server.py 只能进行本地的基础通信(stdio),而小智是通过网络(WebSocket,即你在后台填写的 wss:// 地址)与极空间连接的,两者语言不通。mcp_pipe.py 的作用就是读取你配置的 MCP_ENDPOINT 环境变量,主动连接到小智的服务器。它负责把小智从网络发来的指令提取出来喂给 knowledge_server.py,再把查到的文本结果通过网络发回给小智。

  • start.sh:start.sh(环境配置与启动器)


    • 功能:Docker 容器的启动引导程序。

    • 解析:由于极空间提供的纯净 Python 镜像里没有自带 FastMCP 和 WebSocket 等工具,这个脚本会在每次容器启动的第一时间,执行 pip install 自动下载并安装这些必需的依赖包。安装完毕后,它将 mcp_pipe.py 和 knowledge_server.py 组合运行起来,正式启动整个服务链路。


镜像为python:3.10-slim


docker.m.daocloud.io/library/python:3.10-slim


MCP Server 与普通接口的核心差异

1. 设计目标与调用方不同 - MCP Server:面向 LLM / AI Agent 设计,调用方是模型本身。模型根据自然语言理解,自主决定"调用哪个工具、传什么参数"。 - 普通接口(REST / RPC 等):面向开发者和应用程序设计,调用方是预先写好的代码,调用逻辑由人在编码时硬编码确定。

2. 能力发现机制不同 - MCP Server:运行时动态自描述。客户端连接后可主动列出可用工具(tools)、每个工具的 JSON Schema 参数定义、可访问资源(resources)和提示词模板(prompts),模型无需预先阅读文档即可感知能力。 - 普通接口:依赖离线 API 文档(如 OpenAPI),开发者在编码前阅读并写死端点、参数和返回结构;运行时不具备动态发现能力。

3. 协议抽象层级不同 - MCP:是一个**元协议 / 接入规范**,定义了 tools、resources、prompts 三类标准化抽象,运行在传输层之上,支持 stdio、HTTP+SSE、Streamable HTTP 等多种传输方式。 - 普通接口:通常就是具体的端点设计,直接定义请求 / 响应格式,没有统一的"工具 / 资源 / 提示词"抽象层。

4. 数据返回后的用途不同 - MCP:返回结果作为**上下文**直接注入模型对话,供模型继续推理、组合多步调用或生成最终回答;强调"数据进模型"。 - 普通接口:返回数据由应用程序自行解析、渲染或存储,强调"数据进程序"。

5. 通信模式不同 - MCP:偏向长连接、双向通信,支持资源订阅(notifications)、进度推送、服务器主动发消息。 - 普通接口:典型的请求—响应(request-response)模式,客户端主动发起、服务器被动应答。

6. 生态与可移植性不同 - MCP:一次接入、多端可用。任何支持 MCP 协议的客户端(Claude Desktop、Cursor、各类 Agent 框架)都能直接使用同一个 MCP Server,无需为每个平台单独适配。 - 普通接口:每个调用方都需要单独编写对接代码,接口变更需要同步修改所有调用端。 ---

一句话总结:普通接口是"给程序调用的功能端点",MCP Server 是"给 AI 模型动态发现并自主调用的标准化能力接入层"——核心差异在于调用方是代码还是模型、能力是写死还是动态发现、结果是进程序还是进上下文。


MCP 的能力发现机制是基于 JSON-RPC 2.0 协议的“请求-响应”模型。当大模型客户端(如小智、Claude Desktop)与你的服务器建立连接后,客户端会主动发送 tools/list、resources/list 和 prompts/list 这三个标准化请求,服务器则通过返回严格定义的 JSON 数据结构,向客户端“暴露”自己的能力边界。


核心能力发现协议与标准 JSON 结构

服务器响应大模型客户端请求时,必须遵循以下标准化的 JSON 结构(通常由底层的 SDK 自动生成并封包)。


1. Tools(工具):用于执行动作和计算

工具必须包含明确的名称、描述,以及基于 JSON Schema 定义的输入参数格式。大模型只有精确理解了 inputSchema,才能正确构造函数调用的参数。


JSON

{
  "tools": [
    {
      "name": "query_inventory",
      "description": "查询指定药品的当前库存数量和存放位置。",
      "inputSchema": {
        "type": "object",
        "properties": {
          "medicine_name": {
            "type": "string",
            "description": "药品的标准名称,例如:布洛芬"
          }
        },
        "required": ["medicine_name"]
      }
    }
  ]
}

2. Resources(资源):用于读取被动数据

资源通常代表特定的文件、数据库记录或系统状态。它通过类似 URL 的 uri 协议来标识,必须包含 MIME 类型以便大模型知道如何解析(如 text/plain 或 application/json)。


JSON

{
  "resources": [
    {
      "uri": "file:///data/family_medical_history.txt",
      "name": "家庭过敏史与病史记录",
      "description": "包含家庭成员的过敏药物清单和既往病史,开药前必须读取。",
      "mimeType": "text/plain"
    }
  ]
}

3. Prompts(提示词模板):用于标准化任务流程

提示词模板允许服务器向客户端提供预设的交互流程,客户端可以通过传入特定的参数(arguments)来实例化这个模板,通常用于固定的业务场景(如代码审查、病情预检)。


JSON

{
  "prompts": [
    {
      "name": "medical_triage_prompt",
      "description": "用于初步分析用户症状的医疗分诊提示词模板",
      "arguments": [
        {
          "name": "symptoms",
          "description": "用户描述的具体症状",
          "required": true
        }
      ]
    }
  ]
}

FastMCP 框架下的完整实现示例

在你的极空间项目中,你使用的是 FastMCP 库。这个库会自动将 Python 函数转换为上述的标准化 JSON 协议报文。以下是一个同时包含 Tools、Resources 和 Prompts 的完整服务端编写规范:


Python

from fastmcp import FastMCP
import json

# 初始化服务
mcp = FastMCP("Zspace_Complete_Server")

# ==========================================
# 1. Tool (工具): 允许大模型主动传入参数并执行计算
# ==========================================
@mcp.tool()
def calculate_dosage(weight_kg: float, age: int) -> str:
    """
    根据患者体重和年龄计算基础退烧药的安全剂量。
    大模型在被问到用药量时会主动调用此工具。
    """
    if age < 12:
        dosage = weight_kg * 10  # 假设儿童每公斤10mg
        return f"建议剂量为 {dosage}mg,请每6小时服用一次。"
    return "成人常规剂量为一次400mg,请勿超量。"

# ==========================================
# 2. Resource (资源): 暴露特定 URI 的静态/动态数据
# ==========================================
# 大模型可以通过 `resources/read` 请求 "config://pharmacy/inventory" 获取内容
@mcp.resource("config://pharmacy/inventory")
def get_inventory_status() -> str:
    """获取当前家庭药箱的实时库存盘点数据"""
    inventory_data = {
        "布洛芬": 2,
        "阿莫西林": 0,
        "创可贴": 15
    }
    return json.dumps(inventory_data, ensure_ascii=False)

# ==========================================
# 3. Prompt (提示词): 提供可传参的系统级指令模板
# ==========================================
@mcp.prompt()
def triage_assistant(symptom_description: str) -> str:
    """
    智能分诊提示词模板。
    客户端可以通过填入 symptom_description,直接生成结构化的对话指令。
    """
    return (
        f"你现在是一位专业的家庭医生助手。请分析以下症状:\n"
        f"【{symptom_description}】\n\n"
        f"请按以下结构输出:\n"
        f"1. 可能的原因\n"
        f"2. 需要调用的本地资源(如家庭过敏史)\n"
        f"3. 建议采取的初步缓解措施"
    )

if __name__ == "__main__":
    # 使用 stdio 通信,mcp_pipe 会自动处理 JSON-RPC 的封装与暴露
    mcp.run(transport='stdio')

通过这种声明式的方法,当你的 mcp_pipe.py 将服务桥接到小智时,FastMCP 会在握手阶段自动提取 Python 函数名、类型注解(float, int, str)以及 Docstring(文档字符串),严格组装成前面的 JSON 报文格式发送给大模型,完成“能力发现”。


如果在你的实际业务场景中,需要让小智不仅能“搜索”(Tool),还能直接“阅读”某几个固定的配置文件(Resource),你会更倾向于使用哪种方式来暴露你的家庭数据?