mirror of
https://github.com/HeyPuter/puter.git
synced 2026-07-08 08:12:15 +00:00
fix mcp server cloudfront cache bug
This commit is contained in:
@@ -145,7 +145,10 @@ function formatPuterError(err) {
|
||||
function jsonResponse(body) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
// Per-user MCP results must never be cached by any CDN in front of the
|
||||
// worker. (POST isn't cached by default, but be explicit — a misconfigured
|
||||
// edge cache that ignores method/query could otherwise leak responses.)
|
||||
headers: { 'content-type': 'application/json', 'Cache-Control': 'no-store' },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -166,6 +169,7 @@ async function mcpPost(event) {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Cache-Control': 'no-store',
|
||||
'WWW-Authenticate': `Bearer resource_metadata="${origin}/.well-known/oauth-protected-resource"`,
|
||||
},
|
||||
},
|
||||
@@ -193,9 +197,12 @@ async function mcpPost(event) {
|
||||
return jsonResponse(response);
|
||||
}
|
||||
|
||||
// Discovery / health.
|
||||
// Discovery / health. This is the ONLY endpoint safe to cache: it's public,
|
||||
// identical for every caller, and hammered by clients polling for the tool list.
|
||||
// It's explicitly marked cacheable so a "respect-origin" CDN policy caches this
|
||||
// and nothing else (every other response sends no-store).
|
||||
function mcpInfo() {
|
||||
return {
|
||||
const body = {
|
||||
name: 'puter-mcp',
|
||||
description:
|
||||
'MCP server for Puter filesystem, static website hosting, serverless worker, and app registration operations. POST JSON-RPC to ' +
|
||||
@@ -203,6 +210,14 @@ function mcpInfo() {
|
||||
transport: 'streamable-http',
|
||||
tools: listTools().map((t) => t.name),
|
||||
};
|
||||
return new Response(JSON.stringify(body), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Cache-Control': 'public, max-age=300',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** Attach the MCP routes to the (already-initialized) router. */
|
||||
|
||||
@@ -87,17 +87,27 @@ async function sha256b64url(str) {
|
||||
|
||||
// ---- response helpers ------------------------------------------------------
|
||||
|
||||
// Every OAuth response is per-request (sealed flow/code blobs, one-time auth
|
||||
// codes, tokens) and MUST NOT be cached. Without this, a caching layer in front
|
||||
// of the worker (e.g. the puter.com zone) can replay one user's /authorize
|
||||
// redirect — and thus their stale callback port / code — to everyone.
|
||||
// RFC 6749 §5.1 also mandates no-store on the token endpoint.
|
||||
const NO_STORE = {
|
||||
'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0',
|
||||
Pragma: 'no-cache',
|
||||
};
|
||||
|
||||
function json(status, obj) {
|
||||
return new Response(JSON.stringify(obj), {
|
||||
status,
|
||||
headers: { 'content-type': 'application/json', 'Access-Control-Allow-Origin': '*' },
|
||||
headers: { 'content-type': 'application/json', 'Access-Control-Allow-Origin': '*', ...NO_STORE },
|
||||
});
|
||||
}
|
||||
|
||||
function redirect(location) {
|
||||
return new Response(null, {
|
||||
status: 302,
|
||||
headers: { Location: location, 'Access-Control-Allow-Origin': '*' },
|
||||
headers: { Location: location, 'Access-Control-Allow-Origin': '*', ...NO_STORE },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user