Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/mcp/mcp-app.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</div>
</div>

<div id="legend">
<div id="legend" class="collapsed">
<div id="legend-toggle">
<span>Legend</span>
<svg class="legend-chevron" width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path d="M3 2l4 3-4 3" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
Expand Down
43 changes: 28 additions & 15 deletions apps/mcp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,17 @@ app.use(
"*",
cors({
origin: "*",
allowMethods: ["GET", "POST", "OPTIONS"],
allowHeaders: ["Content-Type", "Authorization", "x-sm-project"],
allowMethods: ["GET", "POST", "DELETE", "OPTIONS"],
allowHeaders: [
"Content-Type",
"Authorization",
"x-sm-project",
"Accept",
"Mcp-Session-Id",
"MCP-Protocol-Version",
"Last-Event-ID",
],
exposeHeaders: ["Mcp-Session-Id", "WWW-Authenticate"],
}),
)

Expand All @@ -50,10 +59,9 @@ app.get("/", (c) => {
// MCP clients use this to discover the authorization server
app.get("/.well-known/oauth-protected-resource", (c) => {
const apiUrl = c.env.API_URL || DEFAULT_API_URL
const resourceUrl =
c.env.API_URL === "http://localhost:8787"
? "http://localhost:8788"
: "https://mcp.supermemory.ai"
const host = c.req.header("x-forwarded-host") || c.req.header("host")
const proto = c.req.header("x-forwarded-proto") || "https"
const resourceUrl = host ? `${proto}://${host}` : "https://mcp.supermemory.ai"

return c.json({
resource: resourceUrl,
Expand Down Expand Up @@ -91,12 +99,13 @@ app.get("/.well-known/oauth-authorization-server", async (c) => {
}
})

const mcpHandler = SupermemoryMCP.mount("/mcp", {
const mcpHandler = SupermemoryMCP.serve("/mcp", {
binding: "MCP_SERVER",
corsOptions: {
origin: "*",
methods: "GET, POST, OPTIONS",
headers: "Content-Type, Authorization, x-sm-project",
methods: "GET, POST, DELETE, OPTIONS",
headers:
"Content-Type, Authorization, x-sm-project, Accept, Mcp-Session-Id, MCP-Protocol-Version, Last-Event-ID",
},
})

Expand All @@ -105,17 +114,20 @@ app.all("/mcp/*", async (c) => {
const token = authHeader?.replace(/^Bearer\s+/i, "")
const containerTag = c.req.header("x-sm-project")
const apiUrl = c.env.API_URL || DEFAULT_API_URL
const mcpURL =
c.env.API_URL === "http://localhost:8787"
? "http://localhost:8788"
: "https://mcp.supermemory.ai"

const reqHost = c.req.header("x-forwarded-host") || c.req.header("host") || ""
const reqProto = c.req.header("x-forwarded-proto") || "https"
const resourceMetadataUrl = reqHost
? `${reqProto}://${reqHost}/.well-known/oauth-protected-resource`
: "/.well-known/oauth-protected-resource"

if (!token) {
return new Response("Unauthorized", {
status: 401,
headers: {
"WWW-Authenticate": `Bearer resource_metadata="${mcpURL}/.well-known/oauth-protected-resource"`,
"WWW-Authenticate": `Bearer resource_metadata="${resourceMetadataUrl}"`,
"Access-Control-Expose-Headers": "WWW-Authenticate",
"Access-Control-Allow-Origin": "*",
},
})
}
Expand Down Expand Up @@ -153,8 +165,9 @@ app.all("/mcp/*", async (c) => {
status: 401,
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Bearer error="invalid_token", resource_metadata="${mcpURL}/.well-known/oauth-protected-resource"`,
"WWW-Authenticate": `Bearer error="invalid_token", resource_metadata="${resourceMetadataUrl}"`,
"Access-Control-Expose-Headers": "WWW-Authenticate",
"Access-Control-Allow-Origin": "*",
},
},
)
Expand Down
Loading