Skip to content
prod 352bb92
Browse

Use the ZajLibrary MCP

Learn · guide · Library MCP

Point an MCP client at https://library.zajapps.com/api/mcp, then run list_contentssearch_libraryget_document. Anonymous callers read public docs and may submit_feedback; a Bearer admin token or signed-in session unlocks private docs and admin feedback tools.


  • Production vs local URLs and port rules
  • Cursor, Claude Code, and admin Bearer wiring
  • All six tools — arguments, enums, and example payloads
  • A search → read → verify → feedback workflow
  • Operator index/embeddings maintenance and troubleshooting

RequirementNotes
MCP-capable clientCursor, Claude Code, or any Streamable HTTP MCP host
Time~10 min connect · ~2 min smoke-test
Local devapp/.env.local with dev DATABASE_URL if testing feedback storage locally
Optional adminMCP_ADMIN_TOKEN in app/.env.local + same value sent as Bearer for private docs / admin tools

EnvironmentMCP URL
Productionhttps://library.zajapps.com/api/mcp
Local devhttp://localhost:4321/api/mcp

Local dev is locked to port 4321 (app/dev-port.mjs). From app/:

Terminal window
cd app
npm run dev

Prod default — use zajlibrary for real deploys and stable citations. Local sometimes — use zajlibrary-local for doc authoring, first-time setup-new QA, unreleased dev content, or testing submit_feedback on the dev queue.

Quick comparison:

SituationServer
Real CodeCanyon deploy; stable handoffzajlibrary (prod)
First walkthrough, WIP docs, local feedback QAzajlibrary-local (:4321, dev running)

The MCP index is build-time — after doc edits: npm run build:index then restart dev. Details: Use local ZajLibrary MCP.


This repo pins production + local MCP in .mcp.json — see Use local ZajLibrary MCP for when to enable each server.

Restart Cursor or reload MCP servers after editing.


graph LR
Client["MCP client"] -->|"Streamable HTTP"| Endpoint["/api/mcp"]
Endpoint --> Search["search_library"]
Endpoint --> Get["get_document"]
Endpoint --> List["list_contents"]
Endpoint --> FB["submit_feedback"]
Endpoint --> LFB["list_feedback"]
Endpoint --> RFB["review_feedback"]
Search --> Index[("docs.json + vectors.json")]
Get --> Index
List --> Index
FB --> DB[("Neon feedback queue")]
LFB --> DB
RFB --> DB

The site is static except this route. Search reads a build-time index regenerated on every npm run dev / npm run build — not live filesystem reads at request time.


No arguments. Returns JSON (and text) with:

FieldMeaning
totalDocsIndexed public doc count (private excluded unless scoped)
semanticEnabledWhether vectors.json has embeddings
commitSha / commitShaShort / indexBuiltAtIndex provenance — compare to prod deploy
categories / subcategories / topicsTopic-first taxonomy counts
shelves / collections / topTagsShelf/register/tag rollups
ArgumentDefaultNotes
query(required)Natural language or keywords
modehybridkeyword · semantic · hybrid (RRF). Falls back to keyword if embeddings empty
limit8Max 25

Returns ranked hits with title, URL, topic crumb (category/subcategory/topic), shelf/kind, snippet, and structuredContent.hits for programmatic clients. Provenance footer on every response.

ArgumentNotes
refTopic-first id, slug path, or full library.zajapps.com URL — e.g. tech-stack/laravel/codecanyon/build/playbooks/setup-new/

Returns full Markdown body plus metadata header. Private docs return not-found unless caller has read-private.

Files to the same DB queue as the site feedback form (source: mcp).

ArgumentRequiredValues / notes
typeyesbug · suggestion · missing · update · question
titleyesConcise summary (min 3 chars; long titles normalized — detail goes in body)
bodynoFull description, repro, expected/actual
pageUrlnoRelative path or https:// URL for the page
docIdnoTopic-first document id
categorynodocs · admin-ui · mcp · feedback-system · content-intake · deploy · auth · database · agent-rules · other
subcategorynoFiner area label
topicnoProduct/content family
sectionnoHeading or UI section
severitynolow · med · high · critical
accuracyStatenounreviewed · confirmed · partially_correct · incorrect · insufficient_detail
evidenceSummarynoCommand output, screenshot note, source citation
externalIdnoExternal id e.g. FB-13
dedupeKeynoStable idempotency key for agents/importers
metadatanoJSON bag: expected, actual, reproSteps, environment, agent, model, etc.

Example:

