☰
MCP接入实战:让AI Agent调用百数低代码平台工具
2026/10/13 10:34:48 网站建设 项目流程

如果你所在的团队最近在尝试接入 AI Agent,大概率会遇到这样一个场景:智能体已经能流畅聊天,能写文案、写代码,但当你想让它“查一下上个月的客户订单”“把某个审批流程跳转一下”时,它却什么都做不了。原因很简单——它没有连接你的业务系统。

MCP(Model Context Protocol,模型上下文协议)解决的核心问题,正是“AI 如何按标准方式调用外部工具”。它的价值不在于多一个接口标准,而在于把工具调用、资源访问、提示词这三类能力统一成一个能被模型自动发现的契约。对于百数这类低代码平台来说,接入 MCP 意味着 CRM 表单、业务数据表、流程引擎都能变成智能体可调用的工具,而且不需要从零搭建 Agent 基础设施。

这篇文章会完整走一遍“百数 MCP 开发”的流程:从 MCP 的基础原理、百数平台的接入路径,到用 Python 编写私有工具函数、基于 FastMCP 暴露成 MCP Server,再到在智能体客户端完成挂载、联调、验证与排错。先说明一句:百数平台的开放接口地址、请求头、认证方式和参数结构,请以官方开放 API 文档为准。本文示例采用通用封装模式,核心目标是帮你掌握“API 能力到 MCP 工具”的转化方法论,而不是死记某个具体接口。

读完这篇文章,你能得到一个最小可用的、连接百数数据的 MCP 服务,并且知道它每一步为什么要这么设计。

1. 这篇文章真正要解决的问题

1.1 会聊天的 Agent 离“能干活”还差一层

现在市面上大多数 Agent 产品,本质上还是“对话模型 + 知识检索”。它能回答“订单超时怎么处理”这种制度问题,却无法回答“我们公司现在有多少笔超时订单”,因为它看不到数据;它也不能替你把超时订单的负责人改掉,因为它没有操作系统的能力。

要让 Agent 产生业务价值,必须打通“模型”和“系统”这两层。模型负责理解意图、拆解任务、生成自然语言;系统负责提供真实数据和可执行的操作。MCP 就是这两层之间的标准化管道。你可以把它理解为:给 Agent 装上一套“USB 接口”,让外部工具即插即用。

1.2 MCP 不是又一个接口标准,而是工具契约化

直接调 REST API 不是不行,但有一个关键问题:模型不知道你的 API 长什么样。就算你把接口文档塞进 Prompt,URL、鉴权、参数格式稍有变化,模型就会调用失败。MCP 的思路是让 Server 主动向模型暴露“工具目录”:它有哪些工具、每个工具叫什么、参数是什么、返回什么格式。模型在对话过程中发现工具、生成参数、发起调用,整个过程有一套标准的 JSON-RPC 2.0 消息格式来约束。

所以,MCP 真正改变的,是把“人阅读文档后编码调用”变成“模型按契约自动发现并调用”。这对企业级集成来说意义很大:一次接入 MCP Server,所有支持 MCP 的客户端都能用,不用每个客户端各写一套适配器。

1.3 百数在 MCP 链路里的定位

百数这类低代码平台,核心能力是表单、数据表、流程引擎和权限管理。它解决的是“企业应用如何快速搭建”的问题,但过去这些能力只对浏览器里的业务用户开放。MCP 的角色,是把百数的能力“翻译”给 AI Agent。

在整条链路里,你会看到四个角色:

AI 智能体(客户端) -> MCP Server(工具服务) -> 百数开放 API -> 业务数据表 | ↓ 私有 Python 工具函数(业务逻辑)

这里特别值得强调的是“私有 Python 工具”这一层。它通常用来做四件事:参数校验、数据清洗、字段裁剪、跨接口编排。比如平台接口返回一个嵌套很深的 JSON,模型看了容易迷糊,你就可以在 Python 函数里把它整理成一行简洁的文本再返回。这就是为什么要“编写私有工具”,而不是直接把官方 API 暴露给模型。

1.4 本文适合哪三类读者

