Skip to content

zotero-roam-mcp: vendored zoteroRoam fork with experimental Roam MCP AI tools - #22

Merged
mattakamatsu merged 2 commits into
mainfrom
zotero-roam-mcp
Sep 1, 2026
Merged

zotero-roam-mcp: vendored zoteroRoam fork with experimental Roam MCP AI tools#22
mattakamatsu merged 2 commits into
mainfrom
zotero-roam-mcp

Conversation

@mattakamatsu

Copy link
Copy Markdown
Contributor

What this is

A new prototype, prototypes/zotero-roam-mcp/. It is a fork, not an original prototype: it vendors 8bitgentleman/zotero-roam v0.7.29 (Apache-2.0, LICENSE included; itself a fork of alixlahuec/zotero-roam) and adds experimental headless MCP capabilities. The extension registers AI tools with Roam through the experimental extensionAPI.ai.addTool API, so agents connected through Roam's MCP server can search the Zotero library and import items into the graph with no UI interaction.

The tools

Discoverable in get_graph_guidelines under extensionTools, invoked with call_extension_tool:

  • zotero-search-items (read): search loaded items by citekey, DOI, Zotero key, or title substring. Reports whether each item already has a Roam page.
  • zotero-import-metadata (edit): headless "Import metadata". Creates the [[@citekey]] page if needed and imports with the user's configured formatter, custom function, or SmartBlock. Refuses duplicate imports unless allowDuplicate: true is passed.
  • zotero-import-notes (edit): headless "Import notes" (notes and PDF annotations).

Registration is feature-detected: on Roam builds without extension AI tools (Local API before 1.1.5) nothing is registered and the extension behaves like the upstream release. Settings are read at call time. The new code is confined to src/services/ai-tools/ plus loader wiring and a hasBlockChildren helper; the same change also exists on a standalone branch of the fork (feat/roam-mcp-ai-tools) for upstreaming.

Shared tooling changes (first commit)

Two repository-level fixes were needed to admit a JSX/TSX prototype; both fix classes of problems that any future React-heavy prototype would hit:

  1. validate-prototypes ran es-module-lexer on every source file, and the lexer cannot parse JSX. It threw an unlabeled "Parse error" on all of them. The check now falls back to an esbuild transform (preserving all non-import type imports) and lexes the transformed code, with tests for the new path. This keeps the roamjs-components default-import check intact for JSX sources.
  2. The root test script ran a bare node --test. Newer Node 22 releases type-strip and execute any prototypes/**/*.test.ts they find, without the prototype's vitest config, so the root runner broke on vendored in-source suites (a variant of the issue noted in Add the Copy for LaTeX prototype #11). It is now scoped to test/*.test.mjs; prototype suites run via the recursive per-package test scripts as before.

Verification

  • pnpm test: root contract tests pass (including new validator tests); the vendored vitest suite passes 428/428.
  • pnpm build: validator passes on all three prototypes; this one emits dist/extension.js (ES module, default {onload, onunload} export) and dist/extension.css, no sourcemap.
  • pnpm prepare:artifacts: packages extension.js, extension.css, README.md, CHANGELOG.md for all three prototypes.

How to test in Roam

  1. Use the preview URL from the CI comment with Roam's "Load Developer Extensions from URL", on a Roam Desktop build that has extension AI tools.
  2. Configure the extension with a Zotero API key and library (same as upstream zoteroRoam).
  3. From a Roam MCP client, call get_graph_guidelines and confirm the three tools are listed, then try zotero-search-items and zotero-import-metadata on a known citekey.

Not vendored

Storybook stories and config, release tooling, the roam/js and sandbox build modes, and upstream's committed build artifacts. The prototype README documents the fork lineage and each deviation from repository conventions.

🤖 Generated with Claude Code

mattakamatsu and others added 2 commits August 31, 2026 00:59
…t runner

es-module-lexer only understands plain JavaScript, so the roamjs-components
default-import check threw an unlabeled "Parse error" on any prototype source
containing JSX. When the direct lex fails, the source is now transformed with
esbuild first (keeping every import clause that is not explicitly
`import type`, via importsNotUsedAsValues + preserveValueImports) and the
transformed code is lexed instead. Files neither parser accepts fail with a
labeled error. Adds esbuild (the catalog version) as a root dependency.

Also scopes the root test script from a bare `node --test` to
`test/*.test.mjs`. Newer Node 22 releases type-strip and execute any
prototypes/**/*.test.ts they find, without the prototype's vitest config, so
the root runner broke on packages with in-source vitest suites. Those suites
are run by each package's own test script in the recursive step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… MCP AI tools

Vendors 8bitgentleman/zotero-roam v0.7.29 (Apache-2.0, LICENSE included;
itself a fork of alixlahuec/zotero-roam) as a prototype, plus a new
src/services/ai-tools service that registers three AI tools through Roam's
experimental extensionAPI.ai.addTool, callable by agents through Roam's MCP
server via call_extension_tool:

- zotero-search-items (read): find loaded items by citekey, DOI, Zotero
  key, or title substring; reports whether each item already has a Roam page
- zotero-import-metadata (edit): headless "Import metadata" that creates the
  [[@citekey]] page if needed and imports with the user's configured
  formatter, custom function, or SmartBlock; refuses duplicate imports
  unless allowDuplicate is passed
- zotero-import-notes (edit): headless "Import notes"

Registration is feature-detected and skipped on Roam builds that predate
extension AI tools. Settings are read at call time.

The vendored copy keeps upstream's conventions and build (Vite, adapted to
emit dist/extension.js + dist/extension.css per the artifact contract, ES
module output, no sourcemap). Storybook stories and release tooling are not
vendored; the full upstream vitest suite (428 tests) is, and passes under
the workspace. The README documents the fork lineage and the deviations
from repository conventions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Roam prototype previews

The preview deployment is ready. Paste a URL below into Load Developer Extensions from URL in Roam:

View publishing details

@mattakamatsu
mattakamatsu merged commit 742f70d into main Sep 1, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant