POML 与 MCP(Model Context Protocol)集成

POML 与 MCP(Model Context Protocol)集成

本文基于官方页面(microsoft.github.io/poml/stable... MCP 的工作原理、安装方式、基于 POML 模板的动态工具集成方案、完整示例、与直接使用 MCP 的对比,以及未来原生支持计划。

导语/背景介绍

  • MCP 是一种开放协议,为 LLM 应用与外部数据源和工具之间提供标准化的上下文访问与工具调用能力。
  • 警告:当前 POML 尚未内置支持 MCP。官方建议通过"工具调用 + 模板"的方式模拟 MCP 行为;未来版本计划提供原生支持。
  • 说明:部分提供方支持远程调用 MCP 服务器(如 OpenAI Response API),这类行为不在本文档范围内,因为开发者无需直接处理 MCP 调用细节。

安装与使用方法(Installation)

bash 复制代码
pip install mcp

工作原理(How MCP Works)

  • 客户端---服务端架构:
    1. 工具发现:MCP 服务器公开可调用的工具/函数
    2. 工具调用:客户端(LLM 应用)按参数调用工具
    3. 响应处理:服务器执行并返回结果给客户端
  • 典型流程:
    • 初始化:建立与 MCP 服务器的连接
    • 列出工具:查询可用工具及其 schema
    • 工具执行:当 LLM 需要调用时向 MCP 服务器发送请求
    • 结果集成:将工具结果整合回对话

动态工具(Dynamic Tools with MCP)

  • 通过 POML 的模板能力,可在运行时动态加载 MCP 服务器提供的工具定义,并在上下文中跟踪交互。
  • 该方案适用于 MCP 的原因(官方表述):
    • MCP 服务器在运行时动态提供工具
    • 不同 MCP 服务器的工具 schema 各不相同
    • 同一个 POML 模板可适配任意 MCP 服务器
    • 需要跨轮次跟踪工具交互

动态工具模板(POML Template for Dynamic Tools)

xml 复制代码
<poml> <system-msg>{{ system }}</system-msg> <human-msg>{{ input }}</human-msg> <!-- Dynamic Tool Loading: Iterates through tools discovered from the MCP server --> <div for="tool in tools"> <!-- Each tool's name, description, and JSON schema are inserted dynamically --> <tool-definition name="{{ tool.name }}" description="{{ tool.description }}"> {{ tool.schema }} </tool-definition> </div> <!-- Interaction History: Maintains conversation history with tool calls and responses --> <div for="i in interactions"> <!-- All dynamic content is provided through the context parameter --> <tool-request for="res in i" id="{{ res.id }}" name="{{ res.name }}" parameters="{{ res.input }}" /> <tool-response for="res in i" id="{{ res.id }}" name="{{ res.name }}"> <!-- Embeds the tool output directly via POML's Object componenet. --> <object data="{{ res.output }}"/> </tool-response> </div> <runtime model="gpt-4.1"/> </poml>

完整示例(Complete Example with MCP Server)

官方示例基于一个"掷骰子"的公共 MCP 演示服务器,演示工具发现、工具调用处理与主对话循环。

1) 工具发现与转换(Tool Discovery and Conversion)

python 复制代码
async def discover_mcp_tools(mcp_session): """Discover available tools from MCP server and convert to POML format""" mcp_tools = (await mcp_session.list_tools()).tools print(f"Available MCP tools: {mcp_tools}") # Convert MCP tools to POML context format. # The format must be compatible with the POML template above. poml_tools = [] for tool in mcp_tools: poml_tools.append({ "name": tool.name, "description": tool.description, "schema": tool.inputSchema }) return poml_tools

2) 处理工具调用(Process Tool Calls)

python 复制代码
async def process_tool_calls(mcp_session, tool_calls): """Execute MCP tool calls and format responses""" responses = [] for tool_call in tool_calls: function = tool_call.function args = json.loads(function.arguments or "{}") # Call MCP server tool result = await mcp_session.call_tool(function.name, args) print(f"Tool {function.name} result: {result}") # Format for POML context. # This format must be compatible with the POML template above. responses.append({ "id": tool_call.id, "name": function.name, "input": args, "output": result.model_dump() }) return responses

3) 主对话循环(Main Conversation Loop)

