Project Memory

How it works

A shared brain for every AI agent you use.

This page walks through what Project Memory does, the architecture behind it, and how to wire your editor up in five minutes.

The problem

Every AI agent — Cursor, Claude Desktop, Copilot, your custom GPT — starts each conversation with no memory of the last one. You explain your stack, your conventions, your half-finished refactor… and an hour later the context window resets and you do it all again.

Worse, none of these agents talk to each other. A decision you captured in Cursor doesn't reach Claude. A task you outlined in Claude is invisible to Cursor. Knowledge fragments across tools and across machines.

What Project Memory is

A single backend that any MCP-compatible agent can read from and write to. Three things live there, scoped per-project, owned by you:

Memory

Free-form notes — facts, decisions, preferences. Agents save them, then later semantic-search across everything you ever told any agent.

  • pm_memory_create
  • pm_memory_update
  • pm_query_memory

Tasks

A shared kanban your agents read and write. Plan in one tool, execute in another. Status changes propagate everywhere.

  • pm_task_create
  • pm_task_update
  • pm_query_task

Code

Local code chunks sync to the cloud (via the optional Electron host). Agents on any machine can semantic-grep without re-indexing.

  • pm_query_code
  • pm_get_context

Architecture at a glance

Bearer · oat_* · audience-bound (RFC 8707)

pmd · multi-tenant · RLS per row

  1. MEMORIES0001–0427
    427
    pmd:m:0042Twin chat handlers must stay in sync — sutra + setu-nextjs.
    pmd:m:0118Audit trigger redacts the embedding column from to_jsonb(new).
    pmd:m:0203RFC 8707 audience binding — tokens scoped per /api/mcp.
    pmd:m:0309pg_cron rows are the source of truth for routine schedules.
    pmd:m:0412Soft-delete on rename keeps the embedding cache warm.
  2. TASKS0001–0118
    118
    pmd:t:0044Wire pm_oauth refresh-rotation revocation chain (RFC 6749 §10.4).
    pmd:t:0061Bump ef_search to 100 per RPC; benchmark recall vs 64.
    pmd:t:0079Add daily spend cap on /api/sync — OpenAI rate-limit gate.
    pmd:t:0094Switch /auth/confirm to safeNext() before redirect.
    pmd:t:0117Move /admin entry to rel="nofollow noindex" on touch.
  3. CODE0001–9821
    9,821
    pmd:c:1402sutra/src/main/mcp/sse-stream.ts · L5-58 · channel relay
    pmd:c:2811setu-nextjs/lib/auth/dispatch.ts · L9-21 · bearer prefix dispatch
    pmd:c:3947project-memory/lib/admin/oauth/access-tokens.ts · L99-119 · rotate
    pmd:c:5210project-memory/supabase/migrations/0002_memory.sql · L60-80 · RLS
    pmd:c:7388sutra/src/main/routines/dispatcher.ts · L42-71 · channel branch

pgvector · HNSW · m=16 · ef_construction=64 · ef_search=100 per RPC

Built on standards: OAuth 2.1 + PKCE for auth, MCP Streamable HTTP for the protocol, Postgres RLS for tenant isolation, pgvector for semantic search.

How to use it — five minutes

1Sign in

Create an account. Email + password, no credit card.

2Add the MCP server to your editor

In Cursor, open ~/.cursor/mcp.json and paste:

{
  "mcpServers": {
    "project-memory": {
      "url": "https://pm.devfrend.com/api/mcp"
    }
  }
}

Claude Desktop, Cline, and other MCP clients use the same shape — check their docs for the file location.

3Approve in your browser

The first time your editor calls a tool, your browser opens a consent screen. One click and the editor receives an OAuth token scoped to this MCP server only. Tokens auto-refresh; you won't be asked again.

4Tell your agent to remember something

In Cursor, type into chat:

Save this to project memory: we use pnpm not npm, and our test runner is vitest with the "test:fast" script for unit tests.

Cursor calls pm_memory_create. Switch to Claude Desktop, ask "what do you know about this project?" — it calls pm_query_memory and gets the same answer.

5Optional: sync your code

Install the setu-host Electron app on your Mac. It watches your repo, chunks files into 500-token windows, and streams them to the cloud over WebSocket. Now any agent on any machine can semantic-search your codebase via pm_query_code.

MCP tools reference

16 tools, all prefixed pm_ to avoid collisions. Read tools support an expand_id arg to fetch one full row instead of a search-result preview — no separate _get tools needed.

Projects

pm_list_projectslist every project you own
pm_create_projectcreate or get-existing (idempotent on fingerprint/slug)
pm_update_projectpatch description / known_paths

Memory

pm_memory_createsave a new memory
pm_memory_updateedit an existing memory
pm_memory_verifybump last_verified_at (still-true marker)
pm_memory_deletesoft-delete a memory
pm_memory_restoreundo a soft-delete
pm_query_memorysemantic search; or expand_id to fetch full row

Tasks

pm_task_createopen a new task
pm_task_updatechange status, edit fields
pm_task_deletesoft-delete a task
pm_task_restoreundo a soft-delete
pm_query_taskfilter by status/priority/tag; or expand_id for full row

Code & context

pm_query_codesemantic search; or expand_id to fetch full chunk
pm_get_contextsession-start bundle of decisions + tasks + recent code

Privacy & security

  • Per-user isolation.Postgres Row-Level Security ensures no user can ever read another's rows, even via a bug in app code.
  • Token audience binding.Every OAuth token is scoped to this MCP server (RFC 8707). Tokens minted for another service can't be reused here.
  • Secret scrubber. Code chunks are stored raw, but the version sent to the embedding model has secrets redacted. OpenAI never sees your API keys.
  • Revocable in one click. /settings/oauth lists every authorized client. Revoke any of them and all access and refresh tokens for that client are invalidated immediately.

FAQ

Is it free?

For personal use during the v0.5 phase, yes. Rate limits will land in the next slice.

Can I self-host?

Yes — it's a Next.js app + Supabase project. Migrations live at supabase/migrations/. Bring your own Supabase, set the env vars, deploy to Vercel.

What happens if my MCP client doesn't support OAuth?

Fall back to long-lived pm_* tokens — generate one at /settings/tokens and put it in the Authorization: Bearer header.

Does it work with Claude Code, Cline, Continue, etc.?

Anything that speaks MCP Streamable HTTP works. The server is fully spec-compliant (MCP 2025-06-18).

Ready to give your agents memory?

Sign in, paste the mcp.json snippet, approve once. Done.

Get started

Portfolio piece

Built by Amar Gupta — AI / MCP / full-stack engineer. One of 7 dogfooded products in the portfolio.