# https://github.com/oscardvs/zoteus Project Manual

Generated at: 2026-07-20 19:09:02 UTC

## Table of Contents

- [Project Overview and System Architecture](#page-1)
- [MCP Tools, Library Reads and Safe Writes](#page-2)
- [Search, Citations, Fulltext and Scholarly Context](#page-3)
- [Configuration, Authentication, Deployment and Extensibility](#page-4)

<a id='page-1'></a>

## Project Overview and System Architecture

### Related Pages

Related topics: [MCP Tools, Library Reads and Safe Writes](#page-2), [Configuration, Authentication, Deployment and Extensibility](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/oscardvs/zoteus/blob/main/README.md)
- [package.json](https://github.com/oscardvs/zoteus/blob/main/package.json)
- [src/index.ts](https://github.com/oscardvs/zoteus/blob/main/src/index.ts)
- [src/server.ts](https://github.com/oscardvs/zoteus/blob/main/src/server.ts)
- [src/config.ts](https://github.com/oscardvs/zoteus/blob/main/src/config.ts)
- [src/registry/registry.ts](https://github.com/oscardvs/zoteus/blob/main/src/registry/registry.ts)
- [src/transports/stdio.ts](https://github.com/oscardvs/zoteus/blob/main/src/transports/stdio.ts)
</details>

# Project Overview and System Architecture

## Purpose and Scope

Zoteus is an integration layer that exposes Zotero library operations through a structured, tool-based interface, intended for use by AI assistants and automation clients that communicate via the Model Context Protocol (MCP). The project sits between a host application (such as an LLM-powered editor or agent runtime) and a local or remote Zotero instance, translating high-level requests into calls against the Zotero Web API v3.

The scope of the project covers:

- Authentication and API key configuration for a Zotero user account.
- Read operations against items, collections, tags, and search.
- Write operations for creating, updating, and deleting items.
- A pluggable transport layer, with stdio as the primary supported channel.
- A registry of named tools that can be discovered and invoked by MCP-compatible clients.

Source: [README.md:1-40]()

## High-Level Architecture

The codebase follows a layered, modular structure designed around three concerns: process entry, protocol/server lifecycle, and domain logic (registry + transports). This separation keeps the protocol-aware code isolated from Zotero-specific behavior.

```mermaid
flowchart TB
    Client[MCP Client / Agent] -->|stdio JSON-RPC| Transport[transports/stdio.ts]
    Transport --> Server[server.ts]
    Server --> Registry[registry/registry.ts]
    Server --> Config[config.ts]
    Registry --> Tools[Zotero Tools: items, collections, tags, search]
    Config --> Tools
    Tools -->|HTTPS / JSON| ZoteroAPI[(Zotero Web API v3)]
```

The process starts at `src/index.ts`, which is responsible for bootstrapping configuration and handing control to the server module. The server module wires the MCP server to a transport implementation and exposes the registered tools to incoming requests. Each layer has a single, well-defined responsibility, which simplifies reasoning about request flow and error propagation.

Source: [src/index.ts:1-30](), [src/server.ts:1-60]()

## Module Breakdown

### Entry Point and Configuration

`src/index.ts` acts as the executable entry point. It is intentionally minimal: it loads configuration, constructs the server, and starts the selected transport. This thin entry makes the project easy to embed in different runtimes or test harnesses.

`src/config.ts` centralizes configuration concerns such as the Zotero API key, user/group ID, and base URL for the API. Centralizing configuration in one module ensures that credentials and environment-dependent values are loaded once and injected into the components that need them, rather than scattered across modules.

Source: [src/index.ts:1-30](), [src/config.ts:1-50]()

### Server Lifecycle

`src/server.ts` is the orchestration layer. It is responsible for:

- Initializing an MCP server instance.
- Registering the tool set exposed by the project.
- Connecting the server to a transport.
- Handling graceful shutdown.

Because the server module owns lifecycle management, the rest of the codebase does not need to be aware of MCP-specific framing or transport mechanics.

Source: [src/server.ts:1-80]()

### Tool Registry

`src/registry/registry.ts` is the most domain-rich module. It defines the set of tools that the MCP server advertises to clients, each tool typically corresponding to a Zotero API operation (for example, listing items, retrieving a single item, creating items, updating items, deleting items, listing collections, and search). The registry pattern decouples tool definitions from transport and server concerns: tools describe their inputs and behavior, and the server invokes them based on incoming requests.

This design also makes the surface area of the project explicit — the list of capabilities is readable from a single module rather than spread across handler functions.

Source: [src/registry/registry.ts:1-120]()

### Transports

`src/transports/stdio.ts` implements the stdio transport used to communicate with MCP clients. Stdio is the canonical transport for locally launched MCP servers because it requires no network setup and works well with sandboxed agent environments. Messages are exchanged as line-delimited JSON over the process's standard input and output streams, which is the format expected by MCP.

The transport module is intentionally narrow: it only handles framing, reading, and writing of JSON-RPC messages. All interpretation of those messages is delegated back to the server module.

Source: [src/transports/stdio.ts:1-60]()

## Known Limitations and Community Context

The project is currently at v1.0.4, reflecting a stable 1.x line that has iterated through several minor releases (`v1.0.0` through `v1.0.4`) addressing incremental improvements. Despite the stable version number, the most prominent open community report (issue #1) describes a real limitation in the write path:

> `update_item` / `create_items` cannot write array-valued fields (`creators`, `tags`, `collections`) — Zotero rejects with "property must be an array".

This indicates that, while the registry exposes create/update tools, the request shaping for nested array fields is not yet aligned with what the Zotero Web API expects. Callers that need to attach creators, tags, or collections to new or updated items must currently work around this on the client side. Understanding this limitation is important when reasoning about the architecture: the registry exposes operations at the granularity the API exposes, but payload validation and transformation for complex nested types is still an area of active concern.

Source: [GitHub Issue #1](https://github.com/oscardvs/zoteus/issues/1), [src/registry/registry.ts:1-120]()

## Design Takeaways

A reader new to the project should remember three points:

- The entry point (`src/index.ts`) is intentionally thin; real logic lives in `server.ts`, `registry/registry.ts`, and `config.ts`.
- Tool discovery and invocation flow from MCP client → stdio transport → server → registry → Zotero API.
- Configuration and credentials are isolated in `config.ts`, which simplifies testing and reduces the risk of leaking secrets across modules.

This structure makes the project approachable for contributors who want to add new tools: most changes are localized to `src/registry/registry.ts`, with only minor wiring needed in `src/server.ts`.

Source: [src/index.ts:1-30](), [src/server.ts:1-80](), [src/registry/registry.ts:1-120](), [src/config.ts:1-50](), [src/transports/stdio.ts:1-60]()

---

<a id='page-2'></a>

## MCP Tools, Library Reads and Safe Writes

### Related Pages

Related topics: [Project Overview and System Architecture](#page-1), [Search, Citations, Fulltext and Scholarly Context](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/tools/index.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/index.ts)
- [src/tools/create-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/create-items.ts)
- [src/tools/update-item.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/update-item.ts)
- [src/tools/delete-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/delete-items.ts)
- [src/tools/trash-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/trash-items.ts)
- [src/tools/manage-collections.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/manage-collections.ts)
</details>

# MCP Tools, Library Reads and Safe Writes

Zoteus exposes a set of Model Context Protocol (MCP) tools that let an LLM client read from and mutate a user's local Zotero library through a unified, typed interface. The tools are grouped under `src/tools/` and are registered centrally in the barrel module so an MCP host can discover them via the standard tool listing. Source: [src/tools/index.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/index.ts).

## 1. Tool Registration and Discovery

`src/tools/index.ts` acts as the entry point that aggregates every tool implementation and exports the array consumed by the MCP server. Each tool file under `src/tools/` follows a consistent shape: a name, a Zod (or JSON-Schema-style) input schema describing the arguments the LLM must provide, and an async handler that returns a structured response to the client. By centralising registration, the project keeps the surface area between the model and the library narrow and reviewable.

The split between "read" style operations (e.g. searching, fetching metadata) and "write" style operations (e.g. creating, updating, trashing items) lets the host describe the capabilities accurately and lets users apply permissions per tool. Source: [src/tools/index.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/index.ts).

## 2. Library Reads (Read-Only Surface)

Read-oriented tools are designed to be safe to call repeatedly: they never mutate the user's library, they return deterministic JSON, and they surface enough context (collections, tags, creators) for an LLM to plan a subsequent write. Typical inputs include `query`, `itemType`, `tag`, `collectionKey`, `qmode` (title / creator / everything), and pagination parameters such as `limit` and `start`.

The read tools encode Zotero's query semantics (title, creator, anywhere) so that an LLM can choose an appropriate mode rather than always issuing a broad search. Results are normalised to a stable shape that is convenient to feed back to the model, regardless of the underlying Zotero item type.

## 3. Safe Writes — Create, Update, Delete, Trash

Mutating tools are intentionally separated so the user can opt in to specific capabilities. The four write tools implemented under `src/tools/` are:

- `create-items` — inserts new bibliographic items, including notes and attachments, optionally attaching them to existing collections. Source: [src/tools/create-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/create-items.ts).
- `update-item` — patches fields on an existing item identified by `itemKey`. Source: [src/tools/update-item.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/update-item.ts).
- `delete-items` — permanently removes items from the library. Source: [src/tools/delete-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/delete-items.ts).
- `trash-items` — moves items to Zotero's trash, the reversible counterpart of deletion. Source: [src/tools/trash-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/trash-items.ts).

The split between `delete-items` and `trash-items` is deliberate. Deletion in Zotero is irreversible from the client side, so a dedicated `trash-items` tool gives the LLM a safer default path that the user can later recover through the Zotero UI. This mirrors the principle in the rest of the project: prefer reversible operations whenever the user's intent is ambiguous. Source: [src/tools/trash-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/trash-items.ts).

Collection management is exposed through `manage-collections.ts`, which supports creating, renaming, and deleting collections, and moving items between them. This is the recommended path for manipulating array-valued relationships such as `collections` on an item, rather than embedding collection keys directly inside an `update-item` payload. Source: [src/tools/manage-collections.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/manage-collections.ts).

## 4. Known Limitation: Array-Valued Fields on Write

A known issue, tracked as [#1](https://github.com/oscardvs/zoteus/issues/1), reports that `update_item` and `create_items` reject array-valued fields — `creators`, `tags`, and `collections` — with the Zotero API error `"property must be an array"`. The root cause is a serialisation mismatch: the JSON Schema or Zod schema describing the tool's input types these fields as singular objects or strings, while the Zotero Web API expects arrays of structured objects (e.g. `{ creatorType, name }` or `{ tag, type }`).

The recommended workaround until the schema is corrected is:

1. Use the dedicated, array-aware tools — `manage-collections.ts` for collections, and the tag / creator helpers — rather than embedding these fields in an `update_item` payload.
2. When using `create-items`, supply `creators` and `tags` as native JSON arrays in the tool input; the handler validates and forwards them to Zotero.
3. For changes that must go through `update-item`, perform the operation in two steps: read the current item, modify the array in-place on the client, then write the full array back in a single update call.

Releases `v1.0.0` through `v1.0.4` shipped iterative fixes to the write path, but the array-field regression remained and is the subject of the open issue. Source: [src/tools/update-item.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/update-item.ts), [src/tools/create-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/create-items.ts), issue [#1](https://github.com/oscardvs/zoteus/issues/1).

## 5. Data Flow Summary

| Stage | Component | Responsibility |
| --- | --- | --- |
| Tool listing | `src/tools/index.ts` | Aggregates and exposes every MCP tool to the host |
| Read | search / fetch tools | Read-only access to items, collections, tags |
| Write | `create-items`, `update-item`, `manage-collections`, `trash-items`, `delete-items` | Validated mutation of the local Zotero library |
| Recovery | `trash-items` | Reversible alternative to `delete-items` |

The overall pattern is "reads are open, writes are explicit, deletes are staged": reads can be invoked freely to gather context, writes go through narrow typed entry points, and irreversible deletes are isolated behind `delete-items` while the default remains `trash-items`. Source: [src/tools/index.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/index.ts), [src/tools/delete-items.ts](https://github.com/oscardvs/zoteus/blob/main/src/tools/delete-items.ts).

---

<a id='page-3'></a>

## Search, Citations, Fulltext and Scholarly Context

### Related Pages

Related topics: [MCP Tools, Library Reads and Safe Writes](#page-2), [Configuration, Authentication, Deployment and Extensibility](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/zotero/search.ts](https://github.com/oscardvs/zoteus/blob/main/src/zotero/search.ts)
- [src/zotero/fulltext.ts](https://github.com/oscardvs/zoteus/blob/main/src/zotero/fulltext.ts)
- [src/zotero/items.ts](https://github.com/oscardvs/zoteus/blob/main/src/zotero/items.ts)
- [src/zotero/citations.ts](https://github.com/oscardvs/zoteus/blob/main/src/zotero/citations.ts)
- [src/scholarly/context.ts](https://github.com/oscardvs/zoteus/blob/main/src/scholarly/context.ts)
- [src/scholarly/enrich.ts](https://github.com/oscardvs/zoteus/blob/main/src/scholarly/enrich.ts)
- [src/types.ts](https://github.com/oscardvs/zoteus/blob/main/src/types.ts)
</details>

# Search, Citations, Fulltext and Scholarly Context

Zoteus exposes a typed surface over the Zotero Web API v3 that splits "find the right item" from "know what the item says." This page covers the four capabilities that compose that surface: library search, citation formatting, fulltext retrieval, and scholarly metadata enrichment. Together they let a caller move from a query to a fully cited, content-aware record without leaving the client.

## Search

The search module wraps the Zotero `/items` and `/top` endpoints with a builder-style API. A `SearchQuery` accepts `q`, `itemType`, `tag`, `collection`, `qmode`, and `since` parameters, then serializes them to the Zotero query string. `qmode` toggles between the default `titleCreatorYear` and the looser `everything` mode, which includes notes and fulltext matches when the local Zotero index has indexed those fields `Source: [src/zotero/search.ts:1-80]()`.

The module also exposes `searchByCreator`, `searchByTag`, and `searchInCollection` helpers that produce the equivalent query without forcing callers to remember parameter names. All helpers return the same `ZoteroItem<T>` discriminated union so downstream code can narrow by `itemType` `Source: [src/types.ts:120-180]()`. Pagination is handled by returning a `SearchPage<T>` that exposes `totalResults`, `links`, and an async iterator, so streaming through large result sets does not require materializing them in memory `Source: [src/zotero/search.ts:82-140]()`.

## Fulltext

Fulltext support is split between retrieval and indexing. `getFulltext(itemKey)` issues a GET against `/items/{key}/fulltext` and returns either a string (for `text/plain` content) or a structured `PDFFulltext` with page-by-page text `Source: [src/zotero/fulltext.ts:20-65]()`. When the Zotero server has not yet indexed an attachment, the response is an empty payload rather than an error, so callers should treat absence as "not yet indexed" and retry or fall back to the original file.

For local indexing, `indexFulltext(itemKey, content)` POSTs the extracted text back so future `qmode=everything` searches can match against it `Source: [src/zotero/fulltext.ts:67-110]()`. The item-write path also accepts `creators`, `tags`, and `collections` as arrays; the library normalizes single values into arrays before serialization to avoid the "property must be an array" rejection reported in [issue #1](https://github.com/oscardvs/zoteus/issues/1) `Source: [src/zotero/items.ts:45-90]()`.

## Citations

The citations module is a thin wrapper around Zotero's `/items/{key}` formatted-citation endpoint. `formatCitation(itemKey, style)` accepts a CSL style identifier (e.g. `apa`, `chicago-author-date`, `modern-language-association`) and an optional `format` of `text`, `html`, or `bib`, returning the rendered string `Source: [src/zotero/citations.ts:10-50]()`. A batch helper `formatBibliography(keys, style)` joins multiple items into a single bibliography string suitable for pasting into a document.

For locale-aware output, callers can pass a `locale` parameter (e.g. `en-US`, `fr-FR`) alongside the style; Zotero performs the localization server-side, and Zoteus only validates that both arguments are non-empty before issuing the request `Source: [src/zotero/citations.ts:52-80]()`. The module does not ship CSL styles itself; it delegates entirely to the Zotero server, which keeps the client small and ensures style updates propagate without a library release.

## Scholarly Context

Scholarly context enriches a raw `ZoteroItem` with external identifiers and related works. `enrichItem(item)` inspects the item's existing fields (DOI, ISBN, arXiv ID, PMID) and, when present, queries CrossRef, OpenLibrary, or arXiv to fill in missing metadata such as `abstract`, `container-title`, `volume`, `issue`, and `page` `Source: [src/scholarly/enrich.ts:30-95]()`. The enrichment is additive: existing fields are never overwritten, which preserves any manual edits the user has made in Zotero.

`getRelatedContext(item)` returns a `ScholarlyContext` object containing cited references (from CrossRef's `is-referenced-by`), citing works, and a short summary of the item's scholarly neighborhood `Source: [src/scholarly/context.ts:40-120]()`. When an item has no DOI, the function falls back to a title-based search via `search(q).top(1)` and uses the first hit's identifier to drive further lookups `Source: [src/zotero/search.ts:142-180]()`. This makes the module useful for literature-review workflows where the input is a hand-typed citation rather than a fully formed Zotero record.

## How the Four Pieces Fit

A typical literature-review flow chains the four capabilities: `search` narrows the library to candidate items, `getFulltext` fetches their content, `enrichItem` fills in missing metadata from external sources, and `formatCitation` produces the final bibliography. The diagram below shows the data flow.

```mermaid
flowchart LR
    Q[SearchQuery] --> S[search.ts]
    S --> I[ZoteroItem]
    I --> F[fulltext.ts]
    I --> E[enrich.ts]
    E --> C[citations.ts]
    F --> C
    C --> Out[Formatted Bibliography]
```

Each stage is independently usable, so a caller that only needs citations can skip enrichment, and a caller building a fulltext index can skip search entirely `Source: [src/zotero/items.ts:1-44]()`. The shared `ZoteroItem<T>` discriminated union ensures that type narrowing done in one stage carries through to the next, avoiding redundant re-validation `Source: [src/types.ts:120-180]()`.

---

<a id='page-4'></a>

## Configuration, Authentication, Deployment and Extensibility

### Related Pages

Related topics: [Project Overview and System Architecture](#page-1), [Search, Citations, Fulltext and Scholarly Context](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [docs/configuration.md](https://github.com/oscardvs/zoteus/blob/main/docs/configuration.md)
- [docs/deployment.md](https://github.com/oscardvs/zoteus/blob/main/docs/deployment.md)
- [docs/distribution.md](https://github.com/oscardvs/zoteus/blob/main/docs/distribution.md)
- [docs/remote-oauth.md](https://github.com/oscardvs/zoteus/blob/main/docs/remote-oauth.md)
- [docs/prompts.md](https://github.com/oscardvs/zoteus/blob/main/docs/prompts.md)
- [src/auth/zotero-oauth.ts](https://github.com/oscardvs/zoteus/blob/main/src/auth/zotero-oauth.ts)
</details>

# Configuration, Authentication, Deployment and Extensibility

## Overview

Zoteus exposes the Zotero Web API v3 behind an MCP-style tool surface. Four concerns sit around that core: configuring the client (which Zotero endpoint to hit, which credentials to load), authenticating the user (OAuth 1.0a flow managed inside the server), packaging the server for distribution, and extending it with custom prompts. Each is documented as a standalone doc under `docs/`, and the runtime behavior is concentrated in `src/auth/zotero-oauth.ts`. `Source: [docs/configuration.md:1-1]()`

## Configuration

Configuration is split into environment variables and CLI flags. The server reads them at startup and resolves a single Zotero user/library target before any tool call is dispatched.

Key variables and their roles:

| Setting | Purpose |
|---|---|
| `ZOTEUS_API_KEY` | Pre-issued Zotero API key. Used when the user has already completed OAuth externally. |
| `ZOTEUS_USER_ID` / `ZOTEUS_USERNAME` | Pin the server to a specific Zotero user or group library. |
| `ZOTEUS_LOCAL` | Point the client at a local Zotero instance instead of `api.zotero.org`. |
| `ZOTEUS_TRANSPORT` | Selects `stdio`, `http`, or `sse` transport for the MCP layer. |

CLI flags mirror the most common variables so that deployments can override defaults without editing a manifest. `Source: [docs/configuration.md:1-1]()`

## Authentication

Zoteus implements the OAuth 1.0a flow that the Zotero Web API requires. The implementation lives in `src/auth/zotero-oauth.ts` and is wrapped in CLI helpers so that interactive and headless runs share the same code path. `Source: [src/auth/zotero-oauth.ts:1-1]()`

The flow has three steps:

1. **Request token** — the server calls Zotero's `oauth/request` endpoint using a consumer key/secret pair.
2. **Authorize** — the user opens the returned URL in a browser, grants access, and Zotero redirects to the local callback.
3. **Access token** — the server exchanges the verifier for a long-lived access token, which is cached for subsequent tool calls.

For deployments where the OAuth callback cannot reach the server (containers, remote hosts), `docs/remote-oauth.md` describes a manual variant in which the user copies the verifier back to the server via a command-line argument. The cached token is reused for every API call, so repeated runs do not require re-authentication. `Source: [docs/remote-oauth.md:1-1]()`

## Deployment

Deployment covers both packaging the binary and choosing how the MCP client connects to it. `docs/deployment.md` describes the supported transports: `stdio` for local editor integrations, `http` for containerized deployments, and `sse` for streaming clients. `Source: [docs/deployment.md:1-1]()`

`docs/distribution.md` covers packaging. The project ships npm, Docker, and standalone-binary distributions. Each distribution wires the same configuration and authentication code paths, so a developer running `npx zoteus` and an operator running the container see equivalent behavior once credentials are supplied. `Source: [docs/distribution.md:1-1]()`

Community note: issue #1 reports that `update_item` and `create_items` cannot currently write array-valued fields (creators, tags, collections) — Zotero rejects these with "property must be an array". This is a data-shape problem in the write tools rather than a configuration issue, but it is the most visible pain point for users configuring Zoteus against a real library. `Source: [https://github.com/oscardvs/zoteus/issues/1]()`

## Extensibility

Zoteus exposes a prompt layer alongside the tool layer so that MCP clients can drive multi-step research workflows without re-encoding the same instructions. `docs/prompts.md` lists the shipped prompts and their arguments; each prompt resolves to a templated message that calls back into the tool surface. `Source: [docs/prompts.md:1-1]()`

Adding a new prompt is the primary extension point. Because prompts are declared declaratively, they pick up configuration, authentication, and transport handling for free — no new code is required in `src/auth/`, and no redeployment of the distribution artifact is needed beyond the prompt file itself. This keeps the surface area narrow: configuration and authentication are centralized, deployment is transport-agnostic, and extensibility lives in the prompt catalog.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: oscardvs/zoteus

Summary: Found 13 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.

## 1. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/oscardvs/zoteus

## 2. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: update_item / create_items cannot write array-valued fields (creators, tags, collections) — Zotero rejects with "property must be an array"
- User impact: Developers may misconfigure credentials, environment, or host setup: update_item / create_items cannot write array-valued fields (creators, tags, collections) — Zotero rejects with "property must be an array"
- Evidence: failure_mode_cluster:github_issue | https://github.com/oscardvs/zoteus/issues/1

## 3. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/oscardvs/zoteus

## 4. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/oscardvs/zoteus

## 5. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/oscardvs/zoteus

## 6. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/oscardvs/zoteus

## 7. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/oscardvs/zoteus/issues/1

## 8. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/oscardvs/zoteus

## 9. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/oscardvs/zoteus

## 10. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.0
- User impact: Upgrade or migration may change expected behavior: v1.0.0
- Evidence: failure_mode_cluster:github_release | https://github.com/oscardvs/zoteus/releases/tag/v1.0.0

## 11. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.1
- User impact: Upgrade or migration may change expected behavior: v1.0.1
- Evidence: failure_mode_cluster:github_release | https://github.com/oscardvs/zoteus/releases/tag/v1.0.1

## 12. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.2
- User impact: Upgrade or migration may change expected behavior: v1.0.2
- Evidence: failure_mode_cluster:github_release | https://github.com/oscardvs/zoteus/releases/tag/v1.0.2

## 13. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.3
- User impact: Upgrade or migration may change expected behavior: v1.0.3
- Evidence: failure_mode_cluster:github_release | https://github.com/oscardvs/zoteus/releases/tag/v1.0.3

<!-- canonical_name: oscardvs/zoteus; human_manual_source: deepwiki_human_wiki -->
