{"record":{"id":"680e9fe97f3f1919","repo":"Hmbown/CodeWhale","slug":"use-a-canonical-numeric-mcp-address","errorCode":null,"errorMessage":"Use a canonical numeric MCP address.","messagePattern":"Use a canonical numeric MCP address\\.","errorType":"validation","errorClass":"ConversionError","httpStatus":null,"severity":"error","filePath":"scripts/convert-plugin.py","lineNumber":243,"sourceCode":"        parsed = urlsplit(url)\n        host = parsed.hostname\n        require(bool(host) and parsed.port != 0, \"MCP URL needs a valid host and port.\")\n    except ValueError:\n        raise ConversionError(\"Invalid MCP endpoint URL.\") from None\n    require(parsed.scheme == \"https\" or (parsed.scheme == \"http\" and host in {\"localhost\", \"127.0.0.1\", \"::1\"}),\n            \"MCP endpoints need HTTPS (or explicit loopback HTTP).\")\n    require(parsed.username is None and parsed.password is None and not parsed.query and not parsed.fragment,\n            \"MCP URLs must not contain credentials, query strings or fragments.\")\n    require(host.isascii() and len(url) <= 4096, \"Use an ASCII MCP hostname and URL of at most 4096 characters.\")\n    # URL implementations disagree on shorthand/hex IPv4 spellings. Emit only\n    # canonical numeric hosts so the reviewed native host set is identical.\n    if \":\" in host or re.fullmatch(r\"(?:[0-9]+|0x[0-9a-f]+)\", host.rsplit(\".\", 1)[-1]):\n        try:\n            address = ipaddress.ip_address(host)\n            require(str(address) == host, \"Use a canonical numeric MCP address.\")\n            host = f\"[{host}]\" if address.version == 6 else host\n        except ValueError:\n            raise ConversionError(\"Use a canonical numeric MCP address.\") from None\n    headers = mapping(config.get(\"headers\", {}))\n    require(len(headers) <= 64, \"At most 64 environment-backed headers are supported.\")\n    env_headers = {}\n    seen_headers = set()\n    for key, value in headers.items():\n        require(re.fullmatch(r\"[A-Za-z0-9!#$%&'*+.^_`|~-]+\", key) is not None, \"Invalid HTTP header name.\")\n        require(key.lower() not in seen_headers and key.lower() not in {\"accept\", \"content-type\"},\n                \"HTTP header names must be unique ignoring case; Accept and Content-Type belong to the native transport.\")\n        seen_headers.add(key.lower())\n        require(isinstance(value, str), \"HTTP headers must reference environment variable names.\")\n        reference = re.fullmatch(r\"\\{env:([A-Za-z_][A-Za-z0-9_]*)\\}\", value) if dialect != \"dsh\" else None\n        require(reference is not None, \"Literal headers, DSH expressions and file interpolation cannot be converted; author native env_headers manually.\")\n        env_headers[key] = reference[1]\n    if env_headers:\n        extension[\"env_headers\"] = env_headers\n    return {\"type\": \"streamable-http\", \"url\": url,\n            \"extensions\": {\"net.codewhale\": extension}}, host\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/convert-plugin.py#L225-L261","documentation":"remote_server() canonicalizes numeric host addresses (IP literals) and raises this error when the host is a numeric/IPv6 form but not in its canonical spelling (str(ipaddress.ip_address(host)) != host), or when ipaddress itself rejects the host.","triggerScenarios":"Hostnames ending in a purely numeric or hex last label (e.g. '0x7f.1', '2130706433') that don't match their canonical IP form, or malformed IPv6 strings that fail ipaddress parsing.","commonSituations":"Using integer or hex shorthand for IPs ('127.1', '0x7f000001'); non-canonical IPv6 like '2001:db8::1:0:0:1' vs compressed form; leading-zero IPv4 octets.","solutions":["Spell the address in canonical form: use dotted-quad IPv4 exactly as ip_address() prints it, or the compressed IPv6 form","Run python -c \"import ipaddress; print(ipaddress.ip_address('YOUR_HOST'))\" to get the canonical spelling","Prefer an ASCII DNS hostname instead of a numeric address"],"exampleFix":"// before\n\"url\": \"http://0x7f000001:8080\"\n// after\n\"url\": \"http://127.0.0.1:8080\"","handlingStrategy":"validation","validationCode":"import ipaddress\naddr = ipaddress.ip_address(host)  # raises for non-canonical/invalid forms\nassert str(addr) == host, \"use canonical numeric address\"","typeGuard":"def is_canonical_ip(host: str) -> bool:\n    try:\n        return str(ipaddress.ip_address(host)) == host\n    except ValueError:\n        return False","tryCatchPattern":null,"preventionTips":["Prefer DNS hostnames over numeric IP literals","Never use hex/integer IP shorthand or leading-zero octets","Get the canonical form via python -c \"import ipaddress; print(ipaddress.ip_address(h))\""],"tags":["python","ip","url","mcp"],"backgroundTag":"invalid-url-format","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}