okraPDF PDF MCP server
Official# okraPDF — PDF MCP server
[](https://www.npmjs.com/package/@okrapdf/pdf-mcp)
[](./LICENSE)
**Give your AI agent real PDF tools over the [Model Context Protocol](https://modelcontextprotocol.io).**
One command connects Claude, Cursor, ChatGPT, or any MCP host to [okraPDF](https://okrapdf.com) —
turn any PDF into a bbox-cited **accessible HTML twin**, then parse, extract, query, and render.
This package is a thin launcher around the hosted okraPDF MCP endpoint
(`https://okrapdf.com/mcp`). There's no server to run locally — it bridges your MCP host
(over stdio) to the remote server and handles sign-in for you.
## Quickstart
```bash
npx @okrapdf/pdf-mcp
```
`view_html` (PDF → accessible HTML twin) works with **no account**. The doc-intelligence tools
prompt a one-time **Clerk sign-in** in your browser the first time an agent calls them.
### Claude Code
```bash
claude mcp add okrapdf -- npx -y @okrapdf/pdf-mcp
```
### Claude Desktop / Cursor
Add to your MCP config (`claude_desktop_config.json` or Cursor's `mcp.json`):
```json
{
"mcpServers": {
"okrapdf": {
"command": "npx",
"args": ["-y", "@okrapdf/pdf-mcp"]
}
}
}
```
### Hosts with native remote MCP (Claude web, ChatGPT, Cursor)
Skip this package and add the URL directly: `https://okrapdf.com/mcp`. The launcher above is only
needed for hosts that speak stdio. Same endpoint, same sign-in.
## Tools
| Tool | What it does | Auth |
| --- | --- | --- |
| `view_html` | Stream any public PDF as a live, bbox-cited **accessible HTML twin** | None |
| doc-intelligence — parse · extract · query · resolve · upload · execute · render · workflow | Layout-aware parse, schema extraction with page/bbox citations, cross-document Q&A, renders, and multi-step workflows | Clerk sign-in |
> Sign-in is identity, not a paywall — the doc-intelligence tools are free with an okraPDF account.
> The public `view_html` accessibility twin needs no account. See [okrapdf.com](https://okrapdf.com).
## Configuration
| Override | How |
| --- | --- |
| Point at a different okraPDF endpoint | `OKRA_MCP_URL=http://localhost:8787/mcp npx @okrapdf/pdf-mcp` (or pass the URL as the first arg) |
| Pass flags to the underlying bridge | Anything after the command is forwarded to [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), e.g. `--transport sse-only`, `--debug` |
## How it works
```
MCP host ──stdio──▶ @okrapdf/pdf-mcp ──HTTPS (Streamable HTTP + OAuth)──▶ okrapdf.com/mcp
```
okraPDF's MCP is a hosted, remote server (Cloudflare Streamable HTTP). This launcher wraps
`mcp-remote` so stdio-only hosts can reach it and complete the Clerk OAuth sign-in for the
account-gated tools.
## Links
- Website: <https://okrapdf.com>
- Docs / connector setup: <https://okrapdf.com/docs>
- Issues: <https://github.com/okrapdf/pdf-mcp/issues>
## License
MIT © okraPDF
TDQS
Scored across 27 tools
Many tools have overlapping purposes: view_document, view_pdf, review_extraction, inspect_html, view_structured, and view_html all present document content in different but easily confusable ways. The distinction between render_ui and create_view is also subtle, and the presence of internal poll/get tools adds noise. Despite verbose descriptions, an agent could pick the wrong tool without deep reading.
Tool names almost all follow a verb_noun snake_case pattern (e.g., upload_document, verify_source, list_workflows). Minor deviations like 'interact' and the mix of view_/inspect_/review_ prefixes for similar actions slightly reduce consistency, but the overall convention is clear and predictable.
27 tools is too many for a single server, especially with three tools explicitly marked as internal (poll_document_view, poll_view_commands, get_render_payload) and several near-duplicate view/render tools. The set feels bloated and would be challenging for an agent to navigate efficiently.
The server covers the core PDF workflow: upload/resolve, query via SQL/search, visual and structured views, verification and citation, plus workflow creation and monitoring. Missing explicit update/delete document operations, but most gaps can be worked around with execute_code or SQL, so the surface is reasonably complete.