## What
Makes the MCP `recall` tool render memories the same way the console **playground** does — rich, scored, relation-aware output — instead of the old flat `### Memory N (NN% match)` list.
The playground pattern is: **profile + rich search → one shared `formatMemories` formatter → feed to the model.** This ports that into the standalone MCP server.
## Changes
- **`format.ts`** (new) — `formatMemories`, lifted verbatim from the playground. Pure, dependency-free. Renders similarity scores, `agg`/`chunk` markers, related-memory arrows (`←` parent, `→` child, `~` related), attached document summaries, and temporal context.
- **`client.ts`** — `SupermemoryClient.search()` now accepts the playground's retrieval knobs (`searchMode` / `rerank` / `rewriteQuery` / `include`) and **stops discarding** the rich response fields (`context`, `documents`, `metadata`, `isAggregated`) during normalization, so the formatter has data to render.
- **`server.ts` (`handleRecall`)** — retrieves memories via `client.search()` with `include: { documents, relatedMemories }`, prepends the user's profile (stable + recent facts) when `includeProfile` is set, and renders memories through `formatMemories`. Output capped at `MAX_RECALL_CHARS`.
## How it maps to the playground
| | Playground | MCP (this PR) |
|---|---|---|
| Profile | injected into its own system prompt (`<user_profile>`) | prepended to `recall` output / exposed via `context` prompt |
| Search | hook pre-fetch **or** tool | `recall` tool (model-triggered) |
| Formatting | `formatMemories` → system prompt | `formatMemories` → `recall` tool result |
## Testing
Verified end-to-end against a local API + local MCP, driven through a real MCP client (and Claude Desktop). `recall` now returns scored memory blocks with `Source:`/`Document:` lines and the legend header. Existing e2e assertions remain compatible (they match `## User Profile` / `## Relevant Memories`, both still emitted).
## Notes
- One deliberate gap vs the playground: `aggregate` — the public SDK's `search.memories` doesn't expose it, so no `agg` synthesis blocks. Relation arrows render only when memories actually have linked parent/child versions.
- Possible follow-up: expose the `include` / `rerank` knobs as `recall` tool params so callers can toggle relations/documents per call.
- Pre-existing `tsc` errors in `server.ts` (dual `@modelcontextprotocol/sdk` install) and `mcp-app.ts` (DOM `lib`) are unrelated to this change — confirmed by an unchanged baseline.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---
**Session Details**
- Session: [View Session](https://supermemory.us1.vorflux.com/agent-sessions/c616fc88-a725-4961-9011-712bce740601)
- Requested by: Sreeram Sreedhar (sreeram@supermemory.com)
- Address comments on this PR. Add `(aside)` to your comment to have me ignore it.
|
||
|---|---|---|
| .. | ||
| e2e | ||
| src | ||
| .dev.vars.example | ||
| .gitignore | ||
| mcp-app.html | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
| vitest.config.ts | ||
| wrangler.jsonc | ||
Supermemory MCP Server 4.0
A standalone MCP (Model Context Protocol) server for Supermemory that gives AI assistants persistent memory across conversations. Built on Cloudflare Workers with Durable Objects for scalable, persistent connections.
Features
- Authentication - Supports both API keys and OAuth authentication
- Persistent Memory - Save and recall information across sessions
- User Profiles - Auto-generated profiles from stored memories
- Project Scoping - Organize memories by project with
x-sm-projectheader - Analytics - PostHog integration for usage tracking
Setup
Quick Install (Recommended)
npx -y install-mcp@latest https://mcp.supermemory.ai/mcp --client claude --oauth=yes
Replace claude with your MCP client: claude, cursor, windsurf, etc.
Manual Configuration
Add to your MCP client config (Claude Desktop, Cursor, Windsurf, etc.):
{
"mcpServers": {
"supermemory": {
"url": "https://mcp.supermemory.ai/mcp"
}
}
}
The server uses OAuth authentication by default. Your MCP client will automatically discover the authorization server via /.well-known/oauth-protected-resource and prompt you to authenticate.
API Key Authentication (Alternative)
If you prefer to use an API key instead of OAuth, you can pass it directly in the Authorization header. Get your API key from app.supermemory.ai:
{
"mcpServers": {
"supermemory": {
"url": "https://mcp.supermemory.ai/mcp",
"headers": {
"Authorization": "Bearer sm_your_api_key_here"
}
}
}
}
API keys start with sm_ and are automatically detected. When an API key is provided, OAuth authentication is skipped.
Project Scoping (Optional)
To scope all operations to a specific project, add the x-sm-project header:
{
"mcpServers": {
"supermemory": {
"url": "https://mcp.supermemory.ai/mcp",
"headers": {
"x-sm-project": "your-project-id"
}
}
}
}
Tools
memory
Save or forget information about the user.
{
"content": "User prefers dark mode and uses TypeScript",
"action": "save",
"containerTag": "optional-project-tag"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
content |
string | Yes | The memory content to save or forget |
action |
"save" | "forget" |
No | Default: "save" |
containerTag |
string | No | Project tag to scope the memory |
recall
Search memories and get user profile.
{
"query": "What are the user's programming preferences?",
"includeProfile": true,
"containerTag": "optional-project-tag"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | Yes | Search query to find relevant memories |
includeProfile |
boolean | No | Include user profile summary. Default: true |
containerTag |
string | No | Project tag to scope the search |
whoAmI
Get the current logged-in user's information.
{}
Returns: { userId, email, name, client, sessionId }
Resources
| URI | Description |
|---|---|
supermemory://profile |
User profile with stable preferences and recent activity |
supermemory://projects |
List of available memory projects |
Prompts
| Name | Description |
|---|---|
context |
User profile and preferences for system context injection |
Development
Prerequisites
- Bun or Node.js
- Wrangler CLI
Install Dependencies
bun install
Environment Variables
Create a .dev.vars file:
API_URL=http://localhost:8787
or
API_URL=https://api.supermemory.ai
| Variable | Description | Default |
|---|---|---|
API_URL |
Main Supermemory API URL for OAuth validation | https://api.supermemory.ai |
Run Locally
bun run dev
The server will start at http://localhost:8788.
Note: For local development, you also need the main Supermemory API running at the API_URL for OAuth token validation.
End-to-End Tests
The e2e/ suite drives a real MCP server over streamable HTTP (no mocks) and asserts the
core journey: handshake → tool/resource/prompt discovery → whoAmI → listProjects →
memory save → recall round-trip, plus memory-graph/fetch-graph-data, resource reads,
the context prompt, container-tag isolation, and auth rejections.
export SUPERMEMORY_API_KEY=sm_... # staging key (required; tests skip without it)
export SUPERMEMORY_MCP_URL=https://mcp.supermemory.ai/mcp # optional, this is the default
export SUPERMEMORY_API_URL=https://api.supermemory.ai # optional, OAuth authorization server
bun run test:e2e
| File | Covers |
|---|---|
e2e/auth.test.ts |
GET / info, OAuth discovery, 401 on missing/invalid token (runs without a key) |
e2e/oauth.test.ts |
OAuth discovery chain, dynamic client registration, token-endpoint negatives, real refresh→access token round-trip |
e2e/discovery.test.ts |
handshake, tools/resources/prompts listing, whoAmI, listProjects |
e2e/memory.test.ts |
save→recall round-trip, profile variants, forget, container scoping, bad args |
e2e/root-scope.test.ts |
x-sm-project header strips the containerTag param and scopes the whole connection |
e2e/graph.test.ts |
memory-graph, fetch-graph-data, resource reads, context prompt |
OAuth flow tests
mcp.supermemory.ai is an OAuth resource server; the authorization server is the main
API (api.supermemory.ai, better-auth). oauth.test.ts covers the real flow in tiers:
- A–C (no secrets) — discovery chain, dynamic client registration, and token/authorize negatives. These exercise the protocol wiring with no key and no browser, so they always run.
- D (real token) — exchanges a seeded
refresh_tokenfor anaccess_tokenand connects to/mcpwith it, exercising the OAuth-token validation path (not thesm_API-key path). It skips unless both env vars below are set.
# One-time capture (opens a browser for login + consent, prints the env vars):
bun e2e/capture-oauth-token.ts
export SUPERMEMORY_MCP_CLIENT_ID=...
export SUPERMEMORY_MCP_REFRESH_TOKEN=...
Notes:
- Tests skip (not fail) without
SUPERMEMORY_API_KEY; Tier D OAuth tests skip without the refresh-token env vars — so CI is safe without secrets. recallis eventually-consistent (save → ingestion pipeline → memories), so the round-trip polls up to ~90s.forgetremoval is slower still and is asserted as best-effort.- The suite uses unique per-run markers and forgets them in teardown to avoid polluting the account.
Deploy
bun run deploy
Architecture
┌─────────────────┐ OAuth/API Key ┌──────────────────┐
│ MCP Client │◄──────────────►│ Supermemory API │
│ (Claude, Cursor)│ │ (api.supermemory.ai)
└────────┬────────┘ └──────────────────┘
│ ▲
│ MCP Protocol │ Auth Validation
▼ │
┌─────────────────────────────────────────────────────┐
│ Supermemory MCP Server │
│ (mcp.supermemory.ai/mcp) │
│ ┌─────────────────────────────────────────────┐ │
│ │ Cloudflare Durable Object │ │
│ │ • Session state │ │
│ │ • Client info persistence │ │
│ │ • MCP protocol handling │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Tech Stack
- Runtime: Cloudflare Workers
- State: Durable Objects with SQLite
- Framework: Hono
- MCP SDK: @modelcontextprotocol/sdk + agents
- API Client: supermemory SDK
- Analytics: PostHog