第一类:低代码平台的二次开发工程师。你想在表单数据之上加一个 AI 入口,让用户通过对话完成查询和录入。第二类:企业 AI 应用集成工程师。你需要在百数、智能体、内部系统之间搭桥,本文的方法论可以直接复用。第三类:技术负责人。你想判断 MCP 在企业落地的真实工作量,读完大概就知道一个查询工具需要写多少代码、要配什么权限、怎么调试。

2. MCP 基础概念与核心原理

2.1 MCP 是什么,一条链路理解

MCP 是 Anthropic 在 2024 年底开源并推动的开放协议,随后被多家主流 Agent 客户端跟进支持。它定义了一组标准化的消息格式和通信流程,让 AI 应用能与外部工具、数据源、工作流进行能力对接。

你可以把它通俗地理解成“USB-C 协议”。USB-C 统一了物理接口,MCP 统一了 AI 调用工具的逻辑接口。没有 MCP 之前,接入 A 平台是一套代码,接入 B 平台是另一套代码;有了 MCP,只要你的工具服务实现了协议,任何支持协议的客户端都能调用。

2.2 四个核心角色:Host、Client、Server、Tool

  • Host:承载 AI 应用的宿主程序,比如 Claude Desktop、Cursor、Cherry Studio,或者你自己用 Python 写的 Agent 程序。
  • Client:在 Host 内部运行,负责与 MCP Server 建立会话、发送工具发现请求、转发调用请求。
  • Server:提供工具集的服务端进程。它可以是一个独立 Python 进程,也可以是一个 HTTP 服务。
  • Tool:Server 暴露给模型的最小可调用单元,有名称、描述、参数 Schema 和实际执行函数。

一次典型的调用流程是这样:客户端启动后与 Server 完成 initialize 握手;随后客户端请求 tools/list,拿到工具目录;模型在对话中判断需要调用某个工具,生成 JSON 参数;客户端发起 tools/call 请求;Server 执行对应的 Python 函数,把结果返回;模型把结果组织成自然语言回复。整个过程中,模型并不直接执行代码,它只是“决定调用哪个工具”,真正干活的是你的 Python 函数。

2.3 MCP 的传输方式与三类能力

MCP 支持两种主流传输方式。

stdio:Server 作为客户端的一个子进程,通过标准输入输出通信。配置简单,适合本地桌面客户端,也适合开发调试。本文示例主要用这种方式。

Streamable HTTP:Server 拥有一个 HTTP 端点,客户端通过 HTTP 请求访问。适合服务端部署、多客户端共享、远程调用,也是生产环境更推荐的方式。

除了 Tools(工具),MCP 还提供 Resources(资源)和 Prompts(提示模板)。Resources 适合给模型提供只读的数据上下文,Prompts 适合复用复杂指令模板。但对接百数这类业务系统时,最常用到的还是 Tools。

2.4 MCP 与 REST API 的对比

维度传统 REST APIMCP 工具
发现方式需要阅读接口文档,人工编码客户端启动时自动获取 tools/list
调用协议自定义 URL 和 HTTP 方法标准 JSON-RPC 2.0 方法
参数描述写在接口文档或注释里通过 JSON Schema 暴露给模型
适配成本每个客户端编写单独适配层一次接入,多个客户端复用
适用场景后端程序之间的确定性调用Agent 模型自主决策与工具调用

一句话总结:如果你的消费者是“另一个程序员写的后端服务”,REST API 足够;如果你的消费者是“会自己决定怎么调用的 AI 模型”,MCP 更合适。

3. 百数 MCP 接入的三条路径与选型建议

3.1 路径A:直接用官方 API 封装成 MCP 工具

如果百数平台已有开放 API,并且你的工具只是“查一条数据、提交一个表单”,可以直接在 MCP Server 里调用官方接口。优势是开发最快,代码量最小;代价是业务校验逻辑只能跟着官方 API 能力走。如果平台接口返回格式较复杂,模型可能难以稳定解析。

3.2 路径B:在 Python 工具函数中封装业务逻辑(本文重点)

