Skip to main content
Glama
david-wang-0

okular-mcp

by david-wang-0

okular-mcp

An MCP server that tells an LLM session what you are reading in Okular: which documents are open and on what page, the text you have selected with the mouse (with its LaTeX source lines when the PDF has SyncTeX data), and (when you ask) showing you a page. A prompt hook for Claude Code adds the document, the page and your selection to every prompt you type in a project that contains the PDF, and okular-mcp-open lets LaTeX tools open a PDF or do a forward search in Okular.

This server does not read or write PDF content. It implements the viewer-state contract in CONTRACT.md, and the PDF work is done by sibling servers:

  • pdf-reader-writer-mcp: page text with line numbers, links, outline, annotations, marks and notes written back, and locate (selection to line numbers). Every tool takes the path and page this server reports.

  • vscode-pdf-mcp: the same contract for the PDF viewer inside VS Code.

CONTRACT.md is shared: both viewer servers keep an identical copy, and its clauses (C1 to C8) are pinned by tests named after them (test_c3_...). Change it in both repositories together, never in one.

Tools

Tool

What it does

viewer_state()

One entry per Okular window with a document open, the active one first (C1)

get_selection(source="primary")

The text selected with the mouse (primary), attributed to the active document and the page it is on, with its LaTeX source lines when the PDF has SyncTeX data; or the clipboard (clipboard), never attributed (C2)

goto(page, path?)

Show page of path (default: the active document), opening the file first if no window has it; returns its entry after the move. Meant for "show me where that is", not for the model to navigate on its own (C3)

An entry is

{"viewer": "okular", "window": "org.kde.okular-12345", "path": "/abs/paper.pdf",
 "page": 3, "pages": 12, "active": true}

window is the Okular process's D-Bus service name, page is 1-based, pages the page count. Okular reports no focus, so the active entry is the first window that has a document open. With nothing open (or Okular not running), viewer_state and goto without a path fail with a message starting no Okular window with a PDF open.

