MCP 服务快速上手

本指南演示如何在 FlowLLM 中以最小工作量搭建一个可调用的 MCP(Model Context Protocol)服务,覆盖:编写 Op、编排 Flow、配置、启动与客户端调用。


一、编写 Op

MCP 工具的业务逻辑来源于 Flow 中的 Op。可直接复用已有 Op,也可先编写一个简单示例。以下为内置示例 MockSearchOp

from flowllm.core.context import C
from flowllm.core.op import BaseAsyncOp

@C.register_op()
class MockSearchOp(BaseAsyncOp):
    """Mock search operation that uses LLM to generate realistic search results."""
    file_path: str = __file__

    async def async_execute(self):
        query = self.context.query
        if not query:
            self.context.response.answer = "No results found."
            return
        num_results = random.randint(0, 5)
        user_prompt = self.prompt_format("mock_search_op_prompt", query=query, num_results=num_results)
        messages = [
            Message(role=Role.SYSTEM, content="You are a helpful assistant that generates realistic search results in JSON format."),
            Message(role=Role.USER, content=user_prompt),
        ]
        def callback_fn(message: Message):
            return extract_content(message.content, "json")
        search_results: str = await self.llm.achat(messages=messages, callback_fn=callback_fn)
        self.context.response.answer = json.dumps(search_results, ensure_ascii=False, indent=2)

要点: - 类名以 Op 结尾,且用 @C.register_op() 注册后方可在 Flow 中引用。 - 异步对话型 Op 继承 BaseAsyncOp 并实现 async_execute。 - 通过 self.context 读写上下文,self.llm 调用模型,self.prompt_format() 绑定提示词模板。


二、编写yaml config

保存如下配置为: - 覆盖默认:flowllm/flowllm/config/default.yaml - 自定义:项目根新建 my_mcp_config.yaml

backend: mcp
thread_pool_max_workers: 128

mcp:
  transport: sse
  host: "0.0.0.0"
  port: 8001

flow:
  # 将 Flow 以 MCP 工具形式暴露(工具名:demo_mcp_flow)
  demo_mcp_flow:
    flow_content: MockSearchOp()
    description: "search results for a given query."
    input_schema:
      query:
        type: string
        description: "user query"
        required: true

llm:
  default:
    backend: openai_compatible
    model_name: qwen3-30b-a3b-instruct-2507
    params:
      temperature: 0.6

embedding_model:
  default:
    backend: openai_compatible
    model_name: text-embedding-v4
    params:
      dimensions: 1024

vector_store:
  default:
    backend: memory
    embedding_model: default

要点: - Flow 的编排直接在配置文件的 flow 段中定义(如上 demo_mcp_flow)。Flow 名即工具名,在 MCP 中以同名工具暴露。 - input_schema 建议填写,便于客户端生成入参校验与帮助信息。 - backend: mcp 指定以 MCP 服务启动。 - mcp.transport 当前支持 sse;服务默认暴露 SSE 端点 GET /sse。 - flow 中声明的每个 Flow 都将作为一个 MCP 工具对外提供。


三、启动服务

确保已安装 FlowLLM,并在.env中设置模型相关环境变量,可直接参考项目根的示例文件 example.env

export FLOW_LLM_API_KEY="sk-xxxx"
export FLOW_LLM_BASE_URL="https://xxxx/v1"
export FLOW_EMBEDDING_API_KEY="sk-xxxx"
export FLOW_EMBEDDING_BASE_URL="https://xxxx/v1"
  • 使用my_mcp_config启动:
flowllm \
  config=my_mcp_config \
  backend=mcp \
  mcp.transport=sse \
  mcp.port=8002 \
  llm.default.model_name=qwen3-30b-a3b-thinking-2507

成功后(以 host=0.0.0.0, port=8001 为例): - SSE 连接:GET http://0.0.0.0:8001/sse - 工具清单与调用通过 SSE 渠道完成(由 MCP 客户端实现)

服务行为(参考 flowllm/core/service/* 内 MCP 相关实现): - 为每个 Flow 生成同名 MCP 工具(如 demo_mcp_flow) - 采用 SSE 作为传输时,客户端通过单一 SSE 端点进行会话


四、客户端调用与测试

使用内置 FastMcpClient 进行调用(简化示例):

import asyncio

from flowllm.core.utils import FastMcpClient


async def main():
    config = {
        "type": "sse",
        "url": "http://0.0.0.0:8001/sse",
        "headers": {},
        "timeout": 30.0,
    }
    async with FastMcpClient("test_client", config, max_retries=3) as client:
        # 1) 列出可用工具
        tool_calls = await client.list_tool_calls()
        # 2) 调用工具(与 Flow 同名)
        result = await client.call_tool("demo_mcp_flow", {"query": "阿里巴巴前景怎么样?"})
        # 3) 读取结果
        print(result)


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

也可直接运行内置测试脚本:

python -m flowllm.tests.mcp_client_test