Frameworks and SDKs
Load quarry's tools into LangChain, LlamaIndex, the OpenAI Agents SDK, Pydantic AI, ADK, CrewAI, the AI SDK, Mastra, or model APIs.
Every framework on this page loads quarry's tools from one MCP server:
https://quarry.market/api/mcpYour agent gets search (free, across every dataset), get_dataset, ask, and
the account tools described in MCP server. The examples send an
API key so the agent can use your subscriptions.
They read it from the QUARRY_API_KEY environment variable:
export QUARRY_API_KEY=qk_...Without a key, remove the QUARRY_API_KEY line and the header or auth argument:
the agent can still search quarry and read free datasets. To pay per question from
a wallet instead, see Paying with x402.
Each example also needs its model provider's key: ANTHROPIC_API_KEY for the
Claude models used here, OPENAI_API_KEY for the OpenAI examples and CrewAI,
GOOGLE_API_KEY for Google ADK, and AI_GATEWAY_API_KEY for the Vercel AI SDK.
The TypeScript examples use top-level await, so run them as ES modules, for
example with npx tsx agent.mts.
Python
LangChain and LangGraph
LangChain's MCP support ships in the mcp extra of langchain 1.4 and later. It's
still in beta.
pip install "langchain[mcp,anthropic]>=1.4"import asyncio
import os
from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
async def main():
# auth= is sent as "Authorization: Bearer <key>".
quarry = Client("https://quarry.market/api/mcp", auth=QUARRY_API_KEY)
async with MCPAdapter(quarry) as adapter:
tools = await adapter.list_tools()
agent = create_agent("anthropic:claude-sonnet-5", tools)
result = await agent.ainvoke(
{"messages": [{"role": "user", "content": "Find sources on chip lead times and cite them."}]}
)
print(result["messages"][-1].content)
asyncio.run(main())Still on the older langchain-mcp-adapters package? It connects the same way:
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({
"quarry": {
"transport": "http",
"url": "https://quarry.market/api/mcp",
"headers": {"Authorization": f"Bearer {QUARRY_API_KEY}"},
}
})
tools = await client.get_tools() # inside an async function, as aboveLlamaIndex
pip install llama-index-tools-mcp llama-index-llms-anthropicimport asyncio
import os
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.anthropic import Anthropic
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
async def main():
quarry = BasicMCPClient(
"https://quarry.market/api/mcp",
headers={"Authorization": f"Bearer {QUARRY_API_KEY}"},
)
tools = await McpToolSpec(client=quarry).to_tool_list_async()
agent = FunctionAgent(
tools=tools,
llm=Anthropic(model="claude-sonnet-5"),
system_prompt="Answer with quarry's sources and cite them.",
)
print(await agent.run("Find sources on chip lead times and cite them."))
asyncio.run(main())OpenAI Agents SDK
pip install openai-agentsimport asyncio
import os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
async def main():
async with MCPServerStreamableHttp(
name="quarry",
params={
"url": "https://quarry.market/api/mcp",
"headers": {"Authorization": f"Bearer {QUARRY_API_KEY}"},
},
cache_tools_list=True,
# The default is 5 seconds; a search can take longer.
client_session_timeout_seconds=30,
) as quarry:
agent = Agent(
name="Researcher",
instructions="Answer with quarry's sources and cite them.",
mcp_servers=[quarry],
)
result = await Runner.run(agent, "Find sources on chip lead times and cite them.")
print(result.final_output)
asyncio.run(main())Pydantic AI
pip install "pydantic-ai-slim[mcp,anthropic]"import os
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPToolset
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
quarry = MCPToolset(
"https://quarry.market/api/mcp",
headers={"Authorization": f"Bearer {QUARRY_API_KEY}"},
)
agent = Agent("anthropic:claude-sonnet-5", toolsets=[quarry])
result = agent.run_sync("Find sources on chip lead times and cite them.")
print(result.output)MCPToolset replaced MCPServerStreamableHTTP in Pydantic AI 2.
Google ADK
pip install google-adk mcpimport os
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
root_agent = Agent(
name="researcher",
model="gemini-flash-latest",
instruction="Answer with quarry's sources and cite them.",
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://quarry.market/api/mcp",
headers={"Authorization": f"Bearer {QUARRY_API_KEY}"},
)
)
],
)ADK loads root_agent from your agent's agent.py. Start it with adk run or
adk web.
CrewAI
pip install crewai mcpimport os
from crewai import Agent
from crewai.mcp import MCPServerHTTP
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
researcher = Agent(
role="Researcher",
goal="Answer questions with quarry's sources, cited",
backstory="You search quarry and cite the passages you use.",
mcps=[
MCPServerHTTP(
url="https://quarry.market/api/mcp",
headers={"Authorization": f"Bearer {QUARRY_API_KEY}"},
streamable=True,
)
],
)
print(researcher.kickoff("Find sources on chip lead times and cite them.").raw)CrewAI uses OpenAI by default; pass llm= to the agent to change the model.
TypeScript
Vercel AI SDK
For AI SDK 7. The model string goes through the Vercel AI Gateway; use a provider
package such as @ai-sdk/anthropic to call a provider directly.
npm install ai @ai-sdk/mcpimport { createMCPClient } from "@ai-sdk/mcp";
import { generateText, isStepCount } from "ai";
const quarry = await createMCPClient({
transport: {
type: "http",
url: "https://quarry.market/api/mcp",
headers: { Authorization: `Bearer ${process.env.QUARRY_API_KEY}` },
},
});
try {
const { text } = await generateText({
model: "anthropic/claude-sonnet-5",
tools: await quarry.tools(),
stopWhen: isStepCount(5),
prompt: "Find sources on chip lead times and cite them.",
});
console.log(text);
} finally {
await quarry.close();
}The AI SDK doesn't follow redirects to an MCP server, so use the address exactly as
written: no www, no trailing slash. With streamText, close the client in
onEnd instead.
Mastra
npm install @mastra/core @mastra/mcpimport { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";
const quarry = new MCPClient({
id: "quarry",
servers: {
quarry: {
url: new URL("https://quarry.market/api/mcp"),
requestInit: { headers: { Authorization: `Bearer ${process.env.QUARRY_API_KEY}` } },
},
},
});
export const researcher = new Agent({
id: "researcher",
name: "Researcher",
instructions: "Answer with quarry's sources and cite them.",
model: "anthropic/claude-sonnet-5",
tools: await quarry.listTools(),
});
const result = await researcher.generate("Find sources on chip lead times and cite them.");
console.log(result.text);
await quarry.disconnect();Mastra prefixes each tool with the server name: quarry_search, quarry_ask, and
so on.
Model APIs
OpenAI and Anthropic can call quarry for you during a request, from their own servers. Two consequences:
- Always send an API key, even for free datasets. Without one, quarry limits requests by where they come from, and these providers send requests for many customers from the same addresses.
- These calls can't pay per question from your wallet. Paid datasets need a subscription.
OpenAI Responses API
import os
from openai import OpenAI
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
client = OpenAI() # reads OPENAI_API_KEY
response = client.responses.create(
model="gpt-6-astra",
input="Find sources on chip lead times and cite them.",
tools=[
{
"type": "mcp",
"server_label": "quarry",
"server_url": "https://quarry.market/api/mcp",
"headers": {"Authorization": f"Bearer {QUARRY_API_KEY}"},
"require_approval": "never",
}
],
)
print(response.output_text)By default, OpenAI asks for your approval before each call to quarry;
"require_approval": "never" skips that step.
Anthropic Messages API
import os
import anthropic
QUARRY_API_KEY = os.environ["QUARRY_API_KEY"]
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=2048,
messages=[{"role": "user", "content": "Find sources on chip lead times and cite them."}],
mcp_servers=[
{
"type": "url",
"url": "https://quarry.market/api/mcp",
"name": "quarry",
# Anthropic adds "Bearer " itself: pass the bare key.
"authorization_token": QUARRY_API_KEY,
}
],
tools=[{"type": "mcp_toolset", "mcp_server_name": "quarry"}],
betas=["mcp-client-2025-11-20"],
)
print("".join(block.text for block in response.content if block.type == "text"))Every server in mcp_servers needs a matching mcp_toolset entry in tools.