Skip to main content
Glama

Attachment full-text

zotero_fulltext
Destructive

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.

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. All three go through the running Zotero desktop app when there is one (no cloud key needed; "set" needs Zotero 10+ and writes your personal library or a group library the app holds), otherwise the cloud Web API.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "action": "<action>"
    },
    "name": "zotero_fulltext"
  }
}

Input 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`); "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

NameRequiredDescriptionDefault
countNoHow many attachments that map holds.
foundNoaction:"get": whether Zotero holds extracted text for this attachment.
lengthNoCharacters stored (action:"set").
targetNoWhere the write went: "local" (Zotero desktop local API), "desktop" (connector protocol) or "cloud" (Zotero Web API).
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. Changed2 schema fields changedv1.23.0
    • changedInput schema / properties / action / description
      Previous 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`."New value: +"What to do. \"get\" reads one attachment's indexed text (needs `item_key`); \"set\" stores extracted text for it (needs `item_key` + `content`); \"since\" lists attachment keys whose text changed after `since`."
    • addedOutput schema / properties / target
      Added value: +{
      +  "description": "Where the write went: \"local\" (Zotero desktop local API), \"desktop\" (connector protocol) or \"cloud\" (Zotero Web API).",
      +  "type": "string"
      +}
  2. Changed1 schema field changedv1.21.0
    • addedInput schema / properties / library_id / exclusiveMinimum
      Added value: +0
  3. 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#"
  4. 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"
      +}
  5. First observedv1.0.4

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true and openWorldHint=true; the description adds genuinely new context: routing through the desktop app when present versus the cloud Web API, no cloud key needed, and that 'set' requires Zotero 10+ and writes a personal or group library. It stops short of saying what happens to previously stored text on 'set', which is the destructive behavior the annotation flags.

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 disambiguating negation, then a tight per-action breakdown; every sentence carries information. It is slightly redundant with the schema's action enum, which repeats the get/set/since requirements.

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 10-parameter, three-action tool with an output schema and full annotation coverage, the description supplies the remaining essentials: attachment-only constraint, environment/transport, version requirement, and write scope. Nothing needed to call it correctly 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, including which apply to which action. The description restates the action-to-parameter mapping ('provide content and the indexing counts') but adds little syntax or format detail beyond that, so the 3 baseline holds.

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 resource (an attachment's already-extracted full text) and enumerates the three verbs (get/set/since), so the scope is unambiguous. It explicitly distinguishes itself from zotero_search_items, but does not address the very similar sibling zotero_get_fulltext, leaving a residual ambiguity for an agent choosing between the two.

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?

Opens with an explicit when-not ('Not a search: to find which items contain a term, use zotero_search_items with qmode=everything') and then routes each action to its use case, including 'since' for incremental indexing. Alternatives and exclusions are named rather than inferred.

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