github TypeScript re-analysis due

oscardvs/zoteus

github

Zotero MCP server: search, citations, add by DOI, safe writes, semantic search and PDF page images for Claude, ChatGPT and any MCP client. TypeScript, local-first.

maintainer
oscardvs
licence
MIT
first seen
2026-07-20
last seen
2026-09-17
releases · 30d
24
short id

Drift inferred · capture-to-capture

No drift recorded — single capability capture; advisories appear once its surface changes.

capabilities 0 tools
transport stdio · streamable-http · http verified reported listed in the official MCP registry counts 0 tools · 0 res · 0 prompts permission surface via code analysis

No tools enumerated yet for this server.

skills & danger signals github-tarball
prompt-surface shipped agent-instruction files + hidden-content / dangerous-code findings — quoted from the analyzed source

analyzed commit 3bf2637 · analyzer v33 · 4d ago

danger signals1

code evidence vv1.20.0 · github-tarball
evidence-backed findings quoted directly from the published source artifact — not inferred

code files: 316

filesystem 60

  • fs oscardvs-zoteus-3bf2637/bench/two-stage-search.ts :17 import { mkdtempSync, rmSync, statSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/scripts/mcpb-bundle.ts :37 } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/scripts/smoke-live.mjs :33 import { existsSync, mkdtempSync, writeFileSync } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/api/attachments.ts :2 import { readFile, writeFile, stat } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/api/local-writes.ts :2 import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/auth/store.ts :2 import { readFile, writeFile, rename, mkdir } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/codex/generate.ts :1 import { writeFile, mkdir } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/features/attachments/bytes.ts :1 import { readdir, readFile, stat } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/features/attachments/store.ts :1 import { readFile } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/features/search/index-manager.ts :1 import { statSync } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/features/search/persistence.ts :1 import { readFile, writeFile, mkdir, rename, unlink } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/features/search/repair.ts :1 import { unlink } from 'node:fs/promises';
