An authless StreamableHTTP server is reachable by anything on the internet.
There are three resources to protect: your compute, any upstream API quota
your tools consume, and egress bandwidth for large callServerTool payloads.
In authless mode there is no token and stateless transport gives no session ID. Traffic from claude.ai is proxied through Anthropic's egress — every web user arrives from the same small set of IPs:
160.79.104.0/21
2607:6bc0::/48
(See https://platform.claude.com/docs/en/api/ip-addresses.)
Claude Desktop, Claude Code, and other hosts connect directly from the user's machine, so those do have distinct per-user IPs. Per-IP limiting therefore works for direct-connect clients; for claude.ai you can only limit the aggregate Anthropic pool. If true per-user limits matter, that's the trigger to add OAuth.
const ANTHROPIC_CIDRS = ["160.79.104.0/21", "2607:6bc0::/48"];
const TIERS = {
anthropic: { capacity: 600, refillPerSec: 100 }, // shared pool
other: { capacity: 30, refillPerSec: 2 }, // per-IP
};
Match req.ip against the CIDRs, pick a bucket ("anthropic" or
"ip:<addr>"), 429 + Retry-After on exhaust. This is a per-replica
backstop — cross-replica enforcement belongs at the edge (Cloudflare, Cloud
Armor), which keeps the containers stateless.
trust proxy must match your topologyreq.ip only honours X-Forwarded-For if app.set('trust proxy', N) is
set. true trusts every hop, which lets a direct client send
X-Forwarded-For: 160.79.108.42 and claim the Anthropic tier. Set it to the
exact number of trusted hops (e.g. 1 behind a single LB, 2 behind
Cloudflare → origin LB) and never true in production.
Blocking everything outside 160.79.104.0/21 locks out Desktop, Claude Code,
and every other MCP host. Use the CIDRs to tier rate limits, not to gate
access, unless claude.ai-only is an explicit goal.
For tools that wrap a third-party API, an in-process LRU keyed on the normalized query (TTL hours, no secrets in the key) is the primary cost control — repeat queries become free and absorb thundering-herd. Rate limits are the safety net, not the first line.