From the salesagent v3.12 → 4.x migration (SDK_FEEDBACK.md, item #13).
SubdomainTenantMiddleware and the FastMCP allowed_hosts allowlist treat host registration asymmetrically:
- Registering
acme.localhost once in InMemorySubdomainTenantRouter covers both acme.localhost and acme.localhost:3001 at lookup time (per _normalize_host).
- The FastMCP
allowed_hosts allowlist needs both acme.localhost and acme.localhost:* registered explicitly to cover the same surface.
Adopter worked around it in core/main.py's _allowed_hosts() helper by synthesizing the :* variant.
Ask
Make SubdomainTenantMiddleware (or serve()) accept a single host list and synthesize the :* variants for the allowlist automatically. The existing port-stripping at lookup time is great; the allowlist surface should be symmetric.
Acceptance
A single hosts=["acme.localhost", "beta.localhost"] configuration reaches both lookup and allowlist paths without adopter-side string juggling.
From the salesagent v3.12 → 4.x migration (
SDK_FEEDBACK.md, item #13).SubdomainTenantMiddlewareand the FastMCPallowed_hostsallowlist treat host registration asymmetrically:acme.localhostonce inInMemorySubdomainTenantRoutercovers bothacme.localhostandacme.localhost:3001at lookup time (per_normalize_host).allowed_hostsallowlist needs bothacme.localhostandacme.localhost:*registered explicitly to cover the same surface.Adopter worked around it in
core/main.py's_allowed_hosts()helper by synthesizing the:*variant.Ask
Make
SubdomainTenantMiddleware(orserve()) accept a single host list and synthesize the:*variants for the allowlist automatically. The existing port-stripping at lookup time is great; the allowlist surface should be symmetric.Acceptance
A single
hosts=["acme.localhost", "beta.localhost"]configuration reaches both lookup and allowlist paths without adopter-side string juggling.