python 复制代码
async def run_mcp_conversation(mcp_session, context): """Run the conversation loop with MCP tools""" # Discover and add tools to context context["tools"] = await discover_mcp_tools(mcp_session) client = OpenAI() # Conversation loop while True: # Generate OpenAI parameters from POML params = poml.poml("dynamic_tools.poml", context=context, format="openai_chat") response = client.chat.completions.create(**params) message = response.choices[0].message if message.tool_calls: # Process and add tool responses to context responses = await process_tool_calls(mcp_session, message.tool_calls) context["interactions"].append(responses) else: # Final response - conversation complete print(f"Assistant: {message.content}") return message.content

4) 完整集成(Complete Integration)

python 复制代码
import json import asyncio from openai import OpenAI import poml from mcp import ClientSession from mcp.client.sse import sse_client async def main(): # Initialize context for POML context = { "system": "You are a helpful DM assistant. Use the dice-rolling tool when needed.", "input": "Roll 2d4+1", "tools": [], "interactions": [] } # Connect to MCP server (using public demo server) server_url = "https://dmcp-server.deno.dev/sse" async with sse_client(server_url) as (read, write): async with ClientSession(read, write) as mcp_session: await mcp_session.initialize() result = await run_mcp_conversation(mcp_session, context) print(f"Conversation completed: {result}") if __name__ == "__main__": asyncio.run(main())

与直接使用 MCP 的对比(Comparison with Direct MCP Usage)

  • 主要差异(官方表述):
    • 消息管理:直接方式需要手动区分 "role": "assistant""role": "tool";POML 通过请求/响应成对管理,自动处理
    • 内容渲染:直接方式需手动字符串转换与格式化;POML 使用 <object> 组件统一处理各类内容
    • 工具格式:直接方式需手动按 OpenAI 等提供方要求格式化;POML 使用声明式模板完成转换

不使用 POML(Direct Approach)

python 复制代码
# Manually manage message roles and format
messages.append({"role": "assistant", "content": msg.content or "", "tool_calls": msg.tool_calls})
messages.append({"role": "tool", "tool_call_id": tc.id, "name": fn.name, "content": text_result})
# Manually format tool results from MCP
if result.structuredContent is not None:
    text_result = json.dumps(result.structuredContent)
else:
    text_result = "\n".join([c.text for c in result.content if isinstance(c, types.TextContent)])
# Convert MCP tools to OpenAI format
oa_tools.append({
    "type": "function",
    "function": {"name": t.name, "description": t.description, "parameters": t.inputSchema}
})

使用 POML(Structured Approach)

python 复制代码
# Simply track tool request/response pairs
context["interactions"].append([
    {"id": tc.id, "name": fn.name, "input": args, "output": result.model_dump()}
])

未来原生支持(Future Native Support)

  • POML 计划提供 MCP 的原生支持,届时会为 MCP 操作提供简化语法。
  • 在此之前,可采用本文基于模板的方式作为过渡性解决方案。

使用场景

  • 官方页面未提供具体使用场景示例。

总结/展望

  • 文中基于官方页面介绍了 MCP 的工作原理、安装方法、POML 模板的动态工具集成方案、完整示例,以及与直接使用 MCP 的对比与未来计划。
  • 获取完整细节与最新进展,请参考官方文档:
相关推荐
AI大模型2 小时前
文科生也能逆袭AI?这5个方向0基础也能成功转行!
程序员·llm·agent
nil5 小时前
【开源推荐】双击即译!我用 trae 打造了一款轻量级Chrome网页翻译插件
chrome·llm·ai编程
掘我的金7 小时前
POML 与 LangChain 集成
llm
爱分享的飘哥15 小时前
第一百零二章:AI的“未来电影制片厂CEO”:多模态系统落地项目实战(完整 AI 视频创作平台)
人工智能·微服务·系统架构·llm·tts·多模态ai·ai视频创作平台
mguy_119 小时前
如何微调大语言模型(LLM):从 LoRA 到 量化部署
llm
RainbowSea1 天前
3. LangChain4j + 低阶 和 高阶 API的详细说明
java·llm·ai编程
硬核隔壁老王1 天前
收藏!Agentic RAG实战:从入门到智能问答系统完整实现指南
人工智能·程序员·llm
AI大模型1 天前
Dify新版1.8.0发布:新增异步工作流和多模型设置!
程序员·llm·agent
AI大模型1 天前
Claude Code 官方内部团队最佳实践!
llm·agent·claude