# mcp-wire

<img src="mcp-wire-logo.png" alt="mcp-wire logo" width="50%" />

mcp-wire is a Go CLI that installs and configures MCP (Model Context Protocol) servers across multiple AI coding tools from one interface.

## How It Works

No manual config editing needed. Run `mcp-wire` to open a full-screen TUI with guided install and uninstall wizards.

### Visual walkthrough

See the TUI in action (recorded from real runs with isolated target configs):

| Install flow | Uninstall flow |
|--------------|----------------|
| ![Install flow](docs/assets/install.svg) | ![Uninstall flow](docs/assets/uninstall.svg) |

For a step-by-step breakdown of each screen, see [docs/tui-walkthrough.md](docs/tui-walkthrough.md).

### Choose a source

Pick from bundled curated services or the community MCP registry:

```text
mcp-wire — Install

Install › Source

  Where should mcp-wire look for services?

  › Curated services       recommended, maintained by mcp-wire
    Registry services      community-published MCP servers
    Both                   curated + registry combined

↑↓ move  Enter select  Esc back
```

### Search and select a service

Live-filtered search across hundreds of registry entries:

```text
mcp-wire — Install

Install › community ✓ › Service › Targets › Review › Apply

  Search: sentry                                     2 matches

  › ai.sentry/sentry-mcp
    Sentry error tracking and performance monitoring MCP server
    registry · http · remote · API key

    ai.example/sentry-alerts
    Forward Sentry alerts to your AI coding assistant
    registry · sse · remote · none

                          — end of results —

↑↓ move  Enter select  type to filter  Esc back
```

### Review before installing

Registry services show metadata and require explicit confirmation:

```text
mcp-wire — Install

Install › community ✓ › Service › Targets › Review › Apply

  △ Registry Service — not curated by mcp-wire

  ai.sentry/sentry-mcp
  Sentry error tracking and performance monitoring MCP server

  Source:    community registry
  Transport: http
  URL:       https://mcp.sentry.io/sse

  Registry services are community-published. Review before proceeding.

  › Yes, proceed     No, go back

←→ move  Enter confirm  Esc back
```

### Explicit CLI mode

For scripting and CI, explicit commands work without the TUI:

```bash
mcp-wire install jira --target claude --no-prompt
mcp-wire uninstall sentry --target opencode
```

### Diagnostics

Run `mcp-wire doctor` for a read-only diagnostic report. It lists each supported target, whether it is detected on this system, the config path it would write to and whether that file exists, current feature flag state, and the paths mcp-wire uses for its own config, credentials, user-local services, and registry cache. It also prints hints for missing targets and disabled features. The command never writes to any config or credential file.

```bash
mcp-wire doctor
```

### Machine-readable metadata (for agents and automation)

Run `mcp-wire metadata` to print a stable JSON document describing what mcp-wire can do. It is intended for AI agents and scripts that need to inspect capabilities without driving the interactive TUI:

```bash
mcp-wire metadata
```

The document includes the supported transports and install scopes, every target (with install status, config path, supported scopes, and whether it can complete OAuth automatically), every service in the selected source (with transport, auth requirement, and the environment variables it needs), and current feature-flag state. By default only curated services are listed; pass `--source registry` or `--source all` to include community registry services (this requires the registry feature to be enabled).

The top-level `schema_version` field identifies the document structure and is only incremented on breaking changes, so automation can pin to a known shape. The `auth` field on each service is one of `oauth`, `api_key`, or `none`.

```jsonc
{
  "schema_version": 1,
  "mcp_wire_version": "0.2.2",
  "transports": ["http", "sse", "stdio"],
  "scopes": ["user", "project"],
  "targets": [
    {
      "name": "Claude Code",
      "slug": "claude",
      "installed": true,
      "config_path": "/home/you/.claude.json",
      "scopes": ["user", "project", "effective"],
      "supports_oauth": false
    }
  ],
  "services": [
    {
      "name": "sentry",
      "description": "Sentry MCP server (OAuth)",
      "source": "curated",
      "transport": "http",
      "auth": "oauth",
      "install_method": "remote",
      "env": []
    }
  ],
  "features": [
    { "name": "registry", "enabled": false, "description": "Official MCP Registry integration" }
  ]
}
```

Common queries with `jq`:

```bash
# List the slugs of every installed target
mcp-wire metadata | jq -r '.targets[] | select(.installed) | .slug'

# List curated services that require no credentials
mcp-wire metadata | jq -r '.services[] | select(.auth == "none") | .name'

# Show the required environment variables for a specific service
mcp-wire metadata | jq '.services[] | select(.name == "linear") | .env'
```

Like `doctor`, this command is read-only: it never writes to any config or credential file.

### Scope-aware installs (Claude Code)

For targets that support scopes (currently Claude Code), you can choose where MCP config is written:

