Agen host mandiri sebagai alat MCP

Note

Dukungan alat MCP hosting mandiri di .NET akan segera hadir.

Note

Dukungan alat MCP hosting mandiri saat ini tidak tersedia untuk Go.

Gunakan agent-framework-hosting-mcp untuk mengekspos agen Agen Framework atau alur kerja sebagai alat pada Model Context Protocol SDK asli. Paket ini tidak menentukan kerangka kerja web atau mengelola siklus hidup server SDK MCP; aplikasi Anda tetap bertanggung jawab atas Server, pendaftaran handler, transport, kebijakan kunci sesi, autentikasi, otorisasi, dan penerapan.

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

Konversi di batas protokol

mcp_to_run(...) mengonversi argumen alat MCP yang divalidasi menjadi pesan Agent Framework dan opsi obrolan yang dipilih, dan mcp_from_run(...) mengonversi respons lengkap menjadi nilai MCP ContentBlock asli. Gunakan kedua fungsi ini secara langsung ketika kontrak alat aplikasi membutuhkan skema dan handler asli yang sepenuhnya kustom:

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

Hanya nama argumen yang tercantum dalam chat_option_arguments yang disalin ke run["options"]; argumen MCP lainnya tetap tersedia dalam representasi mentah pesan, tetapi tidak diteruskan ke klien model.

Jalankan agen sebagai alat yang dibuat

AgentMCPTool memperoleh nama, deskripsi, dan skema alat bawaan dari agen, serta menjaga agar pencantuman, penguraian, eksekusi, dan konversi hasil tetap selaras sehingga keduanya tidak mungkin menyimpang satu sama lain:

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 menggunakan nama dan deskripsi agen kecuali ditentukan lain. parameters menambahkan properti Skema JSON milik aplikasi yang tetap tersedia dalam argumen MCP mentah, dan chat_option_parameters menambahkan properti yang nilainya secara eksplisit disalin ke dalam opsi obrolan Agent Framework.

Mempertahankan sesi untuk setiap panggilan

Berikan AgentState yang sudah ada dan session_id_parameter agar panggilan berulang dengan session_id buram yang sama, yang ditentukan aplikasi, dapat melanjutkan satu percakapan:

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 hanya melakukan urutan sesi AgentState get/run/set; aplikasi Anda harus mengautentikasi atau mengautorisasi pengidentifikasi sesi dan menserialkan panggilan serentak untuk sesi yang sama, seperti yang dilakukan sampel dengan asyncio.Lock per sesi. Ini bukan pencabangan gaya previous_response_id — aplikasi yang perlu memecah percakapan harus menerima ID sumber dan ID tujuan yang terpisah, menyalin sesi sumber, dan menyimpan hasilnya dengan kunci tujuan.

Jadikan alur kerja sebagai alat

WorkflowMCPTool menghasilkan satu tool MCP native dari jenis input start-executor alur kerja dan mengonversi output alur kerja yang selesai. Dataclass, Pydantic, dan input berbentuk objek lainnya menjadi argumen MCP tingkat atas; input primitif dibungkus dalam nama argumen yang dapat dikonfigurasi:

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

Instans workflow menyimpan status eksekusi, sehingga aplikasi yang memerlukan pemanggilan independen harus menyediakan WorkflowState factory dengan cache_target=False, seperti yang ditunjukkan di atas. Pemulihan titik pemeriksaan, respons human-in-the-loop, dan pengidentifikasi kelanjutan tetap dimiliki aplikasi; jika alur kerja meminta input eksternal, adaptor akan muncul alih-alih mengembalikan hasil alat yang berhasil kosong.

Untuk set lengkap server yang dapat dijalankan - termasuk varian FastMCP yang memperoleh skemanya dari fungsi yang didekorasi - lihat sampel hosting MCP.

Important

Perlakukan pengidentifikasi sesi MCP dan argumen apa pun yang ditentukan session_id aplikasi sebagai input yang tidak tepercaya. Lakukan autentikasi dan otorisasi terhadap pemanggil sebelum menggunakan salah satunya untuk memuat atau menyimpan status sesi, dan tentukan partisi persisten berdasarkan tenant, pengguna, atau ruang kerja yang telah diautentikasi, bukan berdasarkan nilai mentah.

Langkah berikutnya

Masuk lebih dalam: