Skip to main content
Glama

Zotero identity & access

zotero_whoami
Read-only

Check your Zotero identity, API access scopes, server version, and available library backends. Use it to discover your userID and understand which library operations will target, without entering a numeric ID.

Instructions

Resolve the current Zotero identity (userID, username, display name) and per-library access scopes from the configured API key, report the running Zoteus version, and report which library backends are available (cloud Web API and/or the desktop local API). Call this first to discover the userID — never ask the user to type a numeric ID. It also reports which library every call defaults to and WHY (defaultLibrary.source: pinned by whoever runs the server, derived from the key, or the desktop app's own library), whether this caller has a context of their own or shares the one the server operator configured (context), and which single library this context's search index holds (searchIndex). For per-group write permission, call zotero_groups. If no API key is configured, the server runs in local-only read mode against the desktop library (users/0).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
cloudYesWhether a cloud API key is configured and identified a Zotero user.
accessNoWhat the key may do, as Zotero reports it: { user: {...}, groups: {...} }. Null when no key is configured.
updateYesA newer Zoteus release, or null when this is the latest (or the check is off).
userIDNoZotero numeric user id that key belongs to.
contextYesWhether this caller has a context of their own or shares the operator's. Says nothing about any subscription: Zoteus stores no account of its own.
versionYesThe Zoteus release answering this call, e.g. "1.19.0".
localApiYesWhether the Zotero desktop local API answered the probe taken for this call.
usernameNoZotero username on that account.
embeddingsYesSemantic-search health, so a keyword-only fallback is visible here and not only in zotero_index.
attributionYesciteproc-js attribution (CPAL Exhibit B): phrase, copyright, licence and URL.
displayNameNoDisplay name on that account, when it has one.
searchIndexNoWhich single library this context's search index holds. One index file holds one library, so a second library is searchable by meaning only after its own index exists; zotero_groups reports the same fact per group.
defaultLibraryYesThe library every tool reads and writes when a call names none.
localApiReasonNoWhy the desktop local API is out of reach for this caller rather than merely down; present only when it is structurally unavailable.
localApiCheckedNoISO timestamp of that probe, or null when this server does not watch for the desktop app.
localApiWatchedNoWhether this server watches for the desktop app at all (false in hosted mode).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changedv1.21.0
    • addedOutput schema / properties / context
      Added value: +{
      +  "additionalProperties": true,
      +  "description": "Whether this caller has a context of their own or shares the operator's. Says nothing about any subscription: Zoteus stores no account of its own.",
      +  "properties": {
      +    "confined": {
      +      "description": "True when the caller is someone other than the operator of this server (any HTTP/OAuth deployment). File paths a tool accepts are then confined to the server's data directory.",
      +      "type": "boolean"
      +    },
      +    "perUser": {
      +      "description": "True when this call is answered by a context of its own: its own Zotero API key and its own search index, keyed by the Zotero account that authorised. False means it is answered by the context whoever runs this server configured, which every caller of that server shares.",
      +      "type": "boolean"
      +    },
      +    "zoteroUserId": {
      +      "description": "The Zotero user id this context and its search index are keyed by; absent on a single-user install, where there is only one context.",
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "perUser",
      +    "confined"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / defaultLibrary / properties / source
      Added value: +{
      +  "description": "Where that choice came from: \"configured\" (ZOTERO_LIBRARY_ID, set by whoever runs this server), \"key\" (the personal library of the account the API key belongs to) or \"local\" (no key and no setting, so the desktop app's own library).",
      +  "type": "string"
      +}
    • addedOutput schema / properties / defaultLibrary / properties / sourceDetail
      Added value: +{
      +  "description": "The same answer in words, including how to address a different library on a call.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / defaultLibrary / required
      Previous value: -[
      -  "type",
      -  "id"
      -]New value: +[
      +  "type",
      +  "id",
      +  "source",
      +  "sourceDetail"
      +]
    • addedOutput schema / properties / localApiReason
      Added value: +{
      +  "description": "Why the desktop local API is out of reach for this caller rather than merely down; present only when it is structurally unavailable.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / searchIndex
      Added value: +{
      +  "additionalProperties": true,
      +  "description": "Which single library this context's search index holds. One index file holds one library, so a second library is searchable by meaning only after its own index exists; zotero_groups reports the same fact per group.",
      +  "properties": {
      +    "holdsDefaultLibrary": {
      +      "description": "Whether that is the library named in `defaultLibrary`. Present only when the index says which library it holds.",
      +      "type": "boolean"
      +    },
      +    "items": {
      +      "description": "Library items the index represents.",
      +      "type": "number"
      +    },
      +    "library": {
      +      "description": "Canonical id of the library whose rows this context's search index holds: \"user\" for the personal library, \"group:<id>\" for a group. Absent when nothing has been indexed yet, or when the index predates that stamp.",
      +      "type": "string"
      +    },
      +    "libraryLabel": {
      +      "description": "The same thing in words, e.g. \"the personal library\" or \"group 4523\".",
      +      "type": "string"
      +    },
      +    "state": {
      +      "description": "Lifecycle of the background index job: \"idle\", \"building\", \"done\" or \"error\".",
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "version",
      -  "cloud",
      -  "localApi",
      -  "defaultLibrary",
      -  "embeddings",
      -  "update",
      -  "attribution"
      -]New value: +[
      +  "version",
      +  "cloud",
      +  "localApi",
      +  "defaultLibrary",
      +  "context",
      +  "embeddings",
      +  "update",
      +  "attribution"
      +]
  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. Changed1 schema field changedv1.20.0
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": true,
      +  "properties": {
      +    "access": {
      +      "anyOf": [
      +        {
      +          "additionalProperties": {},
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "What the key may do, as Zotero reports it: { user: {...}, groups: {...} }. Null when no key is configured."
      +    },
      +    "attribution": {
      +      "additionalProperties": {},
      +      "description": "citeproc-js attribution (CPAL Exhibit B): phrase, copyright, licence and URL.",
      +      "type": "object"
      +    },
      +    "cloud": {
      +      "description": "Whether a cloud API key is configured and identified a Zotero user.",
      +      "type": "boolean"
      +    },
      +    "defaultLibrary": {
      +      "additionalProperties": true,
      +      "description": "The library every tool reads and writes when a call names none.",
      +      "properties": {
      +        "id": {
      +          "description": "Library id; 0 is the desktop app's own personal library.",
      +          "type": "number"
      +        },
      +        "type": {
      +          "description": "\"user\" or \"group\".",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "type",
      +        "id"
      +      ],
      +      "type": "object"
      +    },
      +    "displayName": {
      +      "description": "Display name on that account, when it has one.",
      +      "type": "string"
      +    },
      +    "embeddings": {
      +      "additionalProperties": true,
      +      "description": "Semantic-search health, so a keyword-only fallback is visible here and not only in zotero_index.",
      +      "properties": {
      +        "active": {
      +          "description": "True only while that provider is genuinely producing vectors.",
      +          "type": "boolean"
      +        },
      +        "configured": {
      +          "description": "The requested ZOTEUS_EMBEDDINGS value, whether or not it works.",
      +          "type": "string"
      +        },
      +        "effective": {
      +          "description": "The embedder actually in use, or \"none (...)\" with the reason.",
      +          "type": "string"
      +        },
      +        "reason": {
      +          "description": "Why the configured provider is not active.",
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "localApi": {
      +      "description": "Whether the Zotero desktop local API answered the probe taken for this call.",
      +      "type": "boolean"
      +    },
      +    "localApiChecked": {
      +      "description": "ISO timestamp of that probe, or null when this server does not watch for the desktop app.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "localApiWatched": {
      +      "description": "Whether this server watches for the desktop app at all (false in hosted mode).",
      +      "type": "boolean"
      +    },
      +    "update": {
      +      "anyOf": [
      +        {
      +          "additionalProperties": true,
      +          "properties": {
      +            "current": {
      +              "description": "Version running now.",
      +              "type": "string"
      +            },
      +            "latest": {
      +              "description": "Newer published version.",
      +              "type": "string"
      +            },
      +            "url": {
      +              "description": "Where to get it.",
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "current",
      +            "latest",
      +            "url"
      +          ],
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "A newer Zoteus release, or null when this is the latest (or the check is off)."
      +    },
      +    "userID": {
      +      "description": "Zotero numeric user id that key belongs to.",
      +      "type": "number"
      +    },
      +    "username": {
      +      "description": "Zotero username on that account.",
      +      "type": "string"
      +    },
      +    "version": {
      +      "description": "The Zoteus release answering this call, e.g. \"1.19.0\".",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "version",
      +    "cloud",
      +    "localApi",
      +    "defaultLibrary",
      +    "embeddings",
      +    "update",
      +    "attribution"
      +  ],
      +  "type": "object"
      +}
  4. Changed1 schema field changedv1.18.0
    • addedInput schema / additionalProperties
      Added value: +false
  5. First observedv1.0.4

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already mark it as read-only and non-destructive, and the description adds meaningful behavioral context beyond them: it explains default library resolution, why the default is chosen, caller context ownership, search-index scope, and behavior without an API key. 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.

Conciseness4/5

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

The description is fairly long but each clause carries distinct diagnostic information, and the most important instruction ('call this first') appears early. It is dense rather than padded, though it could be tightened into shorter sentences for easier parsing.

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 zero-parameter diagnostic tool with an output schema, the description fully covers what the agent needs: why to call it, what it returns conceptually, how defaults are determined, and the alternative for permissions. Nothing essential is missing.

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 parameters and 100% schema coverage, so there is nothing for the description to add about parameters. The description correctly implies this is a no-input discovery call, matching the baseline for parameterless tools.

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 and resource: it resolves the current Zotero identity, access scopes, Zoteus version, and available library backends. It also positions itself as the first call for discovering userID, distinguishing its diagnostic purpose from siblings like zotero_groups.

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?

Explicitly instructs to call this first to learn the userID and never ask the user for a numeric ID. It also names zotero_groups as the alternative for per-group write permission and explains the local-only read mode when no API key is configured.

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