MCP Server Reachable Over HTTP Without Authentication
The MCP server listens on the network and accepts tool calls from anyone.
Why it matters
Over stdio an MCP server only talks to the client that started it. Over HTTP it talks to anything that can reach the port, including other software on the same machine and, behind a careless reverse proxy, the internet. The tools it exposes run with the server's own file system, credentials and network access.
What it looks like
This is the shape of code that triggers the rule. AI tools produce it because it works, and nothing tells them it is unsafe.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("files")
@mcp.tool()
def read(path: str) -> str:
return open(path).read()
if __name__ == "__main__":
mcp.run(transport="sse")The smallest fix
import os
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import PlainTextResponse
class RequireToken(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
if request.headers.get("authorization") != f"Bearer {os.environ['MCP_TOKEN']}":
return PlainTextResponse("unauthorized", status_code=401)
return await call_next(request)
app = mcp.streamable_http_app()
app.add_middleware(RequireToken)The better fix
If you have a few more minutes, this is the approach that holds up as the app grows.
# For servers other people will use, FastMCP supports OAuth:
# mcp = FastMCP("name", auth=AuthSettings(...), token_verifier=MyVerifier())
# For a personal tool, run with transport="stdio" and skip HTTP entirely.Let your AI tool fix it
When the scanner finds this in your project, it fills in the file and line for you. This is the prompt it gives you to paste into Claude Code, Cursor or whatever you use.
How to check the fix worked
1. Send a tools/list request with no Authorization header and confirm a 401 response. 2. Send the same request with a valid token and confirm the tool list.