
Agno is a trademark of its respective owner, used here for identification and integration guidance only. No endorsement, partnership, or affiliation is implied.
Agent a model and a list of tools;
Agno runs the reasoning and tool-calling loop, and — with Team — coordinates several agents
that hand work off to each other. It has first-class MCP client support via MCPTools /
MultiMCPTools.
- What Agno ships — an
Agent/Team/Workflowruntime, model-agnostic providers, 100+ pre-built toolkits, memory and knowledge, and MCP tools overstdio,streamable-http, andsse— including per-run dynamic headers viaheader_provider. - What it doesn’t ship — a way for those agents to act as a real account: sign up for a SaaS tool, hold a funded card, or spend within a budget you control, per end-user.
How the pairing works
- Agno turns any MCP server into a set of tools: point
MCPToolsat the server URL, add it to anAgent’stools, and each MCP tool becomes a function the model can call — no manual schema wiring. - Naive ships a hosted MCP server and mints per-user sessions — short-lived, revocable SSE endpoints whose tool list is the fused native + third-party toolset, already filtered by that user’s Account Kit.
- Each session is one URL + one bearer scoped to one user. Build
MCPToolsfrom it, hand it to anAgent, and every tool call runs as that user — gated server-side.
Tested against:
agno 2.6.x (agno.agent.Agent, agno.tools.mcp.MCPTools /
SSEClientParams, agno.models.openai.OpenAIChat), the mcp Python package 1.x (SSE
transport), and Naive API v2 (hosted MCP server over SSE + per-user sessions), on
Python ≥ 3.10.Naive’s session URL contains /mcp/sse/…, so initialize MCPTools with transport="sse".
Agno now recommends streamable-http for new MCP servers, but it fully supports SSE — use SSE
to match Naive’s endpoint. The scoped bearer rides in the connection headers
(via SSEClientParams or a header_provider), never in the URL. There is no Python Naive SDK
yet, so the control plane (Account Kit, user, session) is shown over the REST API; you can
equally provision from the dashboard, the CLI, or the Node
SDK. Pin your versions and set the model to one you have access to.Prerequisites
- A Naive API key (
nv_sk_...) — get one from the dashboard. - An
OPENAI_API_KEYfor the model that runs the agent (or swap in any other Agno model provider, e.g.agno.models.anthropic.Claude). - Python ≥ 3.10.
Minimal viable integration
The shortest path to an Agno agent that can actually transact: define a policy and provision a user (control plane, once), then at runtime mint a per-user MCP session and hand it to anAgent.
Define the policy, then provision a user
An Account Kit is the spend/capability policy. Here a tenant
user gets a card (capped at $500, approval required), the vault, and an allowlist of apps.
Everything the agent does is bounded by this kit — server-side. These are one-time
control-plane calls:
Mint a per-user MCP session
At runtime, mint a short-lived session for the user. It returns the
scoped SSE endpoint and a bearer that lives in the headers — never in the URL — and expires
(default 15 min, max 24h):
Build the agent — and let it transact
Point Agno’s The model discovers GitHub (
MCPTools at the session’s scoped SSE endpoint, pass it to an Agent, and call
arun. Agno discovers Naive’s tools, exposes them to the model, and runs the tool-calling loop
for you (call tool → feed result back → continue). Keep the connection open for the duration of
the run — the async context manager handles connect/close:naive_connections_connect), returns a connect link for Alice to
authorize, and attempts to issue the card (naive_cards_create) — a real card on Alice’s
account, capped by her kit. The whole agent loop is Agno’s; the real-world actions are Naive’s.The session’s tool list is already filtered by Alice’s kit — the agent never sees a tool the
policy forbids. To narrow further per agent, mint a session against a tighter kit, or pass
include_tools=[...] / exclude_tools=[...] to MCPTools to expose only a subset (e.g.
include_tools=["naive_connections_connect", "naive_cards_create"]).Extension: human-in-the-loop spend
Because the kit setcards.requiresApproval: true, the agent cannot silently spend. When
the model calls the card-issuing tool, Naive freezes the request and the tool result comes
back as a pending approval (HTTP 202) instead of a live card:
pending → executed / failed / denied) and the deny endpoint.
Want a UX gate inside the run too? Agno supports
human-in-the-loop confirmation for MCP tools
that pauses a tool call until you confirm. That shapes the conversation; the real enforcement
is Naive’s server-side approval gate above, which can’t be bypassed from the prompt or the
agent config.
Approvals are only enforced for agent (API-key / MCP) calls on real tenant users. A human
acting in your dashboard, and agent calls on the operator’s own default user, bypass the
gate — so end-user agents stay governed while your own automation isn’t slowed down.
Alternative: one agent definition, every tenant
A Naive session is scoped to one user, so to serve every tenant from the same agent definition, mint a fresh session per request and buildMCPTools from it. The instructions,
model, and tools stay the same — only which user’s session backs the toolset changes, and
every call is Account-Kit-gated server-side:
DELETE /v1/users/{user_id}/sessions/{id}.
Because it’s Agno, you can also compose this into a
Team:
keep a coordinator agent for planning and give a single operator member the Naive
MCPTools. The team reasons and delegates; only the operator can touch the real account, and
every action it takes is still bounded by the per-user session and Account Kit.What stays enforced
No matter how the agent is wired, the policy is enforced where it matters — on Naive’s servers, not in your prompt or your agent config:- Identity — every action runs as a specific tenant user, fully isolated from your other users.
- Capability bounds — the Account Kit decides which
primitives and which apps the agent can touch (
allowlist/blocklist/ per-tool). - Scoped spend — virtual cards are capped per card and per user; the model can’t raise its own limit.
- Human-in-the-loop — sensitive actions (cards, domains, KYC, formation, connecting an app) freeze as approvals until a human says yes.
- Scoped, expiring access — the agent holds a per-user session bearer, not your API key;
it expires (default 15 min) and you can
DELETE /v1/users/:user_id/sessions/:idto revoke it early.
Next steps
- MCP server — the hosted SSE server and its full tool list
- Sessions — per-user MCP sessions, TTL, and revocation
- Account Kits — author spend/capability policy
- Approvals — the human-in-the-loop lifecycle
- Pydantic AI · LlamaIndex — the same MCP-session pairing for other Python stacks