TL;DR#
回帰テストは大事だよね
経緯#
巷で話題のFastAPI-MCPというものを使ってみようとしてとりあえず作ってみたらいい感じに出来たのでインターネット経由で使えるようにしようとした(公開用ではなく個人用)
https://qiita.com/takuya77088/items/4db3bcaedd8ad721b077
インターネット経由なので認証が必要だよなというのでとりあえずBasic認証をかけようと思ったが自分が使っているclineでBasic認証は使えるんだろうかと思い、ドキュメントを見てみると以下のような記述を見つけた。
https://docs.cline.bot/mcp-servers/configuring-mcp-servers#sse-transport
{
"mcpServers": {
"remote-server": {
"url": "https://your-server-url.com/mcp",
"headers": {
"Authorization": "Bearer your-token"
},
"alwaysAllow": ["tool3"],
"disabled": false
}
}
}
おお、Basic認証もいけそうじゃんということでcline_mcp_settings.json
を
{
"mcpServers": {
"mcp-server": {
"disabled": false,
"url": "https://example.com/mcp",
"headers": {
"Authorization": "Basic <base64>"
}
}
}
}
上みたいな感じ(イメージ)に編集しさあ早速使ってみようとやってみると

…え? いやいやちゃんと設定したよね? と確認してみるも設定に異常はなさそうだ。
そこでサーバーのログを確認してみると
(マスキング済み)
Log Message
ID
1160193
Level
ERROR
Start Time
2025-04-25T16:11:36.576410265Z
End Time
2025-04-25T16:11:36.579863591Z
Status Code
401 Unauthorized
Request Method
GET
Request URL
****
Host
****
Remote Address
****
Private Remote Address
****
Private Local Address
****
User Agent
node
Request Headers
Accept: text/event-stream
Accept-Encoding: gzip, br
Accept-Language: *
Cache-Control: no-cache
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: ********
Cf-Ipcontinent: ****
Cf-Ipcountry: ****
Cf-Iplatitude: ****
Cf-Iplongitude: ****
Cf-Ray: ****
Cf-Region: ****
Cf-Region-Code: ****
Cf-Timezone: ****
Cf-Visitor: {"scheme":"https"}
Cf-Warp-Tag-Id: ****
Connection: keep-alive
Hs-Connecting-Port: ****
Pragma: no-cache
Sec-Fetch-Mode: cors
User-Agent: node
X-Forwarded-For: ****
X-Forwarded-Proto: https
Response Headers
Content-Security-Policy: default-src 'self'; upgrade-insecure-requests; block-all-mixed-content
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Origin
Www-Authenticate: Basic
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Powered-By: PHP/7.1.32
X-Xss-Protection: 1; mode=block
Response Body Size
0
Taken Time
127.685µs
Taken Time (Nano)
127685
Log
{"time":"2025-04-25T16:11:36.576482085Z","level":"ERROR","file":"*","line":"*","message":"access denied deny: default (basic_auth)"}
…あれ?Authorization
ヘッダ送られてないっぽい????
ということで調査に乗り出した
調査#
まずissueを探してみると早速ヒット
どうやらMcpの設定の読み込み箇所にバグがあったようだ 下の方にPRが確認できたので見てみると
const SseConfigSchema = BaseConfigSchema.extend({
url: z.string().url(),
+ headers: z.record(z.string()).optional(),
といったような記述が発見された。ではこれは元からなかったのかというとそうでもないようで記録をたどってみるとこの時点では存在したことが確認できる
ではどこで消えたかと言うとzodを使ったスキーマに書き直した際に消失したようだ。
なおこのzodに変更する際には普通にPRでレビューをしているが通過している。AIツールもついぞ指摘することはなかったようだ
なおスキーマ以外にもこの修正PRではMCPのtypescript-sdkのSSEClientTransport
の初期化部分も正確に初期化されていなかったことが示唆されている。時系列的には以下のSSEトランスポートを実装した時点で既にスキーマからはheaders
が消えた状態であったためSSEトランスポート実装者から見落とされた可能性がある。
結論#
とりあえずこのバグが直るまではインターネット経由で自作mcpサーバーを使うのはお預けである..
あとAIのレビューを鵜呑みにするのは危ないということと仕様を書いたらテストを書くのは大事ということが改めて感じられた…
追記: mcp-remoteというライブラリで普通に行けた… みんなこっち使うからバグが表に出なかったのかな…