从业务接口到 MCP Tool:多语言工程化实践指南(Python / TypeScript / Java)

在企业级 AI 落地中,一个关键问题是:如何让大模型安全、稳定地调用业务能力

实践中,通常的做法是:

将业务接口封装为 MCP Server 的 Tool,由 MCP 层统一承担安全控制与协议适配。

相比直接暴露 API,这种方式具备更好的可控性、可观测性与模型适配能力


一、设计思路:从"接口"到"能力"

在编码之前,需要完成一次抽象转换:

text 复制代码
HTTP API → 业务能力 → MCP Tool

1. API 到 Tool 的映射

原始接口:

http 复制代码
POST /api/order/query
{
  "orderId": "123"
}

不建议简单映射为:

text 复制代码
call_api(orderId)

而应转换为:

text 复制代码
query_order(orderId)

👉 核心区别:

  • API:面向"系统调用"
  • Tool:面向"模型理解与决策"

2. Tool 三要素(设计核心)

text 复制代码
name         工具名(动词 + 业务语义)
description  工具用途描述(供模型决策)
input schema 输入参数结构(JSON Schema)

这三者会被 MCP Server 转换为标准元数据,供模型选择和调用。


3. MCP Server 的职责边界

MCP Server 不只是"转发层",而是能力治理层

text 复制代码
参数校验(防止模型误用)
鉴权(用户 / token / 租户)
限流(防止滥用)
日志审计(AI调用可追踪)
异常转换(结构化错误)
字段过滤(敏感信息脱敏)

二、Python 实现(快速原型)

适合场景:AI 原型、工具服务、轻量网关

python 复制代码
from mcp.server.fastmcp import FastMCP
import httpx

mcp = FastMCP("order-mcp-server")

@mcp.tool()
async def query_order(order_id: str) -> dict:
    """根据订单 ID 查询订单"""

    async with httpx.AsyncClient(timeout=5) as client:
        resp = await client.post(
            "https://api.example.com/order/query",
            json={"orderId": order_id},
            headers={"Authorization": "Bearer TOKEN"}
        )
        resp.raise_for_status()

    data = resp.json()

    return {
        "order_id": data["orderId"],
        "status": data["status"],
        "amount": data["amount"]
    }

if __name__ == "__main__":
    mcp.run()

实现要点

  • @mcp.tool() 自动注册 Tool
  • 函数签名 → 输入 schema
  • docstring → description
  • 返回 dict → Tool 输出

三、TypeScript 实现(生产推荐)

适合场景:Node.js 网关、BFF、中台服务

ts 复制代码
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

const server = new McpServer({
  name: "order-mcp-server",
  version: "1.0.0",
});

server.tool(
  "query_order",
  "根据订单 ID 查询订单",
  {
    orderId: z.string().describe("订单唯一标识"),
  },
  async ({ orderId }) => {

    const resp = await fetch("https://api.example.com/order/query", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer TOKEN",
      },
      body: JSON.stringify({ orderId }),
    });

    if (!resp.ok) {
      throw new Error(`接口调用失败: ${resp.status}`);
    }

    const data = await resp.json();

    return {
      content: [
        {
          type: "text",
          text: JSON.stringify({
            orderId: data.orderId,
            status: data.status,
            amount: data.amount,
          }),
        },
      ],
    };
  }
);

server.start();

实现要点

  • 使用 zod 定义 schema(强类型 + 描述)
  • Tool 元数据显式声明
  • 输出结构统一为 content[]
  • 易于扩展鉴权、限流、链路追踪

四、Java 实现(企业级接入)

适合场景:已有微服务体系、Spring Boot 项目

基于 Spring AI:


1. 依赖

xml 复制代码
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

2. 业务层(保持不变)

java 复制代码
@Service
public class OrderService {

    public OrderDTO queryOrder(String orderId) {
        return new OrderDTO(orderId, "PAID", 199.0);
    }
}

