highLogins, sessions and access

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.

Streamable HTTP transport with no auth
import express from 'express';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
const app = express();
app.post('/mcp', async (req, res) => {
  const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
  await server.connect(transport);
  await transport.handleRequest(req, res, req.body);
});
app.listen(3000);

The smallest fix

minimal patch
// Check a bearer token before the transport sees the request
app.use('/mcp', (req, res, next) => {
  const token = req.headers.authorization?.replace(/^Bearer /, '');
  if (!token || token !== process.env.MCP_TOKEN) return res.status(401).end();
  next();
});

The better fix

If you have a few more minutes, this is the approach that holds up as the app grows.

safe alternative
// The SDK ships OAuth helpers for servers that other people will use:
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
app.use('/mcp', requireBearerAuth({ verifier, requiredScopes: ['tools'] }));
// For a personal tool, prefer the stdio transport 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.

In [the file] at line [the line number] an MCP server is exposed over HTTP without authentication: [the flagged code]. If this server is only used locally, switch to StdioServerTransport. Otherwise add middleware before the transport that rejects requests without a valid bearer token (or use the SDK's requireBearerAuth with an OAuth verifier), bind to 127.0.0.1 unless remote access is intended, and add a test that an unauthenticated tools/list request gets 401.

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.