In a previous post we rebuilt our company knowledge base server from an MCP SSE endpoint to a plain FastAPI REST server because MCP client support was too fragmented to be reliable. The conclusion was: REST is the pragmatic choice, MCP can come back when the ecosystem matures.
The ecosystem has matured faster than expected. We added MCP back on top of the FastAPI server and it now works across every client simultaneously: claude.ai, Claude Teams (company-wide), Claude desktop, ChatGPT, and OpenWebUI. This is what we learned in the process.
What changed: SSE is out, Streamable HTTP is in
When we originally built the MCP endpoint, the standard transport was Server-Sent Events (SSE). The client would open a persistent SSE connection and the server would stream tool responses over it. fastapi-mcp supported this with mount_sse().
In fastapi-mcp 0.4.0, SSE transport was deprecated. The replacement is Streamable HTTP, a simpler transport where each MCP interaction is a standard HTTP request/response cycle, optionally streaming over a single connection. You mount it with mount_http() instead of mount_sse().
This matters because claude.ai and ChatGPT both require Streamable HTTP. They do not support SSE. If your server is running an older version of fastapi-mcp with SSE transport, it will not connect to either.
Updating is one line:
# Before (deprecated)
mcp.mount_sse(app, path="/mcp", ...)
# After
mcp.mount_http(app, path="/mcp", ...)
Upgrade the package:
pip install "fastapi-mcp>=0.4.0"
The /mcp URL gotcha
This one catches everyone. When you configure an MCP server URL in any client, the URL must include the /mcp path suffix:
https://your-server.example.com/mcp ✅
https://your-server.example.com ❌
The base domain alone does not work. The MCP handshake is a POST to /mcp with a JSON-RPC initialize request. If you point a client at the root URL, the request hits your / route or returns 404. The client reports a connection failure with no useful error message.
We spent time diagnosing what appeared to be a connectivity issue before realizing the URL was simply missing the suffix. Every client we have tested (claude.ai, Claude Teams, Claude desktop, ChatGPT) requires the full path.
To verify the endpoint manually:
curl -s -X POST https://your-server.example.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "test", "version": "1.0"}
}
}'
A working server responds with its protocol version and tool list:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {"listChanged": false}},
"serverInfo": {"name": "YourServer", "version": "..."}
}
}
If you get a 404 or HTML response, the path is wrong. If you get Not Acceptable, you are missing the Accept: application/json header.
Auth: the /mcp path needs to be open
If your FastAPI server uses API key authentication on a middleware layer, make sure /mcp is excluded from the auth check. MCP clients send the initialize request without credentials: authentication happens at the application level, not the transport level.
@app.middleware("http")
async def auth_middleware(request: Request, call_next):
if request.url.path.startswith("/mcp"):
return await call_next(request)
# check API key for all other routes
...
Without this, the MCP handshake returns a 401 and the client cannot connect.
Connecting each client
With Streamable HTTP transport and the correct URL, every client connects the same way: paste the URL and it works.
| Client | Where to configure | URL format |
|---|---|---|
| claude.ai | Settings → Integrations → Add MCP server | https://your-server.example.com/mcp |
| Claude desktop | claude_desktop_config.json → mcpServers | {"type": "http", "url": "https://..."} |
| ChatGPT | Settings → Connected apps → Add | https://your-server.example.com/mcp |
| OpenWebUI | Workspace → Tools → Import from URL | Use REST endpoint, not MCP |
OpenWebUI does not support MCP. We continue to use the /owu-tool REST endpoint for it.
Claude Teams: company-wide integration
Claude Teams (Anthropic’s business tier) adds a company-wide MCP integration separate from per-user connectors. An admin configures it once and every team member gets access to the tools automatically: no individual setup required.
The configuration path is different from personal connectors:
- claude.ai personal connector: Settings → Integrations → Add MCP server
- Claude Teams company connector: Admin console → Settings → Integrations → Add MCP server
The URL format is the same. Once configured at the admin level, the MCP tools appear in every team member’s conversation context without them needing to do anything. For an internal knowledge base, this is the right setup: one config change, everyone covered.
nginx configuration for SSE
If you are proxying through nginx, SSE requires two additional directives in the location block. Without them, nginx buffers the response and streaming breaks:
location / {
proxy_pass http://localhost:8766;
proxy_buffering off;
proxy_read_timeout 120s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
proxy_buffering off tells nginx to pass chunks through immediately rather than accumulating the full response. proxy_read_timeout 120s prevents nginx from closing the connection during long-running tool calls.
If you use certbot to issue a TLS certificate, it modifies your nginx config automatically but does not add these directives. Add them manually to the server { listen 443 ... } block after certbot runs.
Current state
Our knowledge base server now has a single MCP endpoint that works across every client we use:
https://kb.example.com/mcp
It exposes two tools: search_kb and ask_kb. The entire team accesses it through their AI clients without any per-user configuration. The REST endpoints remain available for Claude Code and anything that prefers direct HTTP.
The previous post’s conclusion, that REST was the pragmatic choice while the MCP ecosystem matured, held for about two weeks. Streamable HTTP and broader client adoption changed the calculus. Both approaches are now worth running in parallel: REST for direct programmatic access, MCP for AI client interoperability.