WEIR

Mastra MCP Client: Connect a Remote Server with Headers

Set up Mastra MCP tools from a remote server: MCPClient with a bearer header, listTools vs listToolsets, a 401 that fails quietly, and real X output.


Published · Updated · 6 min read

Cover image: X research in a Mastra agent

Mastra MCP support comes from @mastra/mcp: create an MCPClient with the server URL and an auth header, then hand listTools() to an Agent.

This guide is for TypeScript developers. It connects Weir's remote MCP server for public X (Twitter) data, picks the tools and shows a real call with its cost. We run Weir.

import { MCPClient } from "@mastra/mcp";

const mcp = new MCPClient({
  servers: {
    weir: {
      url: new URL("https://api.weirapp.io/mcp"),
      requestInit: { headers: { Authorization: `Bearer ${process.env.WEIR_API_KEY}` } },
    },
  },
});

How to connect a Mastra MCP client with an API key

You need Node.js, a Weir key and a model key. Weir takes the key as a header, so there's no browser sign-in.

  1. Installnpm install @mastra/core @mastra/mcp zod
  2. Get a Weir keyCreate one under API keys in your Weir dashboard. Keep it in WEIR_API_KEY.
  3. Set a model keyThe model string anthropic/claude-sonnet-5-5 reads ANTHROPIC_API_KEY.
  4. Run the agentGive the Weir tools to an Agent and call generate(), as below.

As of 24 October 2026, npm lists @mastra/mcp 2.5.0, released on 21 October. It needs @mastra/core 1.79.0 or later and zod 4.2 or later.

Older posts describe an SSE fallback, but Mastra's MCP docs now cover only stdio and Streamable HTTP. Version 2.0, out on 22 September 2026, rebuilt the package on the MCP 2026-07-28 revision. The client now probes for that revision and falls back to the older handshake. Weir serves both.

Mastra MCP example: an X research agent

The script is 26 lines, in two parts. Part one connects and stops if Weir refused:

import { MCPClient } from "@mastra/mcp";

const mcp = new MCPClient({
  servers: {
    weir: {
      url: new URL("https://api.weirapp.io/mcp"),
      requestInit: { headers: { Authorization: `Bearer ${process.env.WEIR_API_KEY}` } },
      connectTimeout: 10_000,
    },
  },
});
const { tools, errors } = await mcp.listToolsWithErrors();
if (errors.weir) throw new Error(`Weir: ${errors.weir}`);

Part two keeps two tools, builds the agent and asks:

import { Agent } from "@mastra/core/agent";

const { weir_search_x, weir_get_x_post } = tools;
const analyst = new Agent({
  id: "x-analyst",
  name: "X analyst",
  instructions: "Search X with limit 5 or less. Link every post you cite.",
  model: "anthropic/claude-sonnet-5-5",
  tools: { weir_search_x, weir_get_x_post },
});
const result = await analyst.generate("What has @mastra posted about MCP?", { maxSteps: 3 });
console.log(result.text);
await mcp.disconnect();

Here's what Mastra does with it, per its 2.5.0 source:

  • It retries a 401 once. Then it logs the error and leaves Weir out of tools.
  • The agent gets Weir's structured result. That's the posts plus meta.creditsCharged and meta.next.
  • A tool error becomes a thrown error. A 402 from Weir reaches the model as error text, so it can stop.

maxSteps: 3 caps the loop, so the model can't keep calling paid tools. The url field takes a URL object, not a string.

listTools or listToolsets: which should you use?

Both return all of Weir's tools, 44 on a default connection. They differ in naming and in where they go:

listTools() listToolsets()
Tool names weir_search_x search_x inside weir
Pass it to new Agent({ tools }) generate() options
Best for One key for the app A key per user or request

Our pick is listTools() for a script or one app-wide key. Use listToolsets() when each user brings a Weir key: build a client per request, pass its toolsets to generate(), then disconnect().

Mastra has no include list, so pick tools by key, as part two does. Each tool you pass adds its description to the prompt.

Weir marks its data tools read-only. Mastra passes that hint to a requireToolApproval function as annotations.readOnlyHint, so you can ask before any tool that writes.

What does the agent get back?

To answer, the model calls weir_search_x, which Mastra sends to Weir as search_x. We made that call through Weir's MCP server on 24 October 2026:

→ search_x {"fromUsers": ["mastra"], "query": "MCP -filter:nativeretweets",
            "onlyOriginal": true, "limit": 1}
← 1 post · 2 credits · nextCursor set
  2026-10-23  16 likes  1,349 views  @mastra
  "New guide on MCP authentication and authorization: ..."

The post comes with its url, text and counts, so the agent can link it. meta.next holds the follow-up call with the new cursor. Weir's docs say only a null cursor marks the end.

2credits for the search above
11credits for a 10-post search
1credit for a search that finds nothing
5,000free Weir credits every month

Weir bills 1 credit per call plus 1 per X post, and failed calls are free. Packs start at $5 for 25,000 credits and never expire, as of October 2026. Every rate is on our pricing page.

If it doesn't work

This is what Weir sent our curl call with no key, on 24 October 2026:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://api.weirapp.io/.well-known/
  oauth-protected-resource/mcp", scope="read:social usage:read monitors:read"
{"error":"unauthorized","error_description":"Authorization is required."}

Through the MCP SDK with Mastra's settings, the no-key connect failed two ways:

Version negotiation probe timed out after 3000ms                (first, cold run)
Version negotiation failed: the server requires authorization (HTTP 401)   (next runs)

The fixes:

  • errors.weir says HTTP 401. The header must read Bearer weir_live_..., and an unset variable sends Bearer undefined. Check the key with Weir's free GET /v1/whoami.
  • "probe timed out after 3000ms". Set connectTimeout on the server, as part one does.
  • "initialized multiple times". You built a second client with the same config. Give each one a unique id, or disconnect() the first.
  • A tool fails with 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

Is Mastra an MCP client or an MCP server?

Both. MCPClient in @mastra/mcp connects your agents to MCP servers over stdio or Streamable HTTP. MCPServer, from the same package, exposes your Mastra tools, agents and workflows to other MCP clients.

How do I pass headers to an MCP server in Mastra?

Put them in requestInit.headers on the server's entry, as this guide does. For a token that changes per request, give the server a custom fetch. Mastra hands it the request context, so it can set the header on each call.

What is the difference between listTools and listToolsets in Mastra?

listTools() returns one flat object with names like weir_search_x, for the Agent constructor. listToolsets() groups tools by server under their own names, for a single generate() or stream() call.

Can Mastra be an MCP server?

Yes. Create an MCPServer with your tools, agents and workflows, then register it in new Mastra({ mcpServers }) or call startStdio(). Since version 2.0 it serves only the 2026-07-28 revision, so clients that speak only older revisions can't connect.

Sources

All checked on 24 October 2026.