show 28 more
  • fs oscardvs-zoteus-3bf2637/src/features/search/sqlite-index.ts :3 import { existsSync } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/lib/caller-path.ts :1 import { realpath } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/lib/logger.ts :3 import { createWriteStream, type WriteStream } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/lib/update-check.ts :1 import { readFile, writeFile, mkdir } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/lib/usage/store.ts :18 import { existsSync, mkdirSync, renameSync } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/tools/attachment.ts :4 import { existsSync } from 'node:fs';
  • fs oscardvs-zoteus-3bf2637/src/tools/pdf-images.ts :3 import { mkdir, writeFile } from 'node:fs/promises';
  • fs oscardvs-zoteus-3bf2637/src/tools/tag-audit.ts :2 import { readFile } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/api/attachments.test.ts :2 import { writeFile, readFile, rm } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/api/local-writes.test.ts :2 import { mkdtempSync, readFileSync, existsSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/auth/store.test.ts :2 import { mkdtemp, rm, writeFile, readFile } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/e2e/live-writes.test.ts :2 import { writeFile, readFile, rm } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/accent-folding.test.ts :2 import { mkdtempSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/attachment-bytes.test.ts :2 import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/embedder-degradation.test.ts :2 import { mkdtempSync, mkdirSync, writeFileSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/embedding-rate-math.test.ts :2 import { readFileSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/pdf-images.test.ts :2 import { readFile } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-async.test.ts :4 import { readFile } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-backends.test.ts :2 import { mkdtempSync, writeFileSync, existsSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-corruption.test.ts :2 import { mkdtempSync, writeFileSync, openSync, writeSync, closeSync, mkdirSync, rmSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-droplist.test.ts :2 import { mkdtempSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-fulltext-resume.test.ts :2 import { mkdtempSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-incremental-update.test.ts :2 import { mkdtempSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-library-guard.test.ts :2 import { mkdtempSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-pause.test.ts :2 import { mkdtemp, readFile } from 'node:fs/promises';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-repair.test.ts :2 import { mkdtempSync, writeFileSync, openSync, writeSync, closeSync, existsSync, readFileSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-resume.test.ts :2 import { mkdtempSync, readFileSync } from 'node:fs';
  • fs (weak) oscardvs-zoteus-3bf2637/tests/features/search-salvage-library.test.ts :2 import { mkdtempSync, readdirSync } from 'node:fs';

20 more not shown — this panel samples each group; the count above is the real total.

shell / exec 3

  • shell (weak) oscardvs-zoteus-3bf2637/scripts/mcpb-bundle.ts :26 import { execFileSync } from 'node:child_process';
  • shell oscardvs-zoteus-3bf2637/src/features/search/embeddings.ts :740 private spawn(specifier: string): Promise<Extractor> {
  • shell (weak) oscardvs-zoteus-3bf2637/tests/features/search-backends.test.ts :3 import { spawn } from 'node:child_process';

network 27

  • net (weak) oscardvs-zoteus-3bf2637/scripts/smoke-live.mjs :32 import { createServer } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/scripts/usage-report.ts :35 const res = await fetch(`${remote.replace(/\/$/, '')}/usage.json?days=${days}`, {
  • net oscardvs-zoteus-3bf2637/src/api/connector-writes.ts :59 const res = await this.fetcher.fetch(`${this.base}/connector/ping`, { method: 'GET' }, { maxRetries: 0 });
  • net oscardvs-zoteus-3bf2637/src/api/http.ts :44 async fetch(
  • net oscardvs-zoteus-3bf2637/src/api/local-client.ts :154 const res = await this.fetcher.fetch(
  • net oscardvs-zoteus-3bf2637/src/api/local-writes.ts :104 const res = await this.fetcher.fetch(
  • net oscardvs-zoteus-3bf2637/src/api/web-client.ts :169 const res = await this.fetcher.fetch(url, { method: 'GET', headers: this.headers() });
  • net oscardvs-zoteus-3bf2637/src/features/attachments/store.ts :92 const res = await ctx.fetcher.fetch(url, { method: 'GET' }, { maxRetries: 2, deadlineMs: 300_000 });
  • net oscardvs-zoteus-3bf2637/src/features/citation/translation-server.ts :22 const res = await this.fetcher.fetch(`${this.baseUrl}/`, { method: 'GET' }, { maxRetries: 0 });
  • net oscardvs-zoteus-3bf2637/src/features/scholar/crossref.ts :42 const res = await this.fetcher.fetch(`${BASE}/works/${stripDoi(doi)}${m}`, { method: 'GET' }, { maxRetries: 1 });
  • net oscardvs-zoteus-3bf2637/src/features/scholar/openalex.ts :84 const res = await this.fetcher.fetch(url, { method: 'GET', headers: this.headers }, { maxRetries: 1 });
  • net oscardvs-zoteus-3bf2637/src/features/search/embeddings.ts :995 fetch('https://api.openai.com/v1/embeddings', {
show 15 more
  • net oscardvs-zoteus-3bf2637/src/index.ts :22 import type { Server } from 'node:http';
  • net oscardvs-zoteus-3bf2637/src/lib/cimd.ts :11 // fetch (TOCTOU). Operators serving a directory connector should set an allowlist.
  • net oscardvs-zoteus-3bf2637/src/lib/lifecycle.ts :1 import type { Server } from 'node:http';
  • net oscardvs-zoteus-3bf2637/src/tools/import.ts :43 const item = await arxivItem(parsed.value, (url, init) => ctx.fetcher.fetch(url, init, { maxRetries: 0, deadlineMs: 60_000 }));
  • net oscardvs-zoteus-3bf2637/src/transports/http.ts :1 import http from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/api/http.test.ts :21 const res = await f.fetch('https://example.test/x');
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/cimd-metadata.test.ts :3 import type { Server } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/dns-rebinding.test.ts :3 import type { Server } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/graceful-shutdown.test.ts :3 import http from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/health-endpoints.test.ts :2 import type { Server } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/http-sessions.test.ts :6 import type { Server } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/http.test.ts :6 import type { Server } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/multitenant.test.ts :5 import type { Server } from 'node:http';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/oauth-flow.test.ts :2 import net from 'node:net';
  • net (weak) oscardvs-zoteus-3bf2637/tests/integration/usage-endpoints.test.ts :2 import type { Server } from 'node:http';

secrets 7

  • secrets (weak) oscardvs-zoteus-3bf2637/scripts/usage-report.ts :34 const token = arg('token') ?? process.env.ZOTEUS_METRICS_TOKEN;
  • secrets oscardvs-zoteus-3bf2637/src/features/search/embeddings.ts :1054 if (!process.env.OPENAI_API_KEY) {
  • secrets (weak) oscardvs-zoteus-3bf2637/tests/e2e/live-writes.test.ts :15 const enabled = Boolean(process.env.ZOTERO_API_KEY) && process.env.ZOTEUS_E2E_WRITE === 'true';
  • secrets (weak) oscardvs-zoteus-3bf2637/tests/e2e/live.test.ts :6 const hasKey = Boolean(process.env.ZOTERO_API_KEY);
  • secrets (weak) oscardvs-zoteus-3bf2637/tests/features/embedder-degradation.test.ts :80 const previous = process.env.OPENAI_API_KEY;
  • secrets (weak) oscardvs-zoteus-3bf2637/tests/features/embedding-config.test.ts :174 const previous = process.env.OPENAI_API_KEY;
  • secrets (weak) oscardvs-zoteus-3bf2637/tests/features/search-electron-fulltext.test.ts :166 process.env.OPENAI_API_KEY = 'sk-test';

install hooks 2

  • prepare oscardvs-zoteus-3bf2637/package.json :50 npm run build
  • prepublishOnly oscardvs-zoteus-3bf2637/package.json :51 npm run build

declared dependencies 18

  • @modelcontextprotocol/sdk@^1.29.0
  • citeproc@^2.4.63
  • cors@^2.8.6
  • express@^5.2.1
  • express-rate-limit@^8.5.2
  • zod@^3.25.76
  • @types/cors@^2.8.19
  • @types/express@^5.0.6
  • @types/node@^22.10.0
  • @typescript-eslint/eslint-plugin@^8.18.0
  • @typescript-eslint/parser@^8.18.0
  • eslint@^8.57.1
show 6 more
  • pkce-challenge@^5.0.1
  • prettier@^3.4.2
  • tsx@^4.19.2
  • typescript@^5.7.2
  • vitest@^2.1.8
  • pdfjs-dist@5.6.205

perm:untrusted 2

  • untrusted (weak) oscardvs-zoteus-3bf2637/tests/integration/oauth-flow.test.ts :114 const consentHtml = await (await fetch(authUrl)).text();
  • untrusted (weak) oscardvs-zoteus-3bf2637/tests/integration/usage-endpoints.test.ts :45 const text = await (await fetch(`${await serve()}/metrics`)).text();

transport_posture 1

  • binds all interfaces (0.0.0.0) oscardvs-zoteus-3bf2637/tests/integration/dns-rebinding.test.ts :37 await expect(startHttp(bareServer(), { port: 0, host: '0.0.0.0' })).rejects.toThrow(/loopback/i);