> ## Documentation Index
> Fetch the complete documentation index at: https://docs.numeral.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Quickstart

> Connect an MCP client to your Numeral account and ask your first question.

You need one thing to get started: a Numeral **secret** API key. Create one in your [developer dashboard](https://dashboard.numeralhq.com/developers) under the API Keys tab.

<Tip>
  Start with an `sk_test_` key. It scopes every tool to your sandbox data, so you can explore without touching production. See [API keys](/essentials/api-keys).
</Tip>

## Connect a client

<Tabs>
  <Tab title="Claude Code">
    Add the server with the CLI:

    ```bash theme={null}
    claude mcp add --transport http numeral https://mcp.numeralhq.com/mcp \
      --header "Authorization: Bearer sk_test_..."
    ```

    Or create a `.mcp.json` in your project root:

    ```json theme={null}
    {
      "mcpServers": {
        "numeral": {
          "type": "http",
          "url": "https://mcp.numeralhq.com/mcp",
          "headers": { "Authorization": "Bearer sk_test_..." }
        }
      }
    }
    ```

    Run `/mcp` inside Claude Code to confirm the server connected and see its tools.
  </Tab>

  <Tab title="Claude Desktop">
    Open **Settings → Developer → Edit Config** and add:

    ```json theme={null}
    {
      "mcpServers": {
        "numeral": {
          "type": "http",
          "url": "https://mcp.numeralhq.com/mcp",
          "headers": { "Authorization": "Bearer sk_test_..." }
        }
      }
    }
    ```

    Restart Claude Desktop. The Numeral tools appear in the tools menu in a new conversation.
  </Tab>

  <Tab title="Cursor">
    Add to `.cursor/mcp.json` in your project (or the global equivalent in Settings → MCP):

    ```json theme={null}
    {
      "mcpServers": {
        "numeral": {
          "url": "https://mcp.numeralhq.com/mcp",
          "headers": { "Authorization": "Bearer sk_test_..." }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Your own agent">
    Use the official MCP SDK. In TypeScript:

    ```ts theme={null}
    import { Client } from "@modelcontextprotocol/sdk/client/index.js"
    import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"

    const transport = new StreamableHTTPClientTransport(
      new URL("https://mcp.numeralhq.com/mcp"),
      {
        requestInit: {
          headers: { Authorization: `Bearer ${process.env.NUMERAL_API_KEY}` },
        },
      }
    )

    const client = new Client({ name: "my-agent", version: "1.0.0" })
    await client.connect(transport)

    const { tools } = await client.listTools()
    const result = await client.callTool({
      name: "list_filings",
      arguments: { status: "pending_client_approval" },
    })
    ```

    Hand `tools` to your model as its tool definitions and execute the calls it requests. The [demo application](/mcp/demo-app) is a complete working example of this loop.
  </Tab>
</Tabs>

<Warning>
  Your secret key grants full read access to your tax data. Keep it server-side — never ship it to a browser or commit it to a repository.
</Warning>

## Ask your first question

Once the server is connected, just ask in plain language. The agent picks the tools:

* *"Which states have I triggered economic nexus in, and how close am I in the others?"*
* *"Are any filings waiting on my approval? What are they for and when are they due?"*
* *"Show me sales by state for last quarter, broken out by who is responsible for remitting."*
* *"Which of my products don't have a sensible tax category assigned?"*
* *"Look up the transaction for reference order 1234 and explain how the tax was calculated."*

## Or call it directly with curl

Useful for debugging, or to see exactly what an agent sees. Note the `Accept` header — the Streamable HTTP transport requires both content types.

<Steps>
  <Step title="Handshake">
    ```bash theme={null}
    curl -X POST https://mcp.numeralhq.com/mcp \
      -H "Authorization: Bearer sk_test_..." \
      -H "Content-Type: application/json" \
      -H "Accept: application/json, text/event-stream" \
      -d '{
        "jsonrpc": "2.0",
        "id": 1,
        "method": "initialize",
        "params": {
          "protocolVersion": "2025-06-18",
          "capabilities": {},
          "clientInfo": { "name": "curl", "version": "1.0.0" }
        }
      }'
    ```

    The response includes `serverInfo` and an `instructions` document describing how the tools fit together.
  </Step>

  <Step title="Discover the tools">
    ```bash theme={null}
    curl -X POST https://mcp.numeralhq.com/mcp \
      -H "Authorization: Bearer sk_test_..." \
      -H "Content-Type: application/json" \
      -H "Accept: application/json, text/event-stream" \
      -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }'
    ```

    Each entry has a `name`, `description`, and `inputSchema`.
  </Step>

  <Step title="Call a tool">
    ```bash theme={null}
    curl -X POST https://mcp.numeralhq.com/mcp \
      -H "Authorization: Bearer sk_test_..." \
      -H "Content-Type: application/json" \
      -H "Accept: application/json, text/event-stream" \
      -d '{
        "jsonrpc": "2.0",
        "id": 3,
        "method": "tools/call",
        "params": {
          "name": "list_merchants",
          "arguments": { "limit": 2 }
        }
      }'
    ```

    Results come back as JSON in the response's text content:

    ```json theme={null}
    {
      "merchants": [
        {
          "id": "mer_1767985271219f6e0c6b2-aa3a-44f4-9da4-83495af23e42",
          "reference_merchant_id": "my-merchant-123",
          "name": "Acme Marketplace Seller",
          "email": "seller@acme.com",
          "default_address": {
            "address_line_1": "123 Main St",
            "address_city": "Austin",
            "address_province": "TX",
            "address_postal_code": "78701",
            "address_country": "US"
          },
          "tax_ids": [{ "type": "EIN", "value": "12-3456789" }],
          "created_at": "2026-01-09T19:01:11.219Z",
          "updated_at": "2026-01-09T19:01:11.219Z"
        }
      ],
      "has_more": true,
      "cursor": "mer_1767985271219f6e0c6b2-aa3a-44f4-9da4-83495af23e42"
    }
    ```

    Paginated tools return `has_more` and a `cursor`. To fetch the next page, pass that `cursor` value back in your next call.
  </Step>
</Steps>

<Note>
  Only `POST` is supported. `GET` and `DELETE` on `/mcp` return `405` — the server is stateless, so there are no SSE streams to resume and no sessions to end. For a health check, use `GET /ping`.
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Tool reference" icon="wrench" href="/mcp/tools">
    Every tool and its inputs.
  </Card>

  <Card title="Authentication & limits" icon="shield" href="/mcp/authentication">
    Testmode, rate limits, and error handling.
  </Card>

  <Card title="Demo application" icon="github" href="/mcp/demo-app">
    Run a full example agent locally.
  </Card>

  <Card title="Building an integration" icon="robot" href="/ai-help/overview">
    Claude skills for writing REST API integration code.
  </Card>
</CardGroup>
