okraPDF PDF MCP server
OfficialClick on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@okraPDF PDF MCP serverconvert this PDF to accessible HTML with citations"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
okraPDF — PDF MCP server
Give your AI agent real PDF tools over the Model Context Protocol. One command connects Claude, Cursor, ChatGPT, or any MCP host to okraPDF — 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
npx @okrapdf/pdf-mcpview_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
claude mcp add okrapdf -- npx -y @okrapdf/pdf-mcpClaude Desktop / Cursor
Add to your MCP config (claude_desktop_config.json or Cursor's mcp.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.
Related MCP server: pdf-mcp
Tools
Tool | What it does | Auth |
| 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_htmlaccessibility twin needs no account. See okrapdf.com.
Configuration
Override | How |
Point at a different okraPDF endpoint |
|
Pass flags to the underlying bridge | Anything after the command is forwarded to |
How it works
MCP host ──stdio──▶ @okrapdf/pdf-mcp ──HTTPS (Streamable HTTP + OAuth)──▶ okrapdf.com/mcpokraPDF'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
License
MIT © okraPDF
Available Tools
27 toolsapprove_runApprove Workflow RunA
Approve or reject a run that is waiting_for_review (the human-in-the-loop gate). Approving emits the validated rows; rejecting discards the run. Returns the refreshed run snapshot.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | Optional reviewer note recorded on the decision. | |
| run_id | Yes | Run id of the waiting_for_review run to decide on. | |
| decision | Yes | approved emits the rows; rejected discards the run. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description states that rejecting 'discards the run', which is a destructive action, but the annotations declare destructiveHint: false. This is a direct contradiction between the description and the annotations, severely undermining trust and transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded: two sentences cover purpose, context, effects, and return value. Every word earns its place, with no redundancy or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the main aspects: what it does, when to use it, effects of both decisions, and what is returned. It does not explain behavior when the run is not in 'waiting_for_review' state, but given the simple nature of the tool and the presence of a clear output snapshot mention, it is mostly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for all three parameters, with clear descriptions for run_id, decision, and note. The tool description adds minimal semantic value beyond the schema, mostly repeating the same information, hence the baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with a specific verb ('Approve or reject') and resource ('a run'). It also distinguishes this from siblings by mentioning the 'human-in-the-loop gate' and the specific state 'waiting_for_review', setting it apart from view/run workflow tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool: when a run is in 'waiting_for_review' state. It does not explicitly mention alternatives or exclusions, but the context is clear enough to guide selection among workflow-related siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_viewCreate ViewARead-only
Render a model-authored chart, table, metric, proof card, or dashboard as an MCP App and progressively preview safe component JSON while tool arguments stream. Use when you already have the data. For document-backed SQL/codemode work, use render_ui instead. Input view is a compact JSON string; top-level arrays are dashboard items. Do not pass HTML, scripts, iframes, or CDN-dependent payloads.
| Name | Required | Description | Default |
|---|---|---|---|
| view | Yes | Compact JSON string describing a model-authored Okra render view. Use this only when you already have the data and want the MCP App to render progressively while arguments stream. Supported safe component types: dashboard, table, metric, bar, line, area, scatter, vega-lite, proof-card, text, and json. Top-level arrays are treated as dashboard items. Do not use html/script/iframe payloads here; arbitrary HTML belongs in render_ui after server-side codemode completes. | |
| title | No | Optional title for the rendered view. | |
| height | No | Preferred inline widget height in pixels. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already establishes that this is a safe read operation. The description adds valuable behavioral context: progressive preview while arguments stream, safe component JSON handling, and top-level array interpretation. It does not cover auth or error behavior, but the added details go well beyond the annotation baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact at four sentences and front-loaded with the core purpose. Each sentence contributes usage guidance or constraints. It loses a point for some redundancy with the schema's parameter descriptions, especially the list of component types.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Combined with the rich schema and readOnly annotation, the description provides all needed context: when to use, when not to use, input format, restrictions, and render behavior. Even without an output schema, the 'progressively preview' phrasing conveys what to expect. This is a complete, self-sufficient description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema itself provides rich parameter descriptions, including supported component types and the compact JSON format. The main description largely restates these points rather than adding new semantic meaning, so per the calibration baseline, a 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb, 'Render,' and enumerates the output types (chart, table, metric, proof card, dashboard), making the tool's purpose unmistakable. It also explicitly contrasts with the sibling tool render_ui, which further disambiguates it. This is a model example of purpose clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states precisely when to use this tool ('when you already have the data') and explicitly directs to render_ui for document-backed SQL/codemode work. It also provides concrete exclusions by prohibiting HTML, scripts, iframes, and CDN-dependent payloads.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_collectionDescribe CollectionA
Call this FIRST, before any execute_code or render_ui SQL. Returns collection metadata, the document list, the SQLite schema, the node data model (what a node / table / cell is, that cell values are raw strings and that row/column headers are positional sibling cells, not labels), and example queries — the context you need to write a working query on the first try.
| Name | Required | Description | Default |
|---|---|---|---|
| document_id | No | Optional document ID to probe for table serialization shape and document-specific query hints. | |
| collection_id | No | Collection ID, slug, or name. Omit to describe all documents accessible to the current API key. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description carries the full burden. It discloses important model semantics (cell values are raw strings; headers are positional sibling cells, not labels) and the full scope of returned context. It doesn't explicitly state whether the operation is read-only or has side effects, but the nature of the tool implies safety, leaving only a minor transparency gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the critical instruction ('Call this FIRST'), then efficiently lists return contents and concludes with the value proposition. Every clause earns its place, and the length is appropriate for the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no required parameters and no output schema, the description is remarkably complete: it enumerates the return types, explains the tricky node data model, and states the overall purpose. The agent has all needed context to invoke it correctly without further exploration.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage for both parameters, describing `document_id` and `collection_id` with usage details. The tool description itself adds no additional parameter-level guidance, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states what the tool does: 'Returns collection metadata, the document list, the SQLite schema, the node data model... and example queries.' It uses a specific verb ('returns') and names concrete resources. It distinguishes from siblings by explicitly positioning it as a prerequisite to execute_code and render_ui, making its role unique.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit timing with 'Call this FIRST, before any execute_code or render_ui SQL,' which tells the agent when to use it relative to key siblings. However, it does not provide when-not-to-use scenarios or alternatives beyond those two tools, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
draft_workflowDraft WorkflowA
Author, create, build, or draft a workflow. For custom/agentic work, pass code as a high-level agent workflow script using agent() / parallel() / pipeline() / phase(). Minimal working code: phase("Extract"); const result = await agent("Extract the invoice total.", { label:"extract", schema:{ type:"object", required:["total"], properties:{ total:{ type:"string" } } } }); return { result };. Each agent call must include a task prompt and a JSON Schema under the schema key, e.g. agent("task", { label:"extract", schema:{ type:"object", required:["rows"], properties:{ rows:{ type:"array" } } } }) or agent({ prompt:"task", label:"extract", schema:{...} }). Plain JS acts as the deterministic controller. This is the path for provider A/B tests, N-provider parser fan-out, judge/compare barriers, and human review via an explicit detect/apply phase split. definition and catalog_workflow_id are only for finite catalog pipelines. Returns workflow_id, readiness, blueprint, and AST when available. Persisted to your account — same as POST /v1/workflows.
| Name | Required | Description | Default |
|---|---|---|---|
| run | No | Start a run immediately after creating when the selected runtime is configured. | |
| code | No | High-level agent workflow script. Author in the agent()/parallel()/pipeline()/phase() grammar. Minimal working script: phase("Extract"); const result = await agent("Extract the invoice total.", { label: "extract", schema: { type: "object", required: ["total"], properties: { total: { type: "string" } } } }); return { result }; Every agent step MUST include a `schema` JSON Schema contract: agent("task prompt", { label: "extract", schema: { type: "object", required: ["rows"], properties: { rows: { type: "array" } } } }) or agent({ prompt: "task prompt", label: "extract", schema: {...} }). The contract key is `schema`; do not use returns/output_schema/json_schema. Barriers are explicit with parallel(() => agent(...)) thunks; pipeline(items, mapper) is sequential by default and can fan out over runtime data with { concurrency }. phase() names the user-visible stage, and human review is modeled as a detect/apply phase split. Use this for provider A/B tests, N-provider parser fan-out, judge/compare barriers, redaction/extraction review, and other custom agent work. The script is captured as the workflow source artifact and runs through the hosted JS controller harness when the runtime bindings are configured. | |
| name | No | Human-readable workflow name. | |
| inputs | No | Run inputs, e.g. { files: ["doc-…"] } for invoice extraction or { document_id: "doc_…" } for an agent workflow. Setting this implies run:true. | |
| definition | No | Finite catalog pipeline only: { steps: [{ type, id?, name?, with?, needs? }] } using GET /v1/steps types. Use this for staff/catalog pipelines, not custom agent work. | |
| catalog_workflow_id | No | Instantiate a staff template as your own workflow (e.g. staff.invoice-extraction, staff.table-ingest). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behavioral traits: the script is 'captured as the workflow source artifact' and 'runs through the hosted JS controller harness,' requires runtime bindings, persists to the user's account, and returns `workflow_id`, `readiness`, `blueprint`, and `AST` when available. It also explains execution semantics like `parallel(() => agent(...))` for barriers and `pipeline(items, mapper)` for fan-out. Annotations are minimal (all false), so this detailed disclosure carries the full transparency burden, and it succeeds.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely packed with valuable information, including a minimal working code example and a second `agent()` call example. The structure is front-loaded with the core purpose and key decision points. It loses a point for some redundancy—the full code example appears in both the description and the `code` parameter's schema description—making it slightly more verbose than necessary, but the complexity of the tool justifies most of the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex workflow-creation tool with six parameters, nested objects, and no output schema, the description covers all necessary bases: parameter usage, execution environment, persistence, return values, and distinguishing between agentic and catalog modes. It includes explicit guidance on the `schema` contract and how to model human review, making it highly complete for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema descriptions cover all six parameters, the tool description adds significant semantic context beyond them. For example, it explains that `inputs` implies `run: true`, that `code` is authored in a specific grammar (with examples and a required `schema` key), and that `definition` is for staff/catalog pipelines only. This enriches parameter understanding and directly informs invocation choices, exceeding the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Author, create, build, or draft a workflow,' providing a clear action and resource. It immediately distinguishes two modes: custom agentic work via `code` versus finite catalog pipelines via `definition`/`catalog_workflow_id`, which differentiates it from siblings like `run_workflow` and `view_workflow`. The explicit mention of use cases (A/B tests, parser fan-out) further sharpens its purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use `code` ('For custom/agentic work') and when to use `definition`/`catalog_workflow_id` ('only for finite catalog pipelines'), including a contrast between the two. It also provides a minimal working example and detailed constraints on `agent()` calls, effectively guiding the agent on selection and invocation. This goes well beyond implicit usage hints.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execute_codeExecute CodeA
Execute JavaScript against Code Mode namespaces — the primary tool for exploring, querying, grepping, reading, and citing documents (results come back here). For a finished chart, table, metric, or HTML display, pass the working query to render_ui instead.
Code Mode API: docs.list() → [{id, file_name, status, total_pages}] docs.status({ docId }) → {phase, totalPages, totalNodes, ...} docs.read({ docId, pages? }) → {markdown, page_count, total_pages, truncated?} docs.ask({ docId, question }) → {answer, citations, trace_id} (LLM — slow, use sparingly) docs.extract({ docId, prompt, jsonSchema }) → {data, trace_id} (LLM — slow, use sparingly) sql.query({ docId, sql }) → {rows, count} — read-only SQL on one doc; rows include document_id sql.queryMany({ docIds, sql }) → {results:[{docId, rows, count}], count} — run the same query across docs sql.search({ query, docId?, docIds? }) → FTS5 keyword/phrase search across one doc or the current collection sql.grep({ query, docId?, docIds?, pages? }) → literal substring search across node values; useful when FTS tokenization is too strict citation.create({ claim, nodes, docId?, minQuality? }) → {id, url, verification} — mint a shareable link.okrapdf.com/c/{id} proof card; minQuality defaults to "high". citation.batch({ items }) → {citations:[{id,url,...}], count} — mint many proof links from multi-doc results.
SQLite tables per doc: nodes (id, parent_id, type, label, value, status, page_number, confidence, metadata, sort_order) nodes_fts — FTS5 on label+value (use MATCH) meta (key, value) page_ledger (page_number, status, pass, vendor, attempt, confidence, error)
Node data model — the nodes table is the extracted document tree:
Each row is one element.
typeis the raw parser type and varies by vendor, so always run SELECT DISTINCT type FROM nodes first (common values: text, table, row, cell, figure, heading).Tables come in TWO shapes depending on the parser; check with SELECT DISTINCT type: (a) a single
tablenode with the whole table serialized in itsvalue(e.g. the gemini-vision default), or (b) a nestedtable→row→celltree: row.parent_id = table.id, cell.parent_id = row.id, and eachcell.valueholds one cell's text (table/row values are usually empty). For shape (b) read a grid by joining BOTH levels and ordering by sort_order; row/column headers are the first/edge cells positionally, NOT stored onlabel(which is usually NULL).valueis always raw text exactly as printed ("88,268", "16 %", "Sept 30, 2025") — never a typed number/date. Cast in SQL for arithmetic, e.g. CAST(REPLACE(REPLACE(value,',',''),'$','') AS REAL).
Prefer SQL/FTS for discovery, filtering, keyword search, counting, and reading content. SQL is fast, free, and deterministic. Only fall back to reading full pages when SQL doesn't have what you need. When answering numerical or factual questions, use sql.query() to find exact values, then compute the answer step by step. If the first query doesn't return what you need, try a different query — iterate rather than guessing from partial data. IMPORTANT: nodes_fts rows contain full page text (5KB+ each). Always use substr() and JOIN nodes for page_number: SELECT n.page_number, substr(n.value, 1, 200) as excerpt FROM nodes_fts f JOIN nodes n ON n.id = f.node_id WHERE nodes_fts MATCH 'keyword' LIMIT 10 High-grade citation workflow:
Never cite from memory or from a generated answer alone. First use SQL/FTS/search to find exact candidate nodes.
For MCP users, prefer verify_source when you have a claim plus rough locator/pages/quote; pass pdf_url + page/pages for eager one-page public-PDF verification without full ingest, or document_id for parsed-node verification. It renders found/not-found/multiple-candidate states as an inline card.
verification_requirement controls what counts as verified. The default is verification_requirement="bbox": require coordinate evidence and only mint a proof link when a bbox is available. Pass verification_requirement="text_match" only when deterministic page-text/text-layer matching is sufficient; it returns a found state without a durable proof link, page-image proof, or bbox-backed confidence claim.
If you already have exact rows, pass rows that include id, document_id, page_number, value, bbox_x/y/w/h, confidence, and status to verify_source mode="exact_node" or citation.create.
For user-facing, audit, legal, or financial claims, visually verify the page/bbox with view_document or review_extraction before presenting the citation as final when the card says multiple_candidates, not_found, or low confidence.
Treat the returned verification_grade, verification_score, and verification_warnings as the citation quality gate; if warnings mention missing bbox, low confidence, or unverified status, disclose that or find better evidence. Only use ask/extract when the answer requires LLM reasoning, not data lookup.
Page images: https://api.okrapdf.com/v1/documents/{docId}/pg_{N}.png
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Async JavaScript body to execute against your document library. Runs in a V8 isolate. No network, no npm — but ESM imports work at render time (esm.sh). Code Mode namespaces: library.list() → [{id, file_name, status, total_pages}] — your whole document library (docs.list = deprecated alias) library.search({ name?, status?, minPages?, maxPages?, limit?, offset? }) → {documents,count} — filter the whole LIBRARY by name/metadata (vs sql.search, which searches text INSIDE a doc) docs.status({ docId }) → {phase, totalPages, totalNodes, ...} docs.read({ docId, pages? }) → {markdown, page_count, total_pages, truncated?} docs.ask({ docId, question }) → slower LLM answer over one doc docs.extract({ docId, prompt, jsonSchema }) → structured LLM extraction sql.query({ docId, sql }) → {rows, count}; stamps rows with document_id sql.queryMany({ docIds, sql }) → {results:[{docId, rows, count}], count} sql.search({ query, docId?, docIds? }) → FTS5 keyword/phrase search sql.grep({ query, docId?, docIds?, pages? }) → literal substring search citation.create({ claim, nodes, docId? }) → {id, url, verification} citation.batch({ items }) → {citations:[{id,url,...}], count} Action verbs (orchestrate: parse · tools · publish — on docs you OWN): docs.engines() → {engines:[{id,tier,category}], count} — the parse-engine menu (free) docs.parse({ docId, vendor }) → re-parse with an explicit engine id (pin/switch); waits, returns {phase, totalNodes, completed} docs.publish({ docId }) → publish a finished doc to a public read URL → {publicDocId, url} tools.extract({ docId, prompt, jsonSchema }) → okrapdf /extract (structured data) tools.to_json({ docId, schema }) → okrapdf /pdf-to-json (document → JSON in your schema) // Compare engines: call docs.parse per vendor (a dynamic workflow can parallel() them) — each call re-parses the same doc. SQLite tables per doc: nodes (id, parent_id, type, label, value, status, page_number, confidence, metadata, sort_order) nodes_fts — FTS5 on label+value (use MATCH) meta (key, value) | page_ledger (page_number, status, pass, vendor, attempt, confidence, error) Return values: return object/array → rendered as JSON viewer on embed return "<div>..." → auto-wrapped in HTML shell (dark theme, system-ui) return "<!DOCTYPE…" → served as full HTML document (you control everything) return { html, scripts } → html body + scripts block, auto-wrapped in shell Rendering HTML views: Return an HTML string. Fragments like "<h1>Hello</h1>" are auto-wrapped in a shell. For full control, return a complete document starting with "<!DOCTYPE html>". For interactive views, use ESM imports — the CSP allows esm.sh, jsdelivr, cdnjs: return `<div id="app"></div> <script type="module"> import { Chart } from 'https://esm.sh/chart.js@4'; // Chart.js, React, D3, Plotly, Three.js — any ESM package works </script>`; Page images available at: https://res.okrapdf.com/v1/documents/{docId}/pg_{N}.png Common SQL: Page content: SELECT value FROM nodes WHERE page_number = 5 ORDER BY sort_order FTS search: SELECT n.page_number, substr(n.value, 1, 200) as excerpt FROM nodes_fts f JOIN nodes n ON n.id = f.node_id WHERE nodes_fts MATCH 'revenue' LIMIT 10 Cross-doc: sql.queryMany({ docIds, sql }) IMPORTANT: nodes_fts rows are full page text (5KB+). Always use substr() to avoid huge results. | |
| public_doc_ids | No | Optional public doc IDs to mount alongside the authenticated user’s private docs for mixed private/public multi-document analysis. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it delivers: it discloses the V8 isolate execution model, network/npm restrictions, ESM import behavior at render time, LLM slowness for ask/extract, return value conventions, and the large FTS row size pitfall. This goes far beyond a basic 'runs code' statement, giving the agent a realistic model of side effects and constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and well-organized using line breaks and lists. However, it is very long and duplicates the API list already present in the `code` parameter description, which wastes some space. Still, the structure makes it navigable, and the density is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex code-execution tool with no output schema, the description is effectively a mini-manual. It covers the execution environment, available namespaces, SQLite schema, node data model, return conventions, page image URLs, and citation workflow, leaving very little ambiguity about how to invoke and interpret the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds deep semantic value: it explains the node data model and two table shapes, gives best-practice SQL patterns (substr + JOIN), clarifies citation verification requirements, and distinguishes library.search from sql.search. This materially helps the agent write correct code for the `code` parameter and understand `public_doc_ids` in a multi-doc context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pair: 'Execute JavaScript against Code Mode namespaces' and immediately positions it as 'the primary tool for exploring, querying, grepping, reading, and citing documents'. It explicitly contrasts with render_ui for finished displays, clearly distinguishing this tool from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: use this for exploration/querying/citing, and 'pass the working query to render_ui instead' for polished UI outputs. Internally, it directs users to prefer SQL/FTS for discovery, to use ask/extract sparingly, and to iterate on queries. It also references verify_source as the preferred citation workflow for MCP users, making alternatives explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_render_payloadGet render payloadA
Internal: the render_ui viewer fetches a large visualization payload that was stashed out-of-band. Not for direct agent use.
| Name | Required | Description | Default |
|---|---|---|---|
| render_id | Yes | render_id from a render_ui result whose visualization payload was stashed out-of-band for the viewer to fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the payload is large and stashed out-of-band, and that the tool is internal. However, it does not describe side effects (e.g., read-only nature), error behavior, or access requirements, leaving some ambiguity for a tool that fetches data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences, front-loaded with 'Internal' and wasting no words. It conveys the essential purpose and usage restriction efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, the description and schema together cover the key aspects: what it fetches, the source of the ID, and the strong restriction against direct use. It could be more complete by describing the return format or what 'visualization payload' contains, but it is adequate for its simple nature.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a clear description of render_id as coming from a render_ui result and being stashed out-of-band. The tool description adds no additional parameter semantics, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool fetches a large visualization payload for the render_ui viewer, using a specific verb and resource. It distinguishes itself from siblings by explicitly marking itself as internal and not for agent use, though it doesn't name an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Not for direct agent use,' providing a clear when-not-to-use directive. It also names the render_ui viewer as the intended consumer, giving context on how the tool fits into the workflow, effectively discouraging direct use and steering agents toward the viewer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_htmlInspect Parsed HTMLA
Show the STRUCTURED text output of a parsed document: the canonical extracted nodes rendered as plain webpage-like HTML pages — no page images, no bounding boxes. Omit page to render the available pages together (capped, ~50 pages for long docs); pass page for one specific page. Uses canonical DocumentAgent nodes (not vendor playground facets) and returns status="ready" only when node-backed HTML exists, else a not-ready state. For the visual extraction (page images + bounding-box overlays) instead, use view_document.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Optional 1-indexed page number to inspect. Omit to render every same-document HTML page in one inspector container. | |
| facet | No | Deprecated no-op retained for older clients. inspect_html always renders canonical document nodes. | |
| selector | No | CSS selector/query to run inside the PDFQuery Inspector UI (e.g. "table", "[data-label=Table]"). | * |
| document_id | Yes | okraPDF document ID to inspect. | |
| parse_facet | No | Deprecated no-op retained for older clients. inspect_html always renders canonical document nodes. | |
| parse_if_missing | No | Deprecated no-op retained for older clients. inspect_html never queues a parser run. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and succeeds: discloses return status ('status="ready"' only when node-backed HTML exists, else not-ready state), page count cap, and exclusions ('no page images, no bounding boxes'). This goes beyond simple read/write hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tightly written sentences: purpose, usage pattern, behavioral guarantee, and alternative tool. Every sentence earns its place, front-loaded with the main purpose, and no redundancy with schema descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately conveys return status and rendering type. It covers key constraints (page cap, canonical nodes) and distinguishes from view_document. Minor gap: doesn't mention error/not-found behavior for invalid document_id, but overall sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by explaining page behavior (omit vs pass), and clarifying deprecated parameters (facet, parse_facet, parse_if_missing) as no-ops. It doesn't cover selector semantics, but schema already does.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Show the STRUCTURED text output of a parsed document' with specific details about canonical nodes rendered as webpage-like HTML. It explicitly contrasts with view_document ('For the visual extraction... instead, use view_document'), distinguishing it from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit usage instructions: omit page for all pages (capped ~50) or pass page for specific page. Clearly directs users to view_document for visual extraction, offering a concrete alternative. Also clarifies canonical vs vendor facets implicitly guiding when to use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
interactInteract with the open document viewerA
Drive the document viewer the user already has open (from view_document): navigate, highlight a node, or auto-highlight text with the pdf-server-style highlight_text arguments query/page/color/content. Pass document_id plus view_uuid or viewUUID from the view_document result. Use commands or actions for ordered batches. Do NOT call view_document again to navigate — that opens a separate viewer.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-indexed page for action="navigate". | |
| color | No | Highlight color for action="highlight_text", e.g. "#FFFF00". | |
| query | No | Text to find/highlight. For highlight_text, the viewer auto-finds matching text geometry. | |
| action | No | Single viewer action. Use commands for batching. | |
| actions | No | Alias for commands, matching pdf-server multi-action interact calls. | |
| content | No | Tooltip/label content for action="highlight_text". | |
| node_id | No | Block/node id to focus for action="highlight" (from a view_document overlay). | |
| commands | No | Batch of viewer actions, processed sequentially. | |
| viewUUID | No | Alias for view_uuid, matching the pdf-server interact argument shape. | |
| view_uuid | No | The open viewer's view_uuid (from the view_document result). | |
| document_id | Yes | okraPDF document ID being viewed. | |
| match_index | No | 0-indexed match for action="search_navigate". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description bears the full burden. It discloses that the tool drives the existing viewer, that highlight_text auto-finds text geometry, and warns that calling view_document again opens a separate viewer. It could elaborate on error behavior or reversibility, but it gives meaningful context beyond a minimal 'interact' statement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences long, front-loaded with the primary purpose, and every sentence delivers essential information: what the tool does, the required context, batching, and a critical anti-pattern. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having 12 parameters and no output schema or annotations, the description provides a complete orientation: it tells the agent where the viewer comes from, how to identify it, how to batch actions, and what to avoid. It leverages the schema for parameter details and focuses on non-obvious aspects, making it sufficient for effective invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover 100% of parameters, setting a baseline of 3. The description adds value by explaining the relationship between document_id and view_uuid/viewUUID, clarifying the 'pdf-server-style' arguments for highlight_text, and noting that commands/actions enable ordered batching. This elevates it above the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool drives an already-open document viewer, listing specific actions (navigate, highlight node, auto-highlight text). It distinguishes itself from the sibling view_document by explicitly warning against using that tool for navigation, which would open a separate viewer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It specifies the prerequisite (user already has a viewer open from view_document) and instructs to pass document_id plus view_uuid or viewUUID. It explicitly tells when to use commands/actions for ordered batches and provides a clear 'do NOT call view_document again' exclusion, giving strong guidance on when and how to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workflow_runsList Workflow RunsARead-only
List workflow runs you started, newest first, so you can recover run_id values from prior MCP sessions before calling view_workflow_run.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum runs to return, newest first. Defaults to 20. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already establishes safety, and the description adds useful behavioral context: the scope ('you started') and ordering ('newest first'). This goes beyond the annotation without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One well-structured sentence that immediately states the action, scope, and purpose. Every word earns its place, with no fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a simple list operation with one optional parameter and an output schema available. The description covers the key nuance (only runs started by the user) and the intended workflow (recovering run_id), making it sufficiently complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single 'limit' parameter, which fully documents its minimum, maximum, default, and meaning. The tool description itself does not add extra parameter-level detail, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists workflow runs, scoped to 'you started', sorted newest first, and explicitly connects to recovering run_id values for view_workflow_run. This distinguishes it from sibling tools like list_workflows or view_workflow_run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear when-to-use scenario: recovering run_id values from prior MCP sessions before calling view_workflow_run. It implies the tool is for your own runs but doesn't explicitly mention exclusions or alternative scenarios (e.g., when you need all runs).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workflowsList WorkflowsARead-only
List workflows you authored, newest first, so you can recover workflow_id values from prior MCP sessions before calling view_workflow or run_workflow.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum workflows to return, newest first. Defaults to 20. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true. The description adds behavioral details beyond annotations: it lists only authored workflows and orders them newest first. It also discloses the purpose of recovering workflow_id values. This is valuable context, though it does not detail pagination or output structure. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The entire description is one concise sentence that conveys the action, scope, ordering, and purpose. There is no redundant wording. It is front-loaded with the core action and immediately gives the agent actionable guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is sufficient for a simple list tool with a single optional parameter and no output schema. It explains what is returned in terms of workflow IDs, the ordering, and the use case. It could have explicitly stated the return shape, but the phrase 'recover workflow_id values' implies the output is at least ID-bearing. Overall, it is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% as the single limit parameter is fully described in the input schema. The description does not add any additional parameter semantics, but the baseline is 3 when schema covers everything. It reinforces the order and default behavior implicitly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'List workflows you authored, newest first'. It identifies the resource (workflows), the scope (authored), and the ordering. It also distinguishes itself from sibling tools by explicitly mentioning use cases for viewing or running workflows, making it unique among the sibling set.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: 'so you can recover workflow_id values from prior MCP sessions before calling view_workflow or run_workflow'. This tells the agent when to use this tool and why. It does not explicitly exclude alternatives like list_workflow_runs, but the stated purpose is sufficient for most scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
play_music_scorePlay Music ScoreARead-only
Render and play a PDF music-score extraction from semantic note events with normalized page bboxes. Use this when demonstrating non-text PDF accessibility: each note has page coordinates, pitch, timing, and an accessible label; the UI synchronizes the source bbox overlay with a playable score. If no input is provided, it opens a seeded public-domain Beethoven Moonlight Sonata excerpt from Mutopia. For real OMR output, pass abc_notation plus notes[].
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Source PDF page number for the note bboxes. Defaults to 1. | |
| notes | No | Semantic notes with normalized PDF-page bboxes, timing, pitch, and accessibility labels. | |
| title | No | Optional score title. Defaults to the demo excerpt title. | |
| composer | No | Optional composer label. | |
| tempo_bpm | No | Playback tempo in quarter-note beats per minute. Defaults to 54. | |
| abc_notation | No | ABC notation to render as playable sheet music. Defaults to the demo excerpt. | |
| source_label | No | Optional source label shown to the model and app. | |
| mapping_source | No | Short provenance label for the bbox-to-note mapping, e.g. "audiveris", "manual-review", or "seeded-demo". | |
| page_image_url | No | Optional rendered page image URL/data URI for the source PDF page. If omitted, the widget draws a compact generated page from the bboxes. | |
| source_pdf_url | No | Optional source score PDF URL. Defaults to the public-domain Mutopia Moonlight Sonata PDF. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds useful behavior beyond that: the seeded default demo (Beethoven excerpt), the requirement of abc_notation + notes[] for real OMR output, and the UI's bbox synchronization with playable score. This is richer than the baseline, though it doesn't cover all potential side effects or auth requirements (which are likely none here).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying distinct value: purpose, use case/details, and default/recipe. Information is front-loaded and every sentence earns its place; it is appropriate for a tool with 10 parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description fully covers invocation context: the tool's purpose, when to use it, what to pass for real OMR, and the default demo behavior. The UI synchronization detail adds completeness for a rendering/playback tool, making it sufficient for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds value by specifying the parameter combination needed for real OMR ('abc_notation plus notes[]') and the default behavior when no input is provided. This goes beyond the field-level descriptions in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function with a specific verb and resource: 'Render and play a PDF music-score extraction from semantic note events with normalized page bboxes.' It distinguishes this from sibling PDF viewing and UI tools by focusing on music-score playback and accessibility.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit use case: 'Use this when demonstrating non-text PDF accessibility.' It also provides a concrete recipe for real OMR output ('pass abc_notation plus notes[]'). However, it does not mention when not to use it or name alternative sibling tools, so it lacks full exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
poll_document_viewPoll document viewA
Internal: the viewer widget refreshes upload/parse/render status, page images, and extracted blocks. Not for direct agent use.
| Name | Required | Description | Default |
|---|---|---|---|
| pages | No | Pages to refresh, using the same range/list syntax as view_document. Defaults to the first 3 pages. | |
| view_uuid | Yes | The open viewer view_uuid from upload_document or view_document. | |
| document_id | Yes | okraPDF document ID being viewed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses only that the tool is internal and what it refreshes, but gives no indication of side effects, return values, or behavior when called. This is insufficient transparency for a tool that agents might encounter.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is only two sentences and immediately front-loads the critical 'Internal' label. It is efficient with words, though it could be slightly more structured to separate the function from the usage restriction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema and no annotations, and the description is minimal. While 'Not for direct agent use' is a key context, the description lacks details about return values, invocation patterns, or how it relates to the broader workflow. This is insufficient for an agent to understand the tool beyond avoiding it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100%, so the parameters are already well documented. The description adds no additional parameter semantics, making a baseline score of 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states what the tool does (refreshes upload/parse/render status, page images, and extracted blocks) and identifies it as an internal viewer widget. This is a specific verb+resource combination and clearly distinguishes it from sibling tools like view_document by labeling it as internal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear exclusion: 'Not for direct agent use.' This tells the agent when not to use it, which is valuable guidance. However, it does not explicitly name alternatives like poll_view_commands, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
poll_view_commandsPoll viewer commandsA
Internal: the viewer widget drains queued interact commands. Not for direct agent use.
| Name | Required | Description | Default |
|---|---|---|---|
| view_uuid | Yes | The open viewer's view_uuid. | |
| document_id | Yes | okraPDF document ID being viewed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that the tool 'drains queued interact commands,' indicating it consumes/mutates state. However, it does not describe the response format, error conditions, or consequences of calling it, leaving gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that clearly communicates the tool's internal purpose and disallows direct agent use. Every word earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool is explicitly marked as internal with a 'not for direct agent use' warning, the description adequately tells an agent to avoid it. It lacks details on triggering conditions or outcomes, but for an internal tool intended to be invisible, this is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides full descriptions for both parameters (document_id and view_uuid), achieving 100% schema coverage. The description adds no additional meaning about parameter usage, so it relies on the schema, which is sufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description specifies that the tool 'drains queued interact commands' for the viewer widget, providing a clear verb and resource. It is marked 'Internal' which differentiates it from agent-facing tools, though it does not explicitly distinguish it from sibling poll_document_view.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states 'Not for direct agent use,' which is a clear when-not-to-use exclusion. It also labels the tool 'Internal,' reinforcing that agents should avoid directly invoking it. This satisfies the guidelines criterion strongly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
render_uiRender UIA
Run codemode against docs/sql/citation and render the returned visualization as an MCP App. Use for charts, tables, metrics, and small dashboards derived from PDFs after you know the schema. Call describe_collection first, and validate exploratory SQL with execute_code before embedding it here; SQL failures are returned as codemode errors. The codemode sandbox includes the preinstalled "okra-render-ui" module with querySql() plus prebuilt component helpers like TimeSeriesLineChart(), DataTable(), MetricCards(), dashboard(), and chart/table/html specs; keep query code separate from reusable UI helpers, return compact data, not screenshots, and do not rely on CDN scripts such as Chart.js inside html().
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | JavaScript codemode source that queries docs/sql/citation and returns a UI spec for the MCP Apps render_ui widget. Runs in the same isolated V8 codemode environment as execute_code: no network, but docs/sql/citation are available. Before writing SQL, call describe_collection to inspect the document list and schema. For exploratory SQL, validate with execute_code first, then move the working query into render_ui. SQL errors are terminal tool errors, and the renderer only gets the UI payload after codemode succeeds. Preinstalled module: const { querySql, render_ui, dashboard, TimeSeriesLineChart, DataTable, MetricCards, barChart, lineChart, areaChart, scatterPlot, vegaLite, proofCard, table, metric, html } = await import("okra-render-ui.js"); SQLite tables per doc: nodes (id, parent_id, type, label, value, status, page_number, confidence, metadata, sort_order) nodes_fts — FTS5 on label+value (use MATCH) meta (key, value) page_ledger (page_number, status, pass, vendor, attempt, confidence, error) Node data model — the `nodes` table is the extracted document tree: - Each row is one element. `type` is the raw parser type and varies by vendor, so always run SELECT DISTINCT type FROM nodes first (common values: text, table, row, cell, figure, heading). - Tables come in TWO shapes depending on the parser; check with SELECT DISTINCT type: (a) a single `table` node with the whole table serialized in its `value` (e.g. the gemini-vision default), or (b) a nested `table` → `row` → `cell` tree: row.parent_id = table.id, cell.parent_id = row.id, and each `cell.value` holds one cell's text (table/row values are usually empty). For shape (b) read a grid by joining BOTH levels and ordering by sort_order; row/column headers are the first/edge cells positionally, NOT stored on `label` (which is usually NULL). - `value` is always raw text exactly as printed ("88,268", "16 %", "Sept 30, 2025") — never a typed number/date. Cast in SQL for arithmetic, e.g. CAST(REPLACE(REPLACE(value,',',''),'$','') AS REAL). Recommended modular style: keep data access in sql.query()/querySql(), then pass the rows into a prebuilt component helper such as TimeSeriesLineChart(), DataTable(), MetricCards(), dashboard(), barChart(), lineChart(), table(), or metric(). This mirrors product UI components without hardcoding screenshots or CDN chart libraries. Return one of — dashboard()/chart/table/metric helpers render inside Okra's bundled MCP App without external libraries. html() is the flexible escape hatch for fully custom layouts, but external scripts/resources are blocked by the MCP App CSP; do not use CDN libraries such as Chart.js, Plotly, or D3. Use dashboard(), chart helpers, or inline SVG/CSS instead: - html("<h1>...</h1>") or { type: "html", html: "<!doctype html>..." } - TimeSeriesLineChart({ title, labels, series: [{ key, label, data }] }) for PostHog-style time-series data - dashboard({ title, items: [barChart(...), lineChart(...), metric(...), table(...)] }) - barChart({ title, data, x, y, series? }) - lineChart({ title, data, x, y, series? }) - vegaLite({ mark, data: { values }, encoding }) for constrained Vega-Lite-like grouped bars / multi-series lines - proofCard({ claim, page_image, bbox, text, url }) to render citation proof inline - scatterPlot({ title, data, x, y, series? }) - table({ title, rows, columns? }) - metric({ title, metrics: [{ label, value, delta? }] }) - any object/array, which renders as JSON/table fallback Examples: // 1) bar chart of blocks per page async () => { const { querySql, barChart } = await import("okra-render-ui.js"); const [{ id: docId }] = await docs.list(); const rows = await querySql("SELECT page_number, count(*) AS blocks FROM nodes GROUP BY page_number ORDER BY page_number", { docId }); return barChart({ title: "Blocks per page", data: rows, x: "page_number", y: "blocks" }); } // 2) query first, then use a reusable product-style component async () => { const { querySql, TimeSeriesLineChart } = await import("okra-render-ui.js"); const [{ id: docId }] = await docs.list(); const rows = await querySql("SELECT page_number AS day, count(*) AS user_count FROM nodes GROUP BY page_number ORDER BY page_number", { docId }); return TimeSeriesLineChart({ title: "Blocks over pages", labels: rows.map((r) => String(r.day)), series: [{ key: "blocks", label: "Blocks", data: rows.map((r) => Number(r.user_count)) }], }); } // 3) nested table → row → cell grid (only when tables are shape (b); cell.value holds each cell) async () => { const { querySql, DataTable } = await import("okra-render-ui.js"); const [{ id: docId }] = await docs.list(); const rows = await querySql("SELECT r.sort_order AS row, c.sort_order AS col, c.value FROM nodes t JOIN nodes r ON r.parent_id = t.id AND r.type = 'row' JOIN nodes c ON c.parent_id = r.id AND c.type = 'cell' WHERE t.type = 'table' ORDER BY t.id, r.sort_order, c.sort_order LIMIT 100", { docId }); return DataTable({ title: "Table cells", rows }); } // 4) FTS keyword search rendered as custom HTML via html() async () => { const { querySql, html } = await import("okra-render-ui.js"); const [{ id: docId }] = await docs.list(); const rows = await querySql("SELECT n.page_number, substr(n.value,1,200) AS excerpt FROM nodes_fts f JOIN nodes n ON n.id = f.node_id WHERE nodes_fts MATCH 'revenue' LIMIT 10", { docId }); return html("<ul>" + rows.map((r) => "<li>p" + r.page_number + ": " + r.excerpt + "</li>").join("") + "</ul>"); } | |
| title | No | Optional fallback title for the rendered UI. | |
| height | No | Preferred inline widget height in pixels. | |
| document_id | No | Optional primary okraPDF document ID to mount for this visualization. Use after resolve_pdf_url when the user points at a public PDF. | |
| public_doc_ids | No | Optional public document IDs to mount alongside the authenticated user library for multi-document visualizations. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and delivers: SQL failures are codemode errors, the renderer only receives the UI payload after codemode succeeds, the sandbox is isolated with no network, and external CDN libs are blocked by CSP. It also explains the module ecosystem and return formats, providing substantial behavioral context beyond a simple 'renders UI' statement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense paragraph that front-loads purpose, then workflow, then constraints. Every sentence earns its place—no filler. For a tool with this complexity, the length is justified and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers prerequisites (describe_collection, execute_code), execution environment (sandbox, no network), error handling, return types (dashboard, chart, table, metric, html), and critical constraints (CSP, no CDN). The schema enriches with data model details and examples, making the overall context highly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 100%, with descriptions for code and document_id already covering meaning. The description adds workflow-level guidance (validate SQL separately, keep query code separate) but does not add new parameter-specific semantics beyond what the schema already provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Run codemode against docs/sql/citation and render the returned visualization as an MCP App.' It clearly scopes the tool to charts, tables, metrics, and small dashboards derived from PDFs, and distinguishes it from siblings by instructing to call describe_collection first and validate exploratory SQL with execute_code before embedding.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage context is given: 'Use for charts, tables, metrics, and small dashboards derived from PDFs after you know the schema.' It provides direct workflow guidance—call describe_collection first, validate with execute_code—and states constraints: return compact data, not screenshots, and avoid CDN scripts. This is clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_pdf_urlResolve PDF URLA
Resolve a lawfully-reachable PDF URL to a stable okraPDF document_id using the D1 URL registry when later okraPDF tool calls need that document_id: execute_code SQL/search/docs.read, render_ui, view_document/review_extraction, verify_source with parsed-node evidence, or workflow runs. Intended for open/public-record sources (SEC EDGAR, gov, public-domain, permissively-licensed arXiv) and for documents the user supplies or has the rights to process. Do NOT use it to fetch behind a paywall, login, or anti-bot wall, and do NOT treat the resulting derivative as a public mirror of a copyrighted source — see internal/content-rights-policy.md (mirror levels). If you only need to read or understand the PDF content for reasoning, use normal web_fetch/browser reading first; for arXiv papers, prefer the arxiv.org/html/... page when available because it is cleaner and cheaper than OCR. Do not use this for "verify", "cite", "prove", "source", or "where in the PDF" requests; call verify_source directly with pdf_url + page/pages instead. Opens the live document viewer immediately while ingest/parse/page previews finish. Do not set wait_for/wait_ms unless the very next tool call depends on query/page/visual readiness.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Lawfully-reachable HTTPS URL for a PDF (open/public-record source or a doc you have rights to; not paywalled/license-gated — those are refused). arXiv /abs and /html URLs normalize to the direct PDF URL. | |
| pages | No | Optional page range/list used with wait_for="page" and passed to the live viewer, e.g. "23" or "1-3". | |
| wait_ms | No | Optional readiness wait budget. Defaults to 0 so the resolver returns quickly after starting ingest. Only set this when the very next tool call depends on parse/page/visual readiness. | |
| wait_for | No | Optional readiness target for wait_ms. document=phase ready, query=nodes ready, page=requested pages have images, visual=initial viewer preview images ready. | |
| processor | No | OCR processor/vendor id for the parse. Defaults to "gemini-vision" (layout-aware Gemini Flash VLM) so view_document gets bbox-bearing citation overlays. Pass "textlayer" for a fast text-only parse without overlays. | |
| open_viewer | No | Whether to open the live MCP document viewer. Defaults to true; the tool is UI-bound so hosts can show progress immediately. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and largely delivers. It discloses the live viewer opening, default wait_ms=0 fast return, wait_for semantics, processor default (gemini-vision with bbox overlays), open_viewer default, and refusal of protected sources. Minor gaps: exact behavior on refusal or error not described, and the internal policy file is referenced but not summarized.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every sentence adds a distinct piece of guidance: purpose, legal constraints, alternatives, viewer behavior, and wait semantics. It is front-loaded with the primary verb+resource. Could be slightly tighter, but none of the content is redundant or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 6 parameters, no annotations, and no output schema, the description is remarkably complete. It covers purpose, legal boundaries, when to use alternatives, what the tool does immediately (open viewer, start ingest), the wait/readiness model, and parameter defaults. The absence of a returned-output schema is partially mitigated by the description naming the resolved document_id as the core output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds substantial meaning beyond schemas: url gets legal/source-type context and arXiv normalization; pages is linked to wait_for='page' and the viewer; wait_ms explains its default and when to set it; wait_for expands each enum phase; processor explains default vs textlayer tradeoff; open_viewer explains the UI-bound default. This goes well beyond a baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Resolve a lawfully-reachable PDF URL to a stable okraPDF document_id using the D1 URL registry.' It names downstream tools that need this ID and explicitly distinguishes itself from verify_source and web_fetch/browser reading, clearly separating it from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when/when-not guidance: disallows paywalled/login/anti-bot sources, directs pure reading to web_fetch/browser, recommends arXiv HTML over OCR, and explicitly steers verification requests to verify_source with pdf_url + page/pages. Alternatives are named and conditions are concrete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
review_extractionReview ExtractionA
Open the extraction review workflow: page images with bbox overlays and clickable extracted blocks that can be verified or flagged. This is the bbox/provenance workflow surface, not a PDF editor.
| Name | Required | Description | Default |
|---|---|---|---|
| pages | No | Pages to render, 1-indexed. Range ("1-5"), list ("1,3,7"), or single ("2"). Defaults to the first 3 pages. Capped at 8. | |
| document_id | Yes | okraPDF document ID to visualize (e.g. doc-abc123). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It describes the interactive elements (images, bbox overlays, clickable blocks) and actions (verify or flag), but does not disclose side effects or what happens after verification/flagging. This is sufficient for a workflow-opening tool but lacks detail on the consequences of those actions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the primary action, and every clause earns its place. The second sentence adds a useful disambiguation without fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a UI workflow surface with two parameters and no output schema. The description covers the core interaction and the look-and-feel (bbox overlays, clickable blocks). It omits details on how verification/flagging propagate, but leaves enough for a competent user to decide whether this is the right tool. It is complete for its simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage for both parameters (pages and document_id). The description adds no parameter-specific meaning, so it does not exceed the baseline. It correctly implies the purpose of the document_id but does not elaborate on pagination or constraints beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Open the extraction review workflow') and a specific surface: 'page images with bbox overlays and clickable extracted blocks that can be verified or flagged.' This clearly distinguishes it from siblings like view_pdf and verify_block, reinforced by the explicit 'not a PDF editor.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for when to use this tool (for reviewing extractions with visual bboxes) and an explicit exclusion ('not a PDF editor'). However, it does not name any alternative tools for comparison, so the guidance stops short of fully explicit when-to-use-vs-alternative instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_workflowRun WorkflowA
Start a run of a runnable workflow you authored (the write counterpart to view_workflow_run). Pass the workflow_id from draft_workflow and inputs (e.g. {files:["doc-…"]} or {document_id:"doc_…"}). Catalog/step-definition invoice pipelines may surface waiting_for_review; agent workflow scripts run through the hosted JS controller harness and return controller_output plus per-agent outputs and event stream when complete. Same as POST /v1/runs.
| Name | Required | Description | Default |
|---|---|---|---|
| inputs | No | Run inputs, e.g. { files: ["doc-…"] } for invoice extraction (the documents to process). | |
| workflow_id | Yes | Workflow id (wf_…) to run, as returned by draft_workflow. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide no safety hints (all false), so the description carries the burden of transparency. It discloses meaningful behavioral details: some pipelines may surface waiting_for_review, agent scripts run via a hosted JS controller and return controller_output plus per-agent outputs and event stream. It also notes the API endpoint equivalence. However, it does not mention auth requirements, error handling, or whether the run is synchronous beyond 'when complete'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence. It uses three concise sentences covering purpose, inputs, and behavioral variations, plus a short API equivalence note. No word is wasted, and all sentences contribute essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (two workflow types, possible review, output structure), the description covers the main points well. It explains the two execution modes and what is returned, and notes the waiting_for_review state. It does not elaborate on the output schema in detail, but an output schema exists in the tool definition, so that is not required. Missing details like approval flow or error cases are non-critical for initial selection.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully covers both parameters with descriptions, so the baseline is 3. The description adds value beyond the schema by giving concrete examples for inputs (e.g., {files:["doc-…"]} for invoice extraction) and explaining that workflow_id comes from draft_workflow. This enriches the parameter semantics beyond the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb+resource: 'Start a run of a runnable workflow you authored'. It also distinguishes from sibling view_workflow_run by calling itself the 'write counterpart', and provides the REST API equivalent (same as POST /v1/runs). This makes the tool's unique purpose immediately clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly frames the tool as the write counterpart to view_workflow_run, guiding when to use it versus its read-only sibling. It also gives a clear prerequisite by telling the user to pass workflow_id from draft_workflow. The distinction between invoice pipelines and agent scripts gives further context on expected behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_usage_feedbackSubmit Usage FeedbackA
Submit detailed feedback about using the okraPDF MCP server. Use this only when the user asks to report feedback or when a reproducible MCP tool/app issue, confusing workflow, missing affordance, or useful agent-DX note should be sent to the okraPDF team. Pass the long feedback string in feedback; include workflow_id or wf_id, run_id, document_id, tool_name, client_name, tags, and other JSON-serializable debug context in options. Do not include secrets or API keys.
| Name | Required | Description | Default |
|---|---|---|---|
| options | No | Optional debug/context object. Prefer workflow_id or wf_id plus run_id when feedback concerns a workflow. | |
| feedback | Yes | Detailed usage feedback from the agent. Long strings are accepted, but do not include secrets, API keys, or unrelated private data. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false and provide no safety hints, so the description carries the burden. It discloses that feedback is sent to the team, specifies allowed content, and warns against including secrets. It does not describe the response/return behavior, but for a feedback submission tool this is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise sentences, front-loaded with purpose and usage, and every sentence earns its place. It avoids redundancy with the schema while adding essential context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the relatively simple tool (2 params, one nested object, no output schema), the description fully covers when to use, what to pass, and what to avoid. It is complete enough for an agent to select and invoke the tool correctly without further clarification.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds significant meaning by naming which option fields to include (workflow_id or wf_id, run_id, document_id, tool_name, client_name, tags) and explicitly warns against secrets. It clarifies the alias relationship between wf_id and workflow_id, going beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to submit detailed feedback about the okraPDF MCP server. It uses a specific verb ('Submit') and resource ('usage feedback'), and distinguishes from siblings by mentioning concrete triggers like reproducible issues, confusing workflows, and agent-DX notes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use this only when the user asks to report feedback or when a reproducible MCP tool/app issue... should be sent.' It also provides exclusion guidance ('Do not include secrets or API keys') and instructs which context fields to include, making it easy for an agent to decide and invoke correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_documentUpload DocumentA
Upload a PDF from a lawfully-reachable URL or base64 PDF bytes for Gemini Flash VLM extraction when later okraPDF tool calls need a document_id for SQL/search/docs.read, render_ui, view_document/review_extraction, parsed-node verification, or workflow runs. URL ingest is corpus-gated (see internal/content-rights-policy.md): open/public-record sources or docs the user has rights to — not paywalled/license-gated. For such URLs, prefer resolve_pdf_url so the D1 URL registry can reuse prior ingests. If you only need to read or understand PDF content for reasoning, use normal web_fetch/browser reading first; for arXiv papers, prefer arxiv.org/html/... when available. Do not use this for "verify", "cite", "prove", "source", or "where in the PDF" requests; call verify_source directly with pdf_url + page/pages instead. Opens a live document viewer immediately; the app polls status, page images, and extracted blocks as they arrive. Set wait=true only for legacy blocking status behavior.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Lawfully-reachable URL of the PDF (open/public-record source or a doc you have the rights to; not behind a paywall/login). License-gated sources are refused. | |
| data | No | Base64-encoded PDF bytes. MCP-only fallback when no public URL or normal multipart upload handoff exists. | |
| wait | No | Legacy blocking mode. Defaults to false so the MCP App opens immediately and polls live document state. | |
| file_name | No | Filename for base64 uploads. Defaults to document.pdf | |
| processor | No | OCR processor/vendor id. Defaults to "gemini-vision", the shared Gemini Flash VLM parser used by /v1/parse. Advanced legacy values include "textlayer", "unstructured", "azure-di", and "parse-proxy". | |
| document_id | No | Custom document ID (auto-generated if omitted) | |
| page_images | No | Page image rendering strategy. 'none' = no rendering; 'cover' = page 1 only; 'eager' = ALL pages rendered at upload via the PdfRasterizer Container (default). 'lazy' is a deprecated alias for 'eager'. | eager |
| vendor_options | No | Vendor-specific options passed through to the selected parsing vendor (AI SDK providerOptions pattern). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It discloses that this opens a live document viewer, polls status/page images, and that wait=true is a legacy blocking mode. It also reveals content-rights constraints (corpus-gated, no paywalled/license-gated sources) and notes that URL ingest is gated by an internal policy.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded with the core purpose and usage guardrails. While longer than most, every sentence contributes useful guidance (alternatives, legal constraints, live-viewer behavior), so it earns its length without being bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (8 params, no output schema, many siblings), the description is remarkably complete. It covers what the tool does, when to use alternatives, legal/access constraints, live behavior, and parameter defaults, leaving little ambiguity for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds minimal extra meaning beyond the schema—e.g., explaining that data is an MCP-only fallback and clarifying page_images 'eager' default, but these are largely redundant with the schema's own descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Upload') and resource ('PDF') with a clear purpose: preparing documents for Gemini Flash VLM extraction and providing document_id for downstream okraPDF tools. It distinguishes itself from alternatives like verify_source and resolve_pdf_url, and even states when not to use it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use (when document_id is needed for downstream tools) and when-not-to-use (for verify/cite/source requests, prefer verify_source; for simple reading, use web_fetch; for arXiv, use arxiv.org/html). It also names resolve_pdf_url as a preferred alternative for URL ingest and mentions corpus-gating for legal access.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_blockVerify BlockA
Mark an extracted block as verified (✓) or wrong (✗), persisted to the document. Called by the view_document viewer when the user clicks a block; also usable directly with document_id + node_id.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | Optional human note, stored with the verification. | |
| node_id | Yes | Node/block ID to verify (from a view_document overlay). | |
| approved | No | true → mark the block verified (✓). false → flag it as wrong (✗). | |
| document_id | Yes | okraPDF document ID the block belongs to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the core behavior (mark as verified/wrong, persisted), but does not mention side effects, reversibility, or permissions. It is informative but not deeply transparent about consequences.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action in the first sentence and usage context in the second. No wasted words, perfectly sized for the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with complete schema coverage and no output schema, the description is nearly complete. It mentions persistence and the viewer-driven calling context, but leaves out edge cases like idempotency or what happens on repeated calls.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides 100% parameter descriptions, so the baseline is 3. The description adds minimal extra semantic value beyond reiterating the document_id + node_id usage, which is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action: 'Mark an extracted block as verified (✓) or wrong (✗), persisted to the document.' This is a specific verb+resource+outcome, distinguishing it from sibling tools like verify_source or approve_run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context for when the tool is used: 'Called by the view_document viewer when the user clicks a block; also usable directly with document_id + node_id.' This explains the invocation path, though it does not explicitly compare with alternatives like verify_source.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_sourceVerify SourceA
Verify a source for a PDF-backed claim and show the result as an inline citation state card. Default mode is high-level: pass document_id, claim, and any rough locator/pages/quote/number; Okra searches parsed nodes, handles not-found and multiple-candidate states, and when a confident source is found mints a durable link.okrapdf.com proof card with quote, page image, bbox focus, confidence, and reasons. For lawfully-reachable PDFs (permitted source or a doc the user has rights to; not paywalled/license-gated) that should not go through full upload/parse yet, pass pdf_url plus page/pages and the tool uses eager_url mode to fetch only that PDF page. verification_requirement defines what counts as verified and defaults to "bbox": eager_url must resolve coordinate evidence before proof is minted, and the API fails rather than returning a proof without bbox. Pass verification_requirement="text_match" only when a deterministic page-text/text-layer match is enough; that returns a found state without a durable proof link, page-image proof, or bbox-backed confidence claim. Use mode="exact_node" with nodes only when the agent is already grounded in exact query rows or node ids. This is the one model-facing source-verification tool; the result also includes create_view arguments for arranging returned card(s) in a custom view.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Alias for pdf_url. | |
| mode | No | Defaults to high-level auto verification. Use exact_node only when passing query rows or node ids; eager_url is inferred when pdf_url is passed without document_id. | |
| page | No | One-based page number for eager URL verification. | |
| claim | No | Single-source assertion to verify. Use sources[] for multiple citations. | |
| label | No | Optional source label shown on the proof card. | |
| nodes | No | Exact query row(s) or node id(s), only for mode="exact_node" or when the agent is already grounded. | |
| pages | No | Rough pages/ranges for a single citation, e.g. "2", "10-12", or "3,7". | |
| quote | No | Optional direct quote, number, phrase, or printed value to find and cite. | |
| locator | No | Natural-language source hint for a single citation. | |
| pdf_url | No | Lawfully-reachable HTTPS PDF URL (permitted source or a doc you have rights to; not paywalled/license-gated) for eager one-page source verification without upload/parse. Provide pages/page too. | |
| sources | No | Batch mode: verify several claims and render them as citation cards. | |
| document_id | No | okraPDF document ID. Required unless every item in sources has document_id. | |
| min_quality | No | Requested citation grade. Defaults to high, but low-confidence/not-found/multiple-candidate states are rendered as cards rather than hidden. | |
| rough_pages | No | Alias for pages when the user says rough pages. | |
| continue_on_error | No | When sources[] is used, keep verified citations even if one item cannot be matched. | |
| verification_requirement | No | What the caller considers verified. Defaults to bbox, which requires coordinate evidence before proof is minted. Use text_match only when a deterministic text-layer/page-text hit is sufficient and no proof link is needed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and succeeds: it discloses parsing of nodes, not-found and multiple-candidate handling, durable proof card contents (quote, page image, bbox focus, confidence, reasons), eager_url's single-page fetch behavior, and the API's failure rather than minting a proof without bbox. This is exceptional transparency for a complex tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with purpose and organized by mode, with each sentence adding behavioral distinction. It could be trimmed slightly, but for a 16-parameter tool with no annotations, the density is appropriate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description compensates by describing success and reduced return states: durable proof links with quote/page image/bbox/confidence/reasons, text_match's found state without proof link, and failure behavior. It also mentions create_view integration, covering nearly all relevant aspects for a tool this complex.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds operational meaning beyond field descriptions: it explains mode inference when pdf_url is passed without document_id, the behavior and default of verification_requirement, and alias relationships (url, rough_pages). This raises the parameter semantics above the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource+outcome: 'Verify a source for a PDF-backed claim and show the result as an inline citation state card.' It also explicitly states 'This is the one model-facing source-verification tool,' distinguishing it from siblings such as verify_block and view_document.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear when-to-use guidance for each mode: default auto requires document_id, eager_url is for lawfully-reachable PDFs that shouldn't be uploaded/parsed, exact_node is for when the agent is already grounded, and text_match is only for deterministic text-layer matches. It does not explicitly name exclusions versus other tools, but it strongly implies this is the sole source-verification entry point.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_documentView DocumentA
Show the VISUAL extraction of a parsed okraPDF document: page images with colored bounding-box overlays over the extracted blocks that have bbox data (a bounded set per page), plus a clickable block list (click a box to highlight its text, and vice versa). Use after upload_document to let the user see and verify the extraction. Pass document_id and optional pages. For the structured text output instead (parsed nodes as plain reading HTML, no images), use inspect_html.
| Name | Required | Description | Default |
|---|---|---|---|
| pages | No | Pages to render, 1-indexed. Range ("1-5"), list ("1,3,7"), or single ("2"). Defaults to the first 3 pages. Capped at 8. | |
| document_id | Yes | okraPDF document ID to visualize (e.g. doc-abc123). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It transparently describes the visual behavior: page images, bounding-box overlays limited to blocks with bbox data, and interactive highlighting. It does not explicitly state that the operation is read-only, but the 'view' nature strongly implies non-mutation, and the described behavior is detailed enough to set expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no waste. It front-loads the core purpose, includes the interactive details, gives usage context, and adds an alternative in a compact form. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity and lack of output schema, the description adequately explains what the user sees, the interactive behavior, and the proper sequencing after upload_document. It also names the primary alternative for structured output. No significant gaps are evident.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides 100% coverage for both parameters, including the pages format, defaults, and cap. The description only says 'Pass document_id and optional pages,' which adds no additional meaning beyond the schema. Baseline 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Show' and clearly identifies the resource: the visual extraction of a parsed okraPDF document. It details the visual output (page images with bounding-box overlays and a clickable block list) and explicitly distinguishes itself from the sibling tool inspect_html, making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('Use after upload_document to let the user see and verify the extraction') and names a clear alternative ('For the structured text output instead... use inspect_html'). This provides strong contextual guidance for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_htmlView a PDF as accessible HTMLA
Drop a PDF (by public URL) and get back a LIVE, streaming, screen-reader-friendly HTML twin of the document — the same accessible rendering okrapdf.com serves. Returns a viewer_url that progressively streams semantic HTML (headings, lists, tables, figure alt text) as the page is parsed, plus an SSE events_url and a static download_url. Use this to make any PDF readable by assistive tech. (Reserved: policy="wcag" will add the WCAG 2.2 AA / PDF-UA / Section 508 conformance audit — not yet implemented.)
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | ||
| policy | No | ||
| pdf_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well by disclosing the streaming nature, progressive parsing, and the three return URLs. It also transparently notes the reserved 'wcag' policy is not yet implemented, adding trustworthy behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately concise and front-loads the core purpose. While it includes some marketing language ('LIVE, streaming, screen-reader-friendly'), every sentence provides useful information, and the parenthetical adds important caveat without excessive verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of annotations and output schema, the description provides substantial contextual information: behavior, return URLs, streaming, and usage. It falls short only in fully documenting parameters (notably title) and not mentioning potential error conditions, but overall it is sufficiently complete for an AI agent to act.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must explain all parameters. It clearly explains pdf_url (public URL) and hints at policy, but fails to mention the 'title' parameter at all. Policy is only described in a reserved, not-yet-implemented context, leaving the actual 'none' behavior unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: converting a PDF into a live, streaming, accessible HTML twin. It uses a specific verb ('Drop a PDF') and defines the resource and expected output, distinguishing it from siblings like view_pdf or view_structured.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the primary use case: 'Use this to make any PDF readable by assistive tech.' This provides clear context, though it does not explicitly mention when not to use it or name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_pdfView PDFA
Open the document as a PDF reader/navigation surface inside the MCP host. Shows page images and, when available, extracted bounding boxes. Use this for quick visual page inspection; use review_extraction when the user is specifically verifying parser output.
| Name | Required | Description | Default |
|---|---|---|---|
| pages | No | Pages to render, 1-indexed. Range ("1-5"), list ("1,3,7"), or single ("2"). Defaults to the first 3 pages. Capped at 8. | |
| document_id | Yes | okraPDF document ID to visualize (e.g. doc-abc123). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that the tool 'Shows page images and, when available, extracted bounding boxes,' which is behavioral output context. The 'PDF reader' phrasing implies a read-only surface, though it does not explicitly state read-only or mention permissions/rate limits. This is adequate for a viewer but not over-detailed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core action, and contains no filler or redundant information. Every sentence contributes value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple viewer tool with two parameters and a clear visual output, the description is complete: it explains what it does, what it shows, and when to use it. The mention of review_extraction also prevents misuse. No output schema exists, so the description's explanation of 'shows page images' serves as an adequate return description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are fully documented in the input schema. The description does not add extra syntax, format details, or relationships beyond what the schema already provides, matching the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Open') and resource ('document as a PDF reader/navigation surface') and explicitly contrasts with review_extraction, distinguishing it from at least one sibling. It clearly conveys that the tool is for visual page inspection with page images and bounding boxes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: 'Use this for quick visual page inspection; use review_extraction when the user is specifically verifying parser output.' This names an alternative and states when to use this tool versus another, which is exemplary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_structuredView Structured TextA
Open the parsed structured text/HTML view inside the MCP host. Use this for reading extracted document content as HTML without page images or bbox overlays; use view_pdf/review_extraction for visual source pages.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Optional 1-indexed page number to inspect. Omit to render every same-document HTML page in one inspector container. | |
| facet | No | Deprecated no-op retained for older clients. inspect_html always renders canonical document nodes. | |
| selector | No | CSS selector/query to run inside the PDFQuery Inspector UI (e.g. "table", "[data-label=Table]"). | * |
| document_id | Yes | okraPDF document ID to inspect. | |
| parse_facet | No | Deprecated no-op retained for older clients. inspect_html always renders canonical document nodes. | |
| parse_if_missing | No | Deprecated no-op retained for older clients. inspect_html never queues a parser run. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the transparency burden. It does disclose that the tool opens a view inside the MCP host and that the view lacks page images/bbox overlays. However, it does not mention that several parameters (facet, parse_facet, parse_if_missing) are deprecated no-ops, nor does it clarify the relationship to inspect_html mentioned in the schema. This is a notable transparency gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is composed of two concise sentences: the first states the action and resource, the second provides usage guidance and alternatives. Every sentence earns its place with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 6 parameters, 3 of which are deprecated no-ops, and no output schema. The description covers the core purpose and usage alternatives but does not address the deprecated parameters or the tool's relationship to inspect_html (referenced in the schema). The absence of an output schema also means the description should clarify what the view contains, which it partially does ('without page images or bbox overlays'). Overall, it is adequate but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description does not add meaning beyond the schema; it only implies the use of document_id and selector through the 'reading extracted document content as HTML' phrase. The schema already documents all parameters, so the description adds little.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Open') and resource ('parsed structured text/HTML view'), and clearly states the scope: reading extracted document content as HTML without page images or bbox overlays. It distinguishes from sibling tools by explicitly directing visual source pages to view_pdf/review_extraction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance ('Use this for reading extracted document content as HTML without page images or bbox overlays') and an explicit alternative ('use view_pdf/review_extraction for visual source pages'). This clearly positions the tool against its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_workflowView WorkflowARead-only
Confirm a workflow as it is being built: finite definitions return visualization + validation, while agent workflow scripts return parse/readiness state and a best-effort plan estimate. Accepts a catalog name (e.g. staff.table-ingest) or a workflow id you authored.
| Name | Required | Description | Default |
|---|---|---|---|
| workflow_id | Yes | Workflow id or catalog name to confirm/visualize (e.g. staff.table-ingest, or a wf_… you authored). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the readOnlyHint annotation by explaining the exact behavioral differences: finite definitions produce visualization+validation, while agent workflow scripts produce parse/readiness state and a best-effort plan estimate. This adds valuable insight into expected behavior without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise—two sentences—and front-loads the core purpose. Every clause adds value: purpose, type-specific behavior, and accepted input format. No wasteful repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only tool with no output schema, the description sufficiently explains what the tool returns and under what conditions. It covers the key differentiators and usage context, making it complete enough for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides a thorough description of parameter workflow_id, including examples. The description reinforces this by mentioning 'catalog name' and 'workflow id you authored,' but does not add substantially new meaning beyond the schema. Baseline 3 is appropriate given 100% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action: 'Confirm a workflow as it is being built.' It also distinguishes between two workflow types and what each returns, which differentiates it from siblings like view_workflow_run or list_workflows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'as it is being built' gives clear context for when to use this tool (during construction/validation of a workflow). It does not explicitly mention alternatives or exclusions, but the context implies it is not for viewing runs or listing workflows, which are covered by siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_workflow_runView Workflow RunARead-only
Monitor a workflow run. For agent workflow scripts, returns status, stats, controller_output, per-agent outputs, event stream, logs, and failed-agent details. For step-definition workflows (e.g. invoice extraction), returns overall status, per-document rows, exceptions, dropped docs, stats, and the human-approval state. Pass the run_id from POST /v1/runs.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | Run id (e.g. dynrun_…) returned by POST /v1/runs or a prior view_workflow_run call. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description adds valuable behavioral context by explaining that the response structure varies by workflow type (agent vs step-definition) and highlights specific fields like human-approval state. This goes beyond the basic read-only indication.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise: a front-loaded purpose statement, a compact enumeration of return fields for two workflow types, and a clear parameter instruction. Every sentence earns its place with no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and readOnlyHint annotation, the description doesn't need to fully enumerate return values but does a good job summarizing major categories. It covers the key behavior and parameter source, though it doesn't address error scenarios or polling behavior, which are minor gaps for a monitoring tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already thoroughly documents the run_id parameter (e.g., dynrun_…, source from POST /v1/runs or prior view_workflow_run call). The description just repeats 'Pass the run_id from POST /v1/runs' without adding new semantics, so it meets the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Monitor' and the resource 'workflow run', and further specifies the detailed return contents for two workflow types. This distinguishes it from sibling tools like view_workflow (which views a workflow definition) and list_workflow_runs (which lists runs).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context that this tool is for monitoring a specific workflow run, and instructs to pass the run_id from POST /v1/runs. While it doesn't explicitly mention alternative tools, the purpose and naming make the appropriate usage evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
27 tool updates
v0.1.0- First observed
approve_run - First observed
create_view - First observed
describe_collection - First observed
draft_workflow - First observed
execute_code - First observed
get_render_payload - First observed
inspect_html - First observed
interact - First observed
list_workflow_runs - First observed
list_workflows - First observed
play_music_score - First observed
poll_document_view - First observed
poll_view_commands - First observed
render_ui - First observed
resolve_pdf_url - First observed
review_extraction - First observed
run_workflow - First observed
submit_usage_feedback - First observed
upload_document - First observed
verify_block - First observed
verify_source - First observed
view_document - First observed
view_html - First observed
view_pdf - First observed
view_structured - First observed
view_workflow - First observed
view_workflow_run
TDQS
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.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted MCP server: convert PDFs to clean, LLM-ready Markdown with tables, formulas and OCR.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Htmlpdf Transform Mcp connects AI agents to real public APIs via MCP. Tools include
The CustomGPT.ai MCP server is a fully managed, RAG-powered endpoint that connects large language models with private knowledge bases and external data sources. It provides tools for retrieval-augmented generation queries (send_message), data ingestion (upload_file), and source listing, enabling AI agents to query private documents like PDFs with high accuracy and real-time citations.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that enables AI assistants to read, search, and analyze PDF files from local paths or URLs. It provides tools for extracting specific page ranges, searching for terms, and retrieving document metadata.4461MIT
- AlicenseAqualityCmaintenanceAn MCP server for reading, rendering, and searching PDF files, specifically optimized for LLMs to extract text, tables, and technical diagrams. It enables metadata retrieval, multi-format text extraction, and page-to-image rendering using PyMuPDF.577MIT
- AlicenseNot gradedqualityAmaintenanceMCP server that reads PDFs and exposes them as structured Markdown, metadata, outlines, images, and tables to LLM consumers via tools like pdf_read_markdown and pdf_info.Apache 2.0
- FlicenseNot gradedqualityDmaintenanceA local MCP server that extracts text-layer content from PDF files, enabling AI agents to inspect, extract text, outlines, and page content.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/okraocr/pdf-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server