Skip to content

Runtime

MCP server

Your agent connects to one endpoint and gets four read-only tools over the public record. Every query names the instant it is asking about, and the answer carries only what was knowable then.

LIVE Hosted at POST /mcp on every plan. Without a key the same tools serve a public sample, so you can point a client at it and see what comes back.

  • MCP
  • Streamable HTTP
  • JSON-RPC 2.0
  • 2025-06-18 · 2025-03-26
  • read-only

The artifact

One tool call, no key

This is a tools/call against a local server on 2026-08-27 and the envelope it answered with, trimmed nowhere. The sample tier needs no credential, so you can paste it now.

terminalno key

$ curl -s -X POST https://api.pit.aqx.llc/mcp \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
         "params":{"name":"pit_query","arguments":{"ticker":"SIVB"}}}'

result.content[0].textcount 1 · sample true

{
  "request_id": "588df012-967b-43d8-a37c-5dfaf61e4056",
  "corpus_version": "sha256:sample",
  "as_of": "2023-03-10T23:59:59Z",
  "visible_by": "published_at",
  "status": "ok",
  "results": [
    {
      "id": "0001193125-23-067777_719739",
      "source_id": "sec.edgar",
      "lane": "certified_pit",
      "form": "8-K",
      "accession": "0001193125-23-067777",
      "cik": "719739",
      "title": "SVB FINANCIAL GROUP 8-K",
      "event_at": null,
      "published_at": "2023-03-10T23:59:59Z",
      "available_at": null,
      "acceptance_at": "2023-03-10T22:23:03Z",
      "committed_at": "2026-08-25T09:18:11Z",
      "availability_basis": "unknown",
      "revision_id": "0001193125-23-067777_719739",
      "supersedes": null,
      "content_sha256": "8a95862ef3953dd206f1afeb5a0ab19014b57f7f332b764e948f6514fdd2d06a",
      "source_locator": "https://www.sec.gov/Archives/edgar/data/719739/000119312523067777/0001193125-23-067777.txt",
      "sample": true,
      "as_of_visible": true
    }
  ],
  "next_cursor": null,
  "count": 1,
  "coverage": {
    "touched": [
      "identity.ticker/SIVB@2023-03-10",
      "sec.edgar/2023-03-10",
      "sec.edgar/frontier:2020-02-18..2023-03-10;holes=0",
      "us.federal_register.pi/2023-03-10",
      "us.federal_register.pi/frontier:2020-02-18..2023-03-10;holes=0"
    ],
    "missing": []
  },
  "error": null,
  "sample": true
}

as_of and visible_by come back on the answer, so the agent can see which clock produced the row it is about to reason over. coverage.touched lists every source-day the query read, and coverage.missing would name any day nobody has certified.

The failure it prevents

A tool that answers with today when you asked about 2023

Most data tools take a ticker and return the current state of the world. An agent replaying March 2023 calls one, gets today's filings, and writes a rationale that reads as foresight.

The clock is a required argument

as_of is on the tool schema, and it is required once you send a key. The model sees it while planning, so the question it forms is already dated.

A date covers 24 hours

2023-03-10 holds a filing accepted at 22:23 that evening as readily as one from breakfast. The server refuses the bare date rather than picking an hour on your behalf, and the message says which format it wants.

pit_query · as_of "2023-03-10"isError true

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"request_id\":\"7d25a6b7-b672-4410-a032-0ccae5990dd5\",\"corpus_version\":\"\",\"as_of\":null,\"visible_by\":null,\"status\":\"error\",\"results\":[],\"next_cursor\":null,\"count\":null,\"coverage\":{\"touched\":[],\"missing\":[]},\"error\":{\"code\":\"invalid_clock\",\"message\":\"as_of needs a time of day: a bare date is an interval, not an instant, and the value must be RFC3339 UTC with a literal Z, like 2023-03-10T23:59:59Z. Received: \\\"2023-03-10\\\"\",\"param\":\"as_of\"}}"
      }
    ],
    "isError": true
  }
}

The refusal comes back as a normal tool result with isError true and the whole envelope in the text, because the model can fix this one by writing a fuller timestamp. A rejected API key is the single case that leaves as a JSON-RPC error (-32001), since no argument the model tries next would repair it.

How it works

One code path, reached two ways

Every tool call lands on the REST handler

Every tools/call is rebuilt as a GET against the /v1 handler in the same process. It walks the same middleware for request id, CORS, rate limit and Bearer auth, lands on the same handler, and returns the same envelope. A cut that /v1/news refuses is refused here with the same code and the same message, because there is no second query path and no second clock parser to disagree with the first.

One tool call is one request against your plan's limit: 60 a minute on Researcher, 300 on Power.

The four tools

ToolAnswersWith a keyWithout
pit_queryThe filings knowable at one instant.GET /v1/news/v1/sample/news
pit_diffThe rows that became knowable between two instants.GET /v1/news/diff/v1/sample/diff
pit_coverageWhich source-days were mined, and how completely.GET /v1/coverage/v1/sample/coverage
pit_metaCorpus version, sources, certified span, plans.GET /v1/metaGET /v1/meta

All four are marked readOnlyHint. Read count before results: a number means the cut was served, and JSON null means the window touches a day nobody has certified, so the answer there is unknown rather than none.

The sample tier, and what it costs you

With no Authorization header the tools serve three companies on a handful of certified days: SVB (SIVB), Apple (AAPL) and Meta (META, FB before the rename). Every row carries sample: true. A ticker the sample does not hold is refused by name rather than answered with somebody else's filings.

A custom connector on claude.ai signs in with OAuth or connects with no credential at all. PIT has no OAuth app yet, so a claude.ai connection is the sample tier. For the whole corpus use a client that sends a header, which today means Claude Code, Cursor, or your own.

Integration

Two lines, then it is in the agent's toolbox

The server is hosted, so nothing is installed and no process runs on your machine. Any client that speaks Streamable HTTP works with one URL, a POST, Content-Type: application/json and the key in an Authorization: Bearer header.

Claude Code

$ claude mcp add --transport http pit https://api.pit.aqx.llc/mcp \
    --header "Authorization: Bearer pit_live_..."

~/.cursor/mcp.json

{
  "mcpServers": {
    "pit": {
      "url": "https://api.pit.aqx.llc/mcp",
      "headers": {
        "Authorization": "Bearer pit_live_..."
      }
    }
  }
}

Drop the header and the connection still works, on the sample. claude mcp list shows it and claude mcp remove pit undoes it.

What is not here yet

  • OAuth, which is what a claude.ai custom connector wants.
  • Resources and prompts. capabilities advertises tools only.
  • A tool for the live tape. /v1/stream is SSE on its own route.
  • Tools for /v1/files and /v1/mapping.
  • Receipts for tool calls. /mcp does not forward the X-PIT-Audit header onto the request it builds, so an MCP call is not written to a decision audit log.

Related

What sits either side of it

Upstream

Point-in-Time API

The corpus and the query surface these four tools dispatch into.

Alongside

Decision Audit Logs

Receipts for what a production agent was served, on the REST path today.

Downstream

Evaluation Harness

The offline runner, for when the agent should read a frozen window with the network off.