(request: Request)
| 53 | ] as const; |
| 54 | |
| 55 | const dumpHeaders = (request: Request): Record<string, string> => { |
| 56 | const out: Record<string, string> = {}; |
| 57 | for (const name of HEADERS_TO_DUMP) { |
| 58 | const value = request.headers.get(name); |
| 59 | if (value !== null) out[`mcp.http.header.${name}`] = value; |
| 60 | } |
| 61 | const authHeader = request.headers.get("authorization"); |
| 62 | if (authHeader) { |
| 63 | out["mcp.http.header.authorization.scheme"] = authHeader.split(" ", 1)[0] ?? ""; |
| 64 | out["mcp.http.header.authorization.length"] = String(authHeader.length); |
| 65 | } |
| 66 | // Record the full header name list too — surfaces anything unexpected |
| 67 | // without us having to enumerate every possibility up front. |
| 68 | out["mcp.http.header.names"] = Array.from(request.headers.keys()).sort().join(","); |
| 69 | return out; |
| 70 | }; |
| 71 | |
| 72 | // JSON-RPC shapes — narrow to just the fields we fingerprint. Using Schema |
| 73 | // collapses the typeof-guard pile and surfaces "what does an MCP client |
no test coverage detected