Skip to main content

Agents and MCP

One endpoint, https://intelclaw.org/api/mcp, stateless JSON-RPC 2.0 over HTTP. Any account can create a free API key. Samples and discovery need no key at all; paid data needs a subscription to that listing.

Want client config files instead of raw calls? See For agents.

1. initialize

Standard MCP handshake. Returns server info and the tools capability. No key.

curl: initialize

curl -s "https://intelclaw.org/api/mcp" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}}'
2. tools/list

Lists live listings that expose an MCP tool. Each tool carries its listing slug and niche in _meta, so your agent knows which listing to subscribe to. No key.

curl: tools/list (no key)

curl -s "https://intelclaw.org/api/mcp" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

TypeScript: tools/list

const res = await fetch("https://intelclaw.org/api/mcp", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ jsonrpc: "2.0", id: 2, method: "tools/list" }),
});
const { result } = await res.json();
for (const tool of result.tools) {
  // _meta["intelclaw.dev/listing"] is the listing slug to subscribe to
  console.log(tool.name, tool._meta?.["intelclaw.dev/listing"]);
}
3. tools/call

Same entitlement check as the REST API. A paid call without a key returns HTTP 401. A key whose account has no subscription to that listing returns HTTP 403. The result has the data as text in content and as JSON in structuredContent.

curl: tools/call (key + subscription)

curl -s "https://intelclaw.org/api/mcp" -H "Content-Type: application/json" \
  -H "Authorization: Bearer $INTELCLAW_KEY" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"your_tool_name","arguments":{"query":"example"}}}'

TypeScript: tools/call with error handling

async function callTool(name: string, args: Record<string, unknown>) {
  const res = await fetch("https://intelclaw.org/api/mcp", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.INTELCLAW_KEY}`,
    },
    body: JSON.stringify({ jsonrpc: "2.0", id: 3, method: "tools/call", params: { name, arguments: args } }),
  });
  const msg = await res.json();
  if (msg.error) {
    const status = msg.error.data?.httpStatus;
    if (msg.error.code === -32029) {
      const wait = msg.error.data?.retryAfterSec ?? 60;
      throw new Error(`Rate limited. Retry once after ${wait}s.`);
    }
    if (status === 401) throw new Error("Ask the human for an IntelClaw API key.");
    if (status === 403) throw new Error("This listing needs a plan: /checkout?listing=<slug>");
    throw new Error(msg.error.message);
  }
  return msg.result.structuredContent;
}
Errors an agent should handle
  • 401 No API key was sent, or the key was not recognised. Stop and ask the human for an IntelClaw API key (any account can create one free at /dashboard/keys). Retry with Authorization: Bearer im_…. Meanwhile the free sample and discovery reads still work.
  • 403 The key is valid, but its account has no subscription to this listing, or a metered plan used its monthly cap. Do not retry. Tell the human which listing needs a plan and link /checkout?listing={slug}. Keep using ?sample=1 if a sample is enough.
  • 429 Rate limited. Wait for the Retry-After header (seconds), then retry once. Don't hammer.

Over MCP, 401 and 403 arrive as JSON-RPC error -32001 with data.httpStatus. Rate limits arrive as -32029 with data.retryAfterSec.

Without a key: 60 requests per minute. With a key: 120 requests per minute per listing. Metered plans include 10,000 calls a month; calls past the cap return HTTP 403. The Live Price Feed plan has no monthly cap.

Command palette

Search and jump to pages or resources