From b767519aabdc243e6efcc4a9dd026cc802260920 Mon Sep 17 00:00:00 2001 From: nanameru <4869nanataitai@gmail.com> Date: Sat, 12 Sep 2026 15:32:32 +1000 Subject: [PATCH 1/5] =?UTF-8?q?Cloudflare=E3=83=87=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=A4=E7=94=A8=E3=83=AA=E3=82=BD=E3=83=BC=E3=82=B9=E3=82=92?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E3=81=99=E3=82=8B=20Refs=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test-board.yaml | 22 ++++++++++++++++++++++ wrangler.jsonc | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test-board.yaml diff --git a/test-board.yaml b/test-board.yaml new file mode 100644 index 0000000..d910d05 --- /dev/null +++ b/test-board.yaml @@ -0,0 +1,22 @@ +version: 1 +project: + name: "substack-mcp" + test_command: "npm run type-check" + repo: "nanameru/substack-mcp" + +source_roots: + - worker + - src + +cases: [] + - id: TC-001 + title: "Cloudflare Remote MCP本番デプロイ: OAuth保護されたMCPへ接続し読み取り専用で下書きを1件取得する" + feature: "Cloudflare Remote MCP本番デプロイ" + scenario: "OAuth保護されたMCPへ接続し読み取り専用で下書きを1件取得する" + status: doing + priority: high + type: e2e + source: [worker/index.ts, worker/oauth.ts, src/substack_mcp/cloud_api.py, wrangler.jsonc] + test_file: "" + issues: [6] + notes: "本番OAuth接続後、tools/listとlist_drafts(limit=1)のみを実行する。書き込み系ツールは呼ばない。" diff --git a/wrangler.jsonc b/wrangler.jsonc index a0ce727..79537c1 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -32,7 +32,7 @@ "kv_namespaces": [ { "binding": "OAUTH_KV", - "id": "REPLACE_WITH_OAUTH_KV_ID" + "id": "2804e83ca60f4b6487b038442fed4779" } ] } From dfd1504f820c6eb71601e5a3238a601e62042f12 Mon Sep 17 00:00:00 2001 From: nanameru <4869nanataitai@gmail.com> Date: Sat, 12 Sep 2026 15:34:25 +1000 Subject: [PATCH 2/5] =?UTF-8?q?OAuth=E7=94=A8MCP=E3=83=8F=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=83=A9=E3=83=BC=E3=82=92Worker=E5=BD=A2=E5=BC=8F?= =?UTF-8?q?=E3=81=A7=E3=83=A9=E3=83=83=E3=83=97=E3=81=99=E3=82=8B=20Refs?= =?UTF-8?q?=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- worker/index.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/worker/index.ts b/worker/index.ts index 6471de1..c5d346c 100644 --- a/worker/index.ts +++ b/worker/index.ts @@ -211,13 +211,18 @@ function createServer() { return server; } -const apiHandler = createMcpHandler(createServer); +const handleMcpRequest = createMcpHandler(createServer); +const apiHandler = { + fetch(request: Request, workerEnv: Env, ctx: ExecutionContext) { + return handleMcpRequest(request, workerEnv, ctx); + }, +} satisfies ExportedHandler; export default new OAuthProvider({ authorizeEndpoint: "/authorize", tokenEndpoint: "/oauth/token", clientRegistrationEndpoint: "/oauth/register", apiRoute: "/mcp", - apiHandler: apiHandler as any, + apiHandler, defaultHandler: authHandler, }); From 5717750bcbe5d0a0250b768323b77b923c3374fb Mon Sep 17 00:00:00 2001 From: nanameru <4869nanataitai@gmail.com> Date: Sat, 12 Sep 2026 17:50:55 +1000 Subject: [PATCH 3/5] =?UTF-8?q?GitHub=E8=AA=8D=E8=A8=BC=E3=81=B8=E3=81=AE?= =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=BC=E3=83=A0=E9=81=B7=E7=A7=BB=E3=82=92?= =?UTF-8?q?=E8=A8=B1=E5=8F=AF=E3=81=99=E3=82=8B=20Refs=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- worker/oauth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/oauth.ts b/worker/oauth.ts index ed3de0d..bd7fed7 100644 --- a/worker/oauth.ts +++ b/worker/oauth.ts @@ -92,7 +92,7 @@ async function authorizeGet(request: Request, env: OAuthEnv): Promise return new Response(html, { headers: { "Content-Type": "text/html; charset=utf-8", - "Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'", + "Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; form-action 'self' https://github.com/login/oauth/authorize; base-uri 'none'; frame-ancestors 'none'", "Referrer-Policy": "no-referrer", "X-Frame-Options": "DENY", "Set-Cookie": secureCookie(CSRF_COOKIE, csrf, 600), From c8c486bc1396a059c43ec21a88fd5e317bf74a87 Mon Sep 17 00:00:00 2001 From: nanameru <4869nanataitai@gmail.com> Date: Sat, 12 Sep 2026 19:41:58 +1000 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20GitHub=20OAuth=E3=81=AE=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E3=81=AA=E8=A8=BA=E6=96=AD=E6=83=85=E5=A0=B1=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20Refs=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- worker/oauth.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/worker/oauth.ts b/worker/oauth.ts index bd7fed7..b136fc9 100644 --- a/worker/oauth.ts +++ b/worker/oauth.ts @@ -161,8 +161,22 @@ async function callback(request: Request, env: OAuthEnv): Promise { }), }); if (!tokenResponse.ok) return jsonError("GitHub token exchange failed", 502); - const tokenData = (await tokenResponse.json()) as { access_token?: string }; - if (!tokenData.access_token) return jsonError("GitHub did not return an access token", 502); + const tokenData = (await tokenResponse.json()) as { + access_token?: string; + error?: string; + }; + if (!tokenData.access_token) { + // GitHub commonly returns HTTP 200 with a machine-readable OAuth error. + // Surface only that non-secret error code so credential/configuration issues + // can be distinguished without logging the authorization code or secrets. + const oauthError = tokenData.error?.replace(/[^a-z0-9_]/gi, "").slice(0, 80); + return jsonError( + oauthError + ? `GitHub token exchange failed: ${oauthError}` + : "GitHub did not return an access token", + 502, + ); + } const userResponse = await fetch("https://api.github.com/user", { headers: { From a13a77f3d4135ff71ec20e4c7797289ba2d82ee3 Mon Sep 17 00:00:00 2001 From: nanameru <4869nanataitai@gmail.com> Date: Sat, 12 Sep 2026 20:32:40 +1000 Subject: [PATCH 5/5] =?UTF-8?q?test:=20Remote=20MCP=E6=9C=AC=E7=95=AA?= =?UTF-8?q?=E7=96=8E=E9=80=9A=E3=82=92=E5=AE=8C=E4=BA=86=20Refs=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test-board.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test-board.yaml b/test-board.yaml index d910d05..a156ca0 100644 --- a/test-board.yaml +++ b/test-board.yaml @@ -8,15 +8,15 @@ source_roots: - worker - src -cases: [] +cases: - id: TC-001 title: "Cloudflare Remote MCP本番デプロイ: OAuth保護されたMCPへ接続し読み取り専用で下書きを1件取得する" feature: "Cloudflare Remote MCP本番デプロイ" scenario: "OAuth保護されたMCPへ接続し読み取り専用で下書きを1件取得する" - status: doing + status: passed priority: high type: e2e source: [worker/index.ts, worker/oauth.ts, src/substack_mcp/cloud_api.py, wrangler.jsonc] test_file: "" issues: [6] - notes: "本番OAuth接続後、tools/listとlist_drafts(limit=1)のみを実行する。書き込み系ツールは呼ばない。" + notes: "2026-09-12にChatGPTからOAuth接続し、11ツールの認識とlist_drafts(limit=1)の成功を確認。記事本文は表示せず、書き込み系ツールは未実行。"