大模型(LLM)正以前所未有的速度发展,它们的能力已经渗透到各个领域。如何更好地利用这些强大的模型,让它们能够访问外部信息和工具,成为了一个重要的研究方向。MCP (Model Context Protocol) 作为一种开放标准,正为大模型与外部工具的交互提供了一种高效、便捷的解决方案。本文将深入探讨如何利用 STDIO (标准输入/输出) 传输方式,快速构建一个 MCP 服务器,无需复杂的配置和部署,即可让你的大模型拥有强大的外部能力。

什么是 MCP?以及为何如此重要?

MCP (Model Context Protocol) 是一种专门为大模型设计的通信协议。它允许像 Claude 或 GPT-4 这样的 LLM 通过结构化的 API 调用外部工具。想象一下,你可以创建一个工具,让语言模型像调用函数一样使用它来进行搜索、数学计算、数据库查询,或者任何你能想到的功能。

MCP 的重要性体现在以下几个方面:

  • 扩展大模型能力: 大模型本身虽然知识储备丰富,但在处理实时信息、特定领域数据以及执行复杂计算等方面存在局限性。MCP 允许大模型访问外部工具,弥补这些不足,从而大幅提升其解决问题的能力。
  • 可组合性与灵活性: 通过 MCP,开发者可以构建各种各样的工具,并将它们组合起来,形成强大的工作流。例如,可以将一个搜索工具与一个数学计算工具结合,让大模型先搜索相关信息,然后进行数据分析。
  • 标准化接口: MCP 提供了一套标准的接口规范,使得不同的工具可以无缝地与大模型进行交互。这降低了开发成本,并提高了系统的可维护性。
  • 安全性和控制: 通过 MCP,开发者可以精确控制大模型可以访问哪些工具,以及每个工具的使用权限。这有助于保障数据的安全性和模型的稳定性。

举个例子,假设你想让大模型帮你分析某个股票的走势。如果没有 MCP,你可能需要将股票数据手动输入到模型中,并编写复杂的代码进行分析。而有了 MCP,你可以构建一个股票数据查询工具,让大模型通过 MCP 协议直接调用该工具获取实时数据,并进行分析。

STDIO:极简的 MCP 工具构建方式

在众多 MCP 传输方式中,STDIO (标准输入/输出) 无疑是最简单、最直接的一种。它允许你通过标准输入/输出来构建 MCP 兼容的工具,这意味着:

  • 无需服务器: 工具直接在本地运行,无需搭建额外的服务器。
  • 无需网络配置: 工具通过标准输入/输出进行通信,无需进行复杂的网络配置。
  • 跨平台兼容: 只要你的机器支持标准输入/输出,就可以运行该工具。
  • 易于集成: STDIO 可以无缝地与 LangChain、LangGraph 等流行的 LLM 开发框架集成。

与传统的 HTTP 方式相比,STDIO 方式更加轻量级,更加易于上手,特别适合用于快速原型开发和本地调试。

使用 Python 和 Tavily API 构建一个 STDIO MCP 服务器

接下来,我们将通过一个具体的例子,演示如何使用 Python 和 Tavily API 构建一个 STDIO MCP 服务器。这个服务器的功能是利用 Tavily API 进行网络搜索,并将搜索结果返回给大模型。

1. 准备工作

首先,你需要安装以下依赖:

pip install fastmcp requests langchain langgraph

然后,你需要获取一个 Tavily API Key,并将其设置为环境变量:

export TAVILY_API_KEY="your_real_api_key"

你可以在 Tavily 官网免费注册一个 API Key。

2. 创建 MCP 服务器

使用 FastMCP 创建一个简单的 MCP 服务器:

from mcp.server import FastMCP

mcp = FastMCP("tavily-search-server")

这段代码创建了一个名为 “tavily-search-server” 的 MCP 服务器实例。

3. 添加 Tavily Web 搜索工具

定义一个函数 tavily_search,该函数调用 Tavily API 进行网络搜索,并将搜索结果返回:

import os
import requests

TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")

@mcp.tool()
def tavily_search(query: str) -> str:
    """Use Tavily API to search the web and return the top result."""
    url = "https://api.tavily.com/search"
    headers = {"Authorization": f"Bearer {TAVILY_API_KEY}"}
    payload = {"query": query, "max_results": 1}
    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()
    results = response.json()
    return results["results"][0]["content"] if results.get("results") else "No results found."

