Connect from LangGraph
Give a LangGraph agent policy-scoped, read-only access to your bank accounts through the agentis MCP server — about twenty lines of code, one API key, no OAuth flow.
# Overview
The agentis MCP server speaks Streamable HTTP at https://mcp.agentis.capital/mcp and authenticates server-to-server clients with a single Bearer header. LangGraph consumes it through langchain-mcp-adapters, which turns the server's tools — list_accounts, list_account_transactions, check_account_balance, and the rest of the toolset — into ordinary LangChain tools your agent can call.
The OAuth flow described in the MCP server reference exists for interactive clients where a human approves the connection in a browser. For headless deployments — a LangGraph service, a cron job, a worker — use an agent API key directly; it's the pattern the MCP spec anticipates for machine-to-machine clients.
You'll need:
- An agentis workspace with a connected bank account (setup guide)
- An agent created in the dashboard, with bank accounts assigned to it
- Python ≥ 3.10 with
langgraph≥ 1.0,langchain≥ 1.0,langchain-mcp-adapters≥ 0.3, and the integration package for whichever model provider you use — the MCP server is model-agnostic, and any chat model with solid tool calling works
# Get an agent API key
Every key is agent-scoped and bound to exactly one agent — it inherits that agent's policy and bank-account assignments. Two ways to issue one:
- Dashboard — under API Keys, choose Generate Key, pick the agent, and name the key after the deployment that will hold it.
- Self-registration — run
agentis registeron the machine that will host the agent. The CLI prints a verification code, an admin approves it in the browser, and the CLI receives the key.
agts_agent_live_…) is shown exactly once at creation. Copy it straight into your secret store; if you lose it, rotate the agent's key to get a new one.
Keys don't expire on their own — they stay valid until you revoke or rotate them from the dashboard. See Bearer API key in the server reference for prefix semantics.
# Connect
pip install langgraph langchain langchain-mcp-adapters
pip install langchain-anthropic # or langchain-openai, langchain-google-genai, ...
Export the agent key as an environment variable, plus your model provider's API key (ANTHROPIC_API_KEY, OPENAI_API_KEY, …), then:
import asyncio import os from langchain.agents import create_agent from langchain_mcp_adapters.client import MultiServerMCPClient # Example model — any provider works: "openai:...", "google_genai:...", ... MODEL = "anthropic:claude-sonnet-5" async def main(): client = MultiServerMCPClient({ "agentis": { "transport": "http", # Streamable HTTP "url": "https://mcp.agentis.capital/mcp", "headers": {"Authorization": f"Bearer {os.environ['AGENTIS_AGENT_API_KEY']}"}, } }) tools = await client.get_tools() agent = create_agent( MODEL, tools, system_prompt="You are a finance assistant with read-only access " "to the company's bank accounts.", ) result = await agent.ainvoke( {"messages": [{"role": "user", "content": "Summarize last week's transactions."}]} ) print(result["messages"][-1].content) asyncio.run(main())
That's the whole integration. The MCP client underneath handles the Mcp-Session-Id round-trip, the dual Accept header, and streamed responses for you.
- The model is just an example.
create_agenttakes a"provider:model"string (resolved through the matchinglangchain-<provider>package) or any chat-model instance — swap in whatever your stack runs. - Use
create_agentfromlangchain.agents—langgraph.prebuilt.create_react_agentis deprecated since LangGraph 1.0. - Compute concrete dates in code and put them in the prompt (“between 2026-07-08 and 2026-07-15”) rather than letting the model interpret “last week”.
- To verify the connection before wiring up a model:
await client.get_tools()should return the full toolset, and callingview_identityconfirms which agent the key is bound to.
# Routers and local models
The same agent runs on a multi-model router or a model hosted on your own hardware. One rule to know: a "provider:model" string only works for providers LangChain can resolve from the prefix alone — anything that needs a base_url or a gateway key takes a model instance instead.
# OpenRouter — one key, hundreds of models (pip install langchain-openrouter) from langchain_openrouter import ChatOpenRouter model = ChatOpenRouter(model="anthropic/claude-sonnet-5") # reads OPENROUTER_API_KEY # Ollama — local open-source models (pip install langchain-ollama) model = "ollama:qwen3" # string form works; ChatOllama(...) for a remote host or options # vLLM, LM Studio, llama.cpp — any OpenAI-compatible server (pip install langchain-openai) from langchain_openai import ChatOpenAI model = ChatOpenAI(model="qwen3", base_url="http://localhost:8000/v1", api_key="EMPTY") agent = create_agent(model, tools, system_prompt="...")
- Tool calling is non-negotiable. Every agentis operation is a tool call, so the model must support tools reliably. On OpenRouter, filter the model list by tool support; in the Ollama library, use the tools capability tag. Small models tend to mis-parse tool schemas — prefer mid-size and larger models; as of mid-2026, Qwen3 (14B+), Llama 3.1+, and Mistral Small are solid starting points.
- Local models keep your prompts local. With a self-hosted model, prompts, reasoning, and tool results never leave your infrastructure — only the tool calls themselves reach the agentis MCP server, and those stay policy-scoped and read-only either way.
# Handle the key safely
The design principle: the key lives in the transport layer, never in the model's context. The LLM sees tool schemas, the arguments it generates, and tool results — the Authorization header is attached by the MCP client when the tool call executes. A model can't leak a credential it never sees. Keeping it that way in a long-running deployment:
- Inject from the environment or a secret manager. Never hardcode the key or commit it. On LangGraph Platform, use workspace environment secrets.
- Keep it out of graph state. LangGraph checkpointers persist the full state — messages, tool arguments, tool results — and replay it into the context window. Anything placed in state is effectively shown to the model and stored durably. Configure the key on the
MultiServerMCPClientat startup; never thread it through state, prompts, or tool arguments. - Mind tracing. LangSmith records tool arguments and results (not transport headers). If your tool traffic is sensitive, use its hide-inputs/outputs settings or anonymizer hooks.
- One deployment, one agent, one key. Revoking a key then kills exactly one integration. Rotate from the agent's page in the dashboard — rotation issues a new key and immediately revokes the old one, so plan a secret update alongside.
- The policy is the real guardrail. Hiding the key limits exfiltration, not use: the model can invoke whatever the key authorizes, and tool results are untrusted input. Scope the agent's data-access policy and account assignments to the minimum the job needs — that's enforced server-side on every call.
- Short-lived credentials, if you need them. The connection config also accepts an
authfield (anhttpx.Auth) instead of staticheaders— pair it with the OAuth token endpoint for rotating 60-minute access tokens. For most headless deployments, a static key plus rotation is the right trade-off.
# Handle errors
Tool failures come back as structured JSON your agent can route on — reason says why, action says what to do:
{
"reason": "transient_bank_error",
"action": "retry_with_backoff",
"retry_after_seconds": 30,
"hint": "Bank had a transient error or timed out. Retry with exponential backoff starting at ~30s."
}
A capable model will follow these envelopes on its own; for deterministic behavior, handle retry_with_backoff and wait_then_retry in a tool-wrapping layer and surface escalate reasons (like session_expired — the bank consent needs admin re-authorization) to a human. The full enum lives in the server reference.
At the transport level, 401 means the key is invalid or revoked — fix the credential, don't retry. Expect sub-second latency on most tool calls.