koala73/worldmonitor · error · McpProxySsrfError
serverUrl DNS resolution failed
Error message
serverUrl DNS resolution failed: ${message} What it means
SSRF guard error in the MCP proxy's assertServerUrlSafe: resolving the hostname's A/AAAA records via DoH threw (network, timeout, or DNS status failure), so safety could not be established. The underlying error message is embedded; the request is refused rather than allowed through unverified.
Solutions
- Retry — transient DoH failures resolve on retry
- Verify the hostname resolves publicly (dig/nslookup from another host)
- If the DoH endpoint is unreachable from the edge runtime, fix egress or the DNS_JSON_ENDPOINT configuration
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at api/mcp-proxy.ts:168 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- DNS resolution errors: ENOTFOUND and getaddrinfo failures — how hostname lookups fail and how to debug them.
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-08-21).
Data as JSON: /api/errors/d5dd50f418898a25.
Report an issue: GitHub.
Appendix: source
Thrown at api/mcp-proxy.ts:170
* OPTIONS preflights are deliberately NOT emitted — a static 204 that cannot
* fail would double row volume for no diagnostic value. /mcp skips them too
* (McpUsage.skip).
*/
function emitProxyUsage(req, status: number, durationMs: number, ctx, callerIdentity = null): void {
if (!ctx) return;
try {
const usageIdentity = proxyUsageIdentityFor(req, callerIdentity);
emitUsageEvents(ctx, [buildRequestEvent({
requestId: deriveRequestId(req),
domain: 'mcp',
route: '/api/mcp-proxy',
method: req.method,
status,
// Measured from handler entry, so this INCLUDES the auth/rate-limit
// gates — unlike logProxyCall's `started`, which begins after auth.
// The usage row is the end-to-end caller-visible latency.
durationMs,
reqBytes: deriveReqBytes(req),
// Not tracked: the proxy streams upstream bodies through bounded readers
// and jsonResponse sets no content-length, so there is no byte count to
// report without buffering a second time. Size questions belong to
// MAX_MCP_PROXY_RESPONSE_BYTES, not to this row.
resBytes: 0,
customerId: usageIdentity.customer_id,
principalId: usageIdentity.principal_id,
authKind: usageIdentity.auth_kind,
tier: usageIdentity.tier,
planKey: usageIdentity.plan_key,
country: deriveCountry(req),
ipCity: deriveIpCity(req),
ipRegion: deriveIpRegion(req),
executionRegion: deriveExecutionRegion(req),
executionPlane: 'vercel-edge',
originKind: 'mcp',
cacheTier: 'no-store',
ip: deriveIp(req),View on GitHub (pinned to 7d06c8633d)