# Install MCP

> Install, list, and remove MCP servers (Model Context Protocol) for AI coding tools. Use whenever the user mentions installing an MCP, adding an MCP server, Model Context Protocol, playwright MCP, browser MCP, filesystem MCP, or says an MCP isn't working / can't be called / isn't loading. Also triggers on "I want to use tool X but can't access it" — that's often a missing MCP. Supports both ZCode (mcp.servers) and Claude Code (mcpServers) config formats.

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

---


# Install MCP Server

Install, list, and remove MCP servers for AI coding tools (ZCode, Claude Code).

Two config formats exist — this skill auto-detects which tool the user runs and writes the right one:

| Tool | Config file | Node | Shape |
|------|-------------|------|-------|
| **ZCode** | `~/.zcode/cli/config.json` (user) or `<project>/.zcode/config.json` (project) | `mcp.servers` | nested under `mcp` |
| **Claude Code** | `~/.claude.json` (user) or `<project>/.mcp.json` (project) | `mcpServers` | flat top-level |

> ⚠️ **Common mistake**: ZCode uses `mcp.servers` (dot, nested), Claude Code uses `mcpServers` (camelCase, flat). Don't mix them up.

## Step 1: Detect which tool the user runs

Ask or infer from context:
- Working dir contains `.zcode/` or user mentions "ZCode" → ZCode format
- Working dir contains `.claude/` or `.mcp.json`, or user mentions "Claude Code" → Claude Code format
- Unsure → ask: "你用的是 ZCode 还是 Claude Code?"

## Step 2: Check existing config

Read the config file (don't assume it exists):

```bash
# ZCode
cat ~/.zcode/cli/config.json 2>/dev/null || echo "(not exists)"

# Claude Code
cat ~/.claude.json 2>/dev/null || echo "(not exists)"
```

Three cases:
- File doesn't exist → create from scratch with the right skeleton
- File exists, no MCP node → add the node (merge, don't overwrite)
- Same server name exists → ask user whether to overwrite

## Step 3: Confirm prerequisites

Most MCP servers launch via `npx`, needing Node.js 18+:

```bash
node --version    # need v18+
npx --version     # confirm npx available
```

For Python-based MCP, check `python --version` and `uv`/`pip`. Tell the user what's missing.

## Step 4: Write config (merge, never overwrite)

Always merge with Python to avoid corrupting other config. **Never** use text replacement.

**ZCode** (`~/.zcode/cli/config.json`):
```python
import json
path = "~/.zcode/cli/config.json"  # expand ~ to absolute
with open(path, encoding="utf-8") as f:
    config = json.load(f)  # if not exists, start from {}
config.setdefault("mcp", {}).setdefault("servers", {})["server-name"] = {
    "command": "npx",
    "args": ["@package/mcp@latest"]
}
with open(path, "w", encoding="utf-8") as f:
    json.dump(config, f, indent=2, ensure_ascii=False)
```

**Claude Code** (`~/.claude.json`):
```python
import json
path = "~/.claude.json"
with open(path, encoding="utf-8") as f:
    config = json.load(f)
config.setdefault("mcpServers", {})["server-name"] = {
    "command": "npx",
    "args": ["@package/mcp@latest"]
}
with open(path, "w", encoding="utf-8") as f:
    json.dump(config, f, indent=2, ensure_ascii=False)
```

After writing, validate JSON:
```bash
python -c "import json; json.load(open('<path>')); print('✓ valid')"
```

## Step 5: Verify (the critical step most people miss)

**Editing the config does NOT update the current session's tools.** MCP tools are injected at session start; mid-session config changes need a new session to take effect.

Verification path:
1. Have the user check the tool's UI: does the MCP server show "connected"?
2. Have the user start a **brand-new session** (not resume the old one)
3. In the new session, check: can the model see `mcp__<server-name>__*` tools?

> If the user says "I restarted but still can't call it" — they probably resumed the old session instead of starting fresh. Emphasize: **new session, not resume**.

## Common MCP servers

### Playwright (browser automation)
```json
"playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] }
```

### Context7 (up-to-date docs)
```json
"context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] }
```

### Sequential Thinking (structured reasoning)
```json
"sequential-thinking": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"] }
```

### Filesystem (file system access)
```json
"filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "<allowed-dir>"] }
```

### GitHub (GitHub API access)
```json
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "<token>" } }
```

## Remove an MCP server

Read config → delete the key under the servers node → write back. Same "new session to take effect" rule applies.

## Troubleshooting

**Config written but tool shows disconnected?**
- Check JSON is valid (`python -c "import json; json.load(open('<path>'))"`)
- Check `command` is in PATH (`which npx`)
- Check logs: ZCode → `~/.zcode/v2/logs/`, Claude Code → `~/.claude/logs/`

**Restarted the tool but still can't call the MCP?**
- You likely resumed an old session. Start a **new** session.

**`npx` times out on first run?**
- First `npx @xxx/mcp@latest` downloads the package. Run it manually once to cache: `npx @xxx/mcp@latest --help`

**Project-level vs user-level conflict?**
- Project-level overrides user-level for the same server name.

## Key reminders

- Always **merge** JSON with Python, never text-replace (corrupts other config)
- `mcp.servers` (ZCode) vs `mcpServers` (Claude Code) — don't confuse them
- Config changes need a **new session** to take effect — not restart, not resume
- When unsure which tool the user runs, ask