{
"type": "missing",
"title": "Phase 3 env template path not documented",
"body": "Step references Admin-Local/Templates/.env.example but playbook links elsewhere.",
"pageUrl": "/tech-stack/laravel/codecanyon/build/playbooks/setup-new/03-local-dev/",
"category": "docs",
"severity": "med",
"dedupeKey": "setup-new/03-local-dev/env-template"
}

Require list-feedback scope (admin token or allowlisted session).

ArgumentNotes
statusnew · triaged · planned · done · wontfix
reviewDecisionpending · approved · rejected · needs_info · duplicate
implementationStatenot_started · in_progress · implemented · verified · wontfix · not_applicable
category / severitySame enums as submit
searchCase-insensitive match in title, body, docId, pageUrl, evidence
limitDefault 50, max 200

Submitter emails are redacted (hasEmail: true/false only).

ArgumentNotes
idRow id (required)
reviewDecision / implementationStateWorkflow fields (see enums above)
category / severity / accuracyStateOptional reclassification
duplicateOfLink duplicate to another id
reviewNotes / implementationNotes / evidenceSummaryTriage notes

  1. list_contents — read commitShaShort and semanticEnabled.
  2. search_librarymode: hybrid, limit 5–8; read snippets before fetching bodies.
  3. get_document — one or two best hits; cite the returned URL in your answer.
  4. submit_feedback — wrong, missing, or stale content (always include pageUrl or docId when known).

Verify before you declare (coverage + gates)

Section titled “Verify before you declare (coverage + gates)”

When checking whether a playbook step, feedback item, or gate is done, missing, or pending:

BadGood
grep for one string → declare ❌ pendingget_document the Part document → find the ## / #### section → match substance
search_library returns no hit → assume gapBroaden query · try keyword mode · read parent phase page
Checklist box unchecked from memoryRun the verify command; if grep fails, read the prose block it references

For Phase 1 infra gates specifically, 7 · Verify & gate pairs grep smoke checks with substance checks on CLAUDE.local.md and project_context.md — grep alone is never enough.


From repo root (dev server running for local):

Terminal window
cd app && npm run test:mcp
node app/scripts/test-mcp-client.ts http://localhost:4321
node app/scripts/test-mcp-client.ts https://library.zajapps.com

Expected: connects, asserts all six tool names are registered, runs list_contents, searches, fetches one document, prints MCP smoke test passed.

The script exercises read tools by default. Set MCP_ADMIN_TOKEN in the environment to also call list_feedback. Test submit_feedback and review_feedback through your MCP client or the admin dashboard at /admin.


ArtifactWhen it updates
src/mcp/generated/docs.jsonEvery predev / prebuild (gitignored locally)
src/mcp/generated/vectors.jsonnpm run embed with MCP_EMBED=1 + AI_GATEWAY_API_KEYcommitted for Vercel
Terminal window
cd app
npm run embed # needs AI_GATEWAY_API_KEY in .env.local
git add src/mcp/generated/vectors.json

Re-embed after large content changes, commit vectors.json, redeploy. Without vectors, semantic and hybrid degrade to keyword search automatically.


SymptomLikely causeFix
Connection refused on :4321Dev server not running or wrong portcd app && npm run dev — port 4321 only
No document found for "…"Bad ref or private doc without authCopy url from search_library hit; add Bearer token for private shelf
No matches for "…"Query too narrow or index staleBroaden query; try mode: keyword; npm run build:index then restart dev
New page missing from MCPIndex not refreshed after editcd app && npm run build:index then restart dev — index is imported at server start
Local MCP connection refusedDev not runningcd app && npm run dev on port 4321 only; disable zajlibrary-local when dev is off
Semantic seems weakEmpty or stale vectors.jsonRun npm run embed, commit, redeploy
Admin tools return “Admin scope required”Missing or wrong MCP_ADMIN_TOKENMatch client Bearer to server env; restart dev after .env.local change
Feedback insert fails locallyDB env points at wrong Neon branchUse development branch DATABASE_URL in app/.env.local

  • Directoryapp/
    • Directorysrc/
      • pages/api/[transport].ts
      • mcp/search.ts
      • mcp/embed.ts
      • lib/feedback.ts
      • tenant.config.mjs
    • Directoryscripts/
      • build-mcp-index.ts
      • test-mcp-client.ts

  • MCP URL reachable (prod or :4321 local)
  • Client lists all six tools
  • Smoke script passes
  • Agent cites library URLs from tool results, not memory
  • Gaps filed with submit_feedback (pageUrl + dedupeKey when possible)