From 55705387a4a365e12e2be14050a096f2eb41dea1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Feb 2026 14:08:41 +0000 Subject: [PATCH 1/3] Add favicon serving to satisfy MCP Directory Server Logo URL requirement Serves the project icon at /favicon.ico (multi-size ICO) and /favicon.svg so Google's favicon service can discover it for the MCP Directory listing. https://claude.ai/code/session_01TF2N6ru2CZX9Uy4xdfBKgf --- src/icon.ts | 18 ++++++++++++++++++ src/index.ts | 16 ++++++++++++++++ src/main.ts | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 src/icon.ts diff --git a/src/icon.ts b/src/icon.ts new file mode 100644 index 0000000..5c656ab --- /dev/null +++ b/src/icon.ts @@ -0,0 +1,18 @@ +// Server icon assets (generated from project logo SVG) + +export const ICON_SVG = ` + + + + + + + + + + +`; + +// ICO file containing 16x16, 32x32, and 64x64 PNG images +export const ICON_ICO_BASE64 = + "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"; diff --git a/src/index.ts b/src/index.ts index 8d08334..3ae4ee6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import { handleToken, resolveGitHubToken, } from "./auth.js"; +import { ICON_SVG, ICON_ICO_BASE64 } from "./icon.js"; // Type for Cloudflare Worker environment interface Env { @@ -53,6 +54,21 @@ export default { return handleToken(request); } + // Favicon (ICO) + if (url.pathname === "/favicon.ico") { + const bytes = Uint8Array.from(atob(ICON_ICO_BASE64), (c) => c.charCodeAt(0)); + return new Response(bytes, { + headers: { "Content-Type": "image/x-icon", "Cache-Control": "public, max-age=86400" }, + }); + } + + // Favicon (SVG) + if (url.pathname === "/favicon.svg") { + return new Response(ICON_SVG, { + headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=86400" }, + }); + } + // MCP endpoint if (url.pathname === "/mcp" || url.pathname === "/mcp/") { // Resolve PAT: Bearer token (user's PAT) → fallback to server's GITHUB_PAT diff --git a/src/main.ts b/src/main.ts index cff898f..e361733 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,7 @@ import { createServer } from "./server.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from "node:http"; +import { ICON_SVG, ICON_ICO_BASE64 } from "./icon.js"; // Parse CLI args const args = process.argv.slice(2); @@ -45,6 +46,21 @@ async function runHttp() { return; } + // Favicon (ICO) + if (url.pathname === "/favicon.ico") { + const buf = Buffer.from(ICON_ICO_BASE64, "base64"); + res.writeHead(200, { "Content-Type": "image/x-icon", "Cache-Control": "public, max-age=86400" }); + res.end(buf); + return; + } + + // Favicon (SVG) + if (url.pathname === "/favicon.svg") { + res.writeHead(200, { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=86400" }); + res.end(ICON_SVG); + return; + } + if (url.pathname === "/mcp" || url.pathname === "/mcp/") { setCorsHeaders(res); From a7178b188402ddba678140f392d6584278ca44c8 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Feb 2026 14:10:15 +0000 Subject: [PATCH 2/3] Update package-lock.json from npm install https://claude.ai/code/session_01TF2N6ru2CZX9Uy4xdfBKgf --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 8775fc6..4e06f60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.25.2", - "agents": "^0.3.10", + "agents": "0.3.10", "zod": "^3.23.0" }, "bin": { From 6dfbfe075caefde15dea42e98a3c60a5b90c3246 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Feb 2026 14:12:55 +0000 Subject: [PATCH 3/3] Serve favicons from static files instead of inline base64 - Add public/favicon.ico and public/favicon.svg as actual files - Cloudflare Worker: use [assets] in wrangler.toml for automatic static serving - Node.js server: read favicon files from disk via fs.readFileSync - Remove src/icon.ts (base64 blob no longer needed) https://claude.ai/code/session_01TF2N6ru2CZX9Uy4xdfBKgf --- public/favicon.ico | Bin 0 -> 2442 bytes public/favicon.svg | 12 ++++++++++++ src/icon.ts | 18 ------------------ src/index.ts | 16 ---------------- src/main.ts | 12 +++++++++--- wrangler.toml | 3 +++ 6 files changed, 24 insertions(+), 37 deletions(-) create mode 100644 public/favicon.ico create mode 100644 public/favicon.svg delete mode 100644 src/icon.ts diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04a123d7e95ba99d15f4fd05ded7e76abdaaf0d GIT binary patch literal 2442 zcmaKsdpOkF8pnS>#u$cjEoYK`a=(R5gH22&Mv;3VGO46ox7x1N4279cba9WNLYq>Q zjtquoYS4CRM~2C`OfH$+%V7AOIeVXT{@Tx3&-1SL`L6eU-ao$Uvlak=fH)v02Z%BR zgn|Ho1poko{?cE>0H9QKhQs}(5fT89iU0tL+fheZX^ga}Rn`e_?;*;f34k05DcW}} z!KXw?Dhls=5dhGN{|*o+C{hv4*y&`y-z%=@G(ogRl;u`N<>joI2D(4)9Cs7iT{Zln zSayt42$tvPQnmScX@Q2MBu6*CIU9*0-#-I&u`QdHu7QQulPG;~4=c`c7XwK-<=IKv zGxBvBCU!m*hxcB}90`K3cp1&KPo#l|?_q;ak*mg9HEV%hC+AwiH#=Z#yaAlfn%T_F za$jq?^t~L`%U>Okohtlk3I51N!)Qt;X*FiGYO|(s5hn5$VK{v87>S9ChW0`)^N`NP z--%yUuY*vbM(zf@>p34L7IMCz#3u|9Rm`s`^HU5s)M8F(Tu}|iU|GRg!E!rzPrP^3 zCpS4Y;&@ud7^dzKycfP>Y?#-GYeV1GkYG0LFVD`p@7iWA4m`XX1;nrDHM8q$q2?Et4 z_{+S}Y`L?fx2rJN<^oCjtLRFS6tu-}kpz?AMG{G%lM2dQH3^0enU-WRhzC7GixwfP zEKGqV4(~hx-}Obqc8Tk&EtHgc0TD5}f1FpwVp}C{wj`|g!s!-s8?RnmRPP2)Zk~c8?GhH?k0~>- ztaG&+&%9|7cHFbNU>D4UVfoHYcx%A&cuV;?wHugl@jCcj_sLD-N_!Oymi9ihg0#$F z_(AR*JU2jGZYjHgP3_jm5eizS2Z<&(9ikBlc$WTSm|HtThu_uM3cK}nHM+nf$HEa6 z6Ne1?H@4sNqW4h8Pe|7*eFmZGZ=M;YYG;rv!>oL$juJ&j(zXChE7nh0Ojgddog)GE zbZ`ebJ(-tb6Q#trA?=gKwPuEyn!0D@2Ojp@y}XQO-bd|Qa#IDJt~XdJmJ;zw@$4SP z2eo3^fPEY8JY2H`(+VYWg34ky#<>^E#?~E_z{iianP%w#w`I3`^V|OIwP2N^Yi!{^w+`am*xr<(vhVr zTMyzW$$M-aU#ZTb)TG?qVkx56Yq;0i5URrkCy%MB@!bHR*EMzQy0-;O#O?os949K{ z{)GIu^S=y>#NR=VsQ(M{FDC-Rl)ROiuY^y|a@ez+MhPSA6X*hN(3bE58-69k337jh zlGY8m&Ikz#3c4)6pwsIRB1Wt1{d%yK(UXgLAcfZd_(8IVU=%79B_nZC}ljsI~I#Io=(^4QI0b za{0_gjo;zWW-7}0a(GaBTXFW~pE16Adp# z<4*0}^2WEFr%?fNT{nn|Tq!3=KU*zz98H_{P3J%AG<&A^ysz%_Y^GFRQ9(Wbs0$n%b~8y~ zr2Sm+wa%9JzM3sZ1Cqao2Q+7gHP!9xy6Nioqvn0ro2A6Sd&Z=4tCPAd`#8BZC3&}?VJ<70&$4{^d$ygq zSd?&V_m-Qy?dl7&HXr-BemxO${f;&zHjK`EPG3_myPDk_nMs?bQQ$%;qoEb++Ry#$ zZ+btV6wI@MpDcei=j-VY^;pdM0UVVk`x4ea8WOjS&_`cglp#h3F@E(QwvPHenoqr^ zMTj6r6eksBoxmRFsmXyKth(3{$-e722tlwl1Z|eS70E6uP;E7}Re1kYrk)+zan^~B zZ@9Hz2TwDTd};A?&k->Pj`@$93|g2%E!D)-@xZDD zo8Qvuky(;;)E*P3utK^bVmql#fJRhRol(qAxlmrSH(kr4w*BtT3|HX^UFA%jhl=`U zO82<20qq$ovfWeZf54Bmyu5$$B;P2 + + + + + + + + + + + diff --git a/src/icon.ts b/src/icon.ts deleted file mode 100644 index 5c656ab..0000000 --- a/src/icon.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Server icon assets (generated from project logo SVG) - -export const ICON_SVG = ` - - - - - - - - - - -`; - -// ICO file containing 16x16, 32x32, and 64x64 PNG images -export const ICON_ICO_BASE64 = - "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"; diff --git a/src/index.ts b/src/index.ts index 3ae4ee6..8d08334 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,6 @@ import { handleToken, resolveGitHubToken, } from "./auth.js"; -import { ICON_SVG, ICON_ICO_BASE64 } from "./icon.js"; // Type for Cloudflare Worker environment interface Env { @@ -54,21 +53,6 @@ export default { return handleToken(request); } - // Favicon (ICO) - if (url.pathname === "/favicon.ico") { - const bytes = Uint8Array.from(atob(ICON_ICO_BASE64), (c) => c.charCodeAt(0)); - return new Response(bytes, { - headers: { "Content-Type": "image/x-icon", "Cache-Control": "public, max-age=86400" }, - }); - } - - // Favicon (SVG) - if (url.pathname === "/favicon.svg") { - return new Response(ICON_SVG, { - headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=86400" }, - }); - } - // MCP endpoint if (url.pathname === "/mcp" || url.pathname === "/mcp/") { // Resolve PAT: Bearer token (user's PAT) → fallback to server's GITHUB_PAT diff --git a/src/main.ts b/src/main.ts index e361733..d1ec179 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,12 @@ import { createServer } from "./server.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { createServer as createHttpServer, type IncomingMessage, type ServerResponse } from "node:http"; -import { ICON_SVG, ICON_ICO_BASE64 } from "./icon.js"; +import { readFileSync } from "node:fs"; +import { resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const publicDir = resolve(__dirname, "..", "public"); // Parse CLI args const args = process.argv.slice(2); @@ -48,7 +53,7 @@ async function runHttp() { // Favicon (ICO) if (url.pathname === "/favicon.ico") { - const buf = Buffer.from(ICON_ICO_BASE64, "base64"); + const buf = readFileSync(resolve(publicDir, "favicon.ico")); res.writeHead(200, { "Content-Type": "image/x-icon", "Cache-Control": "public, max-age=86400" }); res.end(buf); return; @@ -56,8 +61,9 @@ async function runHttp() { // Favicon (SVG) if (url.pathname === "/favicon.svg") { + const svg = readFileSync(resolve(publicDir, "favicon.svg"), "utf-8"); res.writeHead(200, { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=86400" }); - res.end(ICON_SVG); + res.end(svg); return; } diff --git a/wrangler.toml b/wrangler.toml index 44939ad..14346e4 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -4,6 +4,9 @@ main = "src/index.ts" compatibility_date = "2025-01-29" compatibility_flags = ["nodejs_compat"] +[assets] +directory = "./public" + # Your default GitHub PAT is stored as a secret (never in code) # Run: npx wrangler secret put GITHUB_PAT # Then paste your fine-grained token