Claude Code: MCP & Hooks
Claude Code already reads files, edits code, and runs commands. MCP servers give it named tools for services outside that built-in set, while hooks run checks at fixed points in a session. They solve different problems, but both can widen what Claude is allowed to do.
Add one MCP server or one blocking hook at a time, then test it before relying on the new access.
I rely on hooks when a repeated instruction needs enforcement, because a visible deny result tells me more than another reminder in a prompt.
MCP Servers
MCP is short for the Model Context Protocol. It is an open protocol that lets a client such as Claude Code discover tools exposed by a server.
The main Claude Code guide covers installation and the base agent loop before you extend it with another process or service.
One server might offer issue-search and ticket-update tools. Another server might run read-only database queries. Claude sees each tool's name, description, and input fields, then can call it during the normal agent loop.
The server can run as a local process, connect over HTTP, or come from a plugin. A local server gets the same machine access as the command that starts it. A remote server sends requests to another service. Read the server's own setup page before adding it because the transport tells you where code, prompts, and credentials may travel.
Add an MCP Server
Use claude mcp add for either a remote HTTP endpoint or a local process. The command
needs a short name that you will recognize in /mcp. Most setups use one of these two command shapes:
# Remote HTTP server
claude mcp add --transport http issue-tracker https://mcp.example.com/mcp
# Local stdio server
claude mcp add local-tools -- /absolute/path/to/server
Run claude mcp list to confirm the server is registered, then open Claude Code and run
/mcp to inspect its connection and tools. Begin by asking one read-only question through the server.
For an issue tracker, that could be "list the open tickets assigned to me." Do not begin with an update, delete, or send action while you are still checking authentication and scope.
The official MCP guide
also shows header-based authentication and variable expansion. Keep the secret outside a committed
.mcp.json file. Put only the variable name in shared settings, then define the secret on
each developer's machine or in the approved secret store for the runtime.
Pick the Right MCP Scope
| Scope | Stored For | Use It When |
|---|---|---|
| Local | One project | Private trial |
| Project | .mcp.json | Shared server |
| User | All projects | Personal default |
Local is the default and the safest place to test. Project scope writes shareable settings, so review the command, URL, headers, and variable names before committing it. User scope is convenient for a tool you need in many repos, but it also makes that tool available in sessions that may not need it.
Control MCP Access and Risk
An MCP server is executable software plus a set of model-visible tool descriptions. Check who publishes it, where its source lives, what account permissions it requests, and how updates arrive. A familiar service name does not prove that an unrelated package is maintained by that service.
Tool descriptions can steer the model, which creates a tool-poisoning risk if a server is hostile or becomes hostile after an update. Give the server a token limited to the smallest useful job. A ticket reader does not need ticket-delete rights. A database inspector should begin on a read-only account, never the production owner account.
Claude Code defers most MCP tool definitions and loads them through Tool Search when needed. That
cuts the context cost, but a local server may still keep a process running. Use /mcp to
inspect each server's tool count and context cost. Remove a server when its occasional convenience no
longer pays for its access, process, and update path.
Troubleshoot an MCP Connection
Start with claude mcp list, then inspect the server in /mcp. "Disconnected"
means Claude cannot reach the process or endpoint. "Needs authentication" means the transport works
but the server still needs a login or token. A connected server with no useful tools points back to
the server's own configuration.
- For a local server, run its command outside Claude Code and read the first error.
- Use absolute executable paths when the process works in your shell but not in the app.
- Confirm shared settings refer to a variable name that exists on this machine.
- For HTTP, check the endpoint, transport, headers, and whether the service still accepts that route.
- Restart the session after editing settings so the tool list is discovered again.
Turn on Claude Code debug logging when the server exits without a clear message. Do not paste a debug log into an issue until you have removed tokens, cookies, request headers, and private tool output. Authentication logs can expose the secret you were trying to fix.
Hooks and Automation
Hooks run at named points in Claude Code's lifecycle. PreToolUse fires before a tool call
and can block it. PostToolUse fires after a successful call and can add feedback, but it
cannot undo work that already happened. Stop fires when Claude is about to finish, which
makes it useful for a final check.
Configure hooks through /hooks or in a settings file. The user-level hook file is
~/.claude/settings.json on your machine. Shared project hooks are stored in
.claude/settings.json inside the repository.
Private project hooks belong in .claude/settings.local.json, which should stay out of Git.
| Hook | Event + matcher | What it does |
|---|---|---|
| Auto-format | PostToolUse, Edit|Write | Formats each edit |
| Block commands | PreToolUse, Bash | Denies matched commands |
| Test at stop | Stop, no matcher | Gates completion |
Build a Blocking Hook
This project hook runs a script before every Bash call. The matcher limits it to Bash, and the
if field avoids starting the script unless the command begins with rm:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
}
} The script reads the tool input as JSON from standard input. If it finds a forbidden command, it writes a plain reason to standard error and exits with code 2. Claude Code blocks the tool call and feeds the reason back to Claude. An exit code of 0 allows the call to proceed.
Do not treat a string search for rm -rf as a complete command policy. Shell text can use
aliases, scripts, variables, or a different destructive command. Keep the first hook narrow and
explicit. When the rule needs command parsing, write tests for the parser or move the control to an
operating-system sandbox.
Test Hooks Before Trusting Them
- Run
/hooksand confirm the hook appears at the intended scope. - Call the script with a saved sample JSON payload before asking Claude to trigger it.
- Try one allowed command and one harmless command shaped to hit the deny branch.
- Use
claude --debugwhen the hook does not fire or its JSON cannot be parsed. - Keep standard output clean when returning JSON; stray shell-profile text breaks parsing.
Several hook events cannot block because they run after the relevant action or mark a lifecycle boundary. The hook reference lists the behavior for each event. Read that row before assuming exit code 2 will stop anything.
Choose MCP, a Hook, or CLAUDE.md
| Need | Use | Example |
|---|---|---|
| Reach another service | MCP | Read one issue from a tracker |
| Enforce an event rule | Hook | Block edits to generated files |
| Tell Claude a convention | CLAUDE.md | Use pnpm for this repo |
CLAUDE.md is advice loaded into the model's context. It works well for a style rule, a test command, or a pointer to a code pattern. It cannot guarantee that Claude will follow the text.
A hook is the better fit when the action must be checked every time. Use MCP only when Claude needs a new tool; project instructions and enforcement rules have their own jobs.
These three layers can work well together in one project. A project may expose an issue tracker through MCP, explain the ticket
routine in CLAUDE.md, and use a PreToolUse hook to deny issue deletion. Each layer then
owns one clear job, which makes failures easier to trace.
FAQ
What is the difference between MCP and hooks?
MCP gives Claude Code a tool for reaching another service or local process. A hook runs when a Claude Code event occurs, such as before a shell command or after a file edit. Use MCP when Claude needs another capability. Use a hook to check, block, log, or respond to an action.
Where does Claude Code store MCP settings?
Local-scope servers are stored in your user configuration for one project. Project-scope servers are written to .mcp.json so the team can share them through Git. User-scope servers become available across all your projects. Run claude mcp list and inspect .mcp.json before sharing a setup that contains URLs, commands, or variable names.
Can a hook stop a command before it runs?
Yes, when it runs before the proposed tool call. A PreToolUse hook can inspect a proposed tool call and deny it before Claude Code reaches the normal permission check. A command hook can exit with code 2 and write the reason to standard error, or return a structured deny decision. PostToolUse runs too late to undo the action.
Should I install every MCP server I use once?
No. Start with one server tied to a frequent task, then check its tool list and context cost with /mcp. Each local server can add a running process, credentials, and another update path. Remove servers that do not save enough work to justify their access and upkeep.
Choose the Smallest Extension
Add one MCP server when Claude Code needs a service it cannot reach through its built-in tools. Add one hook when a named session event must trigger a check or block.
Keep both at the smallest scope that works, test their failure paths, and remove them when the access they add no longer earns its place. Continue with Workflows, Debugging & Safety for session planning and permission modes.
Updated July 2026 with facts checked against official Anthropic and MCP sources on July 28, 2026.
Sources
-
[1]
Connect Claude Code to tools via MCP(code.claude.com)
-
[2]
Automate actions with hooks(code.claude.com)
-
[3]
Hooks reference(code.claude.com)
-
[4]
Extend Claude Code(code.claude.com)
-
[5]
Model Context Protocol specification(modelcontextprotocol.io)
Read Next
How to run Claude Code effectively day to day: the planning-first habit, dual-planning for hard features, ultracode for large parallel work, debugging with real context, and the permissions and safety system.
How to configure Claude Code for a real project: CLAUDE.md project files, the context-guidebook pattern for keeping sessions sharp, and session habits that hold up on large codebases.
Beginner-friendly guide to Claude Code: its history, no-terminal Desktop setup, permissions, diffs, CLI, models, pricing, code review, and ecosystem.