# MCP Management

> Install, configure and troubleshoot MCP servers. Use when adding/enabling servers, editing .mcp.json, fixing OAuth, or when a server runs stale code after an upstream fix.

- Skill: `laurigates/mcp-management` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add laurigates/mcp-management`
- Raw SKILL.md: https://api.skillmd.com/api/skills/laurigates/mcp-management/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: laurigates (https://skillmd.com/u/laurigates)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/laurigates/mcp-management

---


# MCP Server Management

Expert knowledge for managing Model Context Protocol (MCP) servers on a project-by-project basis, with support for runtime management, OAuth remote servers, and dynamic server discovery.

For server config examples, the OAuth deep-dive, dynamic-discovery detail,
troubleshooting scripts, and full configuration-pattern examples, see
[REFERENCE.md](REFERENCE.md).

## When to Use This Skill

| Use this skill when... | Use configure-mcp instead when... |
|------------------------|------------------------------------|
| Understanding MCP architecture and concepts | Setting up `.mcp.json` for a new project |
| Managing servers at runtime (enable/disable) | Installing new servers interactively |
| Setting up OAuth remote MCP servers | Running compliance checks on MCP configuration |
| Troubleshooting connection failures | Adding specific servers from the registry |
| Implementing `list_changed` dynamic discovery | Generating project standards reports |

## MCP Architecture Overview

MCP connects Claude Code to external tools and data sources via two transport types:

| Transport | Usage | Auth | Configuration |
|-----------|-------|------|---------------|
| **Stdio** (local) | Command-based servers via `npx`, `bunx`, `uvx`, `go run` | None needed | `.mcp.json` |
| **HTTP+SSE** (remote) | URL-based servers hosted externally | OAuth 2.1 | `.mcp.json` with `url` field |

Local servers declare a `command` + `args`; remote servers declare a `url` +
`headers` (with `${VAR_NAME}` token references, never hardcoded). See
[REFERENCE.md → Server configuration examples](REFERENCE.md#server-configuration-examples).

## Runtime Server Management

### `/mcp` Commands (Claude Code 2.1.50+)

Manage servers without editing configuration files:

| Command | Description |
|---------|-------------|
| `/mcp` | List all configured MCP servers and their connection status |
| `/mcp enable <server>` | Enable a server for the current session |
| `/mcp disable <server>` | Disable a server for the current session (session-scoped only) |

**Note**: Enable/disable are session-scoped. Edit `.mcp.json` for permanent changes.

### Check Server Status

```bash
jq -r '.mcpServers | keys[]' .mcp.json   # List configured servers
jq '.mcpServers.context7' .mcp.json      # Verify a server's config
```

## OAuth Remote Servers (2.1.50+)

Remote HTTP+SSE servers use OAuth 2.1: Claude Code discovers metadata from
`/.well-known/oauth-authorization-server` (cached per URL), the user authorizes
in-browser once, and **step-up auth** re-prompts when a tool needs elevated
scope. To refresh stale OAuth config, `/mcp disable` then `/mcp enable` the
server. Full flow, step-up detail, and caching behavior in
[REFERENCE.md → OAuth support](REFERENCE.md#oauth-support-for-remote-mcp-servers).

## Dynamic Tool Discovery (`list_changed`)

Servers declaring `{"tools": {"listChanged": true}}` push
`notifications/tools/list_changed` when their tool set changes, and Claude Code
refreshes that server's tools **without a session restart** — useful for servers
exposing project-context-specific tools. Same pattern for `resources` and
`prompts`. Subscription is automatic; no client config needed. See
[REFERENCE.md → Dynamic tool discovery](REFERENCE.md#dynamic-tool-discovery-list_changed).

## Troubleshooting

Common failure modes and the diagnostic scripts for each (server won't connect,
missing env vars, OAuth issues, the SDK MCP race condition) are in
[REFERENCE.md → Troubleshooting scripts](REFERENCE.md#troubleshooting-scripts).
Quick OAuth triage:

| Symptom | Likely Cause | Action |
|---------|-------------|--------|
| Authorization prompt repeats | Token not persisted | Check token storage permissions |
| Step-up auth loop | Scope mismatch | Revoke and re-authorize |
| Discovery fails | Server down or URL wrong | Verify server URL and connectivity |
| Cache stale | Server changed OAuth config | Disable/enable server to refresh |

## Stale cached git source

A server registered from a **git URL** rather than a published package serves a
**cached commit**, so an upstream fix never arrives:

```jsonc
"pal": {
  "command": "uvx",
  "args": ["--from", "git+https://github.com/owner/repo.git", "pal-mcp-server"]
}
```

`uvx` resolves the ref to a commit **once**, builds it, and caches by that
commit. Later spawns reuse the build and do **not** re-fetch the branch head. So
after a fix merges to the server's `main`, every client keeps running the old
code — and the symptom is misattributed: you restart the client, the bug
persists, and you suspect the fix, the registration, or the environment.

**Confirm** by comparing the cached checkout's commit against upstream:

```sh
fd -H '<a-file-from-the-repo>' "$(uv cache dir)/git-v0/checkouts"   # .../<hash>/<commit>/...
git ls-remote https://github.com/<owner>/<repo>.git refs/heads/main
```

A cached `<commit>` that is not the current head is the confirmation.

**Fix** — refresh, then restart the client so it re-spawns from the new build:

```sh
uvx --refresh --from git+https://github.com/<owner>/<repo>.git <pkg> </dev/null
```

`</dev/null` feeds EOF so a **stdio** server exits after building instead of
hanging for requests; the rebuild happens during resolve, so the cache is warm
even if the process is then killed.

**Durable fix — publish and pin.** This footgun exists *only* for an unpinned
git source. Once the server is on PyPI, register it as `uvx <pkg>` (or
`uvx <pkg>@<version>`): a version bump re-resolves cleanly and there is no
cached-head-went-stale failure at all. Prefer the `git+` form only as an interim
before the first publish.

## Configuration Patterns

Three scopes, each with a worked `.mcp.json` / `settings.json` / `plugin.json`
example in [REFERENCE.md → Configuration patterns](REFERENCE.md#configuration-patterns):

- **Project-scoped** (recommended) — `.mcp.json` at project root; `.gitignore` it for personal configs or track for team configs.
- **User-scoped** (personal) — `~/.claude/settings.json` for servers available everywhere.
- **Plugin-scoped** — declared in `plugin.json` (or referenced via `"mcpServers": "./.mcp.json"`).

### Post-add approval gate (project-scoped)

A **newly-added project `.mcp.json` server requires one-time user approval before its tools are callable in the *current* session** — this is expected, not an error. Immediately after writing the config, `claude mcp list` shows the server as `⏸ Pending approval (run 'claude' to approve)` and it stays uncallable until the user approves it via the `/mcp` command or restarts the CLI session — both user-only actions the agent cannot perform for them. So after writing a project `.mcp.json` entry, **tell the user proactively** that a one-time approval (`/mcp` or a session restart) is needed for the new server's tools to become available, rather than discovering the gate via a status check and asking mid-flow.

## Agentic Optimizations

| Context | Command |
|---------|---------|
| Quick status check | `jq -c '.mcpServers \| keys' .mcp.json 2>/dev/null` |
| Validate JSON | `jq empty .mcp.json 2>&1` |
| List env vars needed | `jq -r '.mcpServers[] \| .env // {} \| keys[]' .mcp.json 2>/dev/null \| sort -u` |
| Check specific server | `jq -e '.mcpServers.context7' .mcp.json >/dev/null 2>&1 && echo "installed"` |
| Find servers in plugin | `find . -name '.mcp.json' -maxdepth 2` |

## Quick Reference

### Server Types by Transport

| Type | When to Use | Example |
|------|-------------|---------|
| `command` (stdio) | Local tools, no auth needed | `bunx`, `npx`, `uvx`, `go run` |
| `url` (HTTP+SSE) | Remote hosted servers, OAuth needed | `https://...` |

### Key Files

| File | Purpose |
|------|---------|
| `.mcp.json` | Project-level MCP server config (team-shareable) |
| `~/.claude/settings.json` | User-level MCP server config (personal) |
| `plugin.json` | Plugin-level MCP server declarations |

