Repository navigation
Publish and list the MCP servers on Smithery / Claude / Cursor with reproducible manifests #27
Description
Context
docs/marketplace-listings.md has finished copy for Smithery, Claude Desktop, and Cursor, but submissions are pending, the repo isn't public, there is no machine-readable manifest (server.json / smithery.yaml), and the write toolset is clone-only — packages/mcp/package.json is "private": true with no bin. Only the hosted read MCP is npx/mcp-remote friendly. The roadmap §5/§6 calls for one-command install and registry manifests so listings are reproducible.
Goal / user story
As a developer discovering ContextMEM on Smithery/Claude/Cursor, I want to install it in one command and have the listing reflect the real, current tool set (the extract/recall/remember triad), so I can connect it to my agent in under a minute.
Acceptance criteria
-
packages/mcpis publishable as@contextmem/mcp(removeprivate: true, add abinentry + build output) sonpx @contextmem/mcpstarts the local/write stdio server; env requirements (MEMWAL_*,TATUM_API_KEY,CONTEXTMEM_RUNS_DIR) are documented. - A
server.json(MCP registry schema) andsmithery.yamlare committed describing both the stdio (write) server and the hosted (read) URL server, listing the triad tools with descriptions. - The Claude/Cursor/Smithery install snippets in
docs/marketplace-listings.mdare verified against the live hosted URL and the new npx command; the hosted snippet keeps theAuthorization: Bearer <read-token>header. - The share-page / Publish install snippet bug is fixed: private-namespace snippets must include
--header Authorization: Bearer <read-token>(today'sShareMcpInstallomits it → silent 401); add a one-line note that public namespaces need no token. - A short
docs/install page (or section) documents both paths: hosted read viamcp-remote, full triad vianpx @contextmem/mcp, with copy-paste blocks for Claude Desktop, Cursor, and Smithery. - Submission steps are captured but gated behind explicit human approval (per the existing note at the top of
marketplace-listings.md); repo-public flip is a documented prerequisite, not done automatically.
Implementation notes
- Touch
packages/mcp/package.json(publish config,bin, build script — it currently only typechecks), addserver.json+smithery.yamlat repo or package root, and updatedocs/marketplace-listings.md. - Reuse the install-snippet shape from
PublishPanel(apps/webmain.tsx:449-456) when fixingShareMcpInstall(main.tsx:2028). - Smithery hosted URL is already
https://contextmem-hosted-namespace-mcp.petlofi.workers.dev/mcp?namespace=<namespace>; verify it still resolves and thatserver.jsonpoints at it. - Gotcha: the write server needs Node (Tatum/
tar/packProofBundle); make the npx package clearly the Node path and keep the hosted URL as the zero-install read path. - Do not change repo visibility or actually submit — leave those as a checklist for a human, matching the existing approval note.
Sui Overflow angle
Discoverability is how a hackathon project becomes ecosystem infrastructure: being installable from Smithery/Claude/Cursor lets any Sui agent builder pull in Walrus-backed context + Sui-anchored receipts with one command, amplifying the Sui-native story beyond the demo and seeding adoption of the extract/recall/remember triad as a reusable Nexus node.
Dependencies
Soft-depends on the canonical triad issue (listings should describe the triad). Independent of the on-chain receipt work.
Part of the ContextMEM roadmap (#4) • Sui Overflow build.
Activity
harrymove-ctrl commentedon Jun 19, 2026
Implementation Plan
Approach
Make
packages/mcpa real, publishable npm package sonpx @contextmem/mcpstarts the full write/stdio server (the Node-only path that needstar/Tatum/MemWal), while keeping the hosted read server (/mcp?namespace=…) as the zero-install path. Because the stdio server imports threeworkspace:*,private:truepackages (@contextmem/core|walrus|memwal), the cleanest single-package publish is to bundle those workspace deps intodist/with tsup and externalize only true npm runtime deps — avoids publishing four coordinated packages. Add machine-readable manifests (server.jsonper the MCP registry schema +smithery.yaml) describing both servers, fix the real bug (ShareMcpInstallomits theAuthorizationheader → silent 401 on private namespaces), verify the docs snippets against live endpoints, and leave repo-public/submission as a human-gated checklist.Prerequisites & dependencies
@contextmemscope (org + 2FA/automation token). If unavailable, fall back to publishing all four packages or using an alternate scope — decide before Step 1.https://contextmem-hosted-namespace-mcp.petlofi.workers.dev/mcp?namespace=<namespace>but the roadmap namescontextmem-backend.petlofi.workers.dev. Confirm which Worker actually serves/mcp(Step 5) before freezing it inserver.json.docs/marketplace-listings.md:3— do NOT submit or flip repo visibility.Step-by-step
Add a dedicated bin entry (avoids the symlink start bug). Create
packages/mcp/src/bin.tsthat importscreateLocalContextMemMcpServerand unconditionallyawait server.connect(new StdioServerTransport()). Do not rely on the existingimport.meta.url === \file://${process.argv[1]}`guard atpackages/mcp/src/index.ts:324— npm installs the bin as a symlink, soprocess.argv[1](symlink) ≠import.meta.url(realpath) and the server silently won't start undernpx. Keep the guard inindex.tsforbun packages/mcp/src/index.ts` dev use.Make the package publishable + build to
dist/. Editpackages/mcp/package.json:"private": true(:4); add"publishConfig": { "access": "public" }."bin": "dist/bin.js"(string bin ⇒npx @contextmem/mcpruns it directly regardless of bin name),"main": "dist/index.js","files": ["dist"]."build": "tsc -p tsconfig.json --noEmit"(:13) with"build": "tsup"; add"prepublishOnly": "tsup".tsupand declare the externalized runtime deps as realdependencies(see Step 3).Create
packages/mcp/tsup.config.ts:entry: ["src/bin.ts", "src/index.ts", "src/hosted.ts"],format: ["esm"],target: "node20",banner: { js: "#!/usr/bin/env node" }(orchmod +xin build),noExternal: [/^@contextmem\//](inline the three workspace packages so they don't need publishing), and keep large/native deps external.Resolve the dependency graph for the bundle. Inline
@contextmem/core|walrus|memwal(noExternal). Keep external + list underdependencies:@modelcontextprotocol/sdk,zod,@mysten/sui, plus the heavy transitive deps core pulls in —@mozilla/readability,turndown,jsdom,cheerio,fast-xml-parser,nanoid,p-limit,css-tree. MakeplaywrightanoptionalDependencyand confirm it is lazy-imported (screenshots are optional; a hard top-level import would force a browser download on everynpx). If core imports playwright at module load, gate it behind a dynamicimport()so the stdio server boots without it.Fix the
ShareMcpInstallheader bug (acceptance docs: add product roadmap (Harbor storage + Talus on-chain direction) #4). Inapps/web/src/main.tsx:2028-2042:visibility?: "private" | "public"prop. For private, build the Claude snippet with themcp-remote--headerarg, mirroring the working PublishPanel/docs shape:args: ["-y","mcp-remote", mcpUrl, "--header", "Authorization: Bearer <read-token>"], and the Cursor object with aheaders: { Authorization: "Bearer <read-token>" }key. For public, keep the current header-less snippets.Authorization: Bearer <read-token>(generate one in /app/namespaces)."visibilityin: addvisibility: "private" | "public"toShareLinkResponse.share(main.tsx:527), pass it at the call sitemain.tsx:1800/1742, and have the Worker include it in the/api/share-links/:idresponse (apps/api/src/worker.ts). If adding the field to the share endpoint is undesirable, default to emitting the<read-token>placeholder + note unconditionally (still correct, just shows a removable header for public). Reuse the snippet shape referenced atmain.tsx:449-456(the server-generatedsnippetsthat already carry the token in PublishPanel, rendered atmain.tsx:5868-5883).Verify live endpoints (acceptance fix(ci): force bun + pin wrangler in Deploy workflow #3). With the hosted Worker confirmed (Prereqs), run an MCP
initialize+tools/listhandshake against…/mcp?namespace=<a-public-namespace>(e.g.npx -y mcp-remote <url>or a raw JSON-RPC POST) and against a private namespace with theAuthorization: Bearer <read-token>header to prove the header path works and the header-less path 401s. Then smoke-testnpx @contextmem/mcplocally vianpm pack(Step 9) and an MCPtools/list.Author
server.json(acceptance Memory knowledge graph: 3D neural constellation + grounded entity panel #2). Createserver.jsonat repo root (registry-publishable). Use$schema: https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json, reverse-DNSname(e.g.io.github.harrymove-ctrl/contextmem),description,version,repository. Two entries:packages[]:{ registryType: "npm", identifier: "@contextmem/mcp", version, transport: { type: "stdio" }, runtimeHint: "npx", environmentVariables: [...] }documentingMEMWAL_ACCOUNT_ID,MEMWAL_AUTHORIZATION(isSecret),MEMWAL_MCP_URL(optional),TATUM_API_KEY(isSecret),CONTEXTMEM_RUNS_DIR(optional) — exact names confirmed inpackages/memwal/src/index.tsandpackages/walrus/src/storage.ts.remotes[]:{ type: "streamable-http", url: "https://contextmem-hosted-namespace-mcp.petlofi.workers.dev/mcp?namespace={namespace}", variables: { namespace: {...} }, headers: [{ name: "Authorization", description: "Bearer <read-token> for private namespaces", isRequired: false, isSecret: true }] }.Describe the triad (extract/recall/remember) in the description and reference the concrete tools: write/stdio =
scrape_markdown,crawl_site,extract_*,ai_query_website,remember_site_snapshot,upload_proof_to_walrus,recall_site_context,query_site_memory(full list inindex.ts); hosted/read =context_info,list_context,read_context,search_context,recall_memory,get_context_bundle,restore_site_memory(fromhosted.ts:78-267). Validate against the schema with the registrymcp-publisher validateCLI.Author
smithery.yaml(acceptance Memory knowledge graph: 3D neural constellation + grounded entity panel #2). Createsmithery.yamlat repo root for the stdio server:The hosted read URL is listed on Smithery as a Remote server via
server.json/Smithery's remote-add flow (note this in docs, not in this yaml).Update docs (acceptance fix(ci): force bun + pin wrangler in Deploy workflow #3, Spike: run @mysten/seal encrypt+decrypt inside a Cloudflare Worker #5). Edit
docs/marketplace-listings.md: keep the existing Smithery (:24-31) and Claude Desktop (:42-57) snippets — both already includeAuthorization: Bearer <read-token>— but (a) update them to the verified canonical URL from Step 5, (b) add an explicitnpx @contextmem/mcpwrite-server block with env vars, (c) refresh the tool list to the triad. Createdocs/install.mddocumenting both paths with copy-paste blocks for Claude Desktop, Cursor, and Smithery: hosted read vianpx -y mcp-remote <url> --header "Authorization: Bearer <token>", and full triad vianpx @contextmem/mcp. Add a "Submission checklist (HUMAN APPROVAL REQUIRED)" section listing repo-public flip → npm publish → Smithery/Claude/Cursor submission, explicitly gated (acceptance Build HarborClient: reserve→sign→finalize bucket, multipart upload, status poll, download #6), matchingmarketplace-listings.md:3.Publish dry-run (no real publish).
cd packages/mcp && bun run build && npm pack, install the tarball in a temp dir, runnpx <tarball>and assert an MCPtools/listsucceeds with the 20 write tools. Leave the actualnpm publishand registry submission to the human gate.New / changed files
packages/mcp/src/bin.ts(new — stdio entry)packages/mcp/tsup.config.ts(new)packages/mcp/package.json(edit — unprivate, bin, build, files, deps, publishConfig)server.json(new — MCP registry manifest, repo root)smithery.yaml(new — repo root)docs/install.md(new — dual-path install page)docs/marketplace-listings.md(edit — verified snippets, npx block, triad, gated checklist)apps/web/src/main.tsx(edit —ShareMcpInstallheader fix:2028,ShareLinkResponse.share.visibility:527, call site:1800)apps/api/src/worker.ts(edit — addvisibilityto/api/share-links/:idresponse)packages/mcp/src/index.ts(no functional change; entry guard retained)Test plan
bun run --filter @contextmem/mcp buildemitsdist/bin.jswith shebang + exec bit;npm pack→ install tarball in a clean dir →npx @contextmem/mcpboots andtools/listreturns the 20 write tools (round-trip assert). Confirmsprivate:trueremoval +binwork.mcp-publisher validate server.jsonpasses against the registry schema;smithery.yamlparses (Smithery CLI or YAML lint).initialize+tools/listagainst the hosted URL succeeds for a public namespace without a header, returns 401 for a private namespace without a header, and succeeds for the same private namespace withAuthorization: Bearer <read-token>.--header Authorization: Bearer <read-token>line and the public-vs-private note; public share page snippet stays header-less.bun-check.yml(typecheck + test + build) stays green with the newtsupbuild wired into the packagebuildscript.Risks & gotchas
import.meta.url === file://${process.argv[1]}guard breaks under npm's symlinked bin — hence the dedicatedbin.ts(Step 1). Verify on a real install, not justbun run.playwright(browser download),jsdom,cheerioare heavy; a stray top-levelplaywrightimport forces a multi-hundred-MB install on everynpx. Make itoptionalDependencies+ lazy-import; verify the server boots without playwright present.noExternal: @contextmem/*) sidesteps publishing four packages, but any npm dep the bundled code uses at runtime must be in@contextmem/mcp'sdependenciesor the install breaks. Audit transitive imports of core/walrus/memwal. Fallback: publish all four packages with their owndist+ exports.packProofBundleshellstarviachild_process(Node) —server.json/docs must clearly mark@contextmem/mcpas the Node path and the hosted URL as the zero-install read path (issue note).server.jsonships a dead listing. Verify (Step 5) before commit.npm publish, submit, or flip repo visibility — only the dry-run (npm pack). Honormarketplace-listings.md:3.Acceptance-criteria mapping
@contextmem/mcp+bin+ build + env docs → Steps 1, 2, 3, 9 (env names also in Step 6/8).server.json+smithery.yamldescribing stdio + hosted, triad tools → Steps 6, 7.ShareMcpInstallheader bug + public-no-token note → Step 4.docs/install page, both paths, copy-paste blocks → Step 8 (docs/install.md).Effort
M — ~2-3 person-days. ~1 day packaging/bundling + dependency audit (highest-risk), ~0.5 day manifests + validation, ~0.5 day
ShareMcpInstall/workervisibilityfix + verify, ~0.5 day docs + endpoint verification.Implementation plan generated for execution (planning phase). Part of the roadmap (#4).