## Stack Context Single-auth story for the Claude Code supermemory plugin rework: the plugin's hooks and its MCP surface share one credential (`sm_` API key from the existing browser connect flow). That requires `mcp.supermemory.ai` to accept plain API keys, which it currently rejects (OAuth JWT only). ## What? - `validateApiKey()` in `server/auth`: `sm_`-prefixed Bearer tokens validate via the existing `fetchSession()` (`GET /v3/session`) and map to the same `AuthUser` shape as OAuth tokens (`userId` ← `user.id`, `organizationId` ← `org.id`, the key itself as `bearerToken` for downstream API calls). Successful lookups cached per isolate for 60s. - `handleMcpRequest` routes by token shape: `sm_` keys → session validation, everything else → OAuth JWT verification (unchanged). - `sessionInfoSchema` now types the `org.id` field the session endpoint already returns. ## Why? MCP clients that already hold an API key (Claude Code plugin hooks, CLI, scripts) can connect without an OAuth dance or a second consent. OAuth behavior is untouched — the existing "rejects opaque API keys" test on the OAuth validator still passes; keys just get their own path. Malformed keys are rejected without an API round-trip. Tests: 4 new cases (valid key → AuthUser, cache hit → single fetch, 401 → null, malformed → no request). `vitest run src/server/auth` 13/13, `tsc --noEmit` clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds a new authentication path on the MCP entrypoint with in-memory key caching (60s TTL), so revoked keys may remain valid briefly within an isolate; OAuth behavior is unchanged. > > **Overview** > MCP Bearer auth now accepts **`sm_` Supermemory API keys** in addition to OAuth JWTs, so clients that already hold an API key can connect without OAuth. > > **`validateApiKey`** treats keys matching `sm_` plus at least 17 non-space characters as API keys: it calls **`GET /v3/session`** with the key as Bearer, maps **`user.id`** and **`org.id`** into the same **`AuthUser`** shape as OAuth (key kept as **`bearerToken`** for downstream API calls), and caches successful results per isolate for **60s** (up to 1000 entries, full clear on overflow). Malformed keys are rejected locally with no HTTP call; session **401** yields unauthenticated. > > **`handleMcpRequest`** branches on token shape: API keys go through session validation; other tokens still use JWT verification unchanged. > > **`sessionInfoSchema`** now includes optional **`org.id`** typing for session responses used when resolving organization context from API keys. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e54fb11bf1598d07a807eb2b0b63a347aaa58fb6. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> |
||
|---|---|---|
| .. | ||
| e2e | ||
| scripts | ||
| src | ||
| .dev.vars.example | ||
| .gitignore | ||
| package.json | ||
| pnpm-lock.yaml | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.widget.json | ||
| vite.config.dev.ts | ||
| vite.config.ts | ||
| vitest.config.ts | ||
| wrangler.jsonc | ||
Supermemory MCP Server
The Supermemory MCP server gives authenticated AI clients access to a user's memories, profile, spaces, and interactive MCP Apps.
Runtime Model
- MCP SDK v2 with a fresh
McpServerfor every HTTP request - Modern MCP
2026-07-28plus stateless compatibility for 2025 clients - OAuth token validation on every request
- No MCP protocol session or protocol Durable Object
- Active space stored as application state in a dedicated Durable Object
- Space state keyed by authenticated
organizationId + userId
The space used by an operation resolves in this order:
- An explicit
containerTagtool or prompt argument - The account's durable active space
- The Supermemory client default,
sm_project_default
An explicit override applies only to that call. It does not mutate the active space.
Server URL
https://mcp.supermemory.ai/mcp
Example client configuration:
{
"mcpServers": {
"supermemory": {
"url": "https://mcp.supermemory.ai/mcp"
}
}
}
The client discovers the OAuth authorization server through
/.well-known/oauth-protected-resource/mcp.
Tools
Model-visible tools
| Tool | Purpose |
|---|---|
search_memory |
Search memories and optionally include profile context |
listDocuments |
List document metadata and summaries in a space |
getDocument |
Read one document's available content by ID |
listMemories |
List extracted memory entries and their source document IDs |
listSpaces |
List spaces visible to the authenticated account |
whoAmI |
Return identity, access, and active-space context |
add_memory |
Save or forget a memory |
MCP App launchers
| Tool | Purpose |
|---|---|
select-space |
Open the interactive space picker |
memory-graph |
Open the interactive memory graph |
guided-save |
Open the guided memory form |
upload-file |
Open the file upload form |
App-only tools
These tools are available to the embedded MCP App and hidden from the model.
| Tool | Purpose |
|---|---|
set-active-tag |
Persist the selected active space |
save-memory |
Submit the guided save form |
prepare-file-upload |
Prepare a secure direct file upload |
fetch-graph-data |
Fetch graph documents for the app |
Resources And Prompt
| Kind | Name or URI | Purpose |
|---|---|---|
| Resource | supermemory://profile |
Profile facts in the effective space |
| Resource | supermemory://spaces |
Visible spaces |
| Resource | ui://supermemory/app-<sha256>.html |
Embedded MCP App bundle |
| Prompt | context |
Profile and recent context for an optional space |
The App resource and tool metadata include both current nested ui metadata and
the legacy flat resource URI key while MCP Apps completes its SDK v2 migration.
The Worker runtime does not import the SDK v1 Apps server helpers.
Development
Install from the repository root:
bun install
Run the local Worker:
cd apps/mcp
bun run dev
The portless URL is http://mcp.dev.supermemory.
Useful commands:
bun run build
bun run check-types
bun run test:unit
bun run test:e2e
Authenticated end-to-end tests use credentials captured by:
bun e2e/capture-oauth-token.ts
Without stored OAuth credentials, authenticated test groups skip. Public OAuth discovery and rejection tests still run.
Configuration
| Variable | Purpose | Default |
|---|---|---|
API_URL |
Supermemory API and OAuth issuer | https://api.supermemory.ai |
MCP_RESOURCE |
Expected OAuth audience | https://mcp.supermemory.ai/mcp |
ALLOWED_MCP_ORIGIN_HOSTNAMES |
Additional comma-separated browser origins | Built-in host allowlist |
POSTHOG_API_KEY |
Server-side MCP tool analytics project key | Disabled |
POSTHOG_HOST |
PostHog ingestion host | https://us.i.posthog.com |
Storage And Rollout
SpaceState stores only the active space's container tag. It never stores bearer
tokens, MCP client identity, or protocol messages.
The old SupermemoryMCP class and binding remain inert for one rollout. This
keeps the migration non-destructive and rollback-safe. A later deployment can
delete the old protocol class after production traffic and rollback windows
have been checked.