ask_{name} tools with a single serve_agents([...]) call.
Same thing via Pick whichever idiom fits your code — see Agents MCP.
launch(). Agent.launch(protocol="mcp") and PraisonAIAgents.launch(protocol="mcp") both delegate to serve_agents(...), so the tools, endpoint, and session model are identical:Quick Start
1
Install
pip install praisonai-mcp alone is enough for the default http-stream transport. Add praisonai-mcp[all] only if you need extra transports.2
Serve One Agent
Pass a single agent —
serve_agents wraps it in a list for you.3
Serve Multiple Agents
Pass a list to publish every agent on one endpoint.
4
Serve Over stdio
Use
stdio when the MCP client launches your process locally (Claude Desktop).How It Works
Eachask_* call loads that session’s transcript, runs one turn on an isolated copy of your agent, appends the turn, and returns the reply.
Pick a transport based on where the client runs.
Configuration Options
Under
transport="stdio", host and port are ignored — the client owns the process over stdin/stdout. Any value other than "http-stream" or "stdio" raises ValueError.serve_agents(...) returns the underlying MCPServer instance, which is handy for tests and orchestration.
Published Tools
serve_agents([...]) registers one ask_{agent_name} tool per agent plus a single list_agents() discovery tool.
ask_
Input schema:list_agents
Returns the agents available on the endpoint:description falls back through agent.role → the first line of agent.instructions → "Ask the {name} agent.".
Session Model
Sessions are opaque, isolated, and server-owned — the client controls continuity by echoing back thesession_id, nothing more.
session_idis opaque and client-supplied. When present, the adapter loads that session’s transcript, applies it to an isolated per-call agent copy, runs one turn, and appends the user + assistant turns.- Omitting
session_idmints a fresh id per call. It never falls back to a shared sticky session, so history never leaks across clients. Verified bytest_omitted_session_mints_fresh_id_and_no_shared_history. - Transcripts are namespaced per tool. The internal store key is
f"{tool_name}:{session_id}", so reusing onesession_idacrossask_supportandask_billingdoes not mix their histories. Verified bytest_same_session_id_across_agents_does_not_leak_history. - Per-session serialization. Each session holds a
threading.Lock, so overlapping calls to the same session can’t clobber each other’s saved turn. Different sessions never contend. - Per-turn agent isolation. Each turn runs on a shallow
copy.copy(agent)with the session’s history swapped in; the originalAgentis never mutated by concurrent sessions. - Server-owned persona. There is no tool parameter that lets the client set
instructionsor persona. Verified bytest_no_client_instructions_parameter. - AgentOS
/chatnow uses the same per-request clone model asserve_agents, but drops back to the shared template when the agent hashandoffs. See AgentOS Chat Session Isolation.
session_id and send it back on the next turn:
Naming and Disambiguation
Agent names become tool suffixes deterministically. Collisions get a numeric suffix.
Verified by
test_normalized_name_collision_registers_distinct_tools and test_unnamed_agents_do_not_collide.
What Clients See
Withsupport and billing served, list_agents() returns:
ask_support, ask_billing, and list_agents.
Call an agent over the http-stream endpoint:
Client Integration
- Claude Desktop (stdio)
- Cursor (http-stream)
serve_agents_app.py:Best Practices
Serve your own agents with serve_agents, not praisonai.agent.chat
Serve your own agents with serve_agents, not praisonai.agent.chat
Use
serve_agents([...]) for your product agents. The praisonai.agent.chat tool is a generic, server-owned assistant proxy that intentionally cannot be repersonalised by the client.Give every agent a name
Give every agent a name
The name becomes the
ask_{name} tool suffix the client sees. Unnamed agents collapse to ask_agent, ask_agent_2, and so on.Store and resend the session_id
Store and resend the session_id
Keep the returned
session_id on the client side and pass it back on every follow-up turn for the same conversation. Omitting it always starts a fresh session — that is by design.Match the transport to the deployment
Match the transport to the deployment
Prefer
transport='http-stream' for shared deployments. Use transport='stdio' only when the MCP client launches your process (Claude Desktop).Related
Agents MCP
launch(protocol='mcp') — the same code path, delegating herePraisonAI MCP
Umbrella
praisonai mcp serveMCP
Connect agents to MCP servers (client side)
praisonai-mcp Package
Standalone host package guide
MCP Memory Tools
Expose memory over MCP alongside your agents

