Panniantong/Agent-Reach · error · McporterConfigError
mcporter server 定义必须是对象
Error message
mcporter server 定义必须是对象
What it means
Raised when a value under mcpServers is not a JSON object. Each server must be a mapping (command/args/env or url etc.); a string, array, number, or null value fails the isinstance(definition, dict) check and aborts the whole inspection.
Source
Thrown at agent_reach/channels/mcporter.py:62
"""
selected_layers = _select_config_layers(root_dir)
if not selected_layers:
return McporterConfigInspection(frozenset(), None)
names = set()
imports_unchecked = False
sources = []
for config_path, source in selected_layers:
payload = _read_config_object(config_path)
servers = payload.get("mcpServers")
if not isinstance(servers, dict):
raise McporterConfigError("mcporter 配置缺少 mcpServers 对象")
for name, definition in servers.items():
if not isinstance(name, str) or not name.strip():
raise McporterConfigError("mcporter 配置包含无效的 server name")
if not isinstance(definition, dict):
raise McporterConfigError("mcporter server 定义必须是对象")
names.add(name.casefold())
imports = payload.get("imports", _MISSING)
if imports is _MISSING:
# mcporter defaults to importing supported editor configs when the
# key is omitted. Doctor intentionally does not open those files.
imports_unchecked = True
elif not isinstance(imports, list) or not all(
isinstance(item, str) for item in imports
):
raise McporterConfigError("mcporter imports 必须是字符串列表")
elif imports:
imports_unchecked = True
sources.append(source)
return McporterConfigInspection(
frozenset(names),
"+".join(sources),View on GitHub (pinned to 93ae1d18c3)
Solutions
- Wrap each value in an object with the standard fields: '"name": { "command": "...", "args": [...] }' or '"name": { "url": "https://..." }'
- Validate with: jq -e '.mcpServers | to_entries | all(.value | type == "object")' file.json
- To disable a server, delete the key rather than setting it to null
Example fix
// before
{ "mcpServers": { "github": "ghcop mcp serve" } }
// after
{ "mcpServers": { "github": { "command": "ghcop", "args": ["mcp", "serve"] } } } Defensive patterns
Strategy: validation
Validate before calling
import json
def server_defs_ok(path) -> bool:
try:
servers = json.load(open(path, encoding="utf-8")).get("mcpServers", {})
except Exception:
return False
return all(isinstance(v, dict) for v in servers.values()) Type guard
def valid_server_entries(servers: dict) -> bool:
return all(isinstance(k, str) and k.strip() and isinstance(v, dict) for k, v in servers.items()) Try / catch
except McporterConfigError as exc:
if "定义必须是对象" in str(exc):
hint = "each mcpServers value needs {command, args} or {url} shape" Prevention
- Every server value must be an object; wrap bare command strings
- Comment out by removing keys, not nulling values
- Validate pasted configs: jq '.mcpServers | map_values(type=="object")'
When it happens
Trigger: mcpServers contains e.g. '"github": "ghcop mcp serve"' (bare command string), '"github": ["cmd", "arg"]', or '"github": null' in any selected layer.
Common situations: Shorthand configs from blog posts that put the command string directly as the value instead of {"command": ...}; YAML-style config pasted into JSON; a key set to null when commenting out a server.
Related errors
- mcporter 配置缺少 mcpServers 对象
- mcporter 配置包含无效的 server name
- mcporter imports 必须是字符串列表
- mcporter 配置不是有效的 UTF-8 JSON
- mcporter 配置顶层必须是对象
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/6ae9e5b25ff0eae1.
Report an issue: GitHub.