Quickstart: Raw JSON-RPC

Pipeworx is an HTTP MCP gateway. Any client that can POST JSON-RPC 2.0 to a URL talks to it. No SDK required.

Working in a shell and have Node.js? pipeworx call wraps these same calls so you can skip the envelope: npx pipeworx@latest call adzuna_search --country=us | jq.

Endpoint

https://gateway.pipeworx.io/mcp

Or scoped variants:

https://gateway.pipeworx.io/<pack>/mcp        # one pack
https://gateway.pipeworx.io/mcp?task=...      # task-scoped
https://gateway.pipeworx.io/mcp?vertical=...  # vertical-scoped

List tools

curl -X POST https://gateway.pipeworx.io/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | jq '.result.tools[].name'

Call a tool

curl -X POST https://gateway.pipeworx.io/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "ask_pipeworx",
      "arguments": { "question": "What is the US trade deficit with China?" }
    }
  }'

Real capture, trimmed — fred_get_series({series_id: "MORTGAGE30US"}) on the internal (paid-equivalent) tier used for verification:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{ "type": "text", "text": "{\"series_id\":\"MORTGAGE30US\", ...}" }],
    "structuredContent": { "series_id": "MORTGAGE30US", "series_title": "30-Year Fixed Rate Mortgage Average...", "observations": [...] },
    "_meta": {
      "tier": "paid",
      "source": "fred",
      "fetched_at": "2026-08-10T19:51:05.713Z",
      "cost": { "total": 5, "components": [{ "name": "base", "credits": 5 }] }
    }
  }
}

Two things worth calling out that the previous version of this page didn’t mention:

  • result.structuredContent — the same data as content[0].text, already parsed. Read this instead of JSON.parse-ing the text block.
  • _meta.rateLimit ({ limit, remaining, resetAt }) is added for every tier except paid — confirmed in shared/src/responses.ts’s buildMeta(); not shown above because paid/unlimited accounts have nothing to report against a cap. _meta.cache ({ hit, ttl_seconds, fresh_until }) is present when the tool result is cacheable; _meta.source/fetched_at/cost are always present on a successful call.

On an error, _meta carries examples, alternatives, and retry_hint/feedback_hint instead — see error recovery. One exception: an unknown tool name comes back as a bare JSON-RPC -32602 error with no _meta at all — the name is what failed, so there’s nothing to retry-hint; call discover_tools({task}) to find the real name.

Other MCP methods

MethodPurpose
initializeReturns server capabilities + instructions (read these — they tell agents how to use Pipeworx best)
tools/listList tools (with inputSchema.examples and outputSchema)
tools/callInvoke a tool
resources/templates/listList pipeworx:// URI patterns
resources/readFetch a pipeworx://... resource
prompts/listList server-side prompt playbooks
prompts/getGet a prompt with arguments substituted

Authentication

TierHow
Anonymous (50/day)No auth
BYO key (200/day)X-API-Key: your-key header
Free account (200/day)Authorization: Bearer <token> (GitHub OAuth signup at pipeworx.io)
Paid (unlimited)Authorization: Bearer <token> (Stripe subscription)

Pass tool-specific API keys

For paid data sources, pass your own key as a call argument — but the argument name is per-tool, not a universal _apiKey. Check the tool’s inputSchema from tools/list for the exact name. FRED and ATTOM read _apiKey; Altos reads _altosKey:

{
  "name": "fred_get_series",
  "arguments": {
    "series_id": "MORTGAGE30US",
    "_apiKey": "your-fred-api-key"
  }
}
{
  "name": "altos_market_stats",
  "arguments": {
    "region": "ca_94103",
    "_altosKey": "your-altos-api-key"
  }
}

Passing the wrong name (e.g. _apiKey for an Altos tool) is silently dropped as an unrecognized argument — verified live: altos_market_stats with _apiKey set still returns "Altos Research API key required... pass via _altosKey". Trust that message, not the error’s signup_hint field — the generic signup_hint currently says _apikey (lowercase, and wrong for Altos regardless of case) for every tool; see error recovery for the full auth-error pattern. Any argument starting with _ is treated as an injected credential and stripped before analytics logging — this covers _apiKey, _altosKey, and every other per-tool key, not just the generic one.

TypeScript shortcut: @pipeworx/sdk

If you’re in JS/TS, the SDK wraps all of this:

import { Pipeworx } from '@pipeworx/sdk';
const pw = new Pipeworx();
const result = await pw.call('fred_get_series', { series_id: 'MORTGAGE30US' });
npm install @pipeworx/sdk

Last reviewed August 10, 2026