xai-org/grok-build · error
failed to serialize MCP server {name}: {e}
Error message
failed to serialize MCP server {name}: {e} What it means
merge_mcp_servers could not convert a server's JSON config value into a TOML value (toml::Value::try_from failed). TOML cannot represent every JSON shape, e.g. top-level arrays or nulls, so the server entry is rejected rather than written incorrectly.
Source
Thrown at crates/codegen/xai-grok-shell/src/claude_import.rs:987
/// Merge MCP server configs into `[mcp_servers]`. Existing servers are NOT overwritten.
fn merge_mcp_servers(
table: &mut TomlMap<String, TomlValue>,
servers: &[(&str, &McpServerConfig)],
) -> anyhow::Result<usize> {
let mcp = table
.entry("mcp_servers")
.or_insert_with(|| TomlValue::Table(TomlMap::new()));
let mcp_table = mcp
.as_table_mut()
.ok_or_else(|| anyhow::anyhow!("[mcp_servers] is not a table"))?;
let mut count = 0;
for (name, config) in servers {
// Don't overwrite existing server entries.
if !mcp_table.contains_key(*name) {
let serialized = toml::Value::try_from(*config)
.map_err(|e| anyhow::anyhow!("failed to serialize MCP server {name}: {e}"))?;
mcp_table.insert(name.to_string(), serialized);
count += 1;
}
}
Ok(count)
}
/// Merge a list of path strings into `[paths] <key>` (an array of strings).
///
/// Existing entries are preserved; new entries that aren't already present
/// are appended. Returns the number of newly added entries.
fn merge_paths(
table: &mut TomlMap<String, TomlValue>,
key: &str,
new_paths: &[&str],
) -> anyhow::Result<usize> {
let paths = table
.entry("paths")View on GitHub (pinned to bc7f02eddd)
Solutions
- Remove/null-out unsupported values (nulls) in the server's JSON config before importing.
- Provide a TOML-compatible object (strings, numbers, booleans, arrays, tables only) for the server config.
- Skip the failing server and add its entry manually under [mcp_servers.<name>] in the config.
Example fix
// before (claude_desktop_config.json)
{ "mcpServers": { "fs": { "env": null } } }
// after
{ "mcpServers": { "fs": { "env": {} } } } Defensive patterns
Strategy: try-catch
Validate before calling
fn toml_compatible(v: &serde_json::Value) -> bool {
match v {
serde_json::Value::Null => false,
serde_json::Value::Array(a) => a.iter().all(toml_compatible),
serde_json::Value::Object(o) => o.values().all(toml_compatible),
_ => true,
}
} Type guard
fn is_toml_representable(v: &serde_json::Value) -> bool {
toml::Value::try_from(v).is_ok()
} Try / catch
match apply_import(items, &path) {
Err(e) if e.to_string().contains("failed to serialize MCP server") => {
let name = /* extract from message */;
eprintln!("Server '{name}' has TOML-unsupported values (likely nulls); fix its JSON config");
}
r => r?,
} Prevention
- Remove null values from MCP server JSON configs before importing (use empty objects/maps instead).
- Pre-sanitize JSON with a TOML-representability check.
- Prefer skipping/normalizing problematic servers instead of failing the whole import.
When it happens
Trigger: apply_items_to_config imports an MCP server whose config object contains a null value or another TOML-unsupported shape, causing toml::Value::try_from to fail.
Common situations: Claude JSON config has "env": null or a null array element; server config with keys TOML cannot map directly.
Related errors
- failed to serialize MCP server config: {e}
- [mcp_servers] is not a table
- Failed to create agent config: {e}
- Failed to load config: {e}
- Failed to parse config.toml: {e}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/9d40f7ec854806e7.
Report an issue: GitHub.