这是更推荐的路径。仍然调用百数 API,但中间多了一层私有 Python 工具函数。这层函数的价值有三个:第一,可以把平台的嵌套 JSON 裁剪成模型友好的摘要文本,减少 Token 消耗;第二,可以做参数校验、数据脱敏、业务状态判断;第三,可以把多个接口调用组合成一个业务工具,比如“查询客户完整画像”背后可能要调三个数据表,但在 Agent 看来只是一个工具。

这层逻辑放在 MCP Server 进程里,意味着你可以在原有低代码平台权限模型之上,再加一层面向 AI 访问的业务规则。

3.3 路径C:直接连数据库

有人觉得,与其绕 API,不如让 MCP Server 直接连百数底层的 MySQL 数据库,这样查询最快、最灵活。这个方案在技术演示中可以跑通,但在企业生产环境风险很高:绕过平台权限模型,无法复用平台的审批流和字段权限;一旦 Agent 被提示词注入或误调用,可能产生非预期的数据变更;平台升级数据库结构时,你的 SQL 也容易失效。

我的建议是:不要用路径 C。除非你的场景完全只读、数据已经离线备份、并且有独立的数据库账号和审计机制。

3.4 选型建议

落地时的判断标准可以很简单:

  • 只是只读查询,且字段不多:路径 A 最快。
  • 需要状态判断、字段脱敏、跨表组合、写操作:路径 B。
  • 高并发、多团队共享:路径 B + Streamable HTTP 私有化部署。
  • 任何情况:避免路径 C。

本文后面的代码,全部采用路径 B 的思路。

4. 环境准备与前置配置

4.1 运行环境

本文示例需要 Python 3.10 及以上版本,推荐 3.11 或 3.12,MCP Python SDK 对较新版本支持更积极。开发机建议使用 macOS、Linux 或 Windows,命令差异我会分别标注。另外,开发机需要能够访问百数开放 API,也就是网络策略要放通对应域名。

项目目录结构如下:

mcp-baishu-demo/ ├── server.py # MCP Server 入口 ├── baishu_client.py # 百数 API 客户端封装 ├── test_tool.py # 本地调用测试脚本 ├── .env # 密钥配置,不要提交到仓库 └── .gitignore

4.2 安装依赖

推荐使用虚拟环境,避免污染系统 Python。用 pip 的方式:

mkdir mcp-baishu-demo && cd mcp-baishu-demo python -m venv .venv source .venv/bin/activate # Windows 系统执行: .venv\Scripts\activate pip install "mcp[cli]" requests python-dotenv

如果你习惯用 uv,流程更简洁:

uv init mcp-baishu-demo cd mcp-baishu-demo uv add "mcp[cli]" requests python-dotenv

解释一下依赖:mcp[cli]是 MCP Python SDK,附带了mcp命令行工具;requests用于调用百数开放 API;python-dotenv用于读取.env中的密钥配置。

4.3 获取百数开放平台凭证

到百数管理后台找到开放平台或开发者中心入口(具体菜单名称以官方文档为准),创建一个自建应用,拿到 AppID 和 API 密钥。一般需要做两件事:

  • 在权限配置里,为这个应用分配“客户订单”等数据表的查询或提交权限。
  • 在测试环境先用一个简单请求确认凭证有效。

把凭证写入.env:

BAISHU_APP_ID=your_app_id BAISHU_API_KEY=your_api_key BAISHU_BASE_URL=https://api.example.com

注意,.env文件不要提交到 Git 仓库,在.gitignore里加一行.env。

4.4 开发调试工具

  • mcp命令自带 MCP Inspector,可以可视化地查看工具列表、手动填写参数调用工具。
  • Claude Desktop、Cherry Studio、Cursor 等支持 MCP 的客户端,用于最终挂载验证。
  • curl 或 Postman,用于单独验证百数 API 是否可通,这能帮你快速判断问题出在协议层还是数据源层。

5. 核心流程拆解

5.1 第一步:锁定业务场景与数据表

不要上来就写代码。先确定一个真实场景。本文以“客服查订单”为例:客服人员希望用自然语言查询客户订单,按订单状态或客户名称筛选,并得到简洁摘要。这个场景只读、数据敏感度适中、验证成本低,非常适合作为第一个 MCP 工具。