- `user` (default): available across projects
- `project`: only for the current project

```bash
mcp-wire install jira --target claude --scope user
mcp-wire install jira --target claude --scope project
mcp-wire uninstall jira --target claude --scope project
```

## Supported Targets

- `claude` - Claude Code
- `codex` - Codex CLI
- `opencode` - OpenCode

## Supported Services

### Bundled (curated)

These ship with the binary and work out of the box:

- `context7` - Context7 documentation lookup MCP (OAuth)
- `github` - GitHub MCP server (OAuth)
- `jira` - Atlassian Rovo MCP server (OAuth)
- `linear` - Linear MCP server (OAuth)
- `notion` - Notion MCP server (OAuth)
- `sentry` - Sentry MCP server (OAuth)
- `playwright` - Playwright browser automation MCP (`npx @playwright/mcp@latest`)

### MCP Registry (community)

mcp-wire can also install from the [Official MCP Registry](https://registry.modelcontextprotocol.io), giving access to hundreds of community-published MCP servers. Enable with:

```bash
mcp-wire feature enable registry
```

Once enabled, the install wizard offers a source selection step (Curated / Registry / Both) with live search across all registry entries.

## Credential storage

When you accept the "Save to credential store?" prompt during install, mcp-wire writes the credential to:

```
~/.config/mcp-wire/credentials
```

The file is a plain `KEY=value` list, one credential per line. It is created with mode `0600` (owner read/write only) inside a directory created with mode `0700`. mcp-wire re-applies these permissions on every write, including when an existing directory was previously created with broader permissions.

At install time credentials are resolved in this order, and the first match wins:

1. Process environment variables.
2. The local credentials file above.
3. An interactive prompt (skipped when `--no-prompt` is set).

A few things worth knowing:

- Values are stored in plaintext. mcp-wire does not encrypt them or integrate with the system keychain.
- The same values are written into each target tool's MCP config (e.g. `~/.claude.json`, `~/.codex/config.toml`), so target config files are also created with mode `0600`.
- Interactive prompts mask typed input in both the TUI (password-style echo) and the plain CLI (`term.ReadPassword`). mcp-wire never echoes stored credential values back to the screen, into logs, or into error messages.
- To remove stored credentials for a service, use the uninstall flow and answer "Yes" at the "Remove stored credentials?" prompt, or edit the credentials file directly.

## Installation

### Homebrew (macOS/Linux)

```bash
brew tap andreagrandi/tap
brew install mcp-wire
```

### Verify an install

Run the built-in smoke tests to confirm the binary starts and non-mutating commands work. The tests use an isolated temporary `HOME` so they never touch your real MCP config or credentials:

```bash
make smoke-test
```

Or point the script at any already-built binary:

```bash
./scripts/smoke-test-release.sh ./bin/mcp-wire
```

To also verify a Homebrew-installed copy when `mcp-wire` is present in your Cellar:

```bash
SMOKE_TEST_HOMEBREW=true ./scripts/smoke-test-release.sh "$(brew --prefix mcp-wire)/bin/mcp-wire"
```

### Build from source

```bash
git clone https://github.com/andreagrandi/mcp-wire
cd mcp-wire
make build
./bin/mcp-wire
```

## Troubleshooting

See [docs/troubleshooting.md](docs/troubleshooting.md) for solutions to common problems, including:

- Target not detected on your system
- Empty or stale registry search
- Credentials prompted every time
- OAuth follow-up steps after install
- `--no-prompt` failures
- Config file safety and scope behavior

Run `mcp-wire doctor` first for a read-only diagnostic report.

## Contributing

Contributions are welcome, especially new service definitions.

- **Add a new service via YAML**: create a file in `services/` (no Go code required).
- **Service schema**: `name`, `description`, `transport`, and either `url` (for `sse`/`http`) or `command`/`args` (for `stdio`).
- **Transport values**: `http` (streamable HTTP endpoint), `sse` (Server-Sent Events endpoint), `stdio` (local command-based MCP server).
- **OAuth services**: add `auth: oauth` when applicable so install flows can drive authentication hints/automation.
- **Run checks before PRs**: `make test`, `make test-integration`, `make build`.
- **Update `CHANGELOG.md`**: every PR with a user-visible change (commands, flags, services, targets, install flows, packaging) adds a bullet under `## [Unreleased]`. See the "Changelog updates" section in `AGENTS.md` for what counts and how to format entries. CI enforces this.

Example service file:

```yaml
name: example
description: "Example MCP"
transport: http
auth: oauth
url: "https://mcp.example.com/mcp"
env: []
```

Example `stdio` service:

```yaml
name: example-stdio
description: "Example local MCP"
transport: stdio
command: npx
args: ["-y", "@example/mcp-server"]
env: []
```
