{"record":{"id":"501ff56fe0ead8fe","repo":"Hmbown/CodeWhale","slug":"source-contains-unsupported-mcp-fields-review-it-at-its","errorCode":null,"errorMessage":"Source contains unsupported MCP fields; review it at its source","messagePattern":"Source contains unsupported MCP fields; review it at its source","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp/external_import.rs","lineNumber":182,"sourceCode":"            \"allow_private_network\",\n            \"transport\",\n            \"connect_timeout\",\n            \"execute_timeout\",\n            \"read_timeout\",\n            \"disabled\",\n            \"enabled\",\n            \"required\",\n            \"enabled_tools\",\n            \"disabled_tools\",\n            \"headers\",\n            \"env_headers\",\n            \"env_http_headers\",\n            \"bearer_token_env_var\",\n            \"scopes\",\n            \"oauth\",\n            \"oauth_resource\",\n        ];\n        anyhow::ensure!(\n            fields.keys().all(|key| ALLOWED.contains(&key.as_str())),\n            \"Source contains unsupported MCP fields; review it at its source\"\n        );\n        if let Some(oauth) = fields.get(\"oauth\").filter(|v| !v.is_null()) {\n            anyhow::ensure!(\n                oauth\n                    .as_object()\n                    .is_some_and(|map| map.keys().all(|key| key == \"client_id\")),\n                \"Source contains unsupported OAuth fields\"\n            );\n        }\n        let server: McpServerConfig = serde_json::from_value(config)\n            .map_err(|_| anyhow::anyhow!(\"Invalid MCP entry; contents omitted\"))?;\n        anyhow::ensure!(\n            server.command.is_some() != server.url.is_some(),\n            \"MCP entry must have one target\"\n        );\n        if let Some(command) = &server.command {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp/external_import.rs#L164-L200","documentation":"Imported server entries may only contain a whitelist of fields (command, args, env, cwd, url, headers, env_http_headers, bearer_token_env_var, scopes, oauth, oauth_resource, etc.). If an entry has any key outside ALLOWED, checked_source refuses the import and tells you to review the source, because unknown fields could carry behavior the importer cannot safely translate.","triggerScenarios":"discover / discover_from_json_file where a server entry contains a key not in the ALLOWED list — e.g. \"type\", \"disabled\", \"timeout\", \"transport\", tool-specific vendor fields, or nested metadata added by another client.","commonSituations":"Importing configs from other MCP clients that store extra per-server options (type: \"stdio\", disabled flags, timeouts, prompts); a hand-added note or comment field; schema drift after the exporting tool updated its format.","solutions":["Remove or rename unsupported keys in the source entry, keeping only whitelisted fields (command, args, env, cwd, url, headers, env_http_headers, bearer_token_env_var, scopes, oauth, oauth_resource)","Re-express needed semantics with supported fields (e.g. map a transport type to command vs url) and re-run discovery","Review the source at its origin as the message says — determine which tool wrote the extra fields and whether they matter before stripping them"],"exampleFix":"// before (unsupported field \"timeout\")\n{ \"fs\": { \"command\": \"npx\", \"timeout\": 30 } }\n// after\n{ \"fs\": { \"command\": \"npx\" } }","handlingStrategy":"validation","validationCode":"const ALLOWED: &[&str] = &[\"command\",\"args\",\"env\",\"cwd\",\"url\",\"headers\",\"env_http_headers\",\"bearer_token_env_var\",\"scopes\",\"oauth\",\"oauth_resource\"];\nfn entries_use_allowed_fields(path: &std::path::Path) -> bool {\n    std::fs::read_to_string(path).ok()\n        .and_then(|s| serde_json::from_str::<serde_json::Value>(&s).ok())\n        .and_then(|v| v.get(\"mcpServers\").or_else(|| v.get(\"servers\")).cloned())\n        .and_then(|m| m.as_object().cloned())\n        .map(|m| m.values().all(|e| e.as_object()\n            .map_or(false, |o| o.keys().all(|k| ALLOWED.contains(&k.as_str())))))\n        .unwrap_or(false)\n}","typeGuard":"fn only_allowed_fields(v: &serde_json::Value) -> bool {\n    v.as_object().map_or(false, |o|\n        o.keys().all(|k| ALLOWED.contains(&k.as_str())))\n}","tryCatchPattern":"match discover(&path) {\n    Err(e) if e.to_string().contains(\"unsupported MCP fields\") => {\n        eprintln!(\"strip non-whitelisted fields from the source entries and re-import\");\n    }\n    r => r?,\n}","preventionTips":["Keep exported entries limited to the whitelisted fields; drop vendor extras like type/disabled/timeout","Map needed semantics to supported fields before import instead of passing them through","Diff source entries against a known-good importable template after tool upgrades","Review foreign configs at their origin before importing, as the error message advises"],"tags":["mcp","import","validation"],"backgroundTag":"unsupported-config-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T10:30:35.592Z"}