确定场景后,要明确工具边界:只查询,不修改;每次最多返回 10 条;只输出订单号、客户、状态、金额四个字段。边界越清晰,模型越不容易误用。

5.2 第二步:梳理工具目录

建议先在文档里建一张工具清单,例如:

工具名描述参数返回
get_orders查询客户订单列表status、customer、limit订单摘要文本
get_order_detail查询订单详情order_no订单详情文本

这一步看似多余,实际上决定了后面的代码结构和 Agent 的使用体验。工具名称用“动词 + 名词”,参数用下划线风格,描述里说清楚“什么时候用、用什么条件查”。

5.3 第三步:封装百数 API 客户端

不要在 MCP 工具函数里直接写 requests 调用,建议先建立一个独立的客户端类。原因有三:凭证统一管理,不用在多个工具函数里重复读环境变量;超时、重试、解码逻辑只写一处;以后百数更换 SDK 或调整签名方式,你只需要改一个文件。

5.4 第四步:编写工具函数并注册到 FastMCP

FastMCP 是 MCP Python SDK 提供的高级封装,它把“定义工具、注册工具、运行服务”变得很简洁。核心用法是:创建一个 FastMCP 实例,然后用@mcp.tool()装饰一个普通 Python 函数,这个函数就自动变成一个 MCP 工具。

这里有一个非常容易踩坑的地方:工具函数的 docstring 第一行,就是模型用来判断“什么时候调用这个工具”的核心描述。写得太模糊,模型会忽略它;写得太长,模型容易抓不住重点。推荐一句话说清用途,再用 Args 段落补充参数含义。

5.5 第五步:本地启动与检查

本地开发时,可以直接python server.py启动服务,看进程有没有报错。要可视化调试,更推荐运行mcp dev server.py,它会在浏览器打开 MCP Inspector 面板,列出所有工具,支持手动填参调用。

特别提醒:MCP 在 stdio 模式下,标准输出是协议通道,不能随便 print。调试输出要写日志文件或 stderr,否则会破坏协议消息,导致客户端无法识别。

5.6 第六步:挂载到智能体客户端

把 MCP Server 挂到桌面客户端,本质上是告诉客户端“你要以什么命令启动这个子进程”。以 Claude Desktop 为例,需要修改它的claude_desktop_config.json,在mcpServers节点下增加服务名、启动命令、启动参数和环境变量。配置完成后重启客户端,在对话界面应该能看到工具生效。

如果你用的是带图形界面的 MCP 客户端,比如 Cherry Studio,则通常在“设置 -> MCP 服务”里选择“stdio”类型,然后填写命令、参数和环境变量,原理完全相同。

5.7 第七步:联调与发布

联调时,用自然语言向 Agent 提问,观察它是否调用工具、参数是否正确、返回结果是否被正确组织。发现模型不调用工具,优先改描述;发现参数传错,优先检查 JSON Schema 和类型注解;发现返回内容太乱,优先改工具函数的输出格式。

发布到生产环境时,建议从 stdio 迁移到 Streamable HTTP 部署,并配置访问令牌。这样多个智能体客户端可以共享同一个 MCP 服务,也可以做服务端限流和审计。

6. 完整示例与代码实现

6.1 示例需求

我们实现一个查询类 MCP 工具:get_orders,查询百数中的“客户订单”数据表,支持按状态和客户名称筛选,最多返回 10 条订单摘要。

为了让代码可运行且不依赖具体的百数接口文档,我定义如下占位 API 约定(关键点在于演示通用封装思路,读者务必替换为真实接口):

  • 接口:GET/v1/form/orders/list
  • 请求头:X-App-Id、X-Api-Key
  • 返回体:{"code": 0, "data": {"records": [{"order_no": "...", "customer_name": "...", "order_status": "...", "total_amount": 100.0}]}}

你只需要把这四行约定替换成千百数的真实参数。下面开始写代码。

6.2 baishu_client.py:百数 API 客户端封装

