You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Codex 0.160 agents get no T3 Code MCP tools: /mcp answers server/discover with HTTP 400 #16067
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
Install Codex CLI 0.160.0.
Run t3 serve on current main. Seen on 37de6cbde; apps/server/src/mcp/McpHttpServer.ts is unchanged on 1a3f7ad50.
Start a Codex thread and ask the agent to call any t3-code tool, for example orchestrator_capabilities.
Expected behavior
Codex connects to the t3-code MCP server and the agent can call T3 Code's tools.
Actual behavior
Codex marks t3-code as failed at session start, so the agent has none of T3 Code's tools. The provider event log shows:
mcpServer/startupStatus/updated name: t3-code status: failed
MCP client for `t3-code` failed to start: MCP startup failed: handshaking with MCP server failed:
... error: unexpected server response: HTTP 400: , when send discover request
The server trace shows three POST /mcp requests from codex-mcp-client/0.160.0 with mcp-method: server/discover and mcp-protocol-version: 2026-07-28, each answered with status 400. Bearer authentication passes (McpSessionRegistry.resolve succeeds), so the request is rejected during protocol negotiation, not auth.
Likely cause: McpHttpServer.ts pins protocols: [McpProtocol.v2025_06_18]. The bundled Effect (4.0.0-rc.115) ships protocol adapters up to v2025_11_25, and McpServer.ts carries a TODO about session strategy "before v2026-07-28".
A Claude thread in the same build connects and calls the tools normally.
Impact
Major degradation or frequent failure
Version or commit
37de6cbde (the same pin is on main 1a3f7ad50)
Environment
macOS, Node 24, Codex CLI 0.160.0 (ChatGPT sign-in), server started with t3 serve
Logs or stack traces
See "Actual behavior". Server trace span: http.server POST /mcp, http.request.header.mcp-method: server/discover, http.request.header.mcp-protocol-version: 2026-07-28, http.response.status_code: 400.
Workaround
None found. Claude threads are unaffected.
Found by Claude Opus 5.5 in Jcode while running headless acceptance tests on an isolated base dir.
Version: T3 Code 0.0.45 on Windows, Claude Code 2.1.294 (agent-sdk 0.3.276).
At session start the t3-code MCP server shows status: failed, with the error InvalidHTTPResponse fetching http://127.0.0.1:3773. The agent gets no T3 tools, so link_pull_request is unavailable.
The server trace shows the same sequence as the Codex report:
POST /mcp with mcp-method: server/discover and mcp-protocol-version: 2026-07-28 returns 400.
About 1.6 seconds later, a plain initialize returns 200 (@effect/mcp/2025-06-18/initialize).
No tools/list follows, and the client marks the server failed.
Bearer auth passes in both requests. Restarting the app does not help.
The issue says Claude threads are unaffected. That holds only for older Claude Code builds. Builds that send server/discover fail the same way.
Confirming the same failure signature on Windows with Claude Code (T3 Code 0.1.2), with server-trace details, a note on how Claude Code reacts to the 400, and an HTTP framing observation I could not fully attribute (see caveats).
Environment
T3 Code 0.1.2 desktop app (server-runtime.json: serverVersion: 0.1.2, listening on 127.0.0.1:3773)
Windows 11 Pro 10.0.26200
Provider claudeAgent, Claude Code 2.1.310 (agent-sdk 0.3.276)
A local security product on this machine re-signs HTTPS traffic (TLS interception). This matters for the caveats below.
Symptom
At session start the SDK init message reports the server as failed, while other MCP servers in the same session connect:
"mcp_servers":[
{"name":"plugin:context7:context7","status":"failed","source":"plugin"},
{"name":"context7","status":"connected","source":"user"},
{"name":"claude.ai Claude Docs","status":"connected","source":"claudeai"},
{"name":"t3-code","status":"failed","source":"dynamic"}
]
Error: InvalidHTTPResponse fetching http://127.0.0.1:3773. The thread has none of the T3 tools (orchestrator_capabilities, delegate_task, link_pull_request, ...).
It is not intermittent: in my local provider event logs, t3-code is failed in 31 of 32 Claude threads since 2026-10-10 (the remaining one is stuck at starting), never connected. Restarting the desktop app (new server process, still 0.1.2) does not help, and a new thread started after the restart fails the same way.
Registered vs. not added: the init event lists t3-code with "source":"dynamic","status":"failed", so the server is registered (injected by T3 at runtime) and fails at connect time; it is not missing from the thread. claude mcp list does not show it, since dynamic servers are not in the config files. The same command in a plain CLI session shows plugin:context7:context7 failing with InvalidHTTPResponse while context7 connects, so this error also appears for a remote HTTP server outside T3.
Server trace: POST /mcp 400 then 200 on every session start
server.trace.ndjson has 8 session starts from claude-code/2.1.310 (sdk-ts, agent-sdk/0.3.276). Each is a POST /mcp answered with 400, followed 25 ms to 1.6 s later by a POST /mcp answered with 200, after which the client marks t3-code as failed:
2026-10-25T15:30:28.304Z POST /mcp 400 2.8ms
2026-10-25T15:30:29.915Z POST /mcp 200 9.8ms
2026-10-25T15:48:40.876Z POST /mcp 400 1.3ms <- thread started after the app restart
2026-10-25T15:48:40.899Z POST /mcp 200 1.3ms
McpHttpServer.authenticateRequest succeeds, so the 400 is not an auth failure. The 0.1.2 trace does not record the mcp-method / mcp-protocol-version request headers or the response body, so I can't show which header triggered the 400.
Correction to my earlier reading: I first took this 400 for the cause. Claude Code's own debug log (from a different MCP server in a plain CLI session; T3-injected servers don't appear there) shows that it probes the modern protocol first and then falls back on purpose: version negotiation probe failed on the http transport; reconnecting pinned legacy. So the 400 is probably expected from a server that pins 2025-06-18, and the failure for Claude Code happens after the legacy fallback. That would make the server/discover 400 the cause for clients that don't fall back (Codex, per the original report), but not necessarily for Claude Code.
Observation: malformed chunked responses from /mcp
I probed the endpoint without a token. Both POST /mcp and GET /.well-known/oauth-protected-resource/mcp send transfer-encoding: chunked, but the body is not chunk-framed (the JSON follows the headers directly, with no hex chunk-size line). A plain TCP client confirms the raw bytes:
$ curl -i -X POST http://127.0.0.1:3773/mcp -H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' -d '{"jsonrpc":"2.0","id":1,"method":"initialize"}'
HTTP/1.1 401 Unauthorized
transfer-encoding: chunked
www-authenticate: Bearer resource_metadata="http://127.0.0.1:3773/.well-known/oauth-protected-resource/mcp"
content-type: application/json
...
{"error":"invalid_mcp_credential","message":"A valid T3 Code MCP credential is required."}
curl: (56) chunk hex-length char not a hex digit: 0x7b
GET / is fine (it uses content-length). Node's fetch (undici) also rejects these responses ("Invalid character in chunk size"), PowerShell 5.1 fails with "unexpected error occurred on a receive". A strict client such as Claude Code's would report this as InvalidHTTPResponse, which is the error I see.
Caveats (I could not close these)
Possible local interference. The same pattern (transfer-encoding: chunked plus an unframed JSON body) also appears on https://mcp.context7.com/.well-known/oauth-protected-resource/mcp on this machine, where the TLS-intercepting security product is in the path. Controls that were fine: my own Node servers on six loopback ports (JSON with Content-Length, and JSON with explicit/automatic chunking), and JSON from api.github.com and registry.npmjs.org. I tried to turn the product's web protection off, but its interception stayed active (verified through the certificate issuer), so this test was inconclusive. I can't say whether the server itself or something on the path produces the unframed body.
I did not test with a valid bearer token (I didn't want to extract the session credential), so I can't say whether the authenticated initialize response is affected too.
What would help
Log mcp-method, mcp-protocol-version and the response body in the /mcp request span.
Check whether the response to an authenticated initialize is chunk-framed. If it is not, Claude Code would fail right after the fallback exactly as observed.
Happy to run further diagnostics on Windows.
Diagnostics gathered with the help of Claude Code.
Correction (later the same day): on my machine this was Avast, not T3. The conclusions struck through below are wrong.
About 15 minutes later, the same T3 server process returned the same /mcp 401 correctly: content-length: 90 and an intact body. Bun and Node fetch both read it fine. A second, isolated copy of the server built from the same server.asar also answered correctly. In the bad responses, content-length had been removed and transfer-encoding: chunked inserted as the first header without re-framing the body. The T3 server writes content-length, so something between the server and the client rewrote it intermittently.
The fix was adding Avast exceptions (Settings → General → Exceptions) for the URL http://127.0.0.1:3773/* and for claude.exe. Claude Code sessions in T3 now load the t3-code MCP tools again.
This also accounts for the earlier caveat about a TLS-intercepting security product, and for the intermittent pattern in my timeline. DeepSeek probably kept working because its MCP client runs in a different process that the AV filters differently.
The POST /api/nonexistent 404 row in the table below was a false positive from my checker. It's a correctly framed empty chunked body (0\r\n\r\n).
The /mcp 400 on Claude Code's first request (the version-negotiation probe) is still there, but it doesn't break anything once responses reach the client intact.
For anyone else hitting InvalidHTTPResponse fetching http://127.0.0.1:3773 on Windows: check for an antivirus or web shield that filters HTTP (Avast, AVG and similar), and add an exception for 127.0.0.1:3773.
Still reproducing on T3 Code 0.1.7-nightly.20261103.4119 (Windows 10 LTSC 2021) with Claude Code 2.1.317 (agent-sdk 0.3.284). Adding a control test that addresses the "possible local interference" caveat above, plus a regression timeline.
Same signature
Claude Code MCP log: Initializing HTTP transport to http://127.0.0.1:3773/mcp → HTTP Connection failed after 1364ms: InvalidHTTPResponse fetching "http://127.0.0.1:3773/mcp".
server.trace.ndjson: every Claude session start is POST /mcp400 followed by POST /mcp200 (@effect/mcp/2025-06-18/initialize), then no tools/list.
DeepSeek via ACP (user agent node) in the same app, at the same time, works fine: initialize 200 → 202 → tools/list → tools/call all succeed. It never gets the 400.
Malformed chunked responses: control test suggests it's the T3 server (see correction: local AV)
Raw socket dump of an unauthenticated POST /mcp:
HTTP/1.1 401 Unauthorized
transfer-encoding: chunked
cache-control: no-store
www-authenticate: Bearer resource_metadata="http://127.0.0.1:3773/.well-known/oauth-protected-resource/mcp"
content-type: application/json
vary: Accept-Encoding
access-control-allow-origin: *
Connection: close
{"error":"invalid_mcp_credential","message":"A valid T3 Code MCP credential is required."}
No chunk-size line and no terminating 0 chunk. Per route:
Request
Status
transfer-encoding: chunked
Body chunk-framed
POST /mcp (no auth / bad bearer)
401
yes
no
GET /mcp, DELETE /mcp
401
yes
no
GET /.well-known/oauth-protected-resource/mcp
200
yes
no
POST /api/nonexistent
404
yes
no yes (empty body; checker false positive)
GET /, GET /api/auth/session
200
no (content-length)
n/a
Control: a plain node:http server on loopback (127.0.0.1:3799) doing writeHead(401, json) + write + end, read by the same raw-socket client, comes back properly framed (d\r\n{"error":"x"}\r\n0\r\n\r\n). So the loopback path on this machine doesn't strip chunk framing. The unframed bodies come from the T3 server process. That control only showed the AV wasn't rewriting traffic on that port at that moment. (Caveat: Avast Antivirus is installed here, and I can't rule out per-process filtering completely, but this control covers the same client and the same loopback and it turned out to be the cause.)
How clients react to these responses:
Bun 1.3.9 fetch (Claude Code's runtime): InvalidHTTPResponse, the exact error Claude Code reports.
Node fetch (undici): TypeError: terminated.
Working theory, consistent with the note above on the version-negotiation probe: Claude Code's first /mcp request (the modern-protocol probe) gets a 400 whose body is mis-framed the same way. Bun's fetch throws InvalidHTTPResponse instead of returning a 400, so the client never falls back cleanly. I couldn't test authenticated responses (no token available).
Regression timeline (from Claude Code's mcp-logs-t3-code/*.jsonl)
2026-10-24 → 10-31 16:00 UTC: connected every time (Claude Code 2.1.312 / 2.1.314).
2026-10-31 16:39 → 11-02 11:12: intermittent; same InvalidHTTPResponse on failures (2.1.314 / 2.1.316).
2026-11-02 15:00 → now: fails every time (2.1.316 / 2.1.317).
The same Claude Code builds both connected and failed, so the Claude Code version doesn't look like the trigger. I'm on the Nightly channel, but my rotated server logs no longer show which T3 builds were running at those times.
Correction to my comment above (now edited): on my machine the malformed transfer-encoding: chunked responses came from Avast rewriting loopback HTTP, not from the T3 server. The same server process later answered the same request correctly with content-length. Adding Avast exceptions for http://127.0.0.1:3773/* and claude.exe fixed Claude Code's InvalidHTTPResponse, and the T3 MCP tools load again. If you hit this on Windows, check for an HTTP-filtering antivirus or web shield first.
Follow-up: resolved on my machine. The cause was local security software (Norton Safe Web) rewriting loopback HTTP, not the T3 server. This resolves the caveats in my earlier comment and matches the Avast finding in desidia-cyber's comment. I withdraw my earlier suspicion that the T3 server itself sends unframed chunked responses: it does not.
Environment
T3 Code 0.1.2 and 0.1.7 (same failure on both), 127.0.0.1:3773
Windows 11 Pro 10.0.26200, Claude Code 2.1.310 to 2.1.317
Norton 360 for Gamers 26.10 (Avast-engine processes aswEngSrv, afwServ, aswidsagent run alongside it)
Root cause: Norton Safe Web
With Safe Web active, responses from 127.0.0.1:3773 are rewritten: the content-length header is removed and transfer-encoding: chunked is inserted as the first header, but the body is not re-framed into chunks. Strict HTTP clients reject this (Claude Code's runtime reports InvalidHTTPResponse, Node's fetch reports Invalid character in chunk size, curl reports chunk hex-length char not a hex digit).
Raw bytes of GET /.well-known/oauth-protected-resource/mcp on a plain TCP socket:
# Safe Web active (broken) # Safe Web off, or exception added (correct)
HTTP/1.1 200 OK HTTP/1.1 200 OK
transfer-encoding: chunked content-type: application/json
content-type: application/json content-length: 220
... ...
{"resource":"http://127.0.0.1:3773/mcp",... {"resource":"http://127.0.0.1:3773/mcp",...
The same holds for the 401 on POST /mcp (content-length: 90 when intact). So the T3 server sends proper content-length responses.
A/B results
Each row was measured with the well-known endpoint, POST /mcp without a token, and an actual t3-code tool call.
Safe Web main switch
Safe Web sub-switches
Result
on
all on
broken
on
all off (HTTPS scanning, Uncommon application scanning, QUIC/HTTP3, WebSocket protocol, DNS/DoH, botnets)
still broken
off
n/a
works (repeated twice)
on
all on, plus exception http://127.0.0.1/*
works
None of the sub-switches affects the loopback rewriting, tested one at a time and cumulatively. Only the main switch, or an exception, fixes it. The Norton firewall and Auto-Protect are unrelated; turning them off changed nothing.
A separate effect: HTTPS scanning re-signs TLS certificates (issuer Norton Web/Mail Shield) and produced the same malformed framing for https://mcp.context7.com/.well-known/oauth-protected-resource/mcp. That is why plugin:context7:context7 (anonymous, so it goes through OAuth discovery) failed with InvalidHTTPResponse while the header-authenticated context7 entry connected. Turning HTTPS scanning off fixed the plugin (claude mcp list shows all three servers connected).
Fix
Add an exception for http://127.0.0.1/* in Norton's Safe Web settings (the T3 port is 3773, but the wildcard also survives a port change). If you use the context7 plugin, also turn HTTPS scanning off or add an exception for https://mcp.context7.com.
On the earlier POST /mcp 400
Claude Code's debug log shows it probes the modern protocol first and then falls back on purpose (version negotiation probe failed on the http transport; reconnecting pinned legacy), so the 400 is expected from a server that pins 2025-06-18 and is not what broke Claude Code here. The failure came after the fallback, from the rewritten responses above. For clients that do not fall back (Codex, per the original report) the server/discover 400 is still a real problem, and PR #28683 addresses it.
Suggestions
A short troubleshooting note for Windows: InvalidHTTPResponse fetching http://127.0.0.1:3773 with web-shield antivirus software (Norton, Avast, AVG) should be solved with an exception for http://127.0.0.1/*.
If it is cheap, a clearer error or health hint when the t3-code MCP server fails with InvalidHTTPResponse on loopback would save users a long investigation.
Thanks to desidia-cyber for the Avast lead that made this findable.
Diagnostics gathered with the help of Claude Code.
Activity
abdtriedcoding commentedon Oct 8, 2026
Claude Code hits this too, not only Codex.
Version: T3 Code 0.0.45 on Windows, Claude Code 2.1.294 (agent-sdk 0.3.276).
At session start the
t3-codeMCP server showsstatus: failed, with the errorInvalidHTTPResponse fetching http://127.0.0.1:3773. The agent gets no T3 tools, solink_pull_requestis unavailable.The server trace shows the same sequence as the Codex report:
POST /mcpwithmcp-method: server/discoverandmcp-protocol-version: 2026-07-28returns 400.initializereturns 200 (@effect/mcp/2025-06-18/initialize).tools/listfollows, and the client marks the server failed.Bearer auth passes in both requests. Restarting the app does not help.
The issue says Claude threads are unaffected. That holds only for older Claude Code builds. Builds that send
server/discoverfail the same way.borzaka commentedon Oct 25, 2026
Confirming the same failure signature on Windows with Claude Code (T3 Code 0.1.2), with server-trace details, a note on how Claude Code reacts to the
400, and an HTTP framing observation I could not fully attribute (see caveats).Environment
server-runtime.json:serverVersion: 0.1.2, listening on127.0.0.1:3773)claudeAgent, Claude Code 2.1.310 (agent-sdk 0.3.276)Symptom
At session start the SDK
initmessage reports the server as failed, while other MCP servers in the same session connect:Error:
InvalidHTTPResponse fetching http://127.0.0.1:3773. The thread has none of the T3 tools (orchestrator_capabilities,delegate_task,link_pull_request, ...).It is not intermittent: in my local provider event logs,
t3-codeisfailedin 31 of 32 Claude threads since 2026-10-10 (the remaining one is stuck atstarting), neverconnected. Restarting the desktop app (new server process, still 0.1.2) does not help, and a new thread started after the restart fails the same way.Registered vs. not added: the
initevent listst3-codewith"source":"dynamic","status":"failed", so the server is registered (injected by T3 at runtime) and fails at connect time; it is not missing from the thread.claude mcp listdoes not show it, since dynamic servers are not in the config files. The same command in a plain CLI session showsplugin:context7:context7failing withInvalidHTTPResponsewhilecontext7connects, so this error also appears for a remote HTTP server outside T3.Server trace:
POST /mcp400 then 200 on every session startserver.trace.ndjsonhas 8 session starts fromclaude-code/2.1.310 (sdk-ts, agent-sdk/0.3.276). Each is aPOST /mcpanswered with 400, followed 25 ms to 1.6 s later by aPOST /mcpanswered with 200, after which the client markst3-codeas failed:McpHttpServer.authenticateRequestsucceeds, so the 400 is not an auth failure. The 0.1.2 trace does not record themcp-method/mcp-protocol-versionrequest headers or the response body, so I can't show which header triggered the 400.Correction to my earlier reading: I first took this 400 for the cause. Claude Code's own debug log (from a different MCP server in a plain CLI session; T3-injected servers don't appear there) shows that it probes the modern protocol first and then falls back on purpose:
version negotiation probe failed on the http transport; reconnecting pinned legacy. So the 400 is probably expected from a server that pins2025-06-18, and the failure for Claude Code happens after the legacy fallback. That would make theserver/discover400 the cause for clients that don't fall back (Codex, per the original report), but not necessarily for Claude Code.Observation: malformed chunked responses from
/mcpI probed the endpoint without a token. Both
POST /mcpandGET /.well-known/oauth-protected-resource/mcpsendtransfer-encoding: chunked, but the body is not chunk-framed (the JSON follows the headers directly, with no hex chunk-size line). A plain TCP client confirms the raw bytes:GET /is fine (it usescontent-length). Node'sfetch(undici) also rejects these responses ("Invalid character in chunk size"), PowerShell 5.1 fails with "unexpected error occurred on a receive". A strict client such as Claude Code's would report this asInvalidHTTPResponse, which is the error I see.Caveats (I could not close these)
transfer-encoding: chunkedplus an unframed JSON body) also appears onhttps://mcp.context7.com/.well-known/oauth-protected-resource/mcpon this machine, where the TLS-intercepting security product is in the path. Controls that were fine: my own Node servers on six loopback ports (JSON withContent-Length, and JSON with explicit/automatic chunking), and JSON fromapi.github.comandregistry.npmjs.org. I tried to turn the product's web protection off, but its interception stayed active (verified through the certificate issuer), so this test was inconclusive. I can't say whether the server itself or something on the path produces the unframed body.initializeresponse is affected too.What would help
mcp-method,mcp-protocol-versionand the response body in the/mcprequest span.initializeis chunk-framed. If it is not, Claude Code would fail right after the fallback exactly as observed.Happy to run further diagnostics on Windows.
Diagnostics gathered with the help of Claude Code.
desidia-cyber commentedon Nov 3, 2026
Still reproducing on T3 Code 0.1.7-nightly.20261103.4119 (Windows 10 LTSC 2021) with Claude Code 2.1.317 (agent-sdk 0.3.284). Adding a control test that addresses the "possible local interference" caveat above, plus a regression timeline.
Same signature
Initializing HTTP transport to http://127.0.0.1:3773/mcp→HTTP Connection failed after 1364ms: InvalidHTTPResponse fetching "http://127.0.0.1:3773/mcp".server.trace.ndjson: every Claude session start isPOST /mcp400 followed byPOST /mcp200 (@effect/mcp/2025-06-18/initialize), then notools/list.node) in the same app, at the same time, works fine:initialize200 → 202 →tools/list→tools/callall succeed. It never gets the 400.Malformed chunked responses:
control test suggests it's the T3 server(see correction: local AV)Raw socket dump of an unauthenticated
POST /mcp:No chunk-size line and no terminating
0chunk. Per route:transfer-encoding: chunkedPOST /mcp(no auth / bad bearer)GET /mcp,DELETE /mcpGET /.well-known/oauth-protected-resource/mcpPOST /api/nonexistentnoyes (empty body; checker false positive)GET /,GET /api/auth/sessionControl: a plain
node:httpserver on loopback (127.0.0.1:3799) doingwriteHead(401, json)+write+end, read by the same raw-socket client, comes back properly framed (d\r\n{"error":"x"}\r\n0\r\n\r\n).So the loopback path on this machine doesn't strip chunk framing. The unframed bodies come from the T3 server process.That control only showed the AV wasn't rewriting traffic on that port at that moment. (Caveat: Avast Antivirus is installed here,and I can't rule out per-process filtering completely, but this control covers the same client and the same loopbackand it turned out to be the cause.)How clients react to these responses:
fetch(Claude Code's runtime):InvalidHTTPResponse, the exact error Claude Code reports.fetch(undici):TypeError: terminated.Working theory, consistent with the note above on the version-negotiation probe: Claude Code's first
/mcprequest (the modern-protocol probe) gets a 400 whose body is mis-framed the same way. Bun's fetch throwsInvalidHTTPResponseinstead of returning a 400, so the client never falls back cleanly. I couldn't test authenticated responses (no token available).Regression timeline (from Claude Code's
mcp-logs-t3-code/*.jsonl)InvalidHTTPResponseon failures (2.1.314 / 2.1.316).The same Claude Code builds both connected and failed, so the Claude Code version doesn't look like the trigger. I'm on the Nightly channel, but my rotated server logs no longer show which T3 builds were running at those times.
Repro (no token needed)
Expected:
401with a readable JSON body. Actual: transport-level error, because the header says chunked and the body isn't.Diagnostics gathered with the help of Claude Code.
desidia-cyber commentedon Nov 3, 2026
Correction to my comment above (now edited): on my machine the malformed
transfer-encoding: chunkedresponses came from Avast rewriting loopback HTTP, not from the T3 server. The same server process later answered the same request correctly withcontent-length. Adding Avast exceptions forhttp://127.0.0.1:3773/*andclaude.exefixed Claude Code'sInvalidHTTPResponse, and the T3 MCP tools load again. If you hit this on Windows, check for an HTTP-filtering antivirus or web shield first.borzaka commentedon Nov 7, 2026
Follow-up: resolved on my machine. The cause was local security software (Norton Safe Web) rewriting loopback HTTP, not the T3 server. This resolves the caveats in my earlier comment and matches the Avast finding in desidia-cyber's comment. I withdraw my earlier suspicion that the T3 server itself sends unframed chunked responses: it does not.
Environment
127.0.0.1:3773aswEngSrv,afwServ,aswidsagentrun alongside it)Root cause: Norton Safe Web
With Safe Web active, responses from
127.0.0.1:3773are rewritten: thecontent-lengthheader is removed andtransfer-encoding: chunkedis inserted as the first header, but the body is not re-framed into chunks. Strict HTTP clients reject this (Claude Code's runtime reportsInvalidHTTPResponse, Node'sfetchreportsInvalid character in chunk size, curl reportschunk hex-length char not a hex digit).Raw bytes of
GET /.well-known/oauth-protected-resource/mcpon a plain TCP socket:The same holds for the
401onPOST /mcp(content-length: 90when intact). So the T3 server sends propercontent-lengthresponses.A/B results
Each row was measured with the well-known endpoint,
POST /mcpwithout a token, and an actualt3-codetool call.http://127.0.0.1/*None of the sub-switches affects the loopback rewriting, tested one at a time and cumulatively. Only the main switch, or an exception, fixes it. The Norton firewall and Auto-Protect are unrelated; turning them off changed nothing.
A separate effect: HTTPS scanning re-signs TLS certificates (issuer
Norton Web/Mail Shield) and produced the same malformed framing forhttps://mcp.context7.com/.well-known/oauth-protected-resource/mcp. That is whyplugin:context7:context7(anonymous, so it goes through OAuth discovery) failed withInvalidHTTPResponsewhile the header-authenticatedcontext7entry connected. Turning HTTPS scanning off fixed the plugin (claude mcp listshows all three servers connected).Fix
Add an exception for
http://127.0.0.1/*in Norton's Safe Web settings (the T3 port is 3773, but the wildcard also survives a port change). If you use the context7 plugin, also turn HTTPS scanning off or add an exception forhttps://mcp.context7.com.On the earlier
POST /mcp400Claude Code's debug log shows it probes the modern protocol first and then falls back on purpose (
version negotiation probe failed on the http transport; reconnecting pinned legacy), so the400is expected from a server that pins2025-06-18and is not what broke Claude Code here. The failure came after the fallback, from the rewritten responses above. For clients that do not fall back (Codex, per the original report) theserver/discover400 is still a real problem, and PR #28683 addresses it.Suggestions
InvalidHTTPResponse fetching http://127.0.0.1:3773with web-shield antivirus software (Norton, Avast, AVG) should be solved with an exception forhttp://127.0.0.1/*.t3-codeMCP server fails withInvalidHTTPResponseon loopback would save users a long investigation.Thanks to desidia-cyber for the Avast lead that made this findable.
Diagnostics gathered with the help of Claude Code.