Repository navigation
[Bug] MCP SSE endpoint event omits the /server prefix, so clients behind the built-in nginx proxy get a 404 on /mcp/messages #1854
Description
What installation are you running?
Production (netalertx) 📦
Is there an existing issue for this?
- I have searched the existing open and closed issues and I checked the docs https://docs.netalertx.com/
The issue occurs in the following browsers. Select at least 2.
- N/A - This is an issue with the backend
Current Behavior
When you connect to the MCP server through the built-in nginx proxy (http://<host>:20211/server/mcp/sse), the SSE endpoint event sends back an absolute path that has no /server prefix:
event: endpoint
data: /mcp/messages?session_id=0b6b10b07cd94f9989df9c38be26ed77
MCP clients resolve this against the origin and send their requests to http://<host>:20211/mcp/messages?.... nginx has no route for that path and tries to serve it as a static file from /app/front, which returns a 404. The client never finishes connecting. Claude Code shows Error POSTing to endpoint (HTTP 404): ... nginx.
The same request with the /server prefix works (202). Only the advertised URL is wrong. The cause is in server/api_server/mcp_endpoint.py:1061:
yield f"event: endpoint\ndata: /mcp/messages?session_id={session_id}\n\n"Related but different: #1275 (MCP server), #1440 (backend and reverse proxy setup).
Expected Behavior
The advertised endpoint should resolve to a working URL behind the bundled proxy. Two possible fixes:
- Send a relative path (
messages?session_id=...). It resolves against.../mcp/sse, so it works both directly and behind any prefix. - Prepend the prefix from
X-Forwarded-Prefixorrequest.script_root, and have the bundled nginx set that header for/server.
Workaround: connect straight to http://<host>:<GRAPHQL_PORT>/mcp/sse. This bypasses the reverse proxy and any auth middleware in front of it.
Steps To Reproduce
H='Authorization: Bearer <API_TOKEN>'; S='Sec-Fetch-Site: same-origin'
curl -sN -H "$H" -H "$S" http://<host>:20211/server/mcp/sse # -> data: /mcp/messages?session_id=XYZ
curl -X POST -H "$H" -H "$S" -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}' \
"http://<host>:20211/mcp/messages?session_id=XYZ" # -> 404 (nginx)
curl -X POST -H "$H" -H "$S" -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}' \
"http://<host>:20211/server/mcp/messages?session_id=XYZ" # -> 202 acceptedRelevant app.conf settings
LOG_LEVEL='trace'
API_TOKEN='<redacted>'
# GRAPHQL_PORT=20214 set via environmentdocker-compose.yml
services:
netalertx:
image: ghcr.io/netalertx/netalertx:latest
container_name: netalertx
network_mode: host
read_only: true
restart: unless-stopped
cap_drop:
- ALL
cap_add:
- NET_ADMIN
- NET_RAW
- NET_BIND_SERVICE
- CHOWN
- SETUID
- SETGID
volumes:
- ./data:/data
- /etc/localtime:/etc/localtime:ro
tmpfs:
- "/tmp:mode=1700,uid=0,gid=0,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
environment:
PUID: "20211"
PGID: "20211"
LISTEN_ADDR: "0.0.0.0"
PORT: "20211"
GRAPHQL_PORT: "20214"Debug or Trace enabled
- I have read and followed the steps in the wiki link above and provided the required debug logs and the log section covers the time when the issue occurs.
Relevant app.log section
12:55:43 [MCP] Created session: 0b6b10b07cd94f9989df9c38be26ed77
12:55:46 [HTTP] POST /mcp/messages from 127.0.0.1
127.0.0.1 - - [21/Oct/2026 12:55:46] "POST /mcp/messages?session_id=0b6b10b07cd94f9989df9c38be26ed77 HTTP/1.1" 202 -
12:55:46 [MCP] Deleted session: 0b6b10b07cd94f9989df9c38be26ed77
nginx-access.log: the unprefixed request gets a 404, the prefixed one is proxied and gets a 202:
<client> - - [21/Oct/2026:12:55:46 +0200] "POST /mcp/messages?session_id=0b6b10b07cd94f9989df9c38be26ed77 HTTP/1.1" 404 146 "-" "curl/8.7.1" "-"
<client> - - [21/Oct/2026:12:55:46 +0200] "POST /server/mcp/messages?session_id=0b6b10b07cd94f9989df9c38be26ed77 HTTP/1.1" 202 37 "-" "curl/8.7.1" "-"
nginx-error.log: the unprefixed path falls through to static file serving:
2026/10/21 12:55:46 [error] 253#253: *40 open() "/app/front/mcp/messages" failed (2: No such file or directory), client: <client>, server: , request: "POST /mcp/messages?session_id=0b6b10b07cd94f9989df9c38be26ed77 HTTP/1.1", host: "<host>:20211"
Docker Logs
12:53:20 [MCP] Cleaning up expired session: bdf10972895f4efeafecfcf7b50d76c4
(docker logs netalertx --tail 200 2>&1 | grep -iE "mcp|error": nothing else relevant. The 404 happens in nginx before the request reaches the backend.)
Activity
BE+TESTS: relative MCP SSE endpoint path #1854
jokob-sk commentedon Oct 23, 2026
This should be available/fixed in the next release.
It would be great if you could test the
ghcr.io/netalertx/netalertx-dev/ghcr.io/netalertx/netalertx-dev-unsafeDocker image in ~15 minutes (or once the latest GitHub Action finishes).PORTandGRAPHQL_PORTif running instances concurrently) with its own DB and config (a copy of your current setup), as database changes may occur.After updating:
👉 If I don’t receive confirmation that this works, I may revert the changes to avoid introducing bugs.
Thanks in advance,
j
frdmn commentedon Oct 23, 2026
Tested
ghcr.io/netalertx/netalertx-dev:latestin a separate container (own ports and data, same compose setup as in the report) — works 👍endpointevent is now relative:data: messages?session_id=...http://<host>:<PORT>/server/mcp/sse), the client resolves it to/server/mcp/messages?...;initializeandtools/listboth return 202 and the responses arrive on the stream (73 tools).Thanks for the quick merge!
jokob-sk commentedon Oct 23, 2026
Thanks - publishing in ~1h - > closing