# 文件路径:baishu_client.py import os import requests class BaishuClient: """百数开放接口的轻量封装。 注意:URL、请求头和参数名请以百数官方开放 API 文档为准, 这里用占位值演示通用封装方法。 """ def __init__(self, app_id: str | None = None, api_key: str | None = None, base_url: str | None = None): self.app_id = app_id or os.getenv("BAISHU_APP_ID") self.api_key = api_key or os.getenv("BAISHU_API_KEY") self.base_url = base_url or os.getenv("BAISHU_BASE_URL", "https://api.example.com") def _request(self, method: str, path: str, params: dict | None = None, json_body: dict | None = None) -> dict: headers = { "X-App-Id": self.app_id, "X-Api-Key": self.api_key, "Content-Type": "application/json", } url = f"{self.base_url}{path}" resp = requests.request(method, url, headers=headers, params=params, json=json_body, timeout=10) resp.raise_for_status() return resp.json() def list_orders(self, status: str | None = None, customer: str | None = None) -> list[dict]: """查询订单列表,返回原始记录列表。""" params = {} if status: params["filter[order_status]"] = status if customer: params["filter[customer_name]"] = customer data = self._request("GET", "/v1/form/orders/list", params=params) # 以下解析逻辑对应示例返回结构,请按官方实际返回调整 return data.get("data", {}).get("records", [])

这段代码的核心是_request方法,所有对百数 API 的请求都走这一个方法。工具函数里不关心 HTTP 细节,只调用list_orders。如果你以后要接入多个数据表,只需要在BaishuClient里继续增加类似方法。

6.3 server.py:MCP Server 定义与工具注册

# 文件路径:server.py import os from dotenv import load_dotenv from mcp.server.fastmcp import FastMCP from baishu_client import BaishuClient load_dotenv() mcp = FastMCP("baishu-orders") client = BaishuClient() @mcp.tool() def get_orders(status: str | None = None, customer: str | None = None, limit: int = 10) -> str: """查询客户订单列表,返回订单号、客户、状态和金额摘要。 Args: status: 订单状态筛选,例如 pending、completed、cancelled。 customer: 客户名称关键字筛选。 limit: 最多返回的订单条数,默认 10,最大 50。 """ if limit > 50: limit = 50 try: records = client.list_orders(status=status, customer=customer) except Exception as exc: return f"查询订单失败:{exc}" if not records: return "未找到符合条件的订单。" lines = [] for idx, record in enumerate(records[:limit], start=1): lines.append( f"{idx}. 订单号:{record.get('order_no', '-')} " f"客户:{record.get('customer_name', '-')} " f"状态:{record.get('order_status', '-')} " f"金额:{record.get('total_amount', '-')}" ) return "\n".join(lines) if __name__ == "__main__": mcp.run()

这里有几个细节值得说明。

第一,@mcp.tool()装饰器会把函数的名称、参数类型、默认值和 docstring 转换成 MCP 的 JSON Schema。所以status: str | None = None这种类型注解不是可有可无,它直接影响模型能否正确生成参数。

第二,工具函数返回str,而不是直接返回list[dict]。这样模型拿到的是已经整理好的摘要文本,回答时可以直接引用,减少一次“把嵌套 JSON 转成自然语言”的中间步骤。

第三,try/except把底层异常转换成可读字符串返回,而不是抛给 MCP 调用链。这样客户端界面至少能显示“查询订单失败:xxx”,而不是显示一个笼统的“工具调用失败”。

6.4 test_tool.py:本地调用测试脚本

# 文件路径:test_tool.py import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): server_params = StdioServerParameters( command="python", args=["server.py"], env={ "BAISHU_APP_ID": "your_app_id", "BAISHU_API_KEY": "your_api_key", "BAISHU_BASE_URL": "https://api.example.com", }, ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() result = await session.call_tool( "get_orders", {"status": "pending", "limit": 3}, ) for content in result.content: print(content.text) asyncio.run(main())

这个脚本模拟了一个 MCP 客户端:通过 stdio 拉起server.py,建立会话,调用get_orders工具并打印返回结果。它不依赖任何桌面客户端,适合在 CI 或命令行环境做回归测试。

