## Summary
Fixes MCP OAuth discovery so the client-server handshake actually validates against the **MCP 2025-06-18 authorization spec** (which adopts RFC 9728 Protected Resource Metadata + RFC 8707 Resource Indicators).
Previously, a client connecting to `https://mcp.dev.supermemory.ai/mcp` would receive `resource: "https://mcp.supermemory.ai"` (bare host, prod fallback) and reject the connection:
> Protected resource https://mcp.supermemory.ai does not match expected https://mcp.dev.supermemory.ai/mcp (or origin)
## Changes
- **`resource` now includes the `/mcp` endpoint path** — the spec wants the canonical MCP server URI, and the bundled `@modelcontextprotocol/sdk` reference implementation emits the same shape (`new URL(rsPath, base).href`). Bare-host worked with lenient clients that fell back to origin-matching; strict clients rejected it.
- **Path-suffixed metadata route** added at `/.well-known/oauth-protected-resource/mcp` alongside the bare path. The SDK's `metadataHandler` mounts under the resource path, so this matches what spec-strict clients probe first.
- **`WWW-Authenticate`'s `resource_metadata` URL** points to the canonical full URL (`https://host/.well-known/oauth-protected-resource/mcp`).
- **Centralized base-URL derivation** in a new `mcpBaseUrl()` helper, with priority:
1. `MCP_URL` env var — set by portless dev script so dev requests resolve to the tunneled host, not whatever the local proxy sticks in `Host`
2. `x-forwarded-host` / `host` request headers
3. `https://mcp.supermemory.ai` last-resort fallback (only hit when the worker can't see the inbound host at all)
## Production impact
`MCP_URL` is dev-only (not in `wrangler.jsonc` vars), so prod falls through to the `Host` header → `https://mcp.supermemory.ai/mcp`. The wire change in prod is that `resource` now ends with `/mcp` instead of being bare — spec-correct, what strict clients require, and tolerated by lenient ones.
## Contributor DX
Added `apps/mcp/.dev.vars.example` documenting `API_URL`, `MCP_URL`, and `POSTHOG_API_KEY` for contributors running plain `wrangler dev` without portless.
## Test plan
- [x] `curl https://mcp.dev.supermemory.ai/.well-known/oauth-protected-resource` returns `resource: https://mcp.dev.supermemory.ai/mcp`
- [x] `curl https://mcp.dev.supermemory.ai/.well-known/oauth-protected-resource/mcp` returns the same payload
- [x] 401 from `/mcp` carries `WWW-Authenticate: Bearer resource_metadata="…/oauth-protected-resource/mcp"`
- [x] MCP client (vscode extension) connects successfully — previously failed with the resource-mismatch error
- [ ] Verify in prod that bare-host clients continue to work after deploy
## Summary
- Fixed memory graph stuck on "Loading graph data..." caused by field name mismatch after package rewrite (`memoryEntries` vs `memories`, `type` vs `documentType`)
- Improved MCP app UI to match console-v2 design: golden derives edges (#FBBF24), edge glow pass, node hover effects, dot mode at low zoom, vertical controls with keyboard shortcuts, expandable legend
- Synced local `memory-graph` edgeDerives constant with published npm version
## Test plan
- [ ] Run `cd apps/mcp && bun run dev`, connect via Claude Desktop
- [ ] Verify graph renders with golden derives edges and blue dashed extends edges
- [ ] Verify node hover/selection glow effects
- [ ] Verify Fit (Z), Center (C), zoom (+/-) keyboard shortcuts
- [ ] Verify legend expands/collapses
### TL;DR
Enhanced the `forgetMemory` method to try exact content matching first, then fall back to semantic search with a high similarity threshold for more precise memory deletion.
### What changed?
The `forgetMemory` method now uses a two-step approach: first attempting exact content matching via the API, and if that fails with a 404, falling back to semantic search with a similarity threshold of 0.85. The search method also accepts an optional threshold parameter. Error messages now distinguish between exact matches and semantic matches, including similarity scores in the response.
### How to test?
1. Call `forgetMemory` with the exact content of an existing memory to verify direct deletion
2. Call `forgetMemory` with similar but not identical content to test the semantic search fallback
3. Call `forgetMemory` with completely unrelated content to verify the "no matching memory found" response
4. Verify that success messages indicate whether deletion used exact matching or semantic matching with similarity scores
### Why make this change?
This approach provides more precise memory deletion by prioritizing exact matches while still offering a fallback for similar content. The high similarity threshold (0.85) ensures that only very similar memories are deleted when exact matches aren't found, reducing the risk of accidentally deleting unrelated memories.
### fix(mcp): prevent LLM from overriding x-sm-project container tag
- When `x-sm-project` header is configured, the `containerTag` field is now
excluded from memory/recall/context tool schemas
- This prevents LLMs from overriding the configured project by picking a
different containerTag from the available projects list
- When no header is set, behavior is unchanged — containerTag remains visible
in schemas for manual project selection via listProjects
### TL;DR
TESTING REMAINING. This is my hypothesis. @MaheshtheDev please carry on from here or we can test in prod.
Added a proxy endpoint for OAuth authorization server metadata to support non-compliant MCP clients.
### What changed?
Added a new endpoint `/.well-known/oauth-authorization-server` to the MCP server that proxies requests to the main API. This endpoint fetches the authorization server metadata from the API and returns it to clients.
### How to test?
1. Make a GET request to `/.well-known/oauth-authorization-server` on the MCP server
2. Verify that it returns the same metadata as the main API's `/.well-known/oauth-authorization-server` endpoint
3. Test with a client that expects to find the authorization server metadata on the MCP domain
### Why make this change?
Some MCP clients don't correctly follow the OAuth specification. Instead of using the `authorization_servers` array provided in the protected resource metadata, they look for the authorization server metadata directly on the MCP server domain. This proxy endpoint ensures compatibility with these non-compliant clients without requiring them to be updated.