MCP API Gateway:用 FastMCP 把多个外部 API 统一成标准化工具

0 阅读3分钟

MCP API Gateway:用 FastMCP 把多个外部 API 统一成标准化工具

构建一个 MCP 工具网关,把 Tavily 搜索、天气查询、翻译等功能包装成标准化的 MCP 工具,任何 MCP Client 都能直接调用。


一、为什么需要 API Gateway?

在 AI Agent 开发中,一个常见的痛点:

Agent A 需要查天气 → 写一个天气工具
Agent B 需要查新闻 → 再写一个新闻工具
Agent C 需要翻译 → 又写一个翻译工具

每个 Agent 都自己实现一遍 API 集成,重复造轮子

MCP Protocol 的解法:把所有 API 统一包装成 MCP 工具,注册到一个 Server 上。任何 MCP Client(LangChain Agent、Claude Desktop、自定义应用)都能直接调用,一次实现,到处复用


二、架构

                  MCP API Gateway
                         │
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
   search_news      get_weather      translate
    (Tavily)         (Tavily)          (Tavily)
         │               │               │
         └───────────────┼───────────────┘
                         ▼
                   MCP Client
              (LangChain / 自定义)

每个工具背后都对接一个真实的外部 API,但对外暴露的是统一的 MCP 接口——JSON-RPC over STDIO。


三、核心代码

FastMCP 服务器

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("api-gateway", log_level="ERROR")

不需要继承、不需要手动注册。一行代码创建一个 MCP Server。

工具 1:搜索新闻

@mcp.tool()
def search_news(query: str) -> str:
    """
    搜索新闻资讯。

    Args:
        query: 搜索关键词

    Returns:
        新闻标题、摘要和链接
    """
    client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
    results = client.search(query=query, max_results=5)
    ...

@mcp.tool() 做了什么?

  • 读取函数名 → 成为工具的 namesearch_news
  • 读取文档字符串第一行 → 工具的 description
  • 读取类型注解 query: str → 生成 JSON Schema {"query": {"type": "string"}}
  • 自动注册到 list_toolscall_tool 路由

这就是 FastMCP 和旧 API 的区别——旧版需要手动定义 Tool 对象和 Schema,FastMCP 全自动了。

工具 2:查询天气

@mcp.tool()
def get_weather(city: str) -> str:
    """
    查询某个城市的当前天气情况。

    Args:
        city: 城市名称,如"广州"
    """
    ...

工具 3:翻译

@mcp.tool()
def translate(text: str, target_lang: str = "中文") -> str:
    """
    翻译文本到目标语言。

    Args:
        text: 要翻译的文本
        target_lang: 目标语言,如"中文"、"英文"
    """
    ...

target_lang 带有默认值 "中文",所以对客户端来说是可选参数


四、测试:MCP Client 连接

from mcp.client.stdio import stdio_client, StdioServerParameters
from mcp import ClientSession

params = StdioServerParameters(command="python", args=["server.py"])
async with stdio_client(params) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        
        # 客户端自动发现所有工具
        tools = await session.list_tools()
        print(f"可用工具: {[t.name for t in tools.tools]}")
        
        # 调用工具
        result = await session.call_tool("search_news", {"query": "AI Agent"})

输出:

可用工具: ['search_news', 'get_weather', 'translate']

不需要硬编码工具列表。Client 通过 list_tools 动态发现 Server 有什么工具可用,这就是 MCP 的工具发现协议


五、比较:同一个工具,三种写法

方式代码量复用性面试价值
直接在 Agent 里写低(换 Agent 重写)⭐⭐
封装成函数中(需手动适配)⭐⭐⭐
封装成 MCP 工具高(任何 Client 可调)⭐⭐⭐⭐⭐

MCP 方式的优势:

写一次 → 任何地方用
   ↓
LangChain Agent?✅
Claude Desktop?✅
自己的 CLI 脚本?✅
另一个 MCP Server?✅

六、总结

这个项目的核心思路是:把 API 集成从应用层下沉到协议层。工具写一次,对接任何 MCP Client。不管是 LangChain 还是未来的新框架,只要支持 MCP 协议就能直接调用。

适用场景:

  • 团队内部统一工具注册中心
  • 个人工具集,跨项目复用
  • 快速对接第三方 API 到 LLM 应用

可以改进的方向:

  1. streamable-http 传输,支持远程调用
  2. 加工具鉴权(哪些 API Key 能调哪些工具)
  3. 加打点和统计(哪些工具被调了多少次)

七、项目链接

GitHub: github.com/cuzz123/mcp…

完整项目组合: