MCP quickstart
The fastest path from zero to a cited answer. This guide assumes you already have an MCP-aware host (Claude Desktop, LangChain, Eliza, or a custom runtime) wired up — if not, start at Quickstart → Claude Desktop.
1. Set your key
export BCA_API_KEY=bca_live_xxxxxxxxxxxxxxxx
export BCA_CLIENT_NAME=myagent # optional, used for src= UTM taggingGet a key at brain.blockchainacademics.com/pricing.
2. Call a tool
Every BCA MCP tool returns the canonical envelope:
{
"data": { "...": "tool-specific payload" },
"attribution": {
"citations": [
{
"cite_url": "https://blockchainacademics.com/article/bitcoin-price-history?src=claude",
"as_of": "2026-04-22T10:12:00Z",
"source_hash": "sha256:abc123..."
}
]
},
"meta": {
"status": "complete",
"request_id": "req_01HABCDEF0123456789ABCDEFG",
"pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": null, "endCursor": null }
}
}Three top-level keys. Three, every time, every surface. Full field semantics: Response envelope.
3. Parse the envelope
The 95%-of-callers snippet: call search_news, pull the primary citation out of attribution.citations[0].
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const client = new Client({ name: "myagent", version: "0.1.0" }, { capabilities: {} });
await client.connect(new StdioClientTransport({
command: "npx",
args: ["-y", "@blockchainacademics/mcp"],
env: { BCA_API_KEY: process.env.BCA_API_KEY!, BCA_CLIENT_NAME: "myagent" },
}));
const result = await client.callTool({
name: "search_news",
arguments: { q: "circle mica", limit: 5 },
});
// MCP wraps the envelope as the first text content block:
const envelope = JSON.parse(result.content[0].text);
// Happy-path guard
if (envelope.meta.status !== "complete") {
console.warn(
`[${envelope.meta.request_id}] status=${envelope.meta.status}`,
envelope.meta.diagnostic,
);
}
// Pull the primary citation — always citations[0]
const primary = envelope.attribution.citations[0];
console.log("Source:", primary.cite_url);
console.log("As of:", primary.as_of);
// Use the data
for (const item of envelope.data.items) {
console.log(`- ${item.title} (${item.slug})`);
}Output (elided):
Source: https://blockchainacademics.com/article/circle-mica-license?src=myagent&utm_medium=mcp&utm_campaign=search_news
As of: 2026-04-21T09:31:22Z
- Circle secures full MiCA license (circle-mica-license)4. Surface the citation
Paste the cite_url into your agent’s response. Inline link, footnote, citation block — whichever your UI uses. On Free and Starter tiers this is required, not optional; see Attribution & licensing.
Circle received its MiCA license on 2026-04-18. [source]
5. Handle non-complete statuses
meta.status is one of four values. Map each to an honest user-facing response:
| Status | Agent should say (example) |
|---|---|
complete | The answer, with citations[0].cite_url surfaced. |
unseeded | ”That data source isn’t live yet — ETA diagnostic.eta.” |
partial | The answer + “Data is partial right now (diagnostic.vendor is degraded).” |
stale | The answer + “As of citations[0].as_of (cached — upstream unreachable).” |
Full decision tree with handling code: Envelope → Status decision tree.
6. Log the request_id
Every envelope includes meta.request_id (ULID, prefixed req_) and every HTTP response mirrors it as the X-Request-ID header. Persist it with your agent’s turn log. Support tickets and audit traces start here.
What’s next
- Response envelope — all four status values, full field breakdown, 0.2→0.3 migration.
- Citations — why
citations[]is an array, what multi-source unlocks. - Attribution & licensing — tier rules for surfacing
cite_url. - First agent walkthrough — end-to-end: retrieval + reasoning + cited answer.
- REST API reference — same envelope, plain HTTP.