LangChain (Python)
Call the Crypto Brain from a LangChain (Python) agent. Two paths:
- Native Python MCP (
bca-mcpon PyPI): 8 read-only tools, same REST API, same envelope. Fastest path for pure-Python shops. - TypeScript server via stdio: spawns
@blockchainacademics/mcpas a subprocess throughlangchain-mcp-adapters. Gets you all 105 tools.
Both feed the same api.blockchainacademics.com backend. Pick whichever matches your deployment story.
Path A: native bca-mcp (8 tools, pure Python)
bash
pip install bca-mcp langchain langchain-openai langchain-mcp-adapterspython
import asyncio
import os
import sys
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
async def main() -> None:
params = StdioServerParameters(
command=sys.executable,
args=["-m", "bca_mcp"],
env={**os.environ, "BCA_API_KEY": os.environ["BCA_API_KEY"]},
)
async with stdio_client(params) as (r, w), ClientSession(r, w) as s:
await s.initialize()
tools = await load_mcp_tools(s)
print(f"Loaded {len(tools)} BCA tools")
agent = create_react_agent(ChatOpenAI(model="gpt-4o-mini"), tools)
result = await agent.ainvoke({
"messages": [("user",
"Using BCA tools, list the top 3 stories about stablecoin "
"regulation this month with citations.")]
})
print(result["messages"][-1].content)
if __name__ == "__main__":
asyncio.run(main())Wrapping specific tools as LangChain Tools directly
python
from langchain.tools import StructuredTool
# After load_mcp_tools(session) you get a list of StructuredTool objects;
# pick the ones you want rather than passing all 8 to the agent:
search_news = next(t for t in tools if t.name == "search_news")
get_entity = next(t for t in tools if t.name == "get_entity")
get_price = next(t for t in tools if t.name == "get_price")
agent = create_react_agent(ChatOpenAI(model="gpt-4o-mini"),
[search_news, get_entity, get_price])Narrow tool surfaces keep reasoning loops tight and predictable: recommended for production agents.
Path B: TypeScript server via stdio (every tool)
1. Install
bash
pip install langchain langchain-openai langchain-mcp-adapters
# Node 18+ required for the stdio subprocess
node --version2. Set your API key
bash
export BCA_API_KEY="bca_live_xxxxxxxxxxxxxxxx"3. Spin up the agent
python
import asyncio
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
async def main() -> None:
async with MultiServerMCPClient(
{
"blockchainacademics": {
"command": "npx",
"args": ["-y", "@blockchainacademics/mcp"],
"transport": "stdio",
"env": {"BCA_API_KEY": os.environ["BCA_API_KEY"]},
}
}
) as client:
tools = await client.get_tools()
print(f"Loaded {len(tools)} BCA tools")
agent = create_react_agent(
ChatOpenAI(model="gpt-4o-mini"),
tools,
)
result = await agent.ainvoke(
{
"messages": [
(
"user",
"Using BCA tools, list the top 3 news stories about "
"stablecoin regulation this month with citations.",
)
]
}
)
print(result["messages"][-1].content)
if __name__ == "__main__":
asyncio.run(main())Run it:
bash
python bca_agent.pyWhat you get back
Every tool response is wrapped in the canonical envelope (over MCP, data arrives as a fenced string; see Parse the envelope):
python
{
"data": [ ... ], # tool payload
"attribution": {
"citations": [
{
"cite_url": "https://blockchainacademics.com/article/...?src=langchain",
"as_of": "2026-04-20T09:31:22Z",
"source_hash": "sha256:a9f1...",
}
]
},
"meta": {
"status": "complete",
"request_id": "req_01HABCDEF0123456789ABCDEFG",
"pageInfo": {
"hasNextPage": False,
"hasPreviousPage": False,
"startCursor": None,
"endCursor": None,
},
},
}Parse attribution.citations[0].cite_url into your agent's final answer so downstream users can verify the claim.
Tips
- Rate limits: every plan has a per-second rate limit and a monthly quota (see Pricing). Agent loops with tool retries burn through them quickly: cache aggressively or upgrade.
- Long-running jobs:
generate_due_diligenceandgenerate_tokenomics_modelenqueue agent jobs that return a job id; pollget_agent_jobuntil the job is done. See the Tool reference. - Attribution: every
cite_urlcarries UTM parameters that identify the integration. Nothing to add on your side; just surface the link.