coleam00/Archon · error
MCP config ${fieldPath}.${key} must be a string (got ${descr
Error message
MCP config ${fieldPath}.${key} must be a string (got ${describeJsonType(val)}) What it means
While expanding environment-variable references in an MCP server's env or headers record, the library requires every value to be a plain string. A non-string value (number, boolean, null, array, object) makes interpolation impossible, so expandEnvVarsInRecord throws with the exact field path and the JSON type it found. Missing variables are tolerated (collected in missingVars), but wrong types are not.
Source
Thrown at packages/providers/src/mcp/config.ts:31
if (value === null) return 'null';
if (Array.isArray(value)) return 'array';
return typeof value;
}
/**
* Expand $VAR_NAME and ${VAR_NAME} references in string-valued records from
* the supplied environment source.
*/
function expandEnvVarsInRecord(
record: Record<string, unknown>,
missingVars: string[],
envSource: EnvSource,
fieldPath: string
): Record<string, string> {
const result: Record<string, string> = {};
for (const [key, val] of Object.entries(record)) {
if (typeof val !== 'string') {
throw new Error(
`MCP config ${fieldPath}.${key} must be a string (got ${describeJsonType(val)})`
);
}
result[key] = val.replace(
/\$(?:\{([A-Z_][A-Z0-9_]*)\}|([A-Z_][A-Z0-9_]*))/g,
(_, braced: string | undefined, bare: string | undefined) => {
const varName = braced ?? bare ?? '';
const envVal = envSource[varName];
if (envVal === undefined) {
missingVars.push(varName);
}
return envVal ?? '';
}
);
}
return result;
}
View on GitHub (pinned to 0773b97458)
Solutions
- Quote the offending value as a string in the config: true -> "true", 3 -> "3".
- Move non-string data out of env/headers into a config key the server accepts natively.
- Validate the JSON config with a schema (e.g. zod: Record<string,string>) before loading.
Example fix
// before
{"env": {"DEBUG": true, "PORT": 8080}}
// after
{"env": {"DEBUG": "true", "PORT": "8080"}} Defensive patterns
Strategy: validation
Validate before calling
function assertStringRecord(env: unknown, path: string): asserts env is Record<string, string> {
if (typeof env !== 'object' || env === null || Array.isArray(env) ||
!Object.values(env).every((v) => typeof v === 'string')) {
throw new Error(`${path} must be an object of string values`);
}
}
// before loadMcpConfig: for each server in parsed config, assertStringRecord(server.env, `${name}.env`) Type guard
const isStringRecord = (v: unknown): v is Record<string, string> => typeof v === 'object' && v !== null && !Array.isArray(v) && Object.values(v).every((x) => typeof x === 'string');
Prevention
- Keep all env/headers values quoted in JSON, even booleans and numbers.
- Add a JSON schema (additionalProperties: {type: 'string'}) and validate in editor/CI.
- Run a preflight JSON parse + shape check before loadMcpConfig in scripts.
When it happens
Trigger: Calling loadMcpConfig on a JSON config where a server's env or headers entry has a non-string value, e.g. {"env": {"DEBUG": true}} or {"headers": {"X-Retries": 3}}.
Common situations: Hand-editing a config with numeric flags or booleans; copying a Docker/CLI env format that allows integers; a tool exporting env with structured values; JSON schema drift after editing by script.
Related errors
- MCP config ${serverName}.env must be a JSON object of string
- MCP server "${serverName}" must be a JSON object (got ${desc
- MCP config ${serverName}.headers must be a JSON object of st
- MCP config cannot mix top-level "mcpServers" with other keys
- MCP config field "mcpServers" must be a JSON object: ${mcpPa
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/79dfc7a44ca5eaf0.
Report an issue: GitHub.