Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Note
Il supporto per lo strumento MCP per l’hosting autonomo in .NET sarà presto disponibile.
Note
Il supporto dello strumento MCP self-hosting non è attualmente disponibile per Go.
Usare agent-framework-hosting-mcp per esporre un agente o un flusso di lavoro di Agent Framework come strumento nell'SDK del protocollo di contesto del modello nativo. Il pacchetto non sceglie un framework web né gestisce il ciclo di vita del server dell'SDK MCP; la gestione di Server, della registrazione dei gestori, del trasporto, dei criteri relativi alle chiavi di sessione, dell'autenticazione, dell'autorizzazione e della distribuzione resta comunque alla tua applicazione.
pip install --pre agent-framework-hosting-mcp
Eseguire la conversione al limite del protocollo
mcp_to_run(...) converte gli argomenti dello strumento MCP convalidati in messaggi di Agent Framework e le opzioni di chat selezionate e mcp_from_run(...) converte una risposta completata in valori MCP ContentBlock nativi. Usare queste due funzioni direttamente quando il contratto degli strumenti di un'applicazione richiede uno schema e un gestore nativi completamente personalizzati:
@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)
Solo i nomi degli argomenti elencati in vengono copiati in chat_option_argumentsrun["options"]. Gli altri argomenti MCP rimangono disponibili nella rappresentazione non elaborata del messaggio, ma non vengono inoltrati al client del modello.
Ospitare un agente come uno strumento generato
AgentMCPTool ricava da un agente il nome, la descrizione e lo schema dello strumento nativo e mantiene allineati la visualizzazione nell'elenco, il parsing, l'esecuzione e la conversione dei risultati, impedendo che i due si disallineino:
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 utilizza il nome e la descrizione dell'agente, a meno che non venga sottoposto a override.
parameters aggiunge proprietà dello schema JSON di proprietà dell'app che rimangono disponibili negli argomenti MCP non elaborati e chat_option_parameters aggiunge proprietà i cui valori vengono copiati in modo esplicito nelle opzioni di chat di Agent Framework.
Mantenere una sessione per ogni chiamata
Passa un AgentState esistente e un session_id_parameter per consentire a chiamate ripetute con lo stesso session_id opaco definito dall'app di continuare una conversazione:
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 esegue solo la sequenza get/run/set della sessione AgentState; l'applicazione deve autenticare o autorizzare l'identificatore di sessione e serializzare le chiamate concorrenti per la stessa sessione, come fa l'esempio con un asyncio.Lock per sessione. Non si tratta di una ramificazione in stile previous_response_id: un'applicazione che deve diramare una conversazione dovrebbe accettare ID di origine e di destinazione separati, copiare la sessione di origine e memorizzare il risultato con la chiave di destinazione.
Ospitare un flusso di lavoro come strumento
WorkflowMCPTool ricava uno strumento MCP nativo dal tipo di input dell'esecutore di avvio di un flusso di lavoro e converte gli output dei flussi di lavoro completati. Dataclass, Pydantic e altri input a forma di oggetto diventano argomenti MCP di primo livello; gli input primitivi vengono inclusi in un nome di argomento configurabile:
server = Server("agent-framework-hosting-mcp-workflow-sample")
workflow_tool = WorkflowMCPTool(
WorkflowState(create_workflow, cache_target=False),
name="draft_content",
)
Le istanze del flusso di lavoro mantengono lo stato di esecuzione, quindi le applicazioni che necessitano di chiamate indipendenti devono fornire una WorkflowState factory con cache_target=False, come illustrato in precedenza. Il ripristino del checkpoint, le risposte con intervento umano e gli identificatori di continuazione restano sotto la responsabilità dell'applicazione; se un flusso di lavoro richiede un input esterno, l'adattatore genera invece un'eccezione anziché restituire un risultato vuoto ma con esito positivo dello strumento.
Per il set completo di server eseguibili, inclusa la variante FastMCP che deriva il relativo schema da una funzione decorata, vedere gli esempi di hosting MCP.
Importante
Considera l'identificatore di sessione MCP e qualsiasi argomento session_id specificato dall'app come input non attendibile. Autenticare e autorizzare il chiamante prima di utilizzare uno dei due per caricare o salvare lo stato della sessione e derivare il partizionamento durevole dal tenant, dall'utente o dall'area di lavoro autenticati anziché dal valore grezzo.
Passaggi successivi
Approfondimento: