The Claude Agent SDK supports MCP servers natively. Pass Runlayer MCP servers to query() and allow their tools with allowedTools.
Installation
npm install @anthropic-ai/claude-agent-sdk
Set your Anthropic API key:
export ANTHROPIC_API_KEY=your-anthropic-key
HTTP Transport (Production)
Use HTTP transport for production deployments with remote MCP servers:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Get info about the vercel/ai repository",
options: {
mcpServers: {
github: {
type: "http",
url: "https://mcp.runlayer.com/github-a1b2c3/mcp",
headers: {
"x-runlayer-api-key": process.env.RUNLAYER_API_KEY!
}
}
},
allowedTools: ["mcp__github__*"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
The server key sets the tool prefix. A server named github exposes tools as mcp__github__<tool>, so mcp__github__* allows all tools from that server.
Python Example
The Python SDK uses the same mcp_servers and allowed_tools shape:
import asyncio
import os
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"type": "http",
"url": "https://mcp.runlayer.com/github-a1b2c3/mcp",
"headers": {"x-runlayer-api-key": os.environ["RUNLAYER_API_KEY"]},
}
},
allowed_tools=["mcp__github__*"],
)
async for message in query(
prompt="Get info about the vercel/ai repository",
options=options,
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())
Multiple MCP Servers
Add each server to mcpServers and allow each server’s tools:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Create a GitHub issue and a Linear ticket for the bug report",
options: {
mcpServers: {
github: {
type: "http",
url: "https://mcp.runlayer.com/github-a1b2c3/mcp",
headers: { "x-runlayer-api-key": process.env.RUNLAYER_API_KEY! }
},
linear: {
type: "http",
url: "https://mcp.runlayer.com/linear-d4e5f6/mcp",
headers: { "x-runlayer-api-key": process.env.RUNLAYER_API_KEY! }
}
},
allowedTools: ["mcp__github__*", "mcp__linear__*"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
Agent Accounts
Use Agent Accounts when your Claude app should authenticate as an agent, not a user API key. Fetch an M2M token, then pass it to Runlayer’s MCP proxy:
import { query } from "@anthropic-ai/claude-agent-sdk";
const tokenResponse = await fetch(`${process.env.RUNLAYER_URL}/api/v1/oauth/token`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: process.env.RUNLAYER_CLIENT_ID!,
client_secret: process.env.RUNLAYER_CLIENT_SECRET!
})
});
const { access_token: accessToken } = await tokenResponse.json();
for await (const message of query({
prompt: "List recent GitHub issues",
options: {
mcpServers: {
github: {
type: "http",
url: `${process.env.RUNLAYER_URL}/api/v1/proxy/${process.env.SERVER_ID}/mcp`,
headers: { Authorization: `Bearer ${accessToken}` }
}
},
allowedTools: ["mcp__github__*"]
}
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
For on-behalf-of user calls, pass the delegated user’s email as subject_token:
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: process.env.RUNLAYER_CLIENT_ID!,
client_secret: process.env.RUNLAYER_CLIENT_SECRET!,
subject_token: userEmail,
subject_token_type: "urn:runlayer:token-type:user-email"
})
See Agent Account Authentication Recipes for UUID and WorkOS OBO variants.
Resources