6.5 智能体客户端挂载配置

Claude Desktop 的配置示例:

{ "mcpServers": { "baishu-orders": { "command": "python", "args": [ "/absolute/path/to/server.py" ], "env": { "BAISHU_APP_ID": "your_app_id", "BAISHU_API_KEY": "your_api_key", "BAISHU_BASE_URL": "https://api.example.com" } } } }

这里最容易出错的是command。如果你使用了虚拟环境,python可能不是你系统 PATH 里的那个,建议写成虚拟环境中的绝对路径,例如"/path/to/.venv/bin/python",Windows 下对应.venv\Scripts\python.exe。args必须写server.py的绝对路径,否则客户端从不同工作目录启动时可能找不到文件。

如果 MCP Server 以 HTTP 方式部署,客户端配置更简单,只需要填服务地址和一个访问令牌,例如把工具类型选为“Streamable HTTP”,URL 填https://your-domain.com/mcp/baishu-orders。

7. 运行结果与效果验证

7.1 用测试脚本验证工具层

在配置好.env后,运行:

python test_tool.py

预期输出类似:

1. 订单号:SO-2024001 客户:张三 状态:pending 金额:2380.00 2. 订单号:SO-2024005 客户:李四 状态:pending 金额:560.50

如果输出“未找到符合条件的订单”,说明服务链路是通的,只是筛选条件没有匹配数据。如果输出异常信息,则优先检查百数 API 凭证和网络连通性。

这个脚本先用起来,能帮你把“MCP 协议层问题”和“百数 API 问题”快速分开。协议层有问题,脚本跑不通;API 凭证或参数有问题,脚本能跑通但返回特定错误。

7.2 用 MCP Inspector 验证参数边界

运行:

mcp dev server.py

MCP Inspector 会在浏览器打开一个调试界面。你可以在 Tools 列表里看到get_orders,手动填入status=pending、limit=3,点击调用,查看返回内容。这里主要验证两件事:JSON Schema 是否正确生成;不同参数组合下工具函数是否稳定。

建议测试几个异常参数,比如limit=999、customer传一个不存在的名称、status传空字符串。工具函数应该给出合理的返回,而不是抛出未处理异常。

7.3 在桌面客户端做端到端验证

把 MCP Server 挂载到 Claude Desktop 或 Cherry Studio 后,用自然语言提问:“帮我查一下状态为 pending 的客户订单。”一个成功的表现是:Agent 明确说“我将调用 get_orders 工具”,然后返回订单列表,最后用自然语言总结。

如果模型没有调用工具,优先检查工具描述。如果模型调用了但参数传错,检查类型注解和默认值。如果工具调用成功但回答内容与返回不一致,检查返回文本是否过长、字段是否清晰。这一步做通,说明整条“智能体 -> MCP Server -> 百数 API -> 数据表”链路已经完整可用。

8. 常见问题与排查思路

8.1 高频问题对照表

问题现象可能原因排查方式解决方案
客户端找不到 baishu-orders 工具MCP 配置路径错误或服务启动失败查看客户端日志;手动运行启动命令检查绝对路径、Python 命令和依赖是否齐全
调用工具提示 401 / 403API 密钥错误或没有数据表权限用 curl 单独请求百数 API重新生成密钥;在开放平台分配数据表权限
返回中文乱码编码不一致在终端运行 test_tool.py 确认字符串统一使用 UTF-8;避免手动 encode/decode
工具调用超时百数 API 响应慢或网络不通用 curl 测试接口响应时间增大 timeout;精简查询条件;改用异步 HTTP
模型传入参数不符合预期JSON Schema 与模型理解不一致在 Inspector 中查看工具 Schema优化 docstring 和参数描述;收紧类型注解
stdio 模式下客户端无输出在 Server 代码里使用了 print检查 stdout 是否被业务日志污染日志写文件或 stderr,stdout 只走 MCP 协议
客户端重启后工具消失服务进程未重新拉起查看客户端进程列表确认 command 和 args 正确;不要使用相对路径
返回结果被模型转述失真返回文本过长或结构不清晰检查工具返回内容长度精简字段;返回结构化 JSON 或更短摘要

