Server¶
HTTP-facing surface for hosted agents. AgentServer is the standalone
form (murmur serve); AgentRouter is the embedded form mounted on a
user-supplied FastAPI app.
The [server] extra is required for these imports — see
Installation.
AgentServer¶
AgentServer
¶
AgentServer(
*,
runtime: AgentRuntime | None = None,
run_store: RunStore | None = None,
drain_timeout: float = 30.0,
sse_emitter: SSEEventEmitter | None = None,
dashboard_dir: Path | None = None,
event_store: EventStore | None = None,
auth_token: str | None = None,
)
Registers agents / groups and serves them via FastAPI.
server = AgentServer() server.register(my_agent) server.register_group(my_crew) await server.serve(port=8421)
For tests, build the app via :meth:app and drive it with
httpx.AsyncClient(transport=httpx.ASGITransport(app=server.app)).
Source code in src/murmur/server/app.py
register_group
¶
register_group(group: AgentGroup) -> None
Register a group under its group.name.
Source code in src/murmur/server/app.py
register_mcp
¶
register_mcp(
agent: Agent, *, tool_name: str | None = None, description: str | None = None
) -> None
Enroll an agent for MCP exposure — opt-in, distinct from
:meth:register.
register() makes an agent reachable over HTTP; this method
additionally exposes it as an MCP tool that clients (Claude
Desktop, Cursor, MCP Inspector, …) call once :meth:serve_mcp
is running. Agents registered only with register() stay
invisible to MCP clients.
tool_name defaults to agent.name; override when you
want a public-facing name distinct from the internal one
(e.g. agent "researcher-v3" → tool "research").
description defaults to a truncated agent.instructions
and is what the calling LLM reads to decide when to invoke the
tool — make it specific.
The agent is also auto-registered for the runtime so the MCP
bridge can dispatch via runtime.run without an extra
server.register(agent) call. Re-enrolling an agent under
the same tool_name replaces the previous entry.
Source code in src/murmur/server/app.py
serve_mcp
async
¶
serve_mcp(
*,
transport: Literal["stdio", "http"] = "stdio",
server_name: str = "murmur",
instructions: str | None = None,
host: str = "127.0.0.1",
port: int = 8765,
) -> None
Run the MCP server.
Blocks until the transport exits (Ctrl-C for stdio; standard
ASGI shutdown for HTTP). Constructs a fresh :class:FastMCP
per call so multiple invocations on the same server work
cleanly. Raises :class:ImportError with a setup hint if the
murmur-runtime[mcp-server] extra isn't installed.
Only agents added via :meth:register_mcp appear as tools. If
no agents are enrolled, raises :class:RegistryError rather
than silently starting an empty server.
Source code in src/murmur/server/app.py
serve
async
¶
Start the server. Handles SIGTERM / SIGINT for graceful shutdown.
Source code in src/murmur/server/app.py
AgentRouter¶
AgentRouter
¶
AgentRouter(
*,
runtime: AgentRuntime | None = None,
run_store: RunStore | None = None,
drain_timeout: float = 30.0,
server: AgentServer | None = None,
start_workers: bool = True,
worker_runtime: AgentRuntime | None = None,
worker_concurrency: int = 10,
prefix: str = "",
tags: list[str] | None = None,
sse_emitter: SSEEventEmitter | None = None,
)
A FastAPI APIRouter that exposes registered agents and groups.
Constructable standalone or backed by a pre-built :class:AgentServer.
Users typically pass a :class:~murmur.AgentRuntime and let the router
construct the server internally; advanced users can build the server
themselves and pass it in via server= for shared-state scenarios.
Source code in src/murmur/server/router.py
broker
property
¶
The underlying FastStream broker (KafkaBroker, NatsBroker,
RabbitBroker, RedisBroker) when the runtime is broker-mode,
else None.
Use this to register your own @broker.subscriber("user.events")
handlers next to Murmur's — they share the same connection and the
same lifecycle (started / stopped via the host app's lifespan once
24d lands).
Treated as a documented re-export of FastStream's broker; consult
the FastStream docs for its full API. Returns None when the
runtime is in-process or when the broker is the in-memory testing
broker (which has no FastStream surface).
For "bring your own broker" (the user already has a configured
FastStream broker in their app), pass it through to the runtime via
the existing AgentRuntime(broker_instance=...) kwarg — wrap the
inner broker via :func:murmur.backends._brokers.make_broker (the
_fs_broker= constructor seam).
register_group
¶
register_group(group: AgentGroup) -> None
install_exception_handlers
classmethod
¶
Attach Murmur's error handlers + request-id middleware to app.
Idempotent on the per-handler level (FastAPI replaces handlers for the
same exception type). Call once after :meth:include_router.
Source code in src/murmur/server/router.py
ErrorResponse¶
ErrorResponse
¶
Wire shape returned by the server on any non-2xx response.
AgentRouter.install_exception_handlers(app) — classmethod, called once
on the host FastAPI app to wire Murmur's domain errors to the HTTP
status codes in server/errors.py.