Runtime MCP Management

Attach and detach MCP servers on a live agent without rebuilding

Add or remove MCP integrations on a running agent — no restart, no lost session state.

python
from praisonaiagents import Agent, MCP

agent = Agent(instructions="You are a helpful assistant")
agent.add_mcp_server("notion", MCP("npx -y @notionhq/notion-mcp-server"))
agent.start("Summarise my latest Notion page about Q3 planning")

The user attaches or detaches MCP servers on a live agent; new tools appear on the next turn without restarting.

Diagram

Runtime MCP Management

🤖 Live Agent

➕ add_mcp_server

🔌 MCP Server

🛠️ Tools live next turn

➖ remove_mcp_server

✅ Clean shutdown

Quick Start

  1. Attach an MCP server at runtime
    python
    from praisonaiagents import Agent, MCP
    
    agent = Agent(instructions="You are a helpful assistant")
    
    agent.add_mcp_server("notion", MCP("npx -y @notionhq/notion-mcp-server"))
    
    agent.start("Summarise my latest Notion page about Q3 planning")

    Tools from the attached server are available on the next turn of the same run.

  2. List and remove servers
    python
    print(agent.list_mcp_servers())   # ['notion']
    
    removed = agent.remove_mcp_server("notion")
    print(removed)                     # True
    print(agent.list_mcp_servers())   # []

How It Works

Diagram
MCP ServerAgentUserMCP ServerAgentUser“also connect Notion”add_mcp_server(“notion”, MCP(…))connect + discover toolstool listnext messagecall notion toolresultresponse

Runtime-attached MCPs live in a private _mcp_servers registry on the agent. Each add_mcp_server call registers the server, appends it to self.tools, and refreshes the toolset. Removed servers call mcp.shutdown() best-effort before deregistration.


API Reference

MethodReturnsRaises
add_mcp_server(name, mcp)MCPValueError if name is empty or already attached
remove_mcp_server(name)bool (False if name unknown)—
refresh_tools()List[Any]—
list_mcp_servers()List[str]—

Common Patterns

Gateway agent adds Notion mid-session

python
from praisonaiagents import Agent, MCP

agent = Agent(instructions="You are a helpful assistant")
agent.add_mcp_server("notion", MCP("npx -y @notionhq/notion-mcp-server"))
agent.start("What pages did I update this week?")

Hot-swap under the same name

python
agent.remove_mcp_server("notion")
agent.add_mcp_server("notion", MCP("npx -y @notionhq/notion-mcp-server"))

Direct re-attach without removing first raises ValueError("MCP server 'notion' is already attached. Call remove_mcp_server() first to replace it.").

React to tools/list_changed

python
agent.refresh_tools()

Call refresh_tools() when an MCP server signals that its tool list changed — per-turn assembly already reads self.tools live, but this forces an immediate refresh.


Cleanup

agent.close() and await agent.aclose() both shut down every runtime-attached MCP via _shutdown_runtime_mcp_servers(). Failures on individual servers are logged and skipped so one bad shutdown does not block the rest.

python
agent.close()       # sync — shuts down all runtime-attached MCPs
await agent.aclose()  # async-safe — same guarantee

You do not need to call remove_mcp_server() manually before closing the agent.

agent.close() and await agent.aclose() also walk self.tools and call shutdown() / aclose() on any construction-time MCP objects, so you get the same clean-shutdown guarantee whether you attach an MCP at build time or add one at runtime. See Agent Lifecycle Cleanup.


Best Practices

Use unique, descriptive names

Attach each MCP under a stable name ("notion", "github", "postgres") so you can list and remove servers predictably mid-session.

Remove before re-attaching under the same name

add_mcp_server raises on duplicate names. Call remove_mcp_server(name) first when hot-swapping credentials or server commands.

Tools surface on the next turn

New tools are not injected into the current LLM turn. Send another message (or continue the run) after attaching so the agent sees the expanded toolset.

Rely on close()/aclose() for guaranteed cleanup

Long-running services should still call close() or aclose() when the agent session ends — runtime MCPs are tracked and shut down automatically.


Related