3. MCP Tool 封装

java 复制代码
@Component
public class OrderMcpTools {

    private final OrderService orderService;

    public OrderMcpTools(OrderService orderService) {
        this.orderService = orderService;
    }

    @Tool(description = "根据订单 ID 查询订单")
    public OrderDTO queryOrder(String orderId) {
        return orderService.queryOrder(orderId);
    }
}

4. 注册工具

java 复制代码
@Configuration
public class McpConfig {

    @Bean
    public ToolCallbackProvider tools(OrderMcpTools t) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(t)
                .build();
    }
}

实现要点

text 复制代码
@Tool → Tool 描述
方法签名 → 输入 schema
Service → 业务逻辑复用
DTO → 输出结构

五、推荐架构(关键实践)

text 复制代码
MCP Tool
   ↓
Service(业务逻辑)
   ↓
Repository / RPC / HTTP

为什么不要这样?

text 复制代码
MCP Tool → Controller ❌

原因:

  • Controller 属于 HTTP 协议层(多余转换)
  • 返回结构不适合模型(code/msg/data)
  • 依赖 Request/Session 上下文
  • 可能导致"自调用 HTTP"的性能问题

👉 本质:Tool 是能力入口,不是接口入口


六、Tool 设计最佳实践

1. 粒度设计

text 复制代码
✔ query_order
✔ cancel_order
✔ create_invoice

❌ call_api
❌ execute_request

2. 输入输出设计

text 复制代码
输入:明确字段 + 类型约束 + description
输出:裁剪字段(避免冗余)

3. 错误处理

text 复制代码
业务异常 → 可读语义
系统异常 → 标准错误

4. 安全设计

text 复制代码
鉴权(Token / 用户)
多租户隔离
敏感字段脱敏
调用审计

七、进阶实践方向

1. MCP 聚合网关

text 复制代码
多个系统 → 一个 MCP Server
统一治理 Tool

2. Tool 编排

text 复制代码
query_order → check_status → refund_order

3. Agent 自动调用

text 复制代码
用户输入 → 模型选择 Tool → 执行

八、总结

MCP Tool 本质是"面向模型设计的业务能力接口",而不是传统 API 的简单封装。


核心落地原则

text 复制代码
抽象业务能力(而非接口)
通过 MCP 层做安全与治理
保持 Service 复用
设计模型友好的 schema

最终理解

text 复制代码
Controller → 给前端使用
Tool       → 给模型使用
Service    → 统一业务逻辑

如果你后续要深入,可以继续扩展:

  • Tool schema 设计规范(高成功率)
  • MCP 网关架构(企业级)
  • Tool 调用调试与可观测性

这些才是 MCP 在工程化落地中的关键竞争力。

相关推荐
qcx233 小时前
深度解析Deepseek V4:1M 上下文不是军备竞赛,是养 Agent 的人才知道的痛
java·开发语言
小则又沐风a3 小时前
基础的开发工具(2)---Linux
java·linux·前端
晨非辰3 小时前
吃透C++两大默认成员函数:const成员函数、 & 取地址运算符重载
java·大数据·开发语言·c++·人工智能·后端·面试
啦啦啦_99993 小时前
3. 欠拟合 & 正好拟合 & 过拟合
python
WL_Aurora3 小时前
备战蓝桥杯国赛【Day 4】
python·蓝桥杯
落雪寒窗-3 小时前
Python进阶核心路线(工程向)
开发语言·python
梵得儿SHI3 小时前
(第三篇)Spring AI 架构设计与优化:容器化与云原生部署,基于 K8s 的 AI 应用全生命周期管理
java·ci/cd·docker·云原生·kubernetes·容器化·spring ai
普修罗双战士3 小时前
项目设计-文章系统发布文章完整前后端设计
java·数据库·vue.js·spring boot·git·intellij-idea
阿维的博客日记3 小时前
mcp有什么缺点???
agent·mcp