WEIR

Claude Agent SDK MCP: Add a Remote Server in Python and TS

Add a remote MCP server to the Claude Agent SDK with mcp_servers and a bearer header, allow only the tools you need, and read what comes back. Tested code.


Published · Updated · 7 min read

Cover image: X research on the Agent SDK

To add a remote MCP server to the Claude Agent SDK, pass its URL and an auth header in the mcp_servers option.

This guide is for developers building a research or monitoring agent. It connects Weir's MCP server for public X (Twitter) and Reddit data, in Python and TypeScript. Then it locks the agent to two tools. We run Weir.

options = ClaudeAgentOptions(
    mcp_servers={"weir": {
        "type": "http",
        "url": "https://api.weirapp.io/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['WEIR_API_KEY']}"},
    }},
    allowed_tools=["mcp__weir__search_x"],
)

How to add an MCP server to the Claude Agent SDK

You need two keys: one for Claude and one for the MCP server. Claude Code sends your header on every request to Weir, so there's no browser sign-in.

  1. Get a Weir keyCreate one under API keys in your Weir dashboard. Keep it in WEIR_API_KEY.
  2. Install the SDKpip install claude-agent-sdk, or npm install @anthropic-ai/claude-agent-sdk.
  3. Set your Claude keyAnthropic's quickstart reads ANTHROPIC_API_KEY from the environment.
  4. Run the agentPass the options to query() and loop over the messages.

As of 22 October 2026, PyPI lists claude-agent-sdk 0.2.172 and npm lists @anthropic-ai/claude-agent-sdk 0.3.308. Python needs 3.10 or later, and Node.js needs 18 or later.

Both packages bundle the Claude Code binary, so the install is big. The Python wheel alone is about 120 MB.

You can also keep the server in a .mcp.json file at your project root. Anthropic's docs say ${WEIR_API_KEY} in that file expands from the environment. This guide passes it in code, which keeps the whole setup in one script.

Claude Agent SDK remote MCP server: the Python agent

The script is about 30 lines, shown in two parts. Part one sets the options:

import os
from claude_agent_sdk import ClaudeAgentOptions

WEIR = {
    "type": "http",
    "url": "https://api.weirapp.io/mcp",
    "headers": {"Authorization": f"Bearer {os.environ['WEIR_API_KEY']}"},
}
options = ClaudeAgentOptions(
    mcp_servers={"weir": WEIR},
    tools=[],  # no built-in tools: no Bash, no file edits
    allowed_tools=["mcp__weir__search_x", "mcp__weir__get_x_post"],
    permission_mode="dontAsk",  # deny anything not listed, never prompt
    strict_mcp_config=True,  # ignore .mcp.json and user-level servers
    model="claude-sonnet-5-5", max_turns=6,
)

Why each setting is there:

  • tools=[] turns off Claude Code's built-in tools. A research agent has no need to run shell commands.
  • allowed_tools approves the Weir tools you name. Anthropic's docs say MCP tools need permission before Claude can call them.
  • permission_mode="dontAsk" denies every unlisted call without asking anyone. Anthropic's docs suggest this pair for a locked-down agent.
  • strict_mcp_config stops the agent picking up MCP servers from your project or user settings.

Part two runs the query and reads what comes back:

import asyncio
from claude_agent_sdk import AssistantMessage, ResultMessage, SystemMessage, ToolUseBlock, query

async def main(question: str) -> None:
    async for message in query(prompt=question, options=options):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            print("servers:", message.data.get("mcp_servers"))
        elif isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, ToolUseBlock):
                    print("tool:", block.name, block.input)
        elif isinstance(message, ResultMessage):
            print(message.result, message.total_cost_usd)

asyncio.run(main("What has @claudeai posted about the Agent SDK? Use limit 3."))

The init message lists each MCP server with a status. Anthropic's docs say a server can still read pending at that point, so only treat failed or needs-auth as a problem.

A server that fails to connect doesn't raise an error. The run goes on without its tools, and Claude may answer from what it already knows. So check that status before you trust an answer.

What does the agent get back?

The model's call is search_x with a handle and a phrase. We ran that same call through Weir's MCP server on 22 October 2026:

→ mcp__weir__search_x {"fromUsers": ["claudeai"],
     "query": "\"Agent SDK\" -filter:nativeretweets", "limit": 3}
← 3 posts · 4 credits · nextCursor set
  2025-12-09  156 likes  "You can now use the Agent SDK with the 1M context window..."
  2025-12-09  154 likes  "The Agent SDK now supports sandboxing..."
  2025-12-09  126 likes  "The new interface is experimental and we'd love your feedback..."

