# MCP

Arche runs a Model Context Protocol (MCP) server, so an AI agent can look up
companies, read normalized statements and point-in-time financials, and check
data quality without custom integration code. Each tool calls the same HTTP
route your code would, under your API key, so an agent gets the same figures,
the same provenance and the same plan coverage.

MCP is available on every plan, including Free. A Free key reaches the same
25 companies it can query over HTTP. Modeling, reconciliation and AI tools need
a paid plan; the [tool table](https://docs.arche.fi/mcp#tools) lists the plan each one needs.

## Connect a client

- `URL` (endpoint): `https://api.arche.fi/mcp`
- `Transport` (protocol): Streamable HTTP. Every response is a single JSON body; the server opens no
  event stream, so `GET /mcp` returns `405`.
- `Authentication` (header): `X-Api-Key: ak_…`. Use this header rather than a bearer token: tools pass it
  on to the routes they call, so your plan and coverage apply to every tool
  call.
- `Protocol versions` (string): `2025-06-18`, `2025-03-26` and `2024-11-05`. A client that asks for another
  version is answered with `2025-06-18`.
- `Manifest` (endpoint): `https://api.arche.fi/mcp/manifest` lists every tool with its input schema
  and the plan it needs, and the MCP rate limit for each plan. It needs no API
  key, so an agent can read it before it connects.

Any client that can connect to a remote MCP server over HTTP with a custom
header can use Arche. With Claude Code, for example:

```bash
claude mcp add --transport http arche https://api.arche.fi/mcp \
  --header "X-Api-Key: YOUR_API_KEY"
```

Clients configured from JSON generally take the same three values:

```json
{
  "mcpServers": {
    "arche": {
      "type": "http",
      "url": "https://api.arche.fi/mcp",
      "headers": { "X-Api-Key": "YOUR_API_KEY" }
    }
  }
}
```

Keep the key out of shared configuration files. Most clients can read it from
an environment variable instead.

## Call it directly

The server speaks JSON-RPC 2.0 and supports `initialize`, `ping`, `tools/list`
and `tools/call`. Notifications such as `notifications/initialized` are
acknowledged with `202` and no body.

List the tools:

```bash
curl -X POST "https://api.arche.fi/mcp" \
  -H "X-Api-Key: $ARCHE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
```

Each tool carries a `name`, a `description` and an `inputSchema`. Call one with
its arguments:

```bash
curl -X POST "https://api.arche.fi/mcp" \
  -H "X-Api-Key: $ARCHE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "companies_resolve", "arguments": {"ticker": "AAPL"}}}'
```

The result is the tool's output as JSON text:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"as_of\": \"2026-09-26\", \"cik\": \"0000320193\", \"exchange\": null, \"request_id\": \"58c0f33bcff243b9a4cd83ebc36b89df\", \"ticker\": \"AAPL\"}"
      }
    ],
    "isError": false
  }
}
```

## Tools

Tool names are the method names with `_` in place of `.`. Every tool is
available on every plan unless the table says otherwise; a tool above your
plan returns a `FEATURE_NOT_AVAILABLE` result naming the plan it needs. The
same list, with each tool's input schema, is served at
[`GET /mcp/manifest`](https://api.arche.fi/mcp/manifest).

| Tool                            | What it returns                                                              | Plan   |
| ------------------------------- | ---------------------------------------------------------------------------- | ------ |
| `companies_resolve`             | The CIK for a ticker. Call it first when you only have a ticker.             | Free   |
| `filings_list`                  | A company's EDGAR filings, paginated.                                        | Free   |
| `statements_normalized`         | The latest normalized statement for a period, with optional version history. | Free   |
| `provenance_as_of`              | Financials as they were known on a date, with provenance.                    | Free   |
| `financials_get_as_of_snapshot` | The same as `provenance_as_of`, under a name agents find more readily.       | Free   |
| `dq_anomalies`                  | A normalized statement with its data-quality overlay.                        | Free   |
| `system_health`                 | Service health.                                                              | Free   |
| `system_metadata`               | Service metadata and usage limits.                                           | Free   |
| `modeling_periods`              | Modeling period rows.                                                        | Growth |
| `modeling_ttm`                  | Trailing-twelve-month rows.                                                  | Growth |
| `modeling_growth`               | Growth rows.                                                                 | Growth |
| `modeling_ratios`               | Ratio rows.                                                                  | Growth |
| `modeling_valuation_inputs`     | Valuation inputs for multi-year modeling.                                    | Growth |
| `reconciliation_summary`        | Reconciliation results by category over a range of fiscal years.             | Growth |
| `reconciliation_ledger`         | Individual reconciliation results for one statement.                         | Growth |
| `ai_narratives`                 | Generated narratives for a company.                                          | Growth |
| `ai_peers`                      | Experimental. Peer companies by financial similarity.                        | Scale  |
| `ai_anomalies_explanations`     | Explanations of data-quality anomalies.                                      | Scale  |
| `ai_embeddings_metadata`        | Experimental. Embedding metadata.                                            | Scale  |

The `modeling_*` and `ai_*` tools take `company_id`, a UUID, rather than a CIK.
Get one from [`/v1/identity/resolve`](https://docs.arche.fi/identity). The modeling tools also need
a snapshot for their `as_of` date; see [Modeling](https://docs.arche.fi/modeling).

## Errors

Two kinds of failure come back differently.

A malformed request is a JSON-RPC error, returned with HTTP `200`:

- `-32700` (JSON-RPC error): The body is not valid JSON.
- `-32600` (JSON-RPC error): The body is not a JSON-RPC 2.0 request, or is an empty batch.
- `-32601` (JSON-RPC error): The JSON-RPC method is not supported.
- `-32602` (JSON-RPC error): The tool does not exist, or its arguments failed validation. `data` lists
  the failures.

A tool that runs and fails, because of your plan, a rate limit or the route it
calls, returns a result with `isError: true`. Its `text` is a JSON error:

```json
{
  "type": "FEATURE_NOT_AVAILABLE",
  "message": "This feature requires the growth plan or higher.",
  "retryable": false,
  "http_status": 403,
  "http_code": "FEATURE_NOT_AVAILABLE",
  "trace_id": null,
  "retry_after_s": null
}
```

Retry only when `retryable` is `true`, and wait `retry_after_s` seconds when it
is set. Quote `trace_id` when you [escalate](https://docs.arche.fi/troubleshooting/request-ids).

## Limits

MCP requests are metered in their own class; see
[Rate limits](https://docs.arche.fi/rate-limits) for your plan's budget, which the manifest also
reports under `rate_limits`. A request body larger than
1 MiB is refused with `413`.

## Next steps

- [API reference](https://docs.arche.fi/reference): Browse the live OpenAPI contract rendered from the public schema.
- [Errors](https://docs.arche.fi/errors): Interpret machine-readable error responses and troubleshoot failed requests.
- [Request IDs](https://docs.arche.fi/troubleshooting/request-ids): Correlate a failed request across your logs, the API response, and the portal.