get_selection returns {"text", "source"}, plus viewer, path and page for source="primary" when a document is open. text is "" when nothing is selected. The primary selection is system-wide: it is whatever was last selected in any window, so it is attributed to Okular's active document on trust, and Okular does not say where in the document it is. So the server looks for the selected words in the text of the active document's current page, then the next page, then the previous one (with poppler's pdftotext, the same text layer Okular selects from), and page is the first page that has them, else the current page. When they occur exactly once on that page and the PDF has a .synctex.gz (or .synctex) next to it, tex gives their LaTeX source lines, from synctex edit at the first and last word and one word of each printed line between:

{"text": "...", "source": "primary", "viewer": "okular", "path": "/abs/paper.pdf",
 "page": 4, "tex": [{"file": "/abs/sec/intro.tex", "lines": [12, 15]}]}

One entry per source file, in document order. A selection may start or end inside a word, and a word TeX hyphenated at a line end matches with or without its hyphen. pdfTeX tags the space after a source line's first word with the line before, so synctex edit alone gives that word the previous line; the server checks with synctex view whether the next line, if it has text, starts right after the word and then takes that line, and it maps a paragraph's last word, which SyncTeX puts on the blank line after it, to the line it is on.

goto fails with no such file: <path> for a path that does not exist, cannot open <path> if Okular fails to load it, and page N outside 1-M before moving if the page is out of range. For a file it cannot load, Okular shows a modal error dialog and answers the D-Bus call only once the user closes it, so goto (and okular-mcp-open) take a few seconds to report cannot open; the dialog stays in Okular until it is closed.

Errors reach the model as their message (as an MCP tool error), not as a generic "Error executing tool".

Related MCP server: PDF Agent MCP

Prompt hook (Claude Code)

okular-mcp-hook is a UserPromptSubmit hook. Add it to a Claude Code settings.json (user or project):

{
  "hooks": {
    "UserPromptSubmit": [
      {"hooks": [{"type": "command", "command": "okular-mcp-hook", "timeout": 5}]}
    ]
  }
}

When the active Okular document lies inside the session's working directory (after resolving symlinks; a PDF in a sibling directory does not count), it adds

The user is reading /abs/project/paper.pdf in Okular, page 3 of 12.
Selected text (page 4):
the words you selected
Source: sec/intro.tex:12-15

to the prompt's context. Otherwise it adds nothing. The selection lines come only when the selected words are found on the document's current page or a page next to it (as for get_selection): the system primary selection cannot be tied to Okular otherwise, and is often the text just selected in the terminal the prompt is typed in. The text is cut at 2000 characters ( […] marks the cut). The Source: lines follow when the PDF has SyncTeX data (:12 alone for a single line), with the file relative to the working directory when it lies inside it.

The hook always exits 0, also on bad input or when Okular or the bus does not answer (each qdbus call may take 0.3 s, and a 0.8 s watchdog ends it silently), so it never blocks a prompt. The selection part has its own deadline, 0.6 s after the hook starts: if reading the selection, pdftotext or synctex is slow or missing, the hook leaves the selection out and still reports the page. Measured on a 54-page paper with SyncTeX data, the whole hook takes about 0.26 s with a selection found and mapped (about 0.14 s of it for the selection part) and about 0.13 s without one.

LaTeX: okular-mcp-open

okular-mcp-open <pdf>                                         # open the PDF
okular-mcp-open --tex <file> --line <n> [--column <n>] <pdf>  # forward search

The same command line as vscode-pdf-mcp-open, so a LaTeX tool can be pointed at either viewer. A window that already shows the PDF is left as it is; otherwise a new Okular window opens it (okular started without arguments, which never joins a running Okular as a tab). The forward search asks synctex view for the page first, then hands Okular the URL file://<pdf>#src:<line> <file> (the --unique forward search), in the window that shows the PDF or else a new one. Okular has no column in a forward search, so --column is accepted and ignored (a negative one means none, as LaTeX Workshop may pass). It prints <pdf>: page <n> of <pages> (what Okular shows once it has settled), exits 1 with the reason on stderr when it cannot (no such file: <pdf>, cannot open <pdf>, no SyncTeX data for <file>:<line> in <pdf>, Okular not starting) and 2 on bad arguments.

A forward search opens the document anew, like okular --unique, so Okular asks to save unsaved annotations first; save in Okular before you jump.

LaTeX Workshop, in VS Code's settings.json:

"latex-workshop.view.pdf.viewer": "external",
"latex-workshop.view.pdf.external.viewer.command": "okular-mcp-open",
"latex-workshop.view.pdf.external.viewer.args": ["%PDF%"],
"latex-workshop.view.pdf.external.synctex.command": "okular-mcp-open",
"latex-workshop.view.pdf.external.synctex.args": ["--tex", "%TEX%", "--line", "%LINE%", "%PDF%"]

Then View LaTeX PDF opens Okular and LaTeX Workshop's forward search (Ctrl+Alt+J) lands in it. Use the absolute path of okular-mcp-open as the command if VS Code does not have it on its PATH. Inverse search is Okular's own: Shift+click in the page opens the source in the editor set under Settings → Configure Okular → Editor.

No reload tool, and saving

Nothing here writes the PDF, and there is no reload tool (C4). Okular's "Reload document on file change" (WatchFile, on by default) re-renders the document by itself after another tool saves it: an incremental save by pdf-reader-writer-mcp showed up in about 1.5 s. But Okular keeps your own unsaved annotations in memory and loses them when the file changes, so save in Okular (Ctrl+S) before another tool writes to the file; the server's instructions tell the model to ask you first.

Requirements

Linux with KDE's Okular on the session D-Bus, plus:

  • qdbus (Qt tools; installed with Okular on most distributions)

  • wl-clipboard on Wayland, or xclip/xsel on X11, for get_selection

  • optional: pdftotext (poppler; poppler or poppler-utils), to find the page of a selection; without it, page is the current page and the hook leaves the selection out

  • optional: synctex (TeX Live), for the tex source lines, the hook's Source: lines and okular-mcp-open --tex

  • Python 3.10+; mcp is the only dependency

Install

With uv:

uv tool install git+https://github.com/david-wang-0/okular-mcp

This installs okular-mcp (the server), okular-mcp-hook and okular-mcp-open. Register the server with your MCP client. Claude Code, user scope:

claude mcp add okular -s user -- okular-mcp

Codex CLI:

codex mcp add okular -- okular-mcp

Any other client: run okular-mcp as a stdio server.

Gotchas

  • Tabs. With several documents in tabs of one window, Okular's D-Bus interface reports the first-opened tab, not the active one (KDE bug 502482). Use separate windows if you rely on viewer_state: the process registers a single /okular object, so other tabs are not reachable over D-Bus at all. With the vscode-pdf-external-open extension, run it without --unique (one window per PDF) and leave --unique to the LaTeX build viewer only; see that README.

  • Selection text is Okular's text layer, returned verbatim: hyphenation and column order can be messy. A selection whose words the page's text does not have in that order (it spans a page break, or Okular split a formula differently from pdftotext) is not found: page is then the current page, without tex, and the hook leaves it out.

  • Minimal client environments. Some MCP clients (Codex, the Python SDK's client) start servers with only HOME, PATH, SHELL and USER. Before any qdbus, wl-paste, xclip or xsel call, the server (and the hook) recover DBUS_SESSION_BUS_ADDRESS and WAYLAND_DISPLAY from XDG_RUNTIME_DIR (or /run/user/<uid>), so no per-client env block is needed on a systemd desktop (C5).

Development

uv venv && uv pip install -e '.[test]'
.venv/bin/pytest                    # the default suite: fakes only, about 15 s
.venv/bin/pytest -m integration     # real Okular, headless on a private bus, about 30 s

The default suite never starts Okular or touches the real bus or selection. Unit tests run against fakes (a fake session bus behind viewer._call, a fake subprocess.run and PATH, fake pdftotext/synctex output); the tests of a CONTRACT.md clause are named after it (test_c3_...). The process-level tests run the real entry points with the fake qdbus, wl-paste, pdftotext and synctex executables of tests/fakes.py on PATH: tests/test_mcp.py drives okular-mcp over stdio with the mcp package's client (tool list, instructions, results, error messages), tests/test_hook_process.py runs okular-mcp-hook as Claude Code does (C6-C8, timing included), and tests/test_packaging.py checks the console scripts. With pdflatex, synctex and pdftotext installed, tests/test_sourcelines.py also compiles small LaTeX documents and checks the selections' pages and source lines with the real tools.

The integration suite (tests/integration/, marker integration, deselected by default) needs okular, dbus-run-session, qdbus (or qdbus6), pdflatex, synctex and pdftotext, and skips with the list of what is missing; its C4 test also needs pdf-reader-writer-mcp on PATH. It is headless and never touches your Okular or screen: dbus-run-session provides a private bus, and every Okular and every process under test runs on it with QT_QPA_PLATFORM=offscreen, without DISPLAY/WAYLAND_DISPLAY, with temporary XDG config, data, cache, state and runtime directories, and (for the code under test) a fake wl-paste as the selection. Okular's output goes to files in pytest's temporary directory, and everything on the private bus (Okulars, and daemons it started such as ksecretd) is killed at the end. It covers C1 (not running, no document, several windows), C3 goto (moving, out of range, no such file, a broken PDF, a closed file, a symlink, a path with spaces and #), okular-mcp-open (new window, reuse, forward search into an \input file, no SyncTeX data, exit codes), the hook with a selection on and off the page, and C4: a mark written by pdf-reader-writer-mcp, after which Okular reloads the file and stays on the document and page.

Coverage, including the processes the tests start ([tool.coverage.run] in pyproject.toml):

uv pip install coverage
.venv/bin/coverage run -m pytest && .venv/bin/coverage combine && .venv/bin/coverage report -m

okular_mcp/viewer.py is the only Okular-specific module (windows, entries, active, goto, and new_window, open_url, wait_loaded for okular-mcp-open), selection.py reads the system selection, sourcelines.py finds it on the page and maps it to source lines, hook.py is the prompt hook, open.py is okular-mcp-open.

License

MIT

Available Tools

13 tools
add_notePDF: margin note or replyA

Put a comment icon in the margin, or reply to an annotation.

Comment icon in the margin: level with near_text, or as a threaded reply to the annotation reply_to (an xref from annotations, e.g. to answer the user's own note), else at the top of the page. color as in mark_text. Same save-Okular-first caveat as mark_text.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteYes
pageNo
pathNo
colorNo
reply_toNo
near_textNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false and destructiveHint=false, so the write/safety profile is covered. The description adds one genuine behavioral fact — the 'save-Okular-first' caveat — but only by deferring to mark_text, so the agent must already know that sibling to act on it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the two modes and back-loading the anchor elaboration. Dense and waste-free, though the backtick-heavy cross-references cost some readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists so return values need no explanation, and the annotation set covers safety. But for a non-idempotent mutation with 6 undocumented parameters, the description omits whether near_text and reply_to are mutually exclusive and what happens to page/path defaults.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 6 parameters, so the schema gives no semantics. The description compensates for three of them (near_text, reply_to, color) with clear roles, but leaves note, page, and path entirely unexplained, including which anchor fields are mutually exclusive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (place a comment icon / reply to an annotation) on a specific resource, and explicitly splits the tool into two modes: a margin note anchored via near_text, or a threaded reply via reply_to. An agent can distinguish it from mark_text and annotations by the named anchors alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives selection logic for the anchor: use near_text for a margin-level icon, reply_to (an xref from annotations) to answer an existing note, otherwise it falls back to the top of the page. It names sibling tools but never states the when-not condition versus mark_text, which is the closest alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

annotationsPDF: highlights and notesB
Read-only

All highlights, notes and attachments saved in the PDF.

All annotations in the PDF (default: the open document): page, type, author, highlighted text, note. Only annotations saved to the file are visible.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, and the description adds genuinely useful behavior beyond that: only annotations saved to the file are visible, and the default scope is the currently open document. It doesn't cover pagination or result ordering, but the key visibility caveat is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is short and front-loaded, but the first sentence ('All highlights, notes and attachments saved in the PDF') is largely restated by the second sentence ('All annotations in the PDF'), so one of the two sentences is partly redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value formatting needn't be spelled out, and the description still names the fields. Safety is covered by annotations. The remaining gap is the undocumented 'page'/'path' parameters, which is minor for a simple read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and neither 'page' nor 'path' is documented in the schema. The description's word 'page' appears in a list of return fields, not as a filter explanation, and 'path' is only obliquely hinted at via 'default: the open document.' The parameters are largely left for the agent to infer.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the resource and operation: retrieving all highlights, notes and attachments saved in a PDF, including the fields returned (page, type, author, text, note). It is distinct enough from write siblings like add_note/mark_text/remove_annotation, though it never explicitly contrasts itself with them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is a scoping hint that the default target is "the open document," but no explicit when-to-use guidance and no routing to alternatives such as get_selection or page_text. An agent gets no criteria for choosing this tool over its read siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

attach_filePDF: attach a text fileB

Embed a text file (Markdown, Mermaid) as a paperclip annotation.

Embed a text file (e.g. notes.md, diagram.mmd) as a paperclip annotation in the margin, level with near_text or at the top of the page; or replace the file of an existing attachment replace_xref. Okular saves it via the icon's context menu. Same save-Okular-first caveat as mark_text.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
noteNo
pageNo
pathNo
colorNo
contentYes
near_textNo
replace_xrefNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false, but the description adds genuinely useful operational context: Okular persists the attachment via the icon's context menu, and there is a 'save-Okular-first' caveat shared with mark_text. The replace_xref mode (overwriting an existing attachment's file) is disclosed, which is meaningful given destructiveHint=false. It stops short of explaining auth/permission requirements or what the tool returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The key constraint is front-loaded, but the second sentence restates 'Embed a text file ... as a paperclip annotation' almost verbatim from the opening line, wasting space. The remaining clauses earn their place by conveying placement and save behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and the mutation/save caveat is covered. But with 8 parameters at 0% schema coverage and no explanation of the required ones (name, content) or the placement interplay between page/near_text/path, the description is only minimally sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and there are 8 parameters, so the description carries the full burden — yet it only adds meaning for `near_text` (placement, level with text) and `replace_xref` (target existing attachment). The six remaining parameters (name, note, page, path, color, content) are left completely undetermined by both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Embed') plus resource ('a text file ... as a paperclip annotation') and gives concrete file-type examples (Markdown, Mermaid). An agent can distinguish this from add_note and mark_text, though the description never explicitly contrasts with those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies when this tool applies by describing placement modes ('level with `near_text` or at the top of the page') and a replace flow ('replace the file of an existing attachment `replace_xref`'), and points to `mark_text` for a shared caveat. However it never states when to choose attach_file over add_note or read_attachment, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contextPDF: paragraph around the selectionA
Read-only

The paragraph around the user's mouse selection.

The paragraph around the user's current mouse selection (or text) on the page shown, with neighbours paragraphs before and after and the line numbers, so you can see what they are pointing at without reading the whole page.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
pathNo
textNo
neighboursNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already establishes a safe read, so the description's job is to add beyond that — it does by disclosing what comes back (the paragraph, `neighbours` paragraphs before/after, and line numbers) and that `text` can substitute for the live mouse selection. It does not cover fallback behavior when no selection exists, but the added context is genuine.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and short, but the opening sentence 'The paragraph around the user's mouse selection' is a near-verbatim restatement of the title and is then repeated at the start of the longer second sentence. One sentence of duplication is wasted space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no prose explanation, and the safety profile is covered by annotations. Still, with four parameters at 0% schema description coverage and no clarification of what `page` or `path` do (especially with zero required parameters), an agent cannot fully infer how to target the correct document.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the schema documents nothing and the description must compensate. It explains `neighbours` (paragraphs before and after) and `text` (an alternative to the live selection), covering two of four parameters, but leaves `page` and `path` completely undefined.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a precise resource — the paragraph containing the user's mouse selection, plus neighbouring paragraphs and line numbers. It implicitly contrasts with page-level retrieval via 'without reading the whole page', but never names the distinction against siblings like get_selection or page_text explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a rationale for use ('so you can see what they are pointing at without reading the whole page'), which implies 'use when you need around-the-selection context cheaply'. However there is no explicit guidance on when to prefer get_selection or page_text instead, and no stated preconditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_selectionOkular: mouse selectionA
Read-only

Text the user has selected with the mouse, with page and lines.

Text currently selected with the mouse ('primary') or on the clipboard ('clipboard'), with the document path, page and line numbers when it is found on the page Okular shows (line numbers match page_text and context).

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceNoprimary

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint=true annotation already establishes this as a safe read. The description adds real context beyond that: selection may come from the mouse or clipboard, and line numbers are only populated when the text is found on the current page. It still omits what happens when nothing is selected or how the two sources behave differently.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The two sentences overlap heavily: the first ('Text the user has selected with the mouse, with page and lines') largely restates the second. It is short but not maximally economical; the lead could be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and the safety profile is carried by annotations. Given the one-parameter, read-only scope, the description covers what an agent needs. Minor gaps remain around the default source behavior and empty-selection handling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single 'source' parameter has only a default and no documentation. The description compensates by naming the accepted conceptual values ('primary' for mouse selection, 'clipboard' for the clipboard), which is the key semantic an agent needs to set that parameter correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb+resource: retrieving the text the user has selected with the mouse, plus page and line numbers. It implicitly distinguishes itself from siblings like page_text and context by noting the line numbers match those tools' output. It does not name an alternative it is not, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clarifies the two retrieval modes ('primary' mouse selection vs 'clipboard') and that line numbers appear only when the text is found on the currently shown page, which implies usage. However, there is no explicit statement of when to reach for this instead of page_text, context, or viewer_state.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gotoOkular: show a page to the userA

Jump Okular to a page for the user.

Jump Okular to page of path (default: current document; opens it if needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageYes
pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the bar is lower. The description adds real behavioral context by noting the target defaults to the current document and that the document will be opened if needed — a genuine side effect not captured by annotations — but says nothing about page-number validity, range errors, or what happens if the jump fails.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and followed by the precise semantics of the parameters. The opening sentence slightly restates the second, but there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. For a two-parameter navigation tool whose annotations cover the safety profile, the description supplies the essentials (target page, default document, open-if-needed); only page-numbering and error behavior are unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden and largely does: it explains that `page` is the destination and that `path` defaults to the current document (opening it if necessary). It does not specify page numbering (1-based?) or out-of-range behavior, leaving a small gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (jump) and resource (Okular page/document), so an agent can tell it apart from siblings such as page_text, viewer_state, or outline. It is clear and concrete, though it never explicitly contrasts itself with those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: 'for the user' indicates this is the navigation/display action, and the parenthetical clarifies the current-document default. There is no explicit when-to-use guidance or reference to alternatives like viewer_state or page_text.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_textPDF: highlight or underline textA

Highlight, underline, squiggle or strike out a passage, with a note.

Mark every occurrence of text on a page (default: the one shown) as highlight, underline, squiggly or strikeout, saved into the PDF under a distinct author; quote enough words to be unique. A note sits on the mark, or with note_in_margin on a comment icon in the margin replying to it (least intrusive). color: blue, yellow, green, orange, pink, purple, red, cyan, grey, #rrggbb or r,g,b in 0-1 (default light blue; red for strikeout). The user must save Okular first or their unsaved marks are lost.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteNo
pageNo
pathNo
textYes
colorNo
styleNohighlight
note_in_marginNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare a non-readonly, non-idempotent, non-destructive mutation, but the description adds substantial context beyond them: marks are saved under a distinct author, the note placement model (on the mark vs a margin icon replying to it), and critically 'The user must save Okular first or their unsaved marks are lost.' That save-state warning is exactly the kind of behavioral disclosure annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and no filler sentences, but the remaining content is packed into one dense paragraph, mixing parameter details and a warning. Slightly denser than ideal, though every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be described, and the mutation behavior, note model, and save requirement are well covered. The only gap is that `path` semantics are never explained, leaving the agent to infer the target file.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden, and it documents text, note, page (default the shown page), color (full enum list plus default and strikeout override), style, and note_in_margin. Only `path` is left unexplained, so the coverage is strong but not total.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb set (highlight, underline, squiggle, strike out) on a clear resource (a text passage in the PDF), and the title 'PDF: highlight or underline text' reinforces it. An agent can distinguish this from add_note, which adds a standalone note, without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives actionable guidance: mark every occurrence of `text`, default to the shown page, and 'quote enough words to be unique.' It also frames note_in_margin as the least intrusive option. It stops short of explicitly routing between siblings like add_note or remove_annotation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

outlinePDF: table of contentsC
Read-only

The document's table of contents.

The document's bookmark tree (sections with page numbers), a map of the paper.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds almost nothing behavioral beyond that – it doesn't say what happens when a document has no bookmarks, whether output nests, or pagination/limits. The mention of 'sections with page numbers' is content, not behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is short and front-loaded, but the second sentence largely repeats the first ('table of contents' vs 'bookmark tree... a map of the paper'), so it is somewhat redundant rather than tightly informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the tool is a simple read. Still, for a tool with an undocumented parameter and no edge-case behavior, the description leaves gaps that an agent would need to guess at.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single `path` parameter has 0% schema description coverage and is never mentioned in the description. The phrase 'The document's' weakly implies a current/default document, but it does not explain what path selects or that omitting it uses the active document.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource ('table of contents' / 'bookmark tree (sections with page numbers)') that an agent can distinguish from read-only siblings like page_text, links, or annotations. It lacks a clear verb and slightly restates the title, but the resource is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use, when-not-to-use, or alternative guidance. Nothing routes the agent between outline, page_text, links, or context, so the agent must infer usage from the purpose alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

page_textPDF: page text, numbered linesB
Read-only

Numbered text lines of a page range.

Numbered text lines of a page range (default: the page shown in Okular); lines such as "12-30" narrows to a window. Line numbers match context.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
pageNo
pathNo
linesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so safety is covered by structured data. The description adds genuinely useful behavior beyond that: the default page source (Okular's current page) and the `lines` window syntax ("12-30"). It stops short of describing output shape, but that is largely covered by the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The remainder is tight and front-loaded, but the first sentence is repeated word-for-word, so a full sentence does not earn its place. The default-page fact is also spliced awkwardly into a parenthetical mid-sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with an output schema and no required parameters, the definition covers the essentials (default page, window filter, line-number alignment with `context`). It is still incomplete on `path` vs `page` resolution and on what the numbered output looks like when no page range is given.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and four parameters exist, so the description carries the full burden. It partially compensates by explaining `lines` ("12-30") and implying page-range pairing via `page`/`to` defaults, but `path` and the exact meaning of `to` are left entirely undocumented, leaving half the parameters opaque.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a concrete verb+resource ('Numbered text lines of a page range'), which is distinct from siblings like get_selection or annotations, and it explicitly ties line numbers to the `context` tool. However, the opening sentence is duplicated verbatim, which dilutes the otherwise clear statement of purpose and adds no differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It mentions the default behavior (the page shown in Okular) and that line numbers align with `context`, which is a mild routing hint, but there is no explicit when-to-use, when-not-to-use, or comparison against siblings such as get_selection or context. An agent must infer when page_text is the right call.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_attachmentPDF: read an attached fileB
Read-only

Read an attached file back as text.

Contents of a file-attachment annotation (an xref from annotations with a file field), decoded as text.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
xrefYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description confirms the read-only, decoded-to-text nature of the operation. It adds the useful detail that the content is decoded as text and that only file-attachment xrefs qualify, but says nothing about failure behavior for invalid/non-file xrefs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and followed by the precise semantic constraint. No filler, though the second sentence is somewhat dense/jargon-laden.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is unnecessary. For a two-parameter read tool the description covers the key linkage to `annotations`, but the undocumented `path` parameter leaves a gap in what an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden. It explains the required `xref` well (an xref from `annotations` carrying a `file` field), but the optional `path` parameter is completely unexplained in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read an attached file back as text') and pins the scope to file-attachment annotations, which separates it from the generic `annotations` sibling. It does not explicitly contrast with the reverse operation `attach_file`, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: it tells the agent the xref must come from `annotations` with a `file` field, which is a de facto precondition. There is no explicit when-not guidance or named alternative for adding attachments.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_annotationPDF: delete an annotationB
Destructive

Delete an annotation by xref.

Delete an annotation by the xref reported by annotations (default: the open document) and save. Same save-in-Okular-first caveat as mark_text.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
xrefYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation semantics are covered. The description adds that it saves and defaults to the open document, plus a 'same save-in-Okular-first caveat as mark_text', which adds context but only by cross-referencing a sibling tool rather than spelling out the caveat.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The critical routing information (xref source, save behavior) is presented early, but the first two sentences duplicate the same 'Delete an annotation by xref' information, so not every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. For a destructive tool, though, deferring the crucial Okular-save caveat to 'same ... as mark_text' leaves an agent without the actual precondition in-context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the load. It does address both parameters—xref's origin (from `annotations`) and path's default (the open document)—but gives no format detail for `path`, leaving half the surface only partially compensated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Delete an annotation') and the addressing key ('by xref'), which cleanly distinguishes it from write-oriented siblings like mark_text and add_note. It falls short of a 5 only because the opening sentence is a near-verbatim restatement of the title before the substantive second sentence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an implied workflow by telling the agent to use the xref 'reported by `annotations`', which is useful routing. However, it never states when to use this versus alternatives (e.g., modifying or hiding an annotation) nor any preconditions, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

viewer_stateOkular: open documents and pagesA
Read-only

Which PDF and page Okular is showing.

Open Okular windows: document path, current page (1-based) and page count.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already establishes a safe read operation, and the description is consistent with that. It adds a short summary of what is returned (document path, 1-based current page, page count) and notes open Okular windows, but does not disclose broader behavioral traits such as permissions or limitations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short, front-loaded sentences with no filler. It states the core purpose first and then summarizes the returned fields, which is appropriately sized for a simple read-only state query.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema and readOnlyHint annotation, the description is nearly complete for correct invocation: it identifies the resource and summarizes the payload. It lacks sibling routing or usage guidance, but that is not required for a zero-parameter read operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero input parameters, so there are no parameter semantics for the description to add. The empty schema is self-explanatory, and the description appropriately focuses on the state being queried.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the specific resource—Okular's current PDF/page state—and enumerates the returned fields (document path, current page, page count). It is clear enough to distinguish this from generic state getters, though it does not explicitly contrast with siblings like page_text or goto.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance or mention of alternatives. The description implies querying the current viewer state, but does not say when to choose this over goto, page_text, or other sibling tools.

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.

  1. 13 tool updatesv0.1.0
    • First observedadd_note
    • First observedannotations
    • First observedattach_file
    • First observedcontext
    • First observedget_selection
    • First observedgoto
    • First observedlinks
    • First observedmark_text
    • First observedoutline
    • First observedpage_text
    • First observedread_attachment
    • First observedremove_annotation
    • First observedviewer_state

TDQS

A3.5/5.0

Scored across 13 tools

Disambiguation5/5

Each tool targets a distinct resource or action: viewer state, selection, page text, context around selection, links, outline, annotations, annotation creation/reading/removal, and navigation. Slight conceptual overlap exists between context/page_text and mark_text/add_note, but the descriptions clearly delimit them.

Naming Consistency3/5

All names use snake_case, but the pattern mixes noun phrases (viewer_state, annotations, outline) with verb_noun forms (get_selection, mark_text, remove_annotation, goto). It remains readable, but there is no single predictable convention across the set.

Tool Count5/5

13 tools is well within the ideal range and matches a PDF reading/annotation server's scope. Each tool represents a distinct operation, and none feels redundant or excessively granular.

Completeness4/5

The surface covers reading, navigation, annotation creation/reading/deletion, and attachments. Minor gaps remain: no explicit save or full-text search operation, and annotations cannot be modified in place, but the core lifecycle is covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to search and query PDF documents through a local RAG system with vector embeddings. Provides semantic document search capabilities while keeping all data stored locally without external dependencies.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to efficiently process large local and online PDFs through selective extraction of text, images, and metadata. It provides tools for content search and document outline navigation to optimize context window usage.
    7
    16
    ISC
  • A
    license
    Not graded
    quality
    A
    maintenance
    Gives AI agents tools to read PDFs, list form fields, apply operations, highlight, add notes, fill fields, place signatures, list signatures, and flatten PDFs.
    1
    AGPL 3.0