CertSafari
    CCAR-P · Lessons

    Domain 7 · Lesson 38/38

    Debugging Claude Code Configuration, MCP Servers and Hooks

    Support debugging and operational issue resolution

    8 min read
    2.33% of exam
    2 sources
    Published 27 Sep 2026
    Docs as of 26 Sep 2026

    What you will be able to do

    • Pick the right built-in command (/doctor, /mcp, /hooks, /permissions, /status, /debug) to inspect a misbehaving setup
    • Diagnose MCP servers that never load, fail to start, or list zero tools, and read their stderr from the debug log
    • Fix the common reasons hooks never fire and settings seem to be ignored
    • Isolate a faulty customisation with a clean config directory or safe mode, and handle memory and search problems

    1.Inspect what Claude Code actually loaded

    When settings don't apply, hooks don't fire or MCP servers don't load, the first question is what Claude Code actually resolved, not what you believe you configured. Each area has a built-in command that shows its live state. Use these before editing any file. They tell you whether the problem is a missing entry, an entry that was rejected, or an entry that is overridden by something with higher precedence.

    Built-in commands for inspecting configuration
    CommandShows
    /doctorInstallation health, invalid settings files, unused extensions, duplicate subagent names, with proposed fixes
    /mcpConnected MCP servers and their status
    /hooksActive hook configurations
    /permissionsResolved allow and deny rules currently in effect
    /statusActive settings sources, including whether managed settings are in effect
    /debug [issue]Enables debug logging and prompts Claude to diagnose using the log output and settings paths

    /status matters in team deployments. If an organisation pushes managed settings, a local file may seem to be ignored simply because a managed setting takes priority. Check the active sources before assuming your file is broken.

    Sources12

    2.MCP servers: never loaded, failed, or empty

    MCP problems show up in three distinct ways, and each has its own cause. If the server never appears at all, the config is usually in the wrong place. Project servers belong in .mcp.json at the repository root, under the mcpServers key. Common mistakes are putting the file inside .claude/, using VS Code's top-level servers key, or adding mcpServers to settings.json, which does not read that key. A project server that is configured correctly also stays disabled until someone approves it. If the one-time approval prompt was dismissed, approve the server from /mcp.

    If the server shows as failed, suspect the launch command. Relative paths in command or args resolve against the directory you started Claude Code from, not against the location of .mcp.json. That is why a server can work from one directory and fail from another. Use absolute paths for local scripts. Executables on PATH, such as npx or uvx, work as they are. If the server starts without the environment variables it needs, set them per server in its .mcp.json entry. If the server shows as connected but lists zero tools, it started but is not returning a tool list. Select Reconnect in /mcp. If the count stays at zero, turn on MCP debug logging and read the server's own stderr.

    MCP symptoms by status
    What /mcp showsLikely causeNext step
    Server missingFile under .claude/, servers key instead of mcpServers, or mcpServers in settings.jsonMove config to .mcp.json at the repo root under mcpServers
    Server disabledOne-time project approval was dismissedApprove it from /mcp
    failedRelative path in command or argsUse absolute paths for local scripts
    Connected, zero toolsServer not returning a tool listReconnect, then run claude --debug=mcp and read stderr

    An admin sets model: claude-opus-4-8 in the project's .claude/settings.json so the whole team defaults to Opus. One engineer's sessions keep starting on Sonnet instead, and /status confirms project settings are being read. What is the most likely explanation?

    Sources1

    3.Why hooks never fire and settings seem ignored

    Hook failures are usually silent, which makes them hard to spot. A matcher is a single string, with | separating tool names, as in "Edit|Write". A JSON array is a schema error: Claude Code rejects the whole user, project or local settings file, so no hook from that file appears in /hooks. Matching is case-sensitive, so "bash" matches nothing, and a misspelled tool name fails the same quiet way. Hooks must also sit under the hooks key in settings.json. Only plugins load a separate hooks/hooks.json.

    ~/.claude.json and ~/.claude/settings.json are different files. The first holds app state and UI toggles. Permissions, hooks and env belong in the second. Precedence can also hide a value: settings.local.json overrides settings.json, and both override the user-level ~/.claude/settings.json. Finally, remember what a permission rule can and cannot guarantee. A Bash(rm *) deny rule matches the literal command string, so it does not block /bin/rm or find -delete. For a hard guarantee, use a PreToolUse hook or the sandbox.

    Sources1

    4.Isolate the culprit, then report it

    If inspection doesn't reveal the cause, remove variables. Starting Claude Code with a throwaway configuration directory shows whether your personal config is responsible. Managed settings still apply in that clean session, and you will be asked to log in again. Restarting with claude --safe-mode turns off all customisations for the session, which quickly shows whether a plugin, MCP server or hook is the source. It is also a useful first step for high CPU or memory use.

    Launch Claude Code with a clean configuration directory to rule out your own settingsbash
    cd /tmp && CLAUDE_CONFIG_DIR=/tmp/claude-clean claude

    For slowness and memory growth, reduce what the session is holding. Use /compact with a focus that drops large output, /clear when earlier conversation is no longer needed, or move work on large files to a subagent so it runs in its own context window. If search is not finding files, a common fix is to install your system ripgrep and tell Claude Code to use it instead of the built-in copy.

    Settings env entry that makes Claude Code use the system ripgrepjson
    {
      "env": {
        "USE_BUILTIN_RIPGREP": "0"
      }
    }

    When you escalate, share only what is safe to share. For a memory problem, attach only the -diagnostics.json file to a GitHub issue. It contains the statistics without any conversation content or credentials. /feedback sends a report straight to Anthropic.

    Sources21

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.You can define a team's project MCP servers under an mcpServers key in .claude/settings.json.Why is that wrong?

      settings.json does not read mcpServers. Project servers go in .mcp.json at the repository root, and user-scoped servers are added with claude mcp add --scope user.

      Covered in MCP servers: never loaded, failed, or empty

    2. 2.~/.claude.json is the global settings file, so permissions and hooks added there apply to every session.Why is that wrong?

      ~/.claude.json holds app state and UI toggles only. Permissions, hooks and env must go in ~/.claude/settings.json.

      Covered in Why hooks never fire and settings seem ignored

    3. 3.A Bash(rm *) deny rule reliably stops the agent from deleting files.Why is that wrong?

      Bash rules match the literal command string, so /bin/rm or find -delete get past them. Use a PreToolUse hook or the sandbox for a hard guarantee.

      Covered in Why hooks never fire and settings seem ignored

    Practise it for real

    Work through the configuration debugging sequence on your own Claude Code install, from inspection to isolation.

    1. 1.In a session, run /doctor and then /mcp.

      Why: /doctor finds invalid settings files and install problems, and /mcp shows each server's status, so you know which area is at fault before changing anything.

      You should see: A setup report with proposed fixes, and a list of MCP servers each shown as connected, failed or awaiting approval.

    2. 2.Run /status and /permissions.

      Why: Settings that seem ignored are often overridden by a higher-precedence source or by managed settings.

      You should see: The active settings sources, including whether managed settings are in effect, and the resolved allow and deny rules.

    3. 3.If a server lists zero tools, start claude --debug=mcp and open ~/.claude/debug/<session-id>.txt.

      Why: The server's own stderr shows why it is not returning a tool list.

      You should see: The MCP server's stderr output in the debug log.

    4. 4.Run cd /tmp && CLAUDE_CONFIG_DIR=/tmp/claude-clean claude, then separately claude --safe-mode.

      Why: The clean directory rules out your personal config, and safe mode turns off all plugins, MCP servers and hooks.

      You should see: A login prompt in the clean session, where managed settings still apply. If the problem disappears in safe mode, one of your customisations is the cause.

    Stuck? Get a nudge

    Change one variable at a time. If safe mode fixes it, re-enable customisations one by one until the problem comes back.

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “Active settings sources, including whether managed settings are in effect”
      ↩︎ Inspect what Claude Code actually loaded
      “Relative file paths in command or args are a frequent cause, since they resolve against the directory you launched Claude Code from”
      ↩︎ MCP servers: never loaded, failed, or empty
      “run claude --debug=mcp and read the server’s stderr in the debug log at ~/.claude/debug/<session-id>.txt”
      ↩︎ MCP servers: never loaded, failed, or empty
      “Project-scoped servers in .mcp.json require a one-time approval.”
      ↩︎ MCP servers: never loaded, failed, or empty
      “A misspelled tool name produces a matcher that matches nothing, so the hook fails silently.”
      ↩︎ Why hooks never fire and settings seem ignored
      “settings.local.json overrides settings.json, and both override ~/.claude/settings.json.”
      ↩︎ Why hooks never fire and settings seem ignored
      “Managed settings still apply if your organization deploys them.”
      ↩︎ Isolate the culprit, then report it
      “Project MCP config goes at the repository root as .mcp.json, not inside .claude/, with servers under the mcpServers key.”
      ↩︎ Exam trap 1
      “~/.claude.json holds app state and UI toggles. permissions, hooks, and env belong in ~/.claude/settings.json.”
      ↩︎ Exam trap 2
      “Bash rules match the literal command string, not the underlying executable”
      ↩︎ Exam trap 3
    2. 2.
      “Run /doctor for a setup checkup and /mcp to check MCP server status”
      ↩︎ Inspect what Claude Code actually loaded
      “Restart with claude --safe-mode to check whether a plugin, MCP server, or hook is the source.”
      ↩︎ Isolate the culprit, then report it
      “attach only the -diagnostics.json file, which carries the statistics behind the printed summary and no conversation content or credentials”
      ↩︎ Isolate the culprit, then report it
      “Move the large-file work to a subagent so it runs in a separate context window”
      ↩︎ Isolate the culprit, then report it

    Ready to test yourself?

    Practise the 12 questions on this subdomain.