Panniantong/Agent-Reach · error · McporterConfigError
mcporter 配置顶层必须是对象
Error message
mcporter 配置顶层必须是对象
What it means
Raised when the parsed mcporter config JSON is not a top-level object (dict). The whole layer schema is an object with mcpServers/imports/defaults keys; a top-level array, string, number, or bare null fails isinstance(payload, dict).
Source
Thrown at agent_reach/channels/mcporter.py:129
try:
raw = read_small_text_no_follow(
config_path,
max_bytes=_MAX_CONFIG_BYTES,
)
except PrivatePathError as exc:
raise McporterConfigError(
f"mcporter 配置文件无法安全读取:{exc}"
) from exc
except (OSError, UnicodeError) as exc:
raise McporterConfigError("mcporter 配置文件无法安全读取") from exc
if raw is None:
raise McporterConfigError("mcporter 配置文件不存在")
try:
payload = json.loads(raw)
except json.JSONDecodeError as exc:
raise McporterConfigError("mcporter 配置不是有效的 UTF-8 JSON") from exc
if not isinstance(payload, dict):
raise McporterConfigError("mcporter 配置顶层必须是对象")
return payload
def configured_server_names(output: str) -> set[str]:
"""Return exact configured server names from ``mcporter ... --json``.
Paths, descriptions, endpoints, and other metadata are deliberately
ignored: only each server object's ``name`` field is a routing signal.
"""
try:
payload = json.loads(output)
except (json.JSONDecodeError, TypeError) as exc:
raise McporterConfigError("mcporter 返回的 JSON 无法解析") from exc
if not isinstance(payload, dict) or not isinstance(payload.get("servers"), list):
raise McporterConfigError("mcporter JSON 缺少 servers 列表")
return {View on GitHub (pinned to 93ae1d18c3)
Solutions
- Wrap the content in an object: '{ "mcpServers": { ...your entries... } }'
- If the file is meaningless, delete it — missing layers are skipped without error
- Check what wrote the file (script/template) and fix its output shape
Example fix
// before
[ { "command": "npx" } ]
// after
{ "mcpServers": { "srv": { "command": "npx" } } } Defensive patterns
Strategy: validation
Validate before calling
import json
def config_toplevel_is_object(path) -> bool:
try:
return isinstance(json.load(open(path, encoding="utf-8")), dict)
except Exception:
return False Type guard
def is_config_object(payload) -> bool:
return isinstance(payload, dict) Try / catch
except McporterConfigError as exc:
if "顶层必须是对象" in str(exc):
show("wrap the file content in { \"mcpServers\": {...} }") Prevention
- Top level of mcporter.json is always an object
- Watch out for jq transforms that output arrays
- An empty object {} satisfies the check; null does not
When it happens
Trigger: mcporter.json contains '[{...}]', '"just a string"', or 'null' at the top level. Note json.loads('null') returns None which is not a dict → this error (distinct from the YAML channel where None returns 'not configured').
Common situations: A jq transform outputting an array; a file containing only a quoted string (e.g. from echo '"$VALUE"' with empty/odd value); an effectively empty file written as 'null'.
Related errors
- mcporter 配置缺少 mcpServers 对象
- mcporter 配置包含无效的 server name
- mcporter server 定义必须是对象
- mcporter imports 必须是字符串列表
- mcporter 配置不是有效的 UTF-8 JSON
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/05bdc91a77c75af2.
Report an issue: GitHub.