Agenti hostovaní ve vlastní režii jako nástroje MCP

Note

Podpora samoobslužného nástroje MCP v .NET bude brzy k dispozici.

Note

Podpora samoobslužného nástroje MCP není aktuálně dostupná pro Go.

Pomocí agent-framework-hosting-mcp můžete zpřístupnit agenta nebo pracovní postup platformy Agent Framework jako nástroj v nativní sadě SDK Model Context Protocol. Balíček nevolí webový framework ani nezajišťuje životní cyklus serveru MCP SDK; vaše aplikace nadále spravuje Server, registraci obslužných rutin, transport, zásady pro klíče relací, ověřování, autorizaci a nasazení.

pip install --pre agent-framework-hosting-mcp

Převést na rozhraní protokolu

mcp_to_run(...) převede ověřené argumenty nástroje MCP na zprávy agenta Framework a vybrané možnosti chatu a mcp_from_run(...) převede dokončenou odpověď na nativní hodnoty MCP ContentBlock . Tyto dvě funkce použijte přímo, když kontrakt nástrojů aplikace potřebuje plně vlastní nativní schéma a obslužnou rutinu:

@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)

Do chat_option_arguments se kopírují pouze názvy argumentů uvedené v run["options"]; ostatní argumenty MCP zůstávají dostupné v nezpracované reprezentaci zprávy, ale klientovi modelu se nepřeposílají.

Hostování agenta jako jednoho vygenerovaného nástroje

AgentMCPTool přebírá od agenta nativní název nástroje, popis a schéma a udržuje jejich výpis, parsování, spouštění a převod výsledků ve vzájemném souladu, takže se tyto dvě části nemohou rozejít:

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 použije název a popis agenta, pokud není zadáno jinak. parameters přidá vlastnosti schématu JSON vlastněné aplikací, které zůstanou dostupné v nezpracovaných argumentech MCP, a chat_option_parameters přidá vlastnosti, jejichž hodnoty se explicitně zkopírují do možností chatu v rozhraní Agent Framework.

Zachovat relaci pro každé volání

Předejte existující AgentState a session_id_parameter, aby opakovaná volání se stejným neprůhledným identifikátorem session_id, definovaným aplikací, mohla pokračovat v jedné konverzaci:

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 provádí pouze sekvenci get/run/set pro relaci; vaše aplikace musí ověřit nebo autorizovat identifikátor relace a serializovat souběžná volání pro stejnou relaci, jak to ukázka dělá pomocí AgentState pro každou relaci. Nejedná se o větvení ve stylu previous_response_id – aplikace, která potřebuje rozdělit konverzaci do větví, by měla přijímat samostatná zdrojová a cílová ID, zkopírovat zdrojovou relaci a uložit výsledek pod cílovým klíčem.

Hostovat workflow jako nástroj

WorkflowMCPTool vytváří jeden nativní nástroj MCP ze vstupního typu spouštěcího vykonavatele pracovního postupu a převádí výstupy dokončeného pracovního postupu. Dataclass, Pydantic a další vstupy tvarované objekty se stanou argumenty MCP nejvyšší úrovně; primitivní vstupy jsou zabalené do konfigurovatelného názvu argumentu:

server = Server("agent-framework-hosting-mcp-workflow-sample")
workflow_tool = WorkflowMCPTool(
    WorkflowState(create_workflow, cache_target=False),
    name="draft_content",
)

Instance workflow zachovávají stav provádění, takže aplikace, které vyžadují nezávislá volání, by měly poskytnout továrnu WorkflowState s cache_target=False, jak je znázorněno výše. Obnovení kontrolního bodu, odpovědi v režimu human-in-the-loop a identifikátory pokračování zůstávají na straně aplikace; pokud pracovní postup vyžaduje externí vstup, adaptér místo vrácení prázdného úspěšného výsledku nástroje vyvolá výjimku.

Kompletní sadu spustitelných serverů včetně varianty FastMCP, která odvozuje její schéma z zdobené funkce, najdete v ukázkách hostování MCP.

Important

Považovat identifikátor relace MCP a libovolný argument definovaný session_id aplikací za nedůvěryhodný vstup. Před použitím kteréhokoli z nich k načtení nebo uložení stavu relace ověřte a autorizujte volajícího a trvalé rozdělení odvoďte od ověřeného tenanta, uživatele nebo pracovního prostoru, nikoli od nezpracované hodnoty.

Další kroky

Jděte hlouběji: