v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.py.mcp.unauthenticated-server

This MCP server is exposed over a NETWORK transport (streamable-http / SSE) but was constructed with no authentication: no auth= and no token_verifier=.

Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.

Why this matters

Its tools are reachable by anyone who can reach the port (CWE-306). A Knostic scan found none of ~2,000 internet-exposed MCP servers required auth; unauthenticated /mcp endpoints are the surface behind CVE-2026-66012 and the Q2-2026 MCP exposure wave.

Require auth before serving over the network: mcp = FastMCP("name", token_verifier=verifier, auth=AuthSettings(issuer_url=..., resource_server_url=..., required_scopes=[...])) (A stdio transport is local and out of scope for this rule.)

VULNERABLE
vulnerable.py
mcp = FastMCP("demo")

@mcp.tool()
def run_query(sql: str) -> str:
    return sql

# ruleid: auth.py.mcp.unauthenticated-server
mcp.run(transport="streamable-http")
SAFE
safe.py
mcp = FastMCP(
    "demo",
    token_verifier=verifier,
    auth=AuthSettings(issuer_url="https://as", resource_server_url="https://rs"),
)

# ok: auth.py.mcp.unauthenticated-server
mcp.run(transport="streamable-http")

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

# oauthlint-disable-next-line auth.py.mcp.unauthenticated-server -- <reason>

References

https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization ↗https://healthsystemcio.com/2026/07/28/mcp-server-exposure-health-isac/ ↗