Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Note
Поддержка самостоятельного размещения инструментов MCP в .NET скоро появится.
Note
Поддержка инструментов MCP для самостоятельного хостинга в настоящее время недоступна для Go.
Используйте agent-framework-hosting-mcp, чтобы предоставить агент Agent Framework или рабочий процесс как инструмент в собственном SDK Model Context Protocol. Пакет не выбирает веб-фреймворк и не управляет жизненным циклом сервера MCP SDK; ответственность за Server, регистрацию обработчиков, транспорт, политику ключей сеанса, аутентификацию, авторизацию и развертывание по-прежнему остаётся на приложении.
pip install --pre agent-framework-hosting-mcp
Преобразование по границе протокола
mcp_to_run(...) преобразует проверенные аргументы инструментов MCP в сообщения Agent Framework и выбранные параметры чата и mcp_from_run(...) преобразует завершенный ответ в собственные значения MCP ContentBlock . Используйте эти две функции непосредственно, когда контракт средства приложения требует полностью настраиваемой собственной схемы и обработчика:
@server.list_tools()
async def list_tools() -> list[types.Tool]:
"""Return the app-owned native MCP tool definition."""
return [
types.Tool(
name="run_agent_manually",
description=agent.description or "",
inputSchema={
"type": "object",
"properties": {
TASK_ARGUMENT: {
"type": "string",
"description": "The request for the hosted agent.",
},
**CHAT_OPTION_ARGUMENTS,
},
"required": [TASK_ARGUMENT],
"additionalProperties": False,
},
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict[str, object] | None) -> list[types.ContentBlock]:
"""Convert, run, and render without the agent-backed adapter."""
if name != "run_agent_manually":
raise ValueError(f"Unknown MCP tool: {name}")
run = mcp_to_run(
arguments,
argument_name=TASK_ARGUMENT,
chat_option_arguments=CHAT_OPTION_ARGUMENTS,
)
result = await agent.run(run["messages"], options=run["options"])
return mcp_from_run(result)
Только имена аргументов, перечисленные в chat_option_arguments, копируются в run["options"]; другие аргументы MCP остаются доступными в необработанном представлении сообщения, но не пересылаются клиенту модели.
Разместить агента как единый сгенерированный инструмент
AgentMCPTool извлекает имя, описание и схему встроенного инструмента из агента и поддерживает согласованность списка, разбора, выполнения и преобразования результатов, чтобы они не расходились:
agent_tool = AgentMCPTool(
agent,
name="run_agent",
argument_description="The request for the hosted agent.",
chat_option_parameters={
"reasoning_effort": {
"type": "string",
"enum": ["low", "medium", "high"],
"description": "Optional reasoning effort for models that support it.",
}
},
)
@server.list_tools()
async def list_tools() -> list[types.Tool]:
"""Describe the app-owned MCP tool schema."""
return await agent_tool.list_tools()
@server.call_tool()
async def call_tool(name: str, arguments: dict[str, object] | None) -> list[types.ContentBlock]:
"""Run the app-owned tool with native MCP and Agent Framework values."""
return await agent_tool.call_tool(name, arguments)
AgentMCPTool использует имя и описание агента, если эти значения не переопределены.
parameters добавляет свойства схемы JSON, принадлежащие приложению, которые остаются доступными в необработанных аргументах MCP, и chat_option_parameters добавляет свойства, значения которых явно копируются в параметры чата Agent Framework.
Сохранять сеанс для каждого вызова
Передайте существующий AgentState и session_id_parameter, чтобы повторные вызовы с одним и тем же непрозрачным идентификатором session_id, определяемым приложением, продолжали один и тот же диалог:
session_locks: dict[str, asyncio.Lock] = {}
@server.list_tools()
async def list_tools() -> list[types.Tool]:
"""Return the agent-derived MCP tool definition."""
return await agent_tool.list_tools()
@server.call_tool()
async def call_tool(name: str, arguments: dict[str, object] | None) -> list[types.ContentBlock]:
"""Serialize calls per app-owned session before using ``AgentState``."""
session_id = arguments.get("session_id") if arguments else None
if not isinstance(session_id, str) or not session_id:
raise ValueError("MCP tool argument 'session_id' must be a non-empty string.")
lock = session_locks.setdefault(session_id, asyncio.Lock())
async with lock:
return await agent_tool.call_tool(name, arguments)
AgentMCPTool выполняет только последовательность get/run/set для сеанса AgentState; ваше приложение должно аутентифицировать или авторизовать идентификатор сеанса и сериализовать одновременные вызовы для одного и того же сеанса, как это показано в примере с отдельным asyncio.Lock для каждого сеанса. Это не ветвление в стиле previous_response_id — приложение, которому нужно разветвить диалог, должно принимать отдельные идентификаторы источника и назначения, копировать исходный сеанс и сохранять результат по ключу назначения.
Размещение рабочего процесса в качестве инструмента
WorkflowMCPTool формирует собственный инструмент MCP на основе типа входных данных стартового исполнителя процесса и преобразует выходные данные завершённого процесса. Dataclass, Pydantic и другие входные данные, формируемые объектом, становятся аргументами MCP верхнего уровня; примитивные входные данные упаковываются в настраиваемое имя аргумента:
server = Server("agent-framework-hosting-mcp-workflow-sample")
workflow_tool = WorkflowMCPTool(
WorkflowState(create_workflow, cache_target=False),
name="draft_content",
)
Экземпляры рабочего процесса сохраняют состояние исполнения, поэтому приложения, которым требуются независимые вызовы, должны предоставлять фабрику WorkflowState с cache_target=False, как показано выше. Восстановление контрольных точек, ответы с участием человека и идентификаторы продолжения остаются в ведении приложения; если рабочий процесс запрашивает внешний ввод, адаптер генерирует исключение вместо возврата пустого успешного результата инструмента.
Полный набор серверов, готовых к запуску, включая вариант FastMCP, который выводит свою схему из декорированной функции, см. в примерах размещения MCP.
Important
Обработайте идентификатор сеанса MCP и любой аргумент, определенный session_id приложением, как ненадежные входные данные. Проверяйте подлинность и авторизуйте инициатора запроса перед тем, как использовать любой из этих механизмов для загрузки или сохранения состояния сеанса, и определяйте устойчивое разбиение на основе аутентифицированного арендатора, пользователя или рабочей области, а не исходного значения.
Дальнейшие действия
Вернитесь глубже: