cd /news/developer-tools/mcp-subagents-and-hooks-in-claude-co… · home topics developer-tools article
[ARTICLE · art-102638] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

MCP, Subagents, and Hooks in Claude Code: The Guide I Wish I'd Had

A developer's guide to extending Claude Code with MCP servers, subagents, and hooks details how to connect external services, manage scopes, and create custom subagents. The guide covers adding MCP servers via CLI or .mcp.json, authentication flows, and using built-in subagents like Explore and Plan, with practical examples for tools like Playwright and Sentry.

read6 min views6 publishedAug 19, 2026

Originally published on El Rack — Spanish tech reviews from a sysadmin/homelab perspective.

Claude Code is capable right out of the box, but it starts to feel thin the moment your project needs to touch external systems: a ticket tracker, a database, your own VPS. This guide covers the four pieces that turn it into a real production tool:

/mcp

): connecting external services as toolsYou'll need Claude Code installed and authenticated, and a terminal open in any project folder.

MCP (Model Context Protocol) lets Claude Code use tools it doesn't ship with by default. Those tools live in MCP servers: local processes or hosted services reachable over a URL. You add them with claude mcp add

, no hand-editing JSON required. Start with the official docs server — it needs no account and no config:

claude mcp add --transport http claude-code-docs https://code.claude.com/docs/mcp

Confirm it connected:

claude mcp list

You should see ✔ Connected

. From inside a session, manage servers any time with /mcp

.

A stdio server is a program Claude Code launches as a subprocess — useful when it needs access to your filesystem or a browser. Example with Playwright, which requires no account:

claude mcp add playwright -- npx -y @playwright/mcp@latest

The --

separates Claude Code's own flags from the command that starts the server. For services that require sign-in (Sentry, Linear, Notion, GitHub), you add them the same way and authenticate from inside the session:

claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

After adding, you'll see ! Needs authentication

. Start a session, run /mcp

, select the server, and choose "Authenticate" — your browser opens for sign-in.

If the service uses a static token instead of OAuth (common with self-hosted instances), pass it directly:

claude mcp add --transport http my-server http://my-host:3001/api/mcp --header "Authorization: Bearer YOUR_TOKEN"

By default, every server is registered at "local" scope: private to you, active only in the current project. Two alternatives depending on how widely you want to share it:

claude mcp add --scope user --transport http claude-code-docs https://code.claude.com/docs/mcp

claude mcp add --scope project --transport http claude-code-docs https://code.claude.com/docs/mcp
Scope File Available to
local
~/.claude.json (project entry)
Only you, only this project
project
.mcp.json at the repo root
Everyone who clones the repo
user
~/.claude.json (top-level mcpServers )
Only you, all your projects

If you'd rather write .mcp.json

by hand to keep it version-controlled with the team:

{
  "mcpServers": {
    "claude-code-docs": {
      "type": "http",
      "url": "https://code.claude.com/docs/mcp"
    },
    "playwright": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@playwright/mcp@latest"]
    }
  }
}

A subagent is an instance with its own context, its own system prompt, and its own tools, working in isolation and returning only a summary. It's the fix for two problems: flooding your main conversation with logs or results you won't reuse, and re-spawning the same kind of worker with the same instructions over and over.

Claude Code ships with three built-in subagents: Explore (read-only code search), Plan (research during plan mode), and general-purpose (complex tasks with access to everything). For a custom one, just ask Claude to write it:

Create a personal subagent in ~/.claude/agents/ called "code-reviewer" that
reviews code for quality, security, and best practices. Make it read-only
and have it use Sonnet.

Claude writes the file with YAML frontmatter plus the system prompt:

---
name: code-reviewer
description: Reviews code for quality, security, and best practices. Use after writing or modifying code.
tools: Read, Grep, Glob
model: sonnet
---

You are a senior code reviewer. For each issue you find, explain the
problem, show the current code, and provide an improved version.

The most useful frontmatter fields: tools

(allowlist), disallowedTools

(denylist), model

(sonnet/opus/haiku/inherit), and mcpServers

(gives an MCP server to that subagent alone, without its context into the main conversation).

Save it in .claude/agents/

to scope it to this project, or ~/.claude/agents/

to make it available everywhere.

There are three ways to use a subagent, from least to most explicit:

Use the code-reviewer subagent to review my recent changes

@"code-reviewer (agent)" review the authentication logic

claude --agent code-reviewer

For independent investigations, you can request several subagents in parallel:

Research the authentication, database, and API modules in parallel using
separate subagents

Each one explores its own area in isolation; you only get the synthesized summary back in your main conversation.

If you type the same instruction over and over, turn it into a command. Classic commands (.claude/commands/*.md

) still work, but the recommended approach now is Skills (.claude/skills/<name>/SKILL.md

) — if a command and a skill share a name, the skill wins.

Classic command, saved as .claude/commands/audit-disk.md

:

---
description: Disk space audit with a configurable threshold
allowed-tools: Read, Bash, Grep
argument-hint: [threshold-percentage]
---

Audit disk space across the servers. Alert threshold: $ARGUMENTS%.

Invoke it with /audit-disk 85

. $ARGUMENTS

captures everything typed after the command; ! command``

injects live shell output (e.g. ! git diff --cached``

).

Same idea as a skill, at .claude/skills/audit-disk/SKILL.md

:

---
name: audit-disk
description: Disk space audit with a configurable threshold. Use when the user asks to check disk space on the servers.
allowed-tools: Read, Bash, Grep
---

Audit disk space across the servers...

The advantage of skills: they can bundle several reference files in the same folder, and Claude can invoke them on its own, without you typing the slash.

If you run in an autonomous mode (--dangerously-skip-permissions

), hooks are how you block dangerous operations without relying on the AI remembering a rule. They fire every time, at the exact lifecycle point you define.

The two most-used events: PreToolUse

(before a tool runs — good for blocking) and PostToolUse

(after — good for formatting, linting, or logging). Configure them in settings.json

:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "./scripts/validate-command.sh" }
        ]
      }
    ]
  }
}

The script receives the command as JSON via stdin, and exit code 2 blocks the operation. Example that stops an overly broad pkill

on a server where multiple processes share the same name:

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if echo "$COMMAND" | grep -qE 'pkill.*node|rm -rf /'; then
  echo "Blocked: command too broad or destructive. Use an exact PID." >&2
  exit 2
fi

exit 0

Make it executable:

chmod +x ./scripts/validate-command.sh

Another common one: auto-format every file Claude touches, without having to ask:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "npx prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\"" }
        ]
      }
    ]
  }
}

Put these four pieces together and Claude Code stops being a terminal assistant and becomes a real automation layer: it connects to whatever it needs (MCP), delegates whatever would clutter its context (subagents), packages whatever repeats (skills), and respects hard limits that don't depend on its memory (hooks). Suggested adoption order: start with one low-risk MCP server, add one read-only subagent, migrate your commands to skills whenever you have time, and — the highest-leverage one if you run in autonomous mode — add at least one hook that blocks the operation you're most afraid of running by accident.

Tutorial by Álvaro Fraguas Bravo for El Rack.

── more in #developer-tools 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/mcp-subagents-and-ho…] indexed:0 read:6min 2026-08-19 ·