@mcp.tool() 装饰器将该函数注册为 MCP 工具。当大模型通过 MCP 协议调用该工具时,tavily_search 函数将被执行。该函数接受一个字符串类型的参数 query,表示搜索关键词,并返回一个字符串类型的搜索结果。函数内部调用 Tavily API 进行搜索,并将返回的 JSON 数据解析后,提取第一个结果的内容。

4. 启动服务器

添加一个简单的入口点来启动服务器:

if __name__ == "__main__":
    print("✅ MCP server has started")
    mcp.run()

将以上代码保存为 tavily_server.py 文件。

5. 与 LangGraph ReAct Agent 集成

现在,我们将使用 LangGraph ReAct Agent 来调用我们刚刚创建的 MCP 服务器。首先,你需要安装 langchain_mcp_adapters 包:

pip install langchain_mcp_adapters

然后,创建一个 Python 文件,例如 agent.py,并添加以下代码:

import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain.chat_models import ChatOpenAI

async def run_agent():
    server_params = StdioServerParameters(
        command=["python", "tavily_server.py"]
    )
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            tools = await load_mcp_tools(session)
            agent_executor = create_react_agent(
                llm=ChatOpenAI(model="gpt-4"),
                tools=tools,
                max_iterations=5,
            )
            result = await agent_executor.ainvoke({
                "input": "What's the latest news about AI policy in Europe?"
            })
            print(result["output"])

if __name__ == "__main__":
    asyncio.run(run_agent())

这段代码首先创建了一个 StdioServerParameters 对象,指定了 MCP 服务器的启动命令。然后,使用 stdio_client 创建一个 STDIO 客户端,并使用 ClientSession 与服务器建立连接。load_mcp_tools 函数从 MCP 服务器加载工具,并将它们传递给 LangGraph ReAct Agent。最后,Agent 使用 Tavily 搜索工具来回答问题 “What’s the latest news about AI policy in Europe?”。

6. 运行 Agent

运行 agent.py 文件:

python agent.py

你会看到 Agent 通过 MCP 服务器调用 Tavily API 进行搜索,并返回搜索结果。

通过这个例子,我们成功地构建了一个基于 STDIO 的 MCP 服务器,并将其与 LangGraph ReAct Agent 集成。整个过程非常简单,无需复杂的配置和部署。

STDIO MCP 的优势与局限性

优势:

  • 简单易用: 无需服务器,无需网络配置,易于上手。
  • 轻量级: 资源占用少,适合本地调试和快速原型开发。
  • 跨平台: 只要支持标准输入/输出,就可以运行。
  • 集成方便: 可以与 LangChain、LangGraph 等 LLM 开发框架无缝集成。

局限性:

  • 单客户端: STDIO 模式只能支持一个客户端连接。
  • 不适合生产环境: STDIO 模式不适合在高并发、高可用性的生产环境中使用。

从 STDIO 到 HTTP:扩展 MCP 服务器的能力

虽然 STDIO 模式非常适合本地开发,但在实际应用中,我们往往需要构建一个可以远程访问、支持多个客户端的 MCP 服务器。这时,我们可以使用 HTTP 协议来实现 MCP 服务器。

HTTP 模式的 MCP 服务器可以部署在云端,通过网络提供服务。它支持多个客户端同时连接,并且可以实现流式响应,从而提高性能和用户体验。

例如,我们可以使用 FastAPI 构建一个 HTTP MCP 服务器,并使用 Server-Sent Events (SSE) 实现流式响应。具体实现细节可以参考后续的文章。

结论

MCP (Model Context Protocol) 为大模型与外部工具的交互提供了一种标准化的解决方案。通过 STDIO 传输方式,我们可以快速构建 MCP 服务器,无需复杂的配置和部署。这使得开发者可以更加专注于工具本身的开发,而不是底层的通信细节。

然而,STDIO 模式也存在一些局限性,例如只能支持单客户端连接。在实际应用中,我们可以根据具体需求选择合适的传输方式,例如 HTTP。

总而言之,MCP 为大模型带来了无限的可能性。通过与外部工具的结合,大模型可以更好地解决实际问题,并为各行各业带来变革。随着 MCP 标准的不断完善和普及,相信未来会有越来越多的开发者加入到 MCP 的生态中,共同推动大模型技术的发展。