Troubleshooting
Common problems and how to diagnose them.
Startup errors
scoped-mcp fails fast at startup and exits with a clear message. The ops log
(stderr / --ops-log) shows the sequence of initialization steps and where
it stopped.
Missing AGENT_ID or AGENT_TYPE
error: AGENT_ID environment variable is not set
Both must be set before starting scoped-mcp. In Claude Code settings.json,
set them in the env block. On the command line:
AGENT_ID=research-01 AGENT_TYPE=research scoped-mcp --manifest manifests/research-agent.yml
Missing required credentials
error: Missing required environment variable(s): INFLUXDB_TOKEN, GRAFANA_URL
scoped-mcp lists every missing credential in one error and exits without starting partially. Set the missing env vars and restart. The credential reference table in the README lists required and optional vars for each module.
Manifest not found or invalid
error: [Errno 2] No such file or directory: 'manifests/research-agent.yml'
error: manifest validation error: modules: field required
Check the path passed to --manifest. Paths are relative to the working
directory at startup, not the manifest’s location. Use an absolute path to
avoid ambiguity.
Module not recognized
error: Unknown module 'redis' — not registered. Available: filesystem, sqlite, ...
Custom modules must be importable from the Python environment. See
examples/custom-module/ for the registration pattern.
Confirming successful startup
On clean startup, the ops log emits four events in sequence:
{"event": "startup", "logger": "ops", "manifest": "manifests/ops-agent.yml", ...}
{"event": "identity_resolved", "logger": "ops", "agent_id": "ops-01", "agent_type": "ops", ...}
{"event": "manifest_loaded", "logger": "ops", "modules": ["influxdb", "grafana", "ntfy"], ...}
{"event": "server_ready", "logger": "ops", "transport": "stdio", ...}
If server_ready does not appear, look at the last ops event for the failure point.
To write ops logs to a file for easier inspection:
scoped-mcp --manifest manifests/ops-agent.yml --ops-log /tmp/ops.jsonl
Scope violations
Reading a scope violation in the audit log
Every scope violation is logged as a scope_violation event with status: blocked:
{
"event": "scope_violation",
"logger": "audit",
"level": "warning",
"agent_id": "build-01",
"tool": "filesystem_read_file",
"args": {"path": "/data/agents/research-01/private.txt"},
"status": "blocked",
"error": "Path '/data/agents/research-01/private.txt' is outside the agent scope for 'build-01'. Expected prefix: /data/agents/build-01",
"elapsed_ms": 0.12,
"timestamp": "..."
}
The error field contains the full scope message. The args field shows
exactly what the agent passed. No backend operation occurs after a violation.
“I got a ScopeViolation but the path looks correct”
Check that base_path in the manifest resolves to the same directory the
agent is writing to. A common issue: base_path: /tmp/scoped-mcp-data resolves
differently if a symlink is involved. Prefer absolute paths without symlinks.
For traversal-style paths (../, symlinks in the path), scoped-mcp resolves
the full path before checking — the resolved path must fall under
{base_path}/agents/{agent_id}/.
Filtering violations in the audit log
# All scope violations for a specific agent
cat audit.jsonl | jq 'select(.event == "scope_violation" and .agent_id == "build-01")'
# All tool calls that were blocked
cat audit.jsonl | jq 'select(.status == "blocked")'
# All tool calls by tool name
cat audit.jsonl | jq 'select(.event == "tool_call" and .tool == "filesystem_write_file")'
Audit and ops log flags
By default, both log streams go to stderr as JSON-L. To write to files:
scoped-mcp \
--manifest manifests/ops-agent.yml \
--audit-log /var/log/scoped-mcp/ops-audit.jsonl \
--ops-log /var/log/scoped-mcp/ops.jsonl
Stderr output continues even when file paths are set — both destinations receive all events. The file output is useful for log shipping (Loki, Splunk, ELK) without losing terminal visibility.
Audit events have "logger": "audit". Ops events have "logger": "ops".
Filter by logger when both streams go to the same destination.
Tools not appearing in Claude Code
If scoped-mcp starts but tools don’t appear in the Claude Code tool list:
- Check that
server_readyappears in the ops log — if not, startup failed silently. - Verify the manifest module names match the built-in module registry (see README).
- Check that the
modefield is set correctly —mode: readgives only read tools; write-only modules likentfyneed nomodefield. - Restart Claude Code after changing
settings.json— MCP servers are started once per session.
Credential values appearing in logs
This should not happen — the sanitization processor redacts values whose keys match
known sensitive suffixes (_TOKEN, _PASSWORD, _SECRET, _KEY, etc.) and a
fixed set of common names (token, password, api_key, etc.).
If you observe a credential value in a log entry, open a security issue via the
private channels in SECURITY.md rather than a public GitHub issue.