Skip to main content
Glama

Attachment full-text

zotero_fulltext
Destructive

Retrieve, store, or track full-text content of Zotero attachment items: get indexed text by key, set extracted text, or list attachments changed since a given library version.

Instructions

Not a search — to find which items contain a term, use zotero_search_items with qmode=everything. This reads, sets, or tracks one attachment's already-extracted full text by key. action: "get" returns the indexed text content plus indexing stats for an attachment item (only attachment items have full text; returns found:false if none); "set" stores extracted text for an attachment (provide content and the indexing counts); "since" returns the map of attachment keys whose full text changed after a given library version (useful for incremental indexing). Only attachment items support full text. "get" and "since" read through the running Zotero desktop app when there is one (no cloud key needed), otherwise the cloud Web API; "set" always writes via the cloud Web API, which has no desktop equivalent, so it needs ZOTERO_API_KEY even for the personal library.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sinceNoLibrary version for "since" (default 0).
actionYesWhat to do. "get" reads one attachment's indexed text (needs `item_key`); "set" stores extracted text for it (needs `item_key` + `content`, cloud only); "since" lists attachment keys whose text changed after `since`.
contentNoExtracted text (set).
item_keyNoAttachment item key (get/set).
library_idNoNumeric id of the library to address, e.g. 5234875 for a group (zotero_groups lists the ids you can reach). Omit to use the configured default library; an id given without library_type is read as a group id.
total_charsNoCharacters the document holds in total (set).
total_pagesNoPages the document holds in total (set); PDFs only.
library_typeNoWhich library to address: "user" (a personal library) or "group" (a shared group library). Omit to use the library this server is configured for. "group" on its own is refused: pass library_id with it.
indexed_charsNoCharacters of the document that were indexed (set); defaults to none reported.
indexed_pagesNoPages that were indexed (set); PDFs only.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
countNoHow many attachments that map holds.
foundNoaction:"get": whether Zotero holds extracted text for this attachment.
lengthNoCharacters stored (action:"set").
changedNoaction:"since": attachment key to the full-text version it changed at.
contentNoThe extracted text itself (action:"get").
item_keyNoThe attachment this call addressed.
totalCharsNoCharacters the document holds in total.
totalPagesNoPages in the document (PDFs).
indexedCharsNoCharacters Zotero has indexed of the document.
indexedPagesNoPages indexed (PDFs).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv1.21.0
    • addedInput schema / properties / library_id / exclusiveMinimum
      Added value: +0
  2. Changed2 schema fields changedv1.20.2
    • removedInput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
    • removedOutput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
  3. Changed8 schema fields changedv1.20.0
    • addedInput schema / properties / action / description
      Added value: +"What to do. \"get\" reads one attachment's indexed text (needs `item_key`); \"set\" stores extracted text for it (needs `item_key` + `content`, cloud only); \"since\" lists attachment keys whose text changed after `since`."
    • addedInput schema / properties / indexed_chars / description
      Added value: +"Characters of the document that were indexed (set); defaults to none reported."
    • addedInput schema / properties / indexed_pages / description
      Added value: +"Pages that were indexed (set); PDFs only."
    • addedInput schema / properties / library_id / description
      Added value: +"Numeric id of the library to address, e.g. 5234875 for a group (zotero_groups lists the ids you can reach). Omit to use the configured default library; an id given without library_type is read as a group id."
    • addedInput schema / properties / library_type / description
      Added value: +"Which library to address: \"user\" (a personal library) or \"group\" (a shared group library). Omit to use the library this server is configured for. \"group\" on its own is refused: pass library_id with it."
    • addedInput schema / properties / total_chars / description
      Added value: +"Characters the document holds in total (set)."
    • addedInput schema / properties / total_pages / description
      Added value: +"Pages the document holds in total (set); PDFs only."
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": true,
      +  "properties": {
      +    "changed": {
      +      "additionalProperties": {
      +        "type": "number"
      +      },
      +      "description": "action:\"since\": attachment key to the full-text version it changed at.",
      +      "type": "object"
      +    },
      +    "content": {
      +      "description": "The extracted text itself (action:\"get\").",
      +      "type": "string"
      +    },
      +    "count": {
      +      "description": "How many attachments that map holds.",
      +      "type": "number"
      +    },
      +    "found": {
      +      "description": "action:\"get\": whether Zotero holds extracted text for this attachment.",
      +      "type": "boolean"
      +    },
      +    "indexedChars": {
      +      "description": "Characters Zotero has indexed of the document.",
      +      "type": "number"
      +    },
      +    "indexedPages": {
      +      "description": "Pages indexed (PDFs).",
      +      "type": "number"
      +    },
      +    "item_key": {
      +      "description": "The attachment this call addressed.",
      +      "type": "string"
      +    },
      +    "length": {
      +      "description": "Characters stored (action:\"set\").",
      +      "type": "number"
      +    },
      +    "totalChars": {
      +      "description": "Characters the document holds in total.",
      +      "type": "number"
      +    },
      +    "totalPages": {
      +      "description": "Pages in the document (PDFs).",
      +      "type": "number"
      +    }
      +  },
      +  "type": "object"
      +}
  4. First observedv1.0.4

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already mark the tool as not read-only and potentially destructive, and the description adds valuable context: 'set' is cloud-only, 'get'/'since' can use the desktop app without a cloud key, non-attachment items return found:false, and only attachment items support full text. It does not explicitly describe overwrite behavior for 'set', but the auth and access distinctions go well beyond the annotations.

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?

The description is dense and front-loaded with the most important differentiation ('Not a search'). There is some redundancy, such as saying 'only attachment items have full text' and later 'Only attachment items support full text', and the action enumeration partially repeats the schema. Overall it is efficient, but not perfectly tight.

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

Completeness5/5

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

For a multi-action tool with 10 parameters, an output schema, and meaningful annotations, this description covers the essential operational context: action semantics, expected inputs, auth requirements, desktop vs cloud behavior, and when to use an alternative tool. Nothing critical for correctly selecting or invoking the tool is missing.

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 100%, so the schema already documents all 10 parameters. The description adds some useful mapping between actions and parameters, like 'provide content and the indexing counts' for 'set', but it mostly reinforces what the schema already states rather than adding significant new parameter-level meaning.

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?

The description opens by stating what the tool is not and then gives a specific multi-mode purpose: 'reads, sets, or tracks one attachment's already-extracted full text by key.' It clearly identifies the resource (attachment items) and differentiates itself from zotero_search_items, which is the main sibling it could be confused with.

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

Usage Guidelines5/5

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

It explicitly tells the agent not to use this tool for searching and routes to zotero_search_items with qmode=everything. It also provides clear action-specific guidance: 'get' and 'since' read via desktop or cloud, while 'set' writes via cloud and requires ZOTERO_API_KEY.

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