All three came from one thread. Each post also carries its url, so the answer can link every claim.

Weir bills 1 credit per call plus 1 per X post, and failed calls are free:

4credits for the search above
11credits for a 10-post search
~900characters of JSON per post in our test
5,000free Weir credits every month

Paid packs start at $5 for 25,000 credits and never expire, as of October 2026. Anthropic bills your model tokens on its own. Every Weir rate is on our pricing page.

The same agent in TypeScript

The options keep their names, in camelCase:

import { query } from "@anthropic-ai/claude-agent-sdk";

const auth = { Authorization: `Bearer ${process.env.WEIR_API_KEY}` };
for await (const message of query({
  prompt: "What has @claudeai posted about the Agent SDK? Use limit 3.",
  options: {
    mcpServers: { weir: { type: "http", url: "https://api.weirapp.io/mcp", headers: auth } },
    tools: [],
    allowedTools: ["mcp__weir__search_x", "mcp__weir__get_x_post"],
    permissionMode: "dontAsk",
    strictMcpConfig: true,
    model: "claude-sonnet-5-5",
    maxTurns: 6,
  },
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

The TypeScript type for an HTTP server also takes a timeout in milliseconds for each tool call.

Both SDKs hand your server config to the Claude Code process as a --mcp-config argument, header included. We saw that in the 0.2.172 source and the 0.3.308 bundle. On a shared machine, treat the process list as a place your Weir key can show up.

Which Claude Agent SDK tools can the agent see?

A default Weir key sees more than 40 tools, Reddit included. Pick the setting by what you want to stop:

Setting What it does
allowed_tools Approves the tools you name
dontAsk mode Denies every unlisted call
disallowed_tools Removes a tool from Claude's context
tools=[] Removes Bash, Read, Edit and the rest
Weir key without Reddit Weir stops listing its 12 Reddit tools

Our pick is the first two plus a key that can only read X. Untick Reddit when you create the key, and the agent never sees those tools.

If it doesn't work

  • The status reads needs-auth or failed. Check WEIR_API_KEY in the shell that runs the agent. Weir answers a missing or bad key with a 401 sign-in challenge, which the SDK can't complete.
  • Claude sees the tool but never calls it. Add its full mcp__weir__ name to allowed_tools.
  • TypeScript rejects "streamable-http". The SDK types declare only "http" for this transport, as our tsc run showed.
  • A big search comes back as a file path. Claude Code saves results over 50,000 characters to a file, and with tools=[] the agent has no Read tool to open it. Keep limit at 20 or less.
  • The first turn waits, then fails. Anthropic's docs give MCP connections 30 seconds. Raise the MCP_TIMEOUT environment variable, in milliseconds.
  • A tool returns 402. Your Weir credits ran out, and retrying won't help.

When not to use Weir

  • Your agent has to post or DM on X. Weir is read-only.
  • You want private data. Weir reads public posts, not bookmarks, DMs or home timelines.
  • Price per post matters most. TwitterAPI.io lists $0.15 per 1,000 tweets as of October 2026, less than our $5 pack.
  • You need a guarantee. Weir isn't licensed by X or affiliated with it, so access can change.

FAQ

Does the Claude Agent SDK support remote MCP servers?

Yes. Pass the server under mcp_servers with "type": "http", its URL and any headers. Anthropic's docs also cover SSE servers, local stdio servers and in-process SDK servers.

How are MCP tools named in the Claude Agent SDK?

Each one is mcp__<server>__<tool>, so Weir's search tool is mcp__weir__search_x. The server part is your key in mcp_servers. Anthropic's docs say dots and spaces in that name become underscores.

How do I allow MCP tools in the Claude Agent SDK?

List each tool as mcp__<server>__<tool> in allowed_tools, or use mcp__weir__* for a whole server. Pair it with permission_mode="dontAsk" so anything you didn't list is denied.

Can the Claude Agent SDK sign in to an MCP server with OAuth?

Not by itself. Anthropic's docs say the SDK won't open a browser, so a server that needs sign-in reports needs-auth. Send a token in headers instead. Weir takes an API key there.

Should I use the Agent SDK or the Claude API's MCP connector?

Use the connector for a plain model call with tools: Anthropic's cloud calls Weir, and you run no binary. Pick the Agent SDK when you want Claude Code's loop, hooks and sessions in your own process. Weir's docs show the connector call.

Sources