fix(skills): make remember skill's project scoping transport-safe - #75
fix(skills): make remember skill's project scoping transport-safe#75irresi wants to merge 2 commits into
Conversation
The membase-remember skill ships to every client via the one-command
installer (npx plugins add copies skills/ into each client's plugin
cache). It instructed all clients to read the membase://project MCP
resource, but that resource only exists on the stdio server (Claude
plugin), where it resolves the slug from process.cwd(). Remote-HTTP
clients (Cursor, Codex, VS Code) connect to the hosted server, which has
no client filesystem and does not expose the resource — so the documented
happy path hard-failed with MCP -32602 on every project-scoped save.
Rewrite the guidance to be transport-safe: derive the project slug from
the repository (git remote or dir name) and pass it to add_memory, or omit
it when unknown; keep membase://project as a documented Claude-plugin-only
optimization. Skill-only change (no bundle rebuild).
Verified live on Codex (remote MCP): the same store task that previously
fired list_mcp_resources ('Unexpected response type') and
read_mcp_resource(membase://project) (-32602) now makes zero resource
calls and stores in one add_memory call with the correct project slug.
Independent review caught a real correctness bug in the first cut: the example 'aristoapp/membase-plugin-mcp -> membase-plugin-mcp' dropped the org and kept only the basename, but the plugin's resolveProjectSlug normalizes the FULL git-remote URL path (owner/repo, '/' -> '-'), yielding 'aristoapp-membase-plugin-mcp'. A remote client following the old example would scope to a different slug than the Claude plugin on the same repo and silently split memories across transports — defeating the cross-tool continuity the fix is meant to preserve. Describe the exact normalization (remote URL path, lowercased, non-alphanumeric runs -> single '-') with a correct worked example, and clarify it's the remote URL, not a remote name. Verified live on Codex: a fresh session now runs 'git remote get-url origin' and produces project 'aristoapp-membase-plugin-mcp', matching the plugin's own auto-resolution.
Independent review round → fixed a real correctness bugAn independent reviewer flagged that the first cut's slug example was wrong in a way that would silently split memories across transports:
So a remote-MCP client following the old example would scope to Fixed in 6ab5090: the skill now describes the exact normalization (remote URL path, lowercased, non-alphanumeric runs → single Verified live on Codex: a fresh session now runs Follow-up (separate issue, not blocking): add a cheap lint guard asserting no |
What
The
membase-rememberskill instructed every client to read themembase://projectMCP resource before a project-scoped save. That resourceonly exists on the stdio server (the Claude Code plugin), where it resolves
the slug from
process.cwd(). Remote-HTTP clients (Cursor, Codex, VS Code)connect to the hosted server at
https://mcp.membase.so/mcp, which has noclient filesystem and does not expose the resource — so the documented happy
path hard-failed with
MCP -32602: Resource membase://project not foundonevery project-scoped save.
Found while dogfooding the plugin on Codex CLI.
Why it hits real users
npx plugins add aristoapp/membase-plugin-mcpcopies the whole repo — includingskills/— into each client's plugin cache (verified:~/.codex/plugins/cache/personal/membase/0.3.0/skills/remember/SKILL.md). Sothe shared skill's instruction reaches remote-HTTP clients whose server can't
serve the resource. It breaks for 3 of the 5 clients.
Root cause
skills/remember/SKILL.md:15-16— shared skill, no transport caveat, toldclients to read
membase://project.packages/stdio-runtime/src/mcp/server.ts:725— the resource is registeredonly on the stdio server and resolves via
resolveProjectSlug(process.cwd(), config)— inherently local-filesystem.expose the same resource.
Fix
Rewrite the guidance to be transport-safe: derive the
projectslug from therepository (git remote or directory name) and pass it to
add_memory, or omitit when unknown; keep
membase://projectdocumented as a Claude-plugin-onlyoptimization. Skill-only change — no bundle rebuild.
Alternatives considered
service; can't know client cwd). Rejected.
get_projecttool — still stdio-only, same transport coupling,extra surface. Rejected.
add_memoryhasa
projectparam; "persistent project context" is the headline use case).Rejected.
clients, minimal blast radius. Chosen.
Verification
pnpm check— all 21 guards green (bundle-provenance confirms no bundle drift;this is a source-of-truth skill edit, not a generated artifact).
pnpm test— full suite green (41 contract + capture-core/stdio/openclaw/cursor/hermes).
list_mcp_resources("Unexpected response type") andread_mcp_resource(membase://project)(-32602) now makes zero resourcecalls and stores in a single
add_memorycall with the correctly-derivedproject: "membase-plugin-mcp"slug.Before: 3 calls, 2 errors. After: 1 call, 0 errors.
Scope note
Leaves the stdio server's
startPromptText(server.ts:165) mention ofmembase://projectuntouched on purpose — that text only ships on the stdioserver, which does expose the resource, so it's correct in context and
editing it would force an unnecessary bundle regen.