Lokalt installerade agenter som MCP-verktyg

Note

Stöd för att självhantera MCP-verktyg i .NET kommer snart.

Note

Stöd för MCP-verktyg för självhosting är för närvarande inte tillgängligt i Go.

Använd agent-framework-hosting-mcp för att exponera en Agent Framework-agent eller ett arbetsflöde som ett verktyg i det interna SDK:t för Model Context Protocol . Paketet väljer inte något webbramverk och omsluter inte serverlivscykeln för MCP SDK; din applikation ansvarar fortfarande för Server, registrering av hanterare, transport, princip för sessionsnycklar, autentisering, auktorisering och driftsättning.

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

Konvertera vid protokollgränsen

mcp_to_run(...) konverterar verifierade MCP-verktygsargument till Agent Framework-meddelanden och valda chattalternativ och mcp_from_run(...) konverterar ett slutfört svar till inbyggda MCP-värden ContentBlock . Använd dessa två funktioner direkt när ett programs verktygskontrakt behöver ett helt anpassat internt schema och en hanterare:

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

Endast argumentnamn som anges i chat_option_arguments kopieras till run["options"]; andra MCP-argument förblir tillgängliga i meddelandets rårepresentation men vidarebefordras inte till modellklienten.

Använd en agent som ett genererat verktyg

AgentMCPTool härleder verktygets egna namn, beskrivning och schema från en agent och håller listning, parsning, körning och resultatkonvertering i linje med varandra så att de inte kan glida isär:

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 använder agentens namn och beskrivning om inget annat anges. parameters lägger till appägda JSON-schemaegenskaper som förblir tillgängliga i de råa MCP-argumenten och chat_option_parameters lägger till egenskaper vars värden uttryckligen kopieras till Agent Framework-chattalternativ.

Behåll en session per samtal

Skicka en befintlig AgentState och en session_id_parameter så att upprepade anrop med samma opaka, appdefinierade session_id kan fortsätta samma konversation:

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 utför endast sessionens get/run/set-sekvens. Programmet måste autentisera AgentState eller auktorisera sessionsidentifieraren och serialisera samtidiga anrop för samma session, som exemplet gör med en per session asyncio.Lock. Det här är inte previous_response_id-style branching – ett program som behöver förgrena en konversation bör acceptera separata käll- och mål-ID: er, kopiera källsessionen och lagra resultatet under målnyckeln.

Publicera ett arbetsflöde som verktyg

WorkflowMCPTool härleder ett inbyggt MCP-verktyg från ett arbetsflödes start-executor-indatatyp och konverterar slutförda arbetsflödesutdata. Dataklass, Pydantic och andra objektformade indata blir MCP-argument på toppnivå. primitiva indata omsluts i ett konfigurerbart argumentnamn:

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

Arbetsflödesinstanser bevarar exekveringstillståndet, så applikationer som behöver oberoende anrop bör tillhandahålla en WorkflowState-fabrik med cache_target=False, som visas ovan. Kontrollpunktsåterställning, human-in-the-loop-svar och fortsättningsidentifierare förblir programägda. Om ett arbetsflöde begär externa indata genereras adaptern i stället för att returnera ett tomt lyckat verktygsresultat.

För den fullständiga uppsättningen körbara servrar, inklusive FastMCP-varianten som härleder sitt schema från en dekorerad funktion, se exempel på MCP-värdar.

Important

Behandla MCP-sessionsidentifieraren och alla appdefinierade session_id argument som ej betrodda indata. Autentisera och auktorisera anroparen innan du använder någon av dem för att ladda eller spara sessionstillstånd, och härled varaktig partitionering från den autentiserade klientorganisationen, användaren eller arbetsytan i stället för det ursprungliga värdet.

Nästa steg

Gå djupare: