Locus product guide · Updated
LangChain MCP: connect paid tools to agents
To give a LangChain agent paid tools over MCP, load the Locus Pro hosted server with MCPAdapter and pass the tools to create_agent. Point it at https://api.paywithlocus.com/api/credits/mcp and send an agent key as a bearer token. A first paid call, such as a Brave web search, costs 30.3 credits, about $0.03. Search, describe and balance checks are free.
Setup, step by step
Step 1
Create an agent key
In the Locus Pro dashboard, open Connect, then API keys, then An agent. Pick the tools the agent may call, a credit cap per call and an expiry. Store the lcac_ key in your secret manager. Your LangChain code gets only this key, never the lcr_ secret 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
Python needs langchain 1.4.0 or later with the mcp extra. The langchain.mcp namespace is in beta, so its API may change. TypeScript needs @langchain/mcp-adapters 2.0 or later.
pip install "langchain[mcp]" # TypeScript npm install @langchain/mcp-adapters@^2.0.0 @langchain/core @langchain/langgraph langchain
Step 3
Connect in Python
LangChain hands auth to a FastMCP Client. A plain string in auth is sent as an Authorization: Bearer header, so pass the bare lcac_ key. The tools keep their client, so the agent still works after the async with block ends.
import os from fastmcp.client import Client from langchain.agents import create_agent from langchain.mcp import MCPAdapter async def main(): client = Client(os.environ["LOCUS_MCP_URL"], auth=os.environ["LOCUS_AGENT_CONNECTION"]) async with MCPAdapter(client) as adapter: tools = await adapter.list_tools() agent = create_agent("claude-sonnet-5", tools) return await agent.ainvoke({"messages": [{"role": "user", "content": "What is my Locus balance?"}]})Step 4
Or connect in TypeScript
Each server under servers takes its own headers. The adapter prefixes tool names with the server key, so the Locus execute tool reaches the model as locus_pro_execute. Close the adapter when the run ends.
import { MCPAdapter } from "@langchain/mcp-adapters"; import { createAgent } from "langchain"; const adapter = new MCPAdapter({ servers: { locus_pro: { url: process.env.LOCUS_MCP_URL!, headers: { Authorization: `Bearer ${process.env.LOCUS_AGENT_CONNECTION}` }, }, }, }); try { const tools = await adapter.listTools(); const agent = createAgent({ model: "claude-sonnet-5", tools }); const result = await agent.invoke({ messages: [{ role: "user", content: "What is my Locus balance?" }], }); console.log(result.messages.at(-1)?.text); } finally { await adapter.close(); }Step 5
Make a first paid call
Name the endpoint and a price ceiling in the prompt. The agent calls execute with max_credits, and the result reports credits_charged and credits_balance. Use any model your LangChain setup supports in place of the one shown.
Use brave/web-search to find three recent articles about MCP security. Pass max_credits 35 and tell me the credits charged.
Which Locus credential should a LangChain agent use?
Use an agent key. LangChain code usually runs unattended in a service, a job or a worker, and nobody is there to approve a browser sign-in. Browser OAuth is for interactive clients such as Claude Code or Cursor.
LangChain's Python adapter can run OAuth with auth="oauth", but it holds tokens in memory by default, so each run repeats the browser step. An agent key avoids that and carries its own tool list, per-call cap and expiry. Give each deployment its own key so you can revoke one without touching the others.
| Credential | Use it for | Where it lives |
|---|---|---|
| Agent key (lcac_) | LangChain services, jobs and workers | The runtime secret manager |
| Browser OAuth | A person using a desktop or coding client | The MCP client's own token store |
| Secret key (lcr_) | Your backend code that creates agent keys | A trusted server, never the agent |
How do I cap what one LangChain tool call can spend?
Set the cap in three places. The per-call limit on the agent key is enforced by Locus, and the model cannot change it. A call priced above it fails with agent_connection_call_limit_exceeded and nothing runs.
The max_credits argument on execute sets a ceiling for one call. A call above the ceiling fails with nothing charged. The model writes that argument, so treat it as a request, not a guarantee.
LangChain middleware adds a third layer. A @wrap_tool_call middleware sees every tool call before it runs and can rewrite it, so it can add max_credits to each execute call. HumanInTheLoopMiddleware can pause execute calls for a person to approve. Workspace spend caps are opt-in on top of these.
What does a first paid call cost through Locus Pro?
Each call is charged the catalog price for that endpoint. 1,000 credits equal $1. Search, describe, price quotes and balance checks are free. Prices checked November 10, 2026.
A worked example: a research question that runs 1 Brave search and 2 Firecrawl scrapes costs at most 30.3 + 38.6 + 38.6 = 107.5 credits, about $0.11. 100 questions cost at most $10.75. The Plus plan includes $20 of credits each billing period, which covers about 186 questions at that worst case.
| Endpoint | Locus price | Price type | Good first test |
|---|---|---|---|
| brave/web-search | 30.3 credits ($0.0303) | Fixed | Web results for one query |
| perplexity/search | Up to 5.8 credits | Variable, capped | Ranked results with dates |
| firecrawl/search | 1.7 credits ($0.0017) | Flat per call | Search plus scraped pages |
| tavily/search | 80.8 to 151.5 credits | Set by request | Results with an optional answer |
Which errors show up in LangChain, and what do they mean?
In Python, a Locus error comes back as an MCP result with isError set. The adapter turns it into a ToolMessage with status="error", so the model reads it and can recover. Transport or session failures raise instead.
In TypeScript, a rejected credential during discovery throws MCPClientError. A rejection during a tool call becomes a ToolException, and under createAgent the model sees it as an error message.
| Error | Cause | Fix |
|---|---|---|
| 401 or UnauthorizedError | Key missing, revoked or sent as "Bearer Bearer" | In Python pass the bare key to auth; the client adds Bearer |
| charge_ceiling_exceeded | Price is above max_credits | Raise max_credits or pick a cheaper endpoint; nothing was charged |
| agent_connection_call_limit_exceeded | Price is above the per-call cap on the key | Raise the cap on the key or use another tool |
| credential_endpoint_denied | The tool is not on the key’s list | Add the tool to the agent key |
| Insufficient credits (HTTP 402) | Balance is below the call price | Add credits, then retry the same call |
| tenant_rate_limited | Plan limit reached: 5 paid calls a minute on Free, 15 on Plus | Wait retryAfter seconds; nothing ran |
Should a LangChain agent use Locus Pro or a provider’s own integration?
Pick by how many providers the agent needs and how steady the volume is.
- Use Locus Pro when one agent needs search, scraping, enrichment or data from several providers, and you do not want an account and key for each.
- Use Locus Pro when volume is low or bursty, since there is no plan minimum and purchased credits do not expire.
- Use a provider’s own LangChain integration when one provider covers the job at steady, high volume. A Brave search, for example, can cost less per call with your own Brave account and API key.
- Use a LangChain @tool function when the logic is your own code and needs no paid API at all.
Frequently asked questions
Does langchain-mcp-adapters still work for LangChain MCP?
In Python, MCP support now ships inside LangChain as langchain.mcp, and MCPAdapter replaces MultiServerMCPClient. The migration guide maps the old transport and headers settings to the new client. In TypeScript, the package is still @langchain/mcp-adapters, and version 2.0 uses MCPAdapter.
Can I reuse these tools in a LangGraph graph?
Yes. create_agent builds a LangGraph agent, and the tools from MCPAdapter are standard LangChain tools. You can pass the same list to a ToolNode in your own StateGraph.
Why does my LangChain agent never call a Locus tool?
Print the names from list_tools first. If the list is empty, check the URL and the key. If the tools are there, name the endpoint in the prompt, for example brave/web-search, so the model knows a paid tool fits the task.
Do I pay for the tools LangChain lists at startup?
No. Listing tools, searching the catalog, describing an endpoint and checking the balance are free. Credits move only when execute runs a paid endpoint.
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.