# Tool use and function calling in Claude Code

In Claude Code, "tool use" means something different from what the API docs
describe. You are not writing JSON Schema definitions or driving a request loop
yourself. Claude Code ships with a built-in toolbox, and you extend it by
connecting
MCP
servers. Claude decides when to reach for a tool. Your job is to know which
tools are available, add new ones when you need them, and write the prompts and
configs that help the agent choose well.

## What tools does Claude Code have out of the box?

Claude Code arrives with a set of built-in tools it can call with no
configuration from you.

| Tool | What it does |
|---|---|
| Read | Opens any file the agent can reach on disk |
| Edit / Write | Makes targeted edits or writes a new file |
| Bash | Runs shell commands (lint, test, build, grep, git) |
| WebSearch | Searches the web for current information |
| WebFetch | Fetches a URL and returns its content |
| Glob / Find | Locates files by pattern |
| NotebookEdit | Reads and edits Jupyter notebooks |
| TodoRead / TodoWrite | Manages the agent's in-session task list |

These tools are always on. You cannot remove them, but you can constrain them
through permissions (see `.claude/settings.json`).

## How does the agent decide to call a tool?

Claude does not call tools at random. It reads your prompt, works out what
information or action it needs, and picks the right tool for that step. The
cycle looks like this:

The loop runs inside Claude Code automatically. You never write it yourself.
What you do control is the quality of the tools on offer and the clarity of the
instructions that decide when each one gets used.

## How do I add tools with MCP?

When the built-in tools are not enough, add an MCP server. Each one registers
its own named tools, which Claude then calls the same way it calls the
built-ins.

### Register a server

```bash
# stdio server (local process)
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/project

# SSE server (remote URL, useful for shared team servers)
claude mcp add my-api --transport sse https://tools.example.com/mcp

# Check what is registered
claude mcp list

# Inspect a server's exposed tools
claude mcp get filesystem
```

After adding a server, restart Claude Code. The agent picks up the new tools
on next launch.A live session will not see a newly added server, so if the agent insists the tool does not exist, you almost certainly skipped the restart rather than misconfigured it. Quit and relaunch, then confirm with `claude mcp list` before assuming the server is broken.

### Scope MCP servers to a project

Committing a `.mcp.json` file means every teammate gets the same tools without
running `claude mcp add` manually.

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
      "type": "stdio"
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "type": "stdio",
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    }
  }
}
```

Use `${ENV_VAR}` syntax for secrets. Claude Code expands them at runtime from
the process environment, so the file itself stays safe to commit. See [MCP
Configuration](/guides/mcp-configuration) for the full set of scopes and secret-handling options.

## Tool hygiene: fewer is better

Every active MCP server adds to the tool list Claude reasons over. A bloated
list makes the agent hesitate, pick the wrong tool, or fire off calls it did
not need. The same principle as good function design applies: narrow,
well-named, single-purpose tools beat wide, ambiguous ones.

Practical rules:

- Register only servers whose tools you need in this project.
- Prefer a focused server (`server-github`) over a general shell executor if
  the task is scoped.
- Audit your registered servers occasionally with `claude mcp list` and remove
  stale ones.

## Guiding tool choice in your prompts

Claude reads your prompt to decide which tool fits. Vague prompts lead to
guessed tool choices. Specific prompts produce reliable ones.

Search the web for the current Node.js LTS version, then update the `.nvmrc` file to match.

That prompt signals two tools: WebSearch first, then Write. Claude does not
guess. It follows the sequence you described.

For repeated workflows, encode the guidance in your project's `CLAUDE.md` so
every session inherits it:

```markdown
## Tool rules
- Always use the `github` MCP tool for PR and issue operations. Do not use Bash + gh CLI for these.
- Run `npm test` via Bash before proposing any edit.
- Never call WebFetch on internal hostnames; use the `filesystem` MCP tool instead.
```

`CLAUDE.md` lives at the repo root and is read automatically at session start.
That makes it the right home for durable tool-routing rules that apply to every
task in the project.

## How do I control tool permissions?

Claude Code asks for permission before running Bash commands or writing files
the first time. You can lock down or loosen these defaults in
`.claude/settings.json`:

```json
{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git log *)",
      "Read(**)"
    ],
    "deny": [
      "Bash(rm -rf *)"
    ]
  }
}
```

Rules use glob patterns. `allow` entries skip the confirmation prompt. `deny`
entries block the call outright; the agent reports a permission error and keeps
planning without that tool.

Keep `deny` rules explicit for dangerous commands rather than trying to list
every safe one. Allowlisting common read-only and build commands removes
friction without opening up destructive paths.An allow glob like `Bash(npm run *)` is looser than it looks: the trailing `*` also matches a chained command, so `npm run build && rm -rf dist` slips through the same pre-approval and runs without a prompt. Anchor allow patterns to the exact subcommand you mean and keep a `deny` for shell chaining (`&&`, `;`, `|`) and `rm -rf`, because allow rules never override the safety of a too-broad wildcard.

## Hooks: run your own code around tool calls

Hooks
let you attach shell commands to agent lifecycle events. They are not MCP
servers and they are not tools the model calls. They are deterministic
sidecars you control.

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "echo '[hook] bash call incoming'" }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          { "type": "command", "command": "npm run lint --silent" }
        ]
      }
    ]
  }
}
```