8.2 一套可复用的排查路径

如果工具调不通,不要东改一下西改一下,按下面的顺序排查:

  1. 先运行python server.py,确认进程能正常启动,依赖没有缺失。
  2. 再用 curl 直接请求百数 API,确认凭证、URL、参数是否正确。
  3. 然后运行python test_tool.py,排除 MCP 协议问题。
  4. 接着用mcp dev server.py调参,定位是 Schema 问题还是业务逻辑问题。
  5. 最后检查客户端配置,重点看路径和环境变量。

排查命令参考:

# 单独验证百数 API,确认凭证有效 curl -H "X-App-Id: your_app_id" -H "X-Api-Key: your_api_key" \ "https://api.example.com/v1/form/orders/list" # 直接启动 MCP Server,观察 stderr 日志 python server.py

每改一个因素,单独验证一次。不要同时改多个变量,这是避免越排越乱的关键。

9. 最佳实践与工程建议

9.1 工具即接口:描述要为模型服务

MCP 工具的函数名、参数名和 docstring,是模型理解工具的唯一线索。命名上使用“动词 + 宾语”,例如get_orders、create_order;描述上第一句话写清功能,第二段开始写参数细节。要学会站在模型的角度审视:如果它只看到这个工具的 Schema,能不能准确决定何时调用、传什么参数?

9.2 返回结果结构化,控制 Token 消耗

模型每读一次工具返回,都要消耗上下文窗口。工具返回的内容越长,模型越容易丢失重点。建议在工具函数里就完成字段裁剪,一个查询工具只返回用户真正关心的 3 到 5 个字段。如果数据量大,宁可只返回前 10 条,也不要让模型去截断自己看不懂的完整 JSON。

9.3 权限最小化与数据安全

这是企业落地 MCP 最重要的一条原则。MCP Server 暴露的是真实业务数据和操作能力,必须做到三点:第一,给应用分配最小数据集权限,不要为了省事把整张表开放;第二,在工具函数层再做一层参数白名单校验,比如limit设置上限、status只允许固定枚举值;第三,涉及手机号、身份证等敏感字段时,在工具层直接脱敏或禁止返回。

API 密钥要放在服务端环境变量中。stdio 模式把密钥写在客户端配置里,只适合个人开发调试;生产环境应该走 Streamable HTTP,由服务端统一持有凭证。

9.4 日志、监控与审计

建议在工具函数入口记录调用参数、调用耗时和调用结果。生产环境使用logging模块写入独立日志文件,不要往标准输出里打印内容。如果工具涉及写操作,必须记录“谁调用的工具、传了什么参数、改了什么数据”,这个审计信息在排查误操作时是唯一的证据。

9.5 版本兼容与依赖锁定

MCP SDK 迭代速度比较快,建议在requirements.txt或 pyproject 中锁定mcp包版本,避免升级后接口行为变化。不同桌面客户端对 MCP 协议版本的支持也有差异,交付前最好在目标客户端上做一遍完整回归。

9.6 生产部署:从 stdio 到 Streamable HTTP

stdio 模式适合本地开发,但生产环境建议迁移到 Streamable HTTP。这样多个智能体可以共享同一个 MCP 工具集,可以在网关层做认证、限流和审计,也方便容器化部署。迁移时需要注意:HTTP 模式下要配置访问令牌,工具函数逻辑不需要改动。

9.7 后续学习方向

本文只讲了 Tools 这一种能力,MCP 还有 Resources 和 Prompts。你可以继续探索:如何把百数数据表的元数据作为 Resource 暴露给模型,让 Agent 理解表结构;如何用 Prompt 模板把企业话术封装起来;如何把多个只读工具扩展成可写工具并加上审批流。实践建议是,先让一个只读查询工具跑通,再用同样的套路逐步扩大工具面。这比一次性设计十个工具更稳妥,也更容易沉淀出团队自己的 MCP 接入规范。建议先收藏备用,真正动手时再回这篇文章对照流程和排查清单。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询