Source: http://www.poma-ai.com/docs/mcp/poma-mcp

# `poma-mcp` — PrimeCut MCP Server

`poma-mcp` is POMA AI's Model Context Protocol server for the **PrimeCut** document-ingestion product. It exposes four tools: submit a file and wait, resume a job, check status, or fetch a completed result. Drop it into Claude Code, Claude Desktop, Cursor, or any other MCP-aware agent and you can ingest documents through natural language and get back hierarchical chunks plus chunksets.

- **Repo:** [github.com/poma-ai/poma-mcp](https://github.com/poma-ai/poma-mcp)
- **Transports:** stdio (`-input -`, required flag), streamable HTTP (`-http :8080`), Docker
- **License:** MPL-2.0

> **This server does not expose Grill tools.** The Grill context engine lives in a separate MCP server — [`poma-grill-mcp`](/mcp/grill-mcp). If you need both products, install both binaries.

## When to use this server

Pick `poma-mcp` when you want:

- The raw PrimeCut output — `chunks` (hierarchical content tree), `chunksets` (pre-grouped embedding windows), or the full `.poma` archive bytes — directly from an agent.
- A simple stdio/HTTP server to feed your own embedding + retrieval stack downstream.
- Direct-ingest mode from the shell (`poma-mcp -input /path/to.pdf`) for scripts and one-off jobs.

If you need Grill ingestion + hybrid search instead, use [`poma-grill-mcp`](/mcp/grill-mcp). The two servers can run side-by-side in the same MCP client config — just give them distinct names (e.g. `poma-primecut` and `poma-grill`).

## 1. Get an API key

Sign up at [console.poma-ai.com](https://console.poma-ai.com) and copy your account API key (prefix `poma_acc_…`).

## 2. Install

> **Homebrew is not available yet** — no tap is published for `poma-mcp`. Build from source (which also gives you the current `primecut_*` tool surface — see the version note under [Tools](#tools)). `brew install poma-ai/poma/poma` installs the POMA **CLI**, not this server.

```bash
git clone https://github.com/poma-ai/poma-mcp
cd poma-mcp
go build -o bin/poma-mcp .
realpath bin/poma-mcp
```

## 3. Wire it into your MCP client

Use the **absolute path** from the previous step.

::: code-group

```json [Claude Code · ~/.claude/claude.json]
{
  "mcpServers": {
    "poma-primecut": {
      "command": "/full/path/to/poma-mcp",
      "args": ["-input", "-"],
      "env": { "POMA_API_KEY": "your-api-key" }
    }
  }
}
```

```json [Claude Desktop · claude_desktop_config.json]
{
  "mcpServers": {
    "poma-primecut": {
      "command": "/full/path/to/poma-mcp",
      "args": ["-input", "-"],
      "env": { "POMA_API_KEY": "your-api-key" }
    }
  }
}
```

```json [Cursor · ~/.cursor/mcp.json]
{
  "mcpServers": {
    "poma-primecut": {
      "command": "/full/path/to/poma-mcp",
      "args": ["-input", "-"],
      "env": { "POMA_API_KEY": "your-api-key" }
    }
  }
}
```

:::

Restart the client. You should now be able to ask things like:

> "Ingest `~/Documents/contract.pdf` with POMA PrimeCut and show me the chunkset for page 3."

## Tools

::: warning Version note
This page documents the current `main` branch. The latest **tagged release (v0.0.7)** still ships the older tool surface (`poma_jobs_ingest` / `poma_jobs_resume` against API v2) — so a plain `brew install` may give you different tool names until the next release is cut. Build from source if you need the `primecut_*` tools today.
:::

`poma-mcp` exposes four tools, all `primecut_*`:

| Tool | What it does |
| --- | --- |
| `primecut_ingest` | Upload a file, wait for processing, return parsed `chunks` + `chunksets`. Set `archiveOutput: true` to also receive the raw `.poma` archive (base64). |
| `primecut_status` | Fetch the current status of a job (non-streaming). Returns `status` and any `error`. |
| `primecut_resume` | Re-attach to a running ingest job by `job_id`. Useful when an MCP connection drops mid-ingest. |
| `primecut_get_result` | Fetch the result of an already-completed job without re-streaming events. |

### `primecut_ingest`

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `file_base64` | string | **yes** | Standard base64 of the file bytes. |
| `filename` | string | no | Original filename (`report.pdf`). Server infers from bytes when omitted. |
| `token` | string | no | API key — overrides `POMA_API_KEY` for this call. |
| `archiveOutput` | boolean | no | Also include the `.poma` archive bytes (base64) in the `data` field. |

The response shape mirrors what the SDK and CLI return: `result.chunks`, `result.chunksets`, plus a `job_id` and a list of status `events`. See the [PrimeCut SDK results page](/sdk/concepts/results-and-archives) for the full structure.

### `primecut_status`

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | **yes** | Job ID to check. |
| `token` | string | no | API key. |

Returns the current `status` (one of `pending`, `processing`, `done`, `failed`, `deleted`, `blocked`), an `error` field when applicable, and a `download_url` once the job is `done`. Non-streaming snapshot — note that `primecut_ingest`/`primecut_resume` already emit live MCP progress notifications during the job, so polling is only needed for jobs started elsewhere.

### `primecut_resume`

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | **yes** | Job ID from a prior ingest. |
| `token` | string | no | API key. |
| `timeout_seconds` | integer | no | Max wait time. Default `600`. |
| `archiveOutput` | boolean | no | Return `.poma` archive bytes in the `data` field. |

Re-attaches to a running job's status stream and returns its terminal result. Useful if `primecut_ingest` returned but the MCP connection dropped before the job finished.

### `primecut_get_result`

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | **yes** | Job ID of a completed job. |
| `token` | string | no | API key. |

Fetch the cached result of a job that already reached `done`. Does not poll, does not re-stream — returns the API's error if the result is not available yet.

## Output shape

`primecut_ingest` returns:

```json
{
  "job_id": "100c65a03a304aa343a1518aa79e8300-20260414T083549Z",
  "result": {
    "chunks": [
      {
        "chunk_index": 0,
        "content": "WGV Rechtsschutzversicherung – Umfassender Schutz",
        "depth": 0,
        "parent_chunk_index": null,
        "poma_page": 1,
        "to_embed": "WGV Rechtsschutzversicherung – Umfassender Schutz"
      }
    ],
    "chunksets": [
      {
        "chunkset_index": 0,
        "chunk_indices": [0, 1, 2],
        "poma_page": 1,
        "text": "…concatenated to_embed text for all member chunks…"
      }
    ]
  },
  "events": [
    { "status": "pending" },
    { "status": "processing" },
    { "status": "done" }
  ]
}
```

| Chunk field | Description |
| --- | --- |
| `chunk_index` | Position in the flat chunk list. |
| `content` | Extracted text (or HTML for tables). |
| `depth` | Nesting depth in the document hierarchy. |
| `parent_chunk_index` | Index of the parent chunk (`null` for root). |
| `poma_page` | Source page number. |
| `to_embed` | Plain-text version used for embedding. |
| `file_id` | Identifier of the source file (present on chunks and chunksets). |
| `image_name` | Set when the chunk describes an image. |
| `table` | Set when the chunk is a table (content is HTML). |

| Chunkset field | Description |
| --- | --- |
| `chunkset_index` | Position in the chunkset list. |
| `chunk_indices` | Indices of the chunks that form this chunkset. |
| `text` | Concatenated `to_embed` text for all member chunks. |
| `poma_page` | Page of the first chunk in the set. |

On error, the MCP response sets `isError: true` and `error` describes the failure: `{ "error": "job failed: unsupported file type" }`.

## Direct file ingest (no MCP client)

For scripts and one-off jobs you can skip the MCP handshake entirely. Pass any non-MCP file path as `-input`:

```bash
POMA_API_KEY=your-key poma-mcp -input /path/to/document.pdf
```

The server runs `primecut_ingest` immediately and prints the JSON result to stdout. Add `-archiveOutput` to also emit the `.poma` archive (base64).

## HTTP mode

Run as a long-lived HTTP server for custom integrations:

```bash
POMA_API_KEY=your-key poma-mcp -http :8080
```

- **MCP endpoint:** `POST http://localhost:8080/v1` (standard streamable HTTP MCP — `initialize` → capture `Mcp-Session-Id` → `notifications/initialized` → `tools/call`).
- **Health check:** `GET http://localhost:8080/health`.

The repo's `test.sh` is a working stdio example you can adapt.

## Docker

Images are tagged by **commit SHA** (no `latest` tag) — pick a tag from [the package registry](https://github.com/poma-ai/poma-mcp/pkgs/container/poma-mcp) first:

```bash
# HTTP mode
docker run -e POMA_API_KEY=your-key -p 8080:8080 \
  ghcr.io/poma-ai/poma-mcp:<tag> -http :8080

# Stdio (default entrypoint)
docker run -i -e POMA_API_KEY=your-key ghcr.io/poma-ai/poma-mcp:<tag>
```

## All flags

| Flag | Default | Description |
| --- | --- | --- |
| `-input <path\|->` | — | Stdio mode: MCP on stdin (`-`) or a non-MCP file path for direct ingest. |
| `-http <addr>` | — | HTTP mode (e.g. `:8080`). `-input` is ignored (with a warning) in HTTP mode. |
| `-token <key>` | — | API key (alternative to `POMA_API_KEY`). |
| `-archiveOutput` | `false` | Always return the `.poma` archive (server-wide). |
| `-roots /a,/b` | — | Restrict file access to these directory prefixes — useful for direct-ingest mode. |

| Env var | Default | Description |
| --- | --- | --- |
| `POMA_API_KEY` | — | Account API key (`poma_acc_…`) used when no `token` is passed. |
| `POMA_API_BASE_URL` | POMA prod | Override the API base for self-hosted/dev backends (version suffix appended automatically). |
| `POMA_STATUS_API_BASE_URL` | POMA prod | Override the status/SSE base for self-hosted/dev backends. |

## Troubleshooting

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Tool calls return `isError: true` with `unauthorized` | Missing or wrong API key | Set `POMA_API_KEY` or pass `token` per call. |
| Large PDFs fail with payload-too-large errors | Base64 inflates JSON body past MCP frame limits | Use `poma-mcp -input <path>` for direct ingest, or POST the raw bytes to the REST API. |
| Agent looks for `grill_*` tools and finds nothing | `poma-mcp` only ships `primecut_*` tools | Install [`poma-grill-mcp`](/mcp/grill-mcp) alongside this server (give them distinct names in your client config). |
| Claude Desktop doesn't see the server | Config edited but client not restarted | Quit and relaunch Claude Desktop. |

## See also

- [`poma-grill-mcp`](/mcp/grill-mcp) — Grill context-engine MCP server (`grill_*` tools).
- [PrimeCut SDK](/sdk/) — same ingestion flow, programmatic.
- [POMA CLI](/cli/) — same workflow from the shell.