ag2-mcp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseServing an AG2 agent as an MCP server
将AG2 Agent部署为MCP服务器
ag2.mcp.MCPServerAgentag2.mcp.MCPServerAgentServer side vs. client side — read this first
服务端 vs 客户端——先阅读此部分
There are two opposite directions, and this skill is only one of them.
| Direction | You want… | Use |
|---|---|---|
| Server (this skill) | other MCP clients to call your AG2 agent | |
| Client | your AG2 agent to call an external MCP server's tools | |
If the user says "let Claude Desktop talk to my agent", "publish my agent over
MCP", or "host an MCP endpoint" → this skill. If they say "give my agent the
GitHub MCP tools" or "connect to an MCP server" → .
ag2-use-builtin-tools存在两种相反的使用方向,本技能仅覆盖其中一种。
| 方向 | 你的需求… | 使用方案 |
|---|---|---|
| 服务端(本技能) | 让其他MCP客户端调用你的AG2 Agent | |
| 客户端 | 让你的AG2 Agent调用外部MCP服务器的工具 | |
如果用户提到“让Claude Desktop与我的Agent交互”、“通过MCP发布我的Agent”或“部署MCP端点”→ 使用本技能。如果用户提到“为我的Agent添加GitHub MCP工具”或“连接到MCP服务器”→ 使用。
ag2-use-builtin-toolsWhen to use
使用场景
- Expose an AG2 agent so external MCP clients (Claude Desktop, Cursor, IDEs) can call it.
- Publish a single conversational -style tool that runs
askand returns the reply.Agent.ask() - Serve reusable prompts (templates) and resources (files/config/dynamic data) over MCP.
- Need multi-turn history per client session, OAuth2-protected HTTP, or per-request context injection.
- 暴露AG2 Agent,让外部MCP客户端(Claude Desktop、Cursor、IDE)可以调用它。
- 发布单个会话式风格的工具,运行
ask并返回回复。Agent.ask() - 通过MCP提供可复用的提示词(模板)和资源(文件/配置/动态数据)。
- 需要为每个客户端会话保存多轮对话历史、OAuth2保护的HTTP服务,或每次请求的上下文注入。
Installation
安装
bash
pip install "ag2[mcp]"Required. Run this install before delivering the code. Without theextra,mcpresolves to a stub that raises a "missing optional dependency" error on use.from ag2.mcp import MCPServer
bash
pip install "ag2[mcp]"必须执行此步骤。在运行代码前先完成安装。如果不安装扩展包,mcp会解析为一个存根类,使用时会抛出“缺少可选依赖”错误。from ag2.mcp import MCPServer
60-second recipe — serve an agent over stdio
60秒快速入门——通过标准输入输出部署Agent
This is the form local MCP clients (Claude Desktop, Cursor, MCP Inspector)
expect. The server reads/writes MCP frames over stdin/stdout.
python
import asyncio
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.mcp import MCPServer
agent = Agent(
name="assistant",
prompt="You are a helpful assistant.",
config=OpenAIConfig(model="gpt-4o-mini"),
)这是本地MCP客户端(Claude Desktop、Cursor、MCP Inspector)期望的运行形式。服务器通过标准输入/输出读取/写入MCP帧。
python
import asyncio
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.mcp import MCPServer
agent = Agent(
name="assistant",
prompt="You are a helpful assistant.",
config=OpenAIConfig(model="gpt-4o-mini"),
)The agent is exposed as ONE conversational tool, named "ask" by default,
Agent会暴露为一个名为"ask"的会话工具(默认名称),
taking a required message
and an optional context
string.
messagecontext接收必填的message
参数和可选的context
字符串参数。
messagecontextserver = MCPServer(
agent,
name="assistant-mcp", # serverInfo.name in the handshake
instructions="Ask me anything.", # client-facing usage hint (NOT the agent prompt)
)
if name == "main":
asyncio.run(server.run_stdio())
Register it with a client (Claude Desktop `claude_desktop_config.json` shown;
Cursor / other clients use the same `command` + `args` shape):
```json
{
"mcpServers": {
"assistant": {
"command": "python",
"args": ["/absolute/path/to/serve_stdio.py"],
"env": { "OPENAI_API_KEY": "sk-..." }
}
}
}The agent must have a modelset. Serving an agent with no config raisesconfig=on the first tool call.MCPAgentConfigError
server = MCPServer(
agent,
name="assistant-mcp", # 握手时的serverInfo.name
instructions="Ask me anything.", # 面向客户端的使用提示(不是Agent的提示词)
)
if name == "main":
asyncio.run(server.run_stdio())
在客户端中注册(以下展示Claude Desktop的`claude_desktop_config.json`配置;Cursor/其他客户端使用相同的`command` + `args`格式):
```json
{
"mcpServers": {
"assistant": {
"command": "python",
"args": ["/absolute/path/to/serve_stdio.py"],
"env": { "OPENAI_API_KEY": "sk-..." }
}
}
}Agent 必须设置模型参数。部署未配置模型的Agent会在首次工具调用时抛出config=。MCPAgentConfigError
Serve over HTTP (streamable HTTP transport)
通过HTTP部署(流式HTTP传输)
MCPServeruvicornpython
import uvicorn
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.mcp import MCPServer
agent = Agent(name="assistant", prompt="You help users.", config=OpenAIConfig(model="gpt-4o-mini"))
app = MCPServer(agent, path="/mcp") # MCP endpoint mounted at /mcp
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)HTTP transport knobs (ignored over stdio):
| Param | Default | Effect |
|---|---|---|
| | URL path the MCP endpoint is served at. |
| | When |
| | Return plain JSON instead of SSE for responses. |
| | OAuth2 bearer enforcement (see below). |
MCPServeruvicornpython
import uvicorn
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.mcp import MCPServer
agent = Agent(name="assistant", prompt="You help users.", config=OpenAIConfig(model="gpt-4o-mini"))
app = MCPServer(agent, path="/mcp") # MCP端点挂载在/mcp路径
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)HTTP传输配置项(标准输入输出模式下忽略):
| 参数 | 默认值 | 作用 |
|---|---|---|
| | MCP端点的URL路径。 |
| | 设置为 |
| | 返回纯JSON而非SSE格式的响应。 |
| | OAuth2令牌验证(详见下文)。 |
Customising the tool
自定义工具
By default the tool is named with an auto-generated description. Override:
askpython
server = MCPServer(
agent,
tool_name="consult_expert",
tool_description="Consult the expert agent about a question.",
stream_progress=True, # forward agent stream events as MCP progress/log notifications (default True)
)The tool always takes a required and an optional string
(prepended to the message). Mirrors 's shape.
messagecontextAgent.as_tool()默认情况下,工具名为,描述为自动生成的内容。可进行如下覆盖:
askpython
server = MCPServer(
agent,
tool_name="consult_expert",
tool_description="Consult the expert agent about a question.",
stream_progress=True, # 将Agent的流事件转发为MCP进度/日志通知(默认值为True)
)工具始终接收必填的参数和可选的字符串参数(会前置到message内容中),与的参数结构一致。
messagecontextAgent.as_tool()Prompts
提示词
Expose reusable prompt templates (MCP + ). A
renderer receives the call arguments as a dict and returns
either a plain (becomes one message) or a list of .
Renderers may be sync or async.
prompts/listprompts/get{name: value}struserPromptMessagepython
from ag2.mcp import MCPServer, Prompt, PromptArgument, PromptMessage
def render_review(args: dict[str, str]) -> list[PromptMessage]:
return [
PromptMessage(role="user", text=f"Review this {args['language']} code:"),
PromptMessage(role="user", text=args.get("code", "")),
]
server = MCPServer(
agent,
prompts=[
Prompt(
name="code_review",
description="Generate a code-review prompt.",
render=render_review,
arguments=(
PromptArgument(name="language", description="Programming language", required=True),
PromptArgument(name="code", description="The code to review", required=False),
),
),
# A bare-string renderer becomes a single user message.
Prompt(name="greet", render=lambda args: f"Say hello to {args['who']}"),
],
)The MCP capability is advertised only when a non-empty list is passed.
prompts暴露可复用的提示词模板(支持MCP的 + 接口)。渲染器会接收调用参数作为字典,并返回纯(会转换为一条消息)或列表。渲染器可以是同步或异步的。
prompts/listprompts/get{name: value}struserPromptMessagepython
from ag2.mcp import MCPServer, Prompt, PromptArgument, PromptMessage
def render_review(args: dict[str, str]) -> list[PromptMessage]:
return [
PromptMessage(role="user", text=f"Review this {args['language']} code:"),
PromptMessage(role="user", text=args.get("code", "")),
]
server = MCPServer(
agent,
prompts=[
Prompt(
name="code_review",
description="Generate a code-review prompt.",
render=render_review,
arguments=(
PromptArgument(name="language", description="Programming language", required=True),
PromptArgument(name="code", description="The code to review", required=False),
),
),
# 纯字符串渲染器会转换为单条user消息。
Prompt(name="greet", render=lambda args: f"Say hello to {args['who']}"),
],
)只有当传入非空列表时,才会对外宣传 MCP能力。
promptsResources
资源
Expose static and templated resources (MCP + ,
plus for templates). returns (text) or
(binary); sync or async.
resources/listresources/readresources/templates/listreadstrbytespython
from pathlib import Path
from ag2.mcp import MCPServer, Resource, ResourceTemplate
server = MCPServer(
agent,
resources=[
Resource(
uri="config://app",
name="app-config",
description="Static app config.",
mime_type="application/json",
read=lambda: '{"env": "prod"}',
),
],
resource_templates=[
# RFC 6570 templates: {var} matches one path segment, {+var} spans '/'.
ResourceTemplate(
uri_template="file:///{+path}",
name="file",
description="Read a file by path.",
read=lambda vars: Path(vars["path"]).read_text(),
),
],
)mime_typetext/plainstrapplication/octet-streambytesNoneresources暴露静态和模板化资源(支持MCP的 + 接口,以及针对模板的接口)。方法返回(文本)或(二进制);可以是同步或异步方法。
resources/listresources/readresources/templates/listreadstrbytespython
from pathlib import Path
from ag2.mcp import MCPServer, Resource, ResourceTemplate
server = MCPServer(
agent,
resources=[
Resource(
uri="config://app",
name="app-config",
description="Static app config.",
mime_type="application/json",
read=lambda: '{"env": "prod"}',
),
],
resource_templates=[
# RFC 6570模板:{var}匹配一个路径段,{+var}跨越多段路径。
ResourceTemplate(
uri_template="file:///{+path}",
name="file",
description="Read a file by path.",
read=lambda vars: Path(vars["path"]).read_text(),
),
],
)当设为时,会根据MCP SDK的默认规则自动设置(类型默认,类型默认)。只有当提供至少一个资源或模板时,才会对外宣传 MCP能力。
mime_typeNonestrtext/plainbytesapplication/octet-streamresourcesSessions — multi-turn history
会话——多轮对话历史
By default () each MCP session (keyed by the transport's
over HTTP, or a single per-process key over stdio) keeps its
own conversation history that accumulates across invocations.
Tune it with , or disable with for fully
stateless calls.
sessions=Truemcp-session-idtools/callSessionConfigsessions=Falsepython
from ag2.mcp import MCPServer, SessionConfig
server = MCPServer(
agent,
sessions=SessionConfig(
max_sessions=1024, # LRU cap; least-recently-used session's history is dropped past the cap
ttl=3600, # optional idle-expiry in seconds (None = never expire)
storage=None, # pluggable history backend; defaults to in-memory MemoryStorage
),
)默认情况下(),每个MCP会话(HTTP模式下由传输层的标识,标准输入输出模式下为单个进程级标识)会保留自己的对话历史,且该历史会在多次调用中累积。可通过进行配置,或设置完全禁用会话,实现纯无状态调用。
sessions=Truemcp-session-idtools/callSessionConfigsessions=Falsepython
from ag2.mcp import MCPServer, SessionConfig
server = MCPServer(
agent,
sessions=SessionConfig(
max_sessions=1024, # LRU上限;超过上限时会删除最近最少使用的会话历史
ttl=3600, # 可选的空闲过期时间(秒),None表示永不过期
storage=None, # 可插拔的历史存储后端;默认使用内存中的MemoryStorage
),
)Or stateless — every call independent:
或者设置为无状态——每次调用完全独立:
stateless = MCPServer(agent, sessions=False)
`storage` accepts any `ag2.history.Storage` (e.g. a Redis-backed store)
for cross-replica continuity. Note: a `stateless=True` **HTTP transport** issues
no session id, so it stays stateless regardless of `sessions=`.stateless = MCPServer(agent, sessions=False)
`storage`参数接受任何`ag2.history.Storage`实现(例如基于Redis的存储),以实现跨副本的会话连续性。注意:**HTTP传输设置`stateless=True`时不会生成会话ID**,因此无论`sessions=`如何设置,都会保持无状态。Structured output → structuredContent
structuredContent结构化输出 → structuredContent
structuredContentIf the agent has a that is an object schema (Pydantic
model / dataclass / dict), advertises it as the tool's
and returns validated to clients. Scalar/union schemas
aren't advertised — those replies flow back as plain text.
response_schemaMCPServeroutputSchemastructuredContentpython
from pydantic import BaseModel
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.mcp import MCPServer
class Weather(BaseModel):
city: str
temp_c: float
agent = Agent(name="weather", prompt="Report weather.", response_schema=Weather,
config=OpenAIConfig(model="gpt-4o-mini"))
server = MCPServer(agent)如果Agent的是对象类型的 schema(Pydantic模型/数据类/字典),会将其作为工具的对外宣传,并向客户端返回经过验证的。标量/联合类型的schema不会对外宣传——这类回复会以纯文本形式返回。
response_schemaMCPServeroutputSchemastructuredContentpython
from pydantic import BaseModel
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.mcp import MCPServer
class Weather(BaseModel):
city: str
temp_c: float
agent = Agent(name="weather", prompt="Report weather.", response_schema=Weather,
config=OpenAIConfig(model="gpt-4o-mini"))
server = MCPServer(agent)tool.outputSchema is set; call results carry result.structuredContent == {"city": ..., "temp_c": ...}
tool.outputSchema已设置;调用结果会携带result.structuredContent == {"city": ..., "temp_c": ...}
undefinedundefinedPer-request context — AskContext
/ ContextProvider
AskContextContextProvider每次请求上下文 —— AskContext
/ ContextProvider
AskContextContextProviderA is an async hook that runs per request. It receives the
authenticated bearer token (an , or
when unauthenticated) and returns an whose non- fields are
passed straight into . Use it to inject per-principal variables,
tools, or prompt — context the stateless executor otherwise omits.
context_providermcp.server.auth.provider.AccessTokenNoneAskContextNoneAgent.ask()python
from typing import Any
from ag2.mcp import AskContext, ContextProvider, MCPServer
async def provide(token: Any) -> AskContext:
# Resolve the caller from `token`, then scope the turn to them.
tenant = "acme" # e.g. token.scopes / a claims lookup
return AskContext(
variables={"tenant": tenant}, # -> Agent.ask(variables=...)
tools=None, # -> Agent.ask(tools=...) (None = leave default)
prompt="Be concise.", # -> Agent.ask(prompt=...)
)
server = MCPServer(agent, context_provider=provide)AskContextvariables: dict | Nonetools: list | Noneprompt: list[str] | str | NoneNonecontext_providermcp.server.auth.provider.AccessTokenNoneAskContextNoneAgent.ask()python
from typing import Any
from ag2.mcp import AskContext, ContextProvider, MCPServer
async def provide(token: Any) -> AskContext:
# 从`token`解析调用方信息,然后将对话限定为该用户的上下文。
tenant = "acme" # 例如从token.scopes或声明中获取
return AskContext(
variables={"tenant": tenant}, # -> Agent.ask(variables=...)
tools=None, # -> Agent.ask(tools=...) (None表示保留默认值)
prompt="Be concise.", # -> Agent.ask(prompt=...)
)
server = MCPServer(agent, context_provider=provide)AskContextvariables: dict | Nonetools: list | Noneprompt: list[str] | str | NoneNoneSecurity — OAuth2 bearer (HTTP only) — needs external setup
安全——OAuth2 Bearer令牌(仅HTTP模式)——需要外部配置
For HTTP, protect the endpoint with OAuth 2.1 bearer auth. The MCP server acts
purely as a Resource Server: it advertises trusted authorization server(s)
via RFC 9728 Protected Resource Metadata at
and verifies presented tokens. Issuing
tokens stays with your external authorization server.
/.well-known/oauth-protected-resourcepython
from ag2.mcp import MCPServer
from ag2.mcp.security import oauth2_scheme, require
security = require(
oauth2_scheme(url="https://auth.example.com"), # absolute http(s) issuer URL
resource_url="https://api.example.com/mcp", # this server's public endpoint
verifier=my_token_verifier, # your mcp TokenVerifier implementation
required_scopes=["mcp.read"], # a token must carry every scope
)
app = MCPServer(agent, path="/mcp", security=security)- 's path component must equal
security.resource_url(herepath), or/mcpraisesMCPServer.ValueError - Missing/invalid token → (with a
401header pointing at the metadata); insufficient scopes →WWW-Authenticate.403 - is a bring-your-own
verifier.mcp.server.auth.provider.TokenVerifierrejects non-oauth2_scheme(url=...)URLs (an OIDC issuer string is not a usable authorization-server URL — pass the full URL).http(s)
Requires external setup: a real authorization server to mint tokens and a concrete. Exercise the unauthenticated path in-process (see testing below); the token round-trip needs your OAuth provider.TokenVerifier
对于HTTP模式,可使用OAuth 2.1 Bearer认证保护端点。MCP服务器仅作为资源服务器:它会通过RFC 9728定义的受保护资源元数据在路径宣传可信的授权服务器,并验证传入的令牌。令牌的颁发由外部授权服务器负责。
/.well-known/oauth-protected-resourcepython
from ag2.mcp import MCPServer
from ag2.mcp.security import oauth2_scheme, require
security = require(
oauth2_scheme(url="https://auth.example.com"), # 授权服务器的绝对http(s) URL
resource_url="https://api.example.com/mcp", # 本服务器的公开端点
verifier=my_token_verifier, # 自定义的mcp TokenVerifier实现
required_scopes=["mcp.read"], # 令牌必须包含所有指定的权限范围
)
app = MCPServer(agent, path="/mcp", security=security)- 的路径部分必须等于
security.resource_url参数(此处为path),否则/mcp会抛出MCPServer。ValueError - 令牌缺失/无效→返回(包含指向元数据的
401响应头);权限范围不足→返回WWW-Authenticate。403 - 是自定义的
verifier实现。mcp.server.auth.provider.TokenVerifier会拒绝非oauth2_scheme(url=...)的URL(OIDC颁发者字符串不是可用的授权服务器URL——必须传入完整URL)。http(s)
需要外部配置:需要一个真实的授权服务器来生成令牌,以及具体的实现。可通过进程内测试验证未认证路径(见下文测试部分);令牌的往返流程需要依赖你的OAuth服务提供商。TokenVerifier
Testing in-process — no sockets, no subprocess
进程内测试——无需套接字,无需子进程
ag2.mcp.testingconnect()ClientSessionserve()httpx.AsyncClientTestConfigag2.testingpython
import asyncio
from ag2 import Agent
from ag2.testing import TestConfig
from ag2.mcp import MCPServer, Resource
from ag2.mcp import testing
async def main() -> None:
agent = Agent(name="assistant", prompt="p", config=TestConfig("Hello from the agent!"))
server = MCPServer(
agent,
resources=[Resource(uri="config://app", name="cfg", read=lambda: '{"env": "prod"}')],
)
# In-memory MCP client/server pair (the MCP analog of an ASGI test client).
async with testing.connect(server) as session:
await session.initialize()
tools = await session.list_tools()
assert [t.name for t in tools.tools] == ["ask"]
result = await session.call_tool("ask", {"message": "Hi"})
assert "Hello from the agent" in result.content[0].text
res = await session.read_resource("config://app")
assert res.contents[0].text == '{"env": "prod"}'
# Exercise the HTTP transport (initialize handshake, session id) in-memory:
async with testing.serve(server) as client:
resp = await client.post(
"/mcp",
headers={"Accept": "application/json, text/event-stream", "Content-Type": "application/json"},
json={
"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2025-06-18", "capabilities": {},
"clientInfo": {"name": "test", "version": "1.0"}},
},
)
assert resp.status_code == 200
assert "mcp-session-id" in resp.headers
print("ok")
if __name__ == "__main__":
asyncio.run(main())testing.connect(server, raise_exceptions=..., **session_kwargs)logging_callbackmessage_handlercaveat for multi-turn:TestConfigbuilds a fresh response iterator per turn, so giving itTestConfig.create()will not showTestConfig("a", "b")then"a"across two separate MCP"b"s — each call replays from the first scripted response. That's a property of the mock, not the server: session history really does accumulate (verify it by inspecting the growing message list a custom test client receives, or use a real model).call_tool
ag2.mcp.testingconnect()ClientSessionserve()httpx.AsyncClientag2.testingTestConfigpython
import asyncio
from ag2 import Agent
from ag2.testing import TestConfig
from ag2.mcp import MCPServer, Resource
from ag2.mcp import testing
async def main() -> None:
agent = Agent(name="assistant", prompt="p", config=TestConfig("Hello from the agent!"))
server = MCPServer(
agent,
resources=[Resource(uri="config://app", name="cfg", read=lambda: '{"env": "prod"}')],
)
# 内存中的MCP客户端/服务器对(相当于ASGI测试客户端的MCP版本)。
async with testing.connect(server) as session:
await session.initialize()
tools = await session.list_tools()
assert [t.name for t in tools.tools] == ["ask"]
result = await session.call_tool("ask", {"message": "Hi"})
assert "Hello from the agent" in result.content[0].text
res = await session.read_resource("config://app")
assert res.contents[0].text == '{"env": "prod"}'
# 在内存中测试HTTP传输(初始化握手、会话ID):
async with testing.serve(server) as client:
resp = await client.post(
"/mcp",
headers={"Accept": "application/json, text/event-stream", "Content-Type": "application/json"},
json={
"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2025-06-18", "capabilities": {},
"clientInfo": {"name": "test", "version": "1.0"}},
},
)
assert resp.status_code == 200
assert "mcp-session-id" in resp.headers
print("ok")
if __name__ == "__main__":
asyncio.run(main())testing.connect(server, raise_exceptions=..., **session_kwargs)logging_callbackmessage_handler多轮对话注意事项:TestConfig会为每轮对话创建新的响应迭代器,因此传入TestConfig.create()不会在两次独立的MCPTestConfig("a", "b")调用中依次返回call_tool和"a"——每次调用都会从第一个脚本化响应开始重播。这是模拟工具的特性,而非服务器的问题:会话历史确实会累积(可通过自定义测试客户端接收的消息列表增长情况来验证,或使用真实模型)。"b"
Public API reference
公开API参考
All importable from :
ag2.mcp| Symbol | Kind | Purpose |
|---|---|---|
| class | Wrap an |
| dataclass | |
| dataclass | |
| dataclass | |
| dataclass | |
| dataclass | |
| dataclass | |
| dataclass | |
| type alias | `async (AccessToken |
| function | Build the single conversational |
From : , , ,
. From : , .
ag2.mcp.securityoauth2_schemerequireSchemeRequirementag2.mcp.testingconnectserve所有API均可从导入:
ag2.mcp| 符号 | 类型 | 用途 |
|---|---|---|
| 类 | 将 |
| 数据类 | 配置多轮对话历史的 |
| 数据类 | 定义提示词模板的 |
| 数据类 | 定义提示词参数的 |
| 数据类 | 定义单条渲染消息的 |
| 数据类 | 定义静态资源的 |
| 数据类 | 定义RFC 6570动态资源的 |
| 数据类 | 定义传入 |
| 类型别名 | `async (AccessToken |
| 函数 | 独立构建单个会话式 |
从可导入:、、、。从可导入:、。
ag2.mcp.securityoauth2_schemerequireSchemeRequirementag2.mcp.testingconnectserveCommon pitfalls
常见陷阱
- Missing extra —
mcp; otherwise the imports are dependency stubs that raise on use.pip install "ag2[mcp]" - Agent has no model config — accepts it, but the first tool call raises
MCPServer. SetMCPAgentConfigError.Agent(config=...) - Confusing server with client — SERVES your agent. To CONSUME an external MCP server's tools from your agent, use
MCPServer(seeMCPServerTool).ag2-use-builtin-tools - ≠ system prompt —
instructions=is client-facing "how to use this server" text in the handshake; it is not derived from the agent's prompt. Pass it explicitly.instructions - HTTP discards sessions — a stateless HTTP transport issues no
stateless=True, so multi-turn history can't key. Usemcp-session-id(default) when you want sessions.stateless=False - path mismatch — its path must equal
security.resource_url; otherwisepathraisesMCPServer.__init__.ValueError - Non-object — only object schemas get
response_schema/outputSchema; scalars/unions come back as text.structuredContent
- 缺少扩展包——需执行
mcp;否则导入的是依赖存根类,使用时会抛出错误。pip install "ag2[mcp]" - Agent未设置模型配置——会接受未配置的Agent,但首次工具调用时会抛出
MCPServer。需设置MCPAgentConfigError。Agent(config=...) - 混淆服务端与客户端——用于部署你的Agent。若要让你的Agent调用外部MCP服务器的工具,请使用
MCPServer(查看MCPServerTool)。ag2-use-builtin-tools - ≠ 系统提示词——
instructions=是握手时面向客户端的“如何使用此服务器”说明文本;并非从Agent的提示词派生而来,需显式传入。instructions - 的HTTP模式会丢弃会话——无状态HTTP传输不会生成
stateless=True,因此无法关联多轮对话历史。若需要会话,请使用默认的mcp-session-id。stateless=False - 路径不匹配——其路径必须与
security.resource_url参数一致;否则path会抛出MCPServer.__init__。ValueError - 非对象类型的——只有对象类型的schema才会生成
response_schema/outputSchema;标量/联合类型会以文本形式返回。structuredContent
Going deeper
深入学习
- Source:
ag2/mcp/{server,sessions,prompts,resources,executor,info,security,testing}.py - Runnable reference covering every sample above: (run with
references/test_server.py, no API keys needed)python references/test_server.py - MCP spec: https://modelcontextprotocol.io
- Client side (consuming MCP servers from an agent): skill
ag2-use-builtin-tools
- 源码:
ag2/mcp/{server,sessions,prompts,resources,executor,info,security,testing}.py - 包含上述所有示例的可运行参考代码:(执行
references/test_server.py即可运行,无需API密钥)python references/test_server.py - MCP规范:https://modelcontextprotocol.io
- 客户端场景(从Agent调用外部MCP服务器):技能
ag2-use-builtin-tools