Locus product guide · Updated
LangGraph tools: add paid MCP tools to a graph
LangGraph runs tools in a ToolNode, and create_agent builds that loop for you. To add paid tools, load the Locus Pro hosted MCP server with LangChain's MCPAdapter, bind the tools to your model and pass the same list to ToolNode. Authenticate with an agent key sent as a bearer token. A Perplexity search through Locus Pro then costs up to 5.8 credits, about $0.006 per call.
Setup, step by step
Step 1
Create an agent key for the graph
In the Locus Pro dashboard, open Connect, then API keys, then An agent. Choose the tools this graph may call, a credit cap per call and an expiry. Keep the lcac_ key in your secret manager and give each deployment its own key.
export LOCUS_AGENT_CONNECTION="lcac_..." # agent key, from your secret store export LOCUS_MCP_URL="https://api.paywithlocus.com/api/credits/mcp"
Step 2
Install LangChain with MCP support
MCPAdapter lives in langchain.mcp, which needs langchain 1.4.0 or later with the mcp extra and is in beta. LangChain's create_agent runs on LangGraph, and the graph classes below come from the langgraph package.
pip install "langchain[mcp]"
Step 3
Load the Locus tools
MCPAdapter discovers the tools and adapts them into LangChain tools. The tools hold their client, so they stay callable after the async with block exits. Each call opens its own MCP session.
import os from fastmcp.client import Client from langchain.mcp import MCPAdapter async def load_locus_tools(): client = Client(os.environ["LOCUS_MCP_URL"], auth=os.environ["LOCUS_AGENT_CONNECTION"]) async with MCPAdapter(client) as adapter: return await adapter.list_tools()Step 4
Wire the tools into a StateGraph
Bind the tools to your chat model and give the same list to ToolNode. The conditional edge sends the run to the tools node while the model keeps asking for tools, then ends.
from langgraph.graph import MessagesState, StateGraph, START, END from langgraph.prebuilt import ToolNode def build_graph(llm, tools): llm_with_tools = llm.bind_tools(tools) def llm_call(state: MessagesState): return {"messages": [llm_with_tools.invoke(state["messages"])]} def should_continue(state: MessagesState): return "tools" if state["messages"][-1].tool_calls else END builder = StateGraph(MessagesState) builder.add_node("llm_call", llm_call) builder.add_node("tools", ToolNode(tools)) builder.add_edge(START, "llm_call") builder.add_conditional_edges("llm_call", should_continue, ["tools", END]) builder.add_edge("tools", "llm_call") return builder.compile()Step 5
Run a first paid call
Here llm is any LangChain chat model that supports tool calling. MCP tools are async, so run the graph with ainvoke. Name the endpoint and a ceiling. The execute result reports credits_charged and credits_balance.
graph = build_graph(llm, await load_locus_tools()) result = await graph.ainvoke({"messages": [{"role": "user", "content": "Use perplexity/search for news on EU AI Act enforcement. Pass max_credits 6 and report the charge."}]})
What are tools in LangGraph?
A tool is a function with a name, a description and an input schema. The model returns a tool call, and LangGraph runs it in a ToolNode. ToolNode handles parallel tool calls, errors and state injection. Tools can read graph state through ToolRuntime.
Tools come from four places. The difference is who holds the credentials and who bills you.
| Tool source | How you add it | Credentials | Who bills you |
|---|---|---|---|
| @tool function | Decorate a Python function | Whatever your code uses | Nobody, unless it calls an API |
| LangChain integration package | Import the integration | That provider's API key | Each provider separately |
| Any MCP server | MCPAdapter.list_tools() | The server's auth scheme | The server's own terms |
| Locus Pro hosted MCP | MCPAdapter with an agent key | One lcac_ key | Prepaid Locus Pro credits |
Should I use create_agent or my own StateGraph?
Start with create_agent. It builds the same model and ToolNode loop as the graph above, and LangChain middleware works with it. A @wrap_tool_call middleware can rewrite each call, and HumanInTheLoopMiddleware can pause chosen tools for approval.
Write your own StateGraph when you need custom routing. One example is a node that checks the price of a pending execute call before the tools node runs it. ToolNode only sees the state you pass it, so pass the full state when tools need custom fields.
What happens to paid calls when a graph retries or resumes?
LangGraph can checkpoint a run and resume it. LangChain notes that resuming a paused MCP call reruns the tool from the beginning, so a paid call can be sent twice.
Locus limits the damage. An identical execute call within one minute replays the stored result with no new charge and returns idempotent_replay. The result also carries the idempotency key it used. Resend that key to retry later without paying twice. For long results, call get_call_result with the call ID instead of repeating the paid call.
What does one research run cost through Locus Pro?
Prices below come from the Locus catalog. 1,000 credits equal $1. Prices checked November 10, 2026.
A run with 2 Perplexity searches and 3 Firecrawl scrapes costs at most 11.6 + 115.8 = 127.4 credits, about $0.13. At 50 runs a day, the worst case is about $6.37 a day.
Both providers run on one agent key and one credit balance. You need no Perplexity or Firecrawl account and no monthly plan, which suits low or uneven volume.
| Endpoint | Locus price | What it returns |
|---|---|---|
| perplexity/search | Up to 5.8 credits | Ranked results with titles, URLs and dates |
| firecrawl/scrape | 1 to 38.6 credits, by request | One page as markdown or structured data |
| firecrawl/map | 1 credit ($0.001) | Every URL on a site, without content |
| router/web-search | 1 to 10.1 credits | Deduplicated sources from several search providers |
How do I keep a LangGraph agent inside a budget?
Put the hard limit on the agent key. Its per-call cap is checked by Locus before the provider is called, and the model cannot raise it. Inside each call, max_credits sets a ceiling, and a call above it fails with nothing charged.
For a budget per run, the key can carry a limit per loop. Then every paid call must include loop_id. Add the graph run ID as loop_id in a @wrap_tool_call middleware or a gate node, so the model never has to remember it.
Which Locus errors should a LangGraph app handle?
A Locus error arrives as an MCP result with isError set. The adapter turns it into a ToolMessage with status="error", and the graph goes on so the model can react. A transport or session failure raises and stops the run.
| Error | Meaning | What the graph should do |
|---|---|---|
| tenant_rate_limited | Plan limit: 5 paid calls a minute on Free, 15 on Plus, 240 on Enterprise, 1,200 on Enterprise Plus | Wait retryAfter seconds, then resend the same call |
| POLICY_LOOP_ID_REQUIRED | The key has a per-loop limit | Add loop_id to every paid call |
| request_in_progress | The same call is still running | Poll the result; do not send a new call |
| Insufficient credits | Balance is too low | Stop the run and add credits |
When is Locus Pro the wrong tool source for LangGraph?
Skip it when a single provider covers the job at steady volume, since a search or scrape can cost less per call with your own Perplexity or Firecrawl account and API key. Skip it for logic that needs no paid API; a @tool function is simpler.
Use it when one graph calls several paid providers, when you want one balance with a ceiling on every call, or when you would rather not run a subscription for each provider.
Frequently asked questions
Do I need ToolNode to use MCP tools in LangGraph?
No. create_agent wires up tool execution for you. In a custom StateGraph, ToolNode is the prebuilt option, or you can write your own node that invokes each tool call.
Can LangGraph.js connect to the same Locus server?
Yes. Use MCPAdapter from @langchain/mcp-adapters 2.0 with the Locus URL and an Authorization header that holds the agent key, then pass the tools to your graph.
Does every tool call open a new MCP session?
In Python, yes by default. The adapter tools open a session per call and close it after. Keep the adapter context open around the graph call if you want one session held for the whole run.
How do I serve a LangGraph agent with Locus tools in a deployment?
Build the agent inside a graph factory so each run discovers the current tools. LangChain suggests a shared connection pool and list_tools with cache_mode use to avoid re-listing tools on every run.
Implementation references
Use these first-party references for current request contracts and account requirements. Tool availability, prices, and negotiated terms can change.
Sources
Third-party details were checked on November 10, 2026. Vendors change pricing and features often, so confirm on their site before you decide.