`PreToolUse` fires before the agent calls the matched tool. `PostToolUse` fires
after it. Use them to enforce conventions (auto-lint after every write), log
tool calls for auditing, or put a check in front of dangerous operations. The
[hooks and guardrails](/guides/hooks-and-guardrails) guide covers every lifecycle event and how to wire them up.

## How do I see which tools Claude called?

You do not need to instrument anything to see which tools Claude called. The
session output prints each tool invocation and its result inline. Run `/cost`
at any point to see token consumption broken down by turn, which tracks how
many round trips of tool use happened.

```bash
/cost
```

For long tasks, watch the tool calls scroll past and use Escape to interrupt
if the agent is heading in the wrong direction. Resume with `claude --continue`
to pick up from the last checkpoint.

## Parallel tool use

Claude Code can call several independent tools in one step without waiting for
your input between them. In the output it shows up as a burst of tool calls
that resolve before the agent writes its next response. The agent handles the
ordering. Two independent calls (reading two separate files, searching two
URLs) run together. When one call's output feeds the next, it sequences them
for you.

You do not configure this. Writing clear, parallel-friendly prompts helps:

Read `src/auth/session.ts` and `src/auth/token.ts`, then describe how the session token lifecycle works end to end.

That prompt lets the agent read both files in parallel before it pieces the
answer together, rather than reading one, waiting, then reading the other.

## Common mistakes

**Registering servers you do not use.** Every extra server increases the tool
list Claude reasons over and can cause it to reach for the wrong tool. Run
`claude mcp list` and prune unused entries.

**Vague CLAUDE.md tool rules.** "Prefer MCP tools" is too loose. Write "use the
`github` MCP tool for all PR operations, not Bash + gh CLI." Precise rules
produce consistent behaviour.

**Leaning on tool descriptions instead of a clear prompt.** MCP server tool
descriptions help, but the task prompt matters more. Describe what you want and
the agent picks the right tool. Naming the tool and the reason is a useful
backup, not a substitute for a clear goal.

**Blocking all Bash with deny rules.** If Bash is fully blocked, Claude cannot
run tests, lint, or build. Deny specific dangerous patterns (`rm -rf`,
`curl | bash`), not the whole command runner.

## Next steps

With your tool set configured and permissions dialled in, two topics follow
naturally: multi-agent workflows, where several Claude Code sessions hand tasks
to each other, and deeper MCP patterns, like wrapping your own internal APIs as
MCP servers so every project agent can reach them. See [Multi-Agent
Architectures](/guides/multi-agent-architectures) and [MCP Fundamentals](/guides/mcp-fundamentals) for both.
