@xevos117/mcp-zotero 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,12 +17,18 @@ For advanced use cases (PDF upload policy, citation style guidance, source trans
17
17
 
18
18
  | Scenario | MCP server | Skill needed? |
19
19
  |---|---|---|
20
- | Local LLM (Claude Code, LM Studio, etc.) | All 15 tools | No |
21
- | Remote/sandboxed LLM (Claude.ai Projects) | API tools (search, add, metadata) | Yes, for citation injection |
20
+ | LLM with filesystem access (Claude Code, LM Studio, etc.) | All 15 tools | No |
21
+ | LLM without filesystem access (Claude.ai Projects, Claude Desktop) | API tools (search, add, metadata) | Yes, for citation injection |
22
22
 
23
- Local LLMs with filesystem access can use all tools directly, including `inject_citations` which reads and writes `.docx` files on disk.
23
+ LLMs with filesystem access can use all tools directly, including `inject_citations` which reads and writes `.docx` files on disk.
24
24
 
25
- Remote LLMs without filesystem access can use the included **Claude skill** (`skills/zotero-skill-mcp-integrations/`), which runs citation injection entirely inside the sandbox. MCP tools handle all Zotero API operations; the skill handles document assembly.
25
+ LLMs without filesystem access — including Claude Desktop, which connects to MCP but cannot generate files locally — can use the included **Claude skill** (`skills/zotero-skill-mcp-integrations/`), which runs citation injection entirely inside a sandbox. MCP tools handle all Zotero API operations; the skill handles document assembly.
26
+
27
+ ### Claude Skill Setup (for Claude.ai Projects and Claude Desktop)
28
+
29
+ 1. Download the skill `.zip` from the latest [GitHub Release](https://github.com/Xevos117/mcp-zotero/releases)
30
+ 2. Extract it and upload the folder to your Claude.ai Project as a skill
31
+ 3. The skill enables citation injection directly inside the sandbox, without requiring local filesystem access
26
32
 
27
33
  ## Setup
28
34
 
@@ -159,7 +165,7 @@ claude mcp add-json "zotero" '{"command":"npx","args":["tsx","src/server.ts"],"e
159
165
  ```bash
160
166
  npm install
161
167
  npm run build # Compile TypeScript
162
- npm test # Run tests (vitest, 377 tests)
168
+ npm test # Run tests (vitest, 382 tests)
163
169
  npx tsx src/server.ts # Run directly without building
164
170
  ```
165
171
 
@@ -105,12 +105,31 @@ export async function handleAddItemsByDoi(zoteroApi, userId, args) {
105
105
  .library("user", userId)
106
106
  .items()
107
107
  .post(zoteroItems);
108
+ if (!response.isSuccess()) {
109
+ const errors = response.getErrors();
110
+ const errorMessages = Object.entries(errors)
111
+ .map(([idx, msg]) => `Item ${idx}: ${typeof msg === "object" ? JSON.stringify(msg) : msg}`)
112
+ .join(", ");
113
+ return formatErrorResponse(`Zotero API write failed: ${errorMessages}`);
114
+ }
108
115
  const createdItems = response.getData();
109
- const success = resolved.success.map((r, i) => ({
110
- doi: r.doi,
111
- item_key: createdItems[i]?.key ?? "unknown",
112
- title: createdItems[i]?.title ?? r.data.title ?? "Untitled",
113
- }));
116
+ if (!createdItems || !Array.isArray(createdItems) || createdItems.length === 0) {
117
+ return formatErrorResponse("Zotero API returned empty response - items may not have been created");
118
+ }
119
+ const success = [];
120
+ for (let i = 0; i < resolved.success.length; i++) {
121
+ const r = resolved.success[i];
122
+ const entity = response.getEntityByIndex(i);
123
+ const itemKey = entity?.key;
124
+ if (!itemKey) {
125
+ return formatErrorResponse(`Failed to get item key for DOI ${r.doi} at index ${i}. API response may be invalid.`);
126
+ }
127
+ success.push({
128
+ doi: r.doi,
129
+ item_key: itemKey,
130
+ title: entity?.title ?? r.data.title ?? "Untitled",
131
+ });
132
+ }
114
133
  let pdf_results;
115
134
  if (auto_attach_pdf) {
116
135
  const apiKey = process.env.ZOTERO_API_KEY;
@@ -101,8 +101,8 @@ export function cslToZoteroItem(csl, options) {
101
101
  place: csl["publisher-place"] ?? "",
102
102
  url: csl.URL ?? "",
103
103
  abstractNote: csl.abstract ?? "",
104
- ISBN: csl.ISBN ?? "",
105
- ISSN: csl.ISSN ?? "",
104
+ ISBN: Array.isArray(csl.ISBN) ? csl.ISBN[0] : csl.ISBN ?? "",
105
+ ISSN: Array.isArray(csl.ISSN) ? csl.ISSN[0] : csl.ISSN ?? "",
106
106
  edition: csl.edition ?? "",
107
107
  numPages: csl["number-of-pages"] ?? "",
108
108
  series: csl["collection-title"] ?? "",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xevos117/mcp-zotero",
3
3
  "type": "module",
4
- "version": "1.0.6",
4
+ "version": "1.0.7",
5
5
  "description": "Unofficial MCP server for Zotero integration with citation management",
6
6
  "repository": {
7
7
  "type": "git",