Claude Code MCP Deep Dive (2): From a Configuration Entry to a Handshake A developer's deep dive into Claude Code's MCP configuration explains that servers can be declared at project (.mcp.json), user, local, or organization-managed scope, with organization definitions taking precedence over all others when server names collide. The writeup notes that Claude Code uses the entire winning server entry rather than merging fields across scopes, and that project-scoped servers require interactive approval before running. After configuration, Claude Code separately connects, handshakes, and negotiates the capabilities each server supports. TL;DR: Claude Code cannot connect to an MCP server until that server appears in configuration. A definition may be private to one project, shared with a team, available to one user everywhere, or managed by an organization. When the same server name appears in more than one scope, precedence determines which complete definition wins. After configuration comes a separate job: connecting, handshaking, and negotiating the capabilities that server actually supports. In the previous article, we used an internal Jira server as the motivating example. Where should that server be declared so Claude Code knows it exists? There is no single answer. It depends on who should use the server and which parts of its configuration are safe to share. Suppose a company provides an MCP server for its internal Jira instance. Everyone on a team should be able to use it, but nobody’s API token should be copied into a shared repository. That is the first configuration problem MCP needs to solve: the connection details for a shared capability should be declared once, while each person can retain control of their private credentials. Claude Code’s current public documentation describes three regular installation scopes, plus organization-managed configuration: .mcp.json file at the project root. It can be committed to version control, so a team can share the server name, endpoint, and launch method without committing personal credentials. ~/.claude.json and applies across that user’s projects. It fits personal utility servers that are unrelated to one repository. The Claude Code MCP reference https://code.claude.com/docs/en/mcp documents the storage locations and intended use of these scopes. The local scope is particularly useful in the shared-Jira scenario. The project’s .mcp.json can declare “this repository uses the Jira server,” while each developer supplies their own credential-bearing configuration privately. The shared repository establishes the integration; the local configuration completes it for one person. There are also server sources outside this regular scope hierarchy. A session can receive temporary configuration through a command-line option, and connectors configured through Claude.ai can reach Claude Code. Those are separate paths, not substitutes for the ordinary project/user/local choice. What if the same server name appears in project, user, and local configuration? Claude Code resolves that conflict predictably. The public precedence order is: Organization-managed server definitions take precedence over all of those when they duplicate a server. The important detail is easy to miss: Claude Code uses the entire server entry from the winning source. It does not merge individual fields from several scopes into one composite record. That distinction makes debugging less mysterious. If a local definition has the same server name as a project definition, the local definition is the one that Claude Code will use; it is not merely a place to append one extra header to the project record. This precedence is practical rather than arbitrary. A team can establish a shared baseline in .mcp.json , while an individual retains an explicit way to substitute a private or project-specific definition. If a managed definition exists for the same server, the organization’s definition wins instead. One more safeguard applies specifically to project-scoped servers. A .mcp.json file usually travels with a repository, so Claude Code asks for approval in interactive sessions before using its project-scoped servers. That makes the connection command and arguments visible before a cloned repository gets to run them. User and local scopes are already the user’s own private configuration, so they do not need the same first-use approval step. A configuration record is only a declaration that a server should exist. The actual connection still has to be established. Claude Code tracks a server’s connection state rather than reducing everything to a single yes-or-no flag. States distinguish a connected server from one that failed to connect, is still connecting, is disabled, or needs authentication. That separation matters because “unreachable” and “reachable but unauthorized” lead to different remedies. A bad URL, missing process, or crashed child process is a connection problem. An expired OAuth session or missing permission is an authentication problem. Treating both as the same generic failure would hide the next useful action. The connection phase and a later tool call also deserve different timeout expectations. A connection that never responds within a short window is often misconfigured or not running at all. A tool call, by contrast, may ask the server to perform a long-running operation. A client should avoid treating those two waits as if they had the same failure meaning. A successful transport connection is not yet the end of the setup path. Claude Code still needs to learn what the server supports. This is capability negotiation. Client and server declare their supported features, and the client enables only the capabilities the server actually advertises. A server might offer tools but no resources; another might expose readable resources while offering no callable tools at all. That is why MCP should not be described simply as “a way to add tools.” Tools, resources, and prompts are distinct capability families. The Model Context Protocol introduction https://modelcontextprotocol.io/introduction frames MCP as a standard connection between AI applications and external systems, including data sources, tools, and workflows. Negotiation keeps that flexibility from becoming guesswork: The result is an intentionally modest rule: use what the server says it supports, rather than assuming every server implements every part of the protocol. After the handshake and capability negotiation complete, the server is connected. But that still does not mean the model can use a new action yet. The connection only establishes a working channel and an agreed feature set. The next questions are how bytes move across that channel, and how a declared server tool becomes a normal entry in Claude Code’s own tool list. Those are separate transformations, and separating them is what makes the system manageable: The series map https://dev.to/ 94be737e156beb4d74df2/claude-code-mcp-deep-dive-0-the-connection-lifecycle-and-tool-exposure-map-84g provides the broader pipeline, while Part 1 https://dev.to/ 94be737e156beb4d74df2/claude-code-mcp-deep-dive-1-from-built-in-tools-to-extensible-capabilities-2n04 explains why MCP exists at all. A handshake assumes Claude Code already knows how to speak to the server. That may mean launching a local child process and communicating over standard input/output, or making requests to a remote service over a network transport. The next article examines that transport choice: which connection paths the protocol standardizes, which paths Claude Code supports in practice, and why a local process and a remote service should not be retried or diagnosed in exactly the same way.