Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
python:
runs-on: macos-14
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install --upgrade build
- run: PYTHONPATH=src python -m unittest discover -s tests -v
- run: PYTHONPATH=src python -m unittest discover -s tests/integration -v
- run: python -m build
- run: python -m pip install --force-reinstall dist/*.whl
- run: agent-switch --version

macos-app:
runs-on: macos-14
steps:
- uses: actions/checkout@v7
- run: swift build --package-path macos-app/AgentSwitch
- run: >-
xcodebuild
-project macos-app/AgentSwitch/AgentSwitch.xcodeproj
-scheme AgentSwitch
-configuration Release
-derivedDataPath "$RUNNER_TEMP/AgentSwitchDerivedData"
CODE_SIGNING_ALLOWED=NO
build

privacy:
runs-on: macos-14
steps:
- uses: actions/checkout@v7
- name: Reject common credential and private-path shapes
run: python3 scripts/privacy_scan.py
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ build/
.firecrawl/
*.egg-info/
.coverage

# Local credentials and runtime state must never enter the product repository.
.env
.env.*
*.env
!*.env.example
secrets.env
backups/
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Changelog

All notable changes to Agent Switch are documented here.

## 0.2.0 - Unreleased

### Added

- Neutral empty registry for new installations.
- Unified MCP `list`, `add`, `set`, `enable`, `disable`, `remove`, and native
`import`/`--adopt` commands.
- macOS MCP editor, target selection, import/adoption, enable/disable, and
removal actions.
- Native import preview showing MCP IDs and secret names before adoption.
- Credential-to-MCP consumer mapping in status and the Secret UI.
- Detected-agent-only reconciliation for clean first-run behavior.

### Security

- Generated wrappers no longer source or export the complete secret store.
- Each MCP receives only its declared credentials; inherited sensitive
variables and unrelated stored credentials are removed.
- Native-config adoption backs up files privately before removing inline MCPs.
- Backup names include both target-path and content digests to prevent collisions.
- Credential-shaped stdio arguments are migrated to declared secret placeholders.
- Positional secret values are rejected.
- Doctor warns about unpinned `npx` packages.

### Changed

- The macOS app prefers an installed Agent Switch CLI and no longer requires a
source checkout when that CLI is available.
- `doctor --strict` now fails for drift or missing required credentials as well
as blocked targets.

## 0.1.3 - 2026-07-13

- Initial public repository preparation with CLI, native dashboard, secret
operations, MCP projections, Skill inventory, and CC Switch compatibility.
28 changes: 28 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Contributing

Agent Switch manages security-sensitive local configuration. Changes should be
small, testable, and preserve unrelated native configuration.

## Development

```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .
PYTHONPATH=src python -m unittest discover -s tests
PYTHONPATH=src python -m unittest discover -s tests/integration
swift build --package-path macos-app/AgentSwitch
python3 scripts/privacy_scan.py
```

## Required boundaries

- Never commit or print real credential values.
- MCPs may receive only the credentials they explicitly declare.
- Manage only the `agent-*` namespace and marked instruction blocks.
- Import/adoption changes require preview, validation, atomic writes, and
private backups.
- A clean user home must remain neutral until the user explicitly acts.

Open an issue before adding a new agent adapter or changing a native config
ownership boundary.
45 changes: 38 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Agent Switch

**One local control plane for AI coding agents, MCP servers, Skills, CLI tools, and secrets.**
**One local control plane for MCP servers and MCP credentials across your AI coding agents.**

[![macOS 14+](https://img.shields.io/badge/macOS-14%2B-111111?logo=apple)](https://www.apple.com/macos/)
[![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/)
Expand All @@ -21,8 +21,8 @@ Requirements:
2. If the canonical checkout does not exist, clone the repository there. If it exists and is clean, update it with git pull --ff-only. Never overwrite uncommitted user work.
3. Install or refresh the Python CLI from that checkout with pipx, and make sure `agent-switch` is on PATH.
4. Run the complete Python test suite. Then build and install the native app by running `macos-app/AgentSwitch/install.sh` from the checkout.
5. Run `agent-switch write-default-config`, then `agent-switch doctor`. Explain the planned managed changes briefly and run `agent-switch reconcile` only if Doctor reports no blocked target.
6. Verify `agent-switch doctor --strict`, `agent-switch agents`, `agent-switch clis`, and `agent-switch skills` all run. Confirm that `~/Applications/Agent Switch.app` opens.
5. Run `agent-switch write-default-config`, then `agent-switch mcp import --dry-run --json` to inventory existing MCPs without changing native configs. Do not adopt existing MCPs until the planned MCP IDs, target apps, and secret NAMES have been shown to me.
6. Run `agent-switch doctor`. Explain the planned managed changes briefly and run `agent-switch reconcile` only if Doctor reports no blocked target. Verify `agent-switch doctor --strict`, `agent-switch agents`, `agent-switch mcp list`, and `agent-switch secret list` all run. Confirm that `~/Applications/Agent Switch.app` opens.
7. Never ask me to paste an API key or token into chat. Never pass a secret as a command argument, print it, or write it to a project .env file. If a secret is needed, tell me to enter it in the Agent Switch app, or pipe it to `agent-switch secret set --stdin NAME` locally.
8. Report exactly what was installed, which agents were enrolled, any missing secret NAMES only, and any action I still need to take. Do not report secret values.
```
Expand All @@ -46,6 +46,7 @@ PYTHONPATH=src python3 -m unittest discover -s tests/integration
macos-app/AgentSwitch/install.sh

agent-switch write-default-config
agent-switch mcp import --dry-run --json
agent-switch doctor
agent-switch reconcile
agent-switch doctor --strict
Expand All @@ -59,15 +60,17 @@ agent-switch doctor --strict

AI tools usually keep separate copies of the same environment: one MCP list for Codex, another for Claude Code, another for Hermes, different instruction files, and secrets scattered across app configs. Those copies drift.

**Agent Switch gives them one managed local environment.** You define a tool once, store each secret once, and reconcile the safe projection into every supported agent.
**Agent Switch gives them one managed local environment.** You register an MCP once, store each credential once, choose its target agents, and reconcile a secret-free projection into every supported agent.

New installations start with an empty registry. Agent Switch never assumes that every user wants the maintainer's preferred MCPs or credentials.

### Core features

| Area | What Agent Switch manages |
| --- | --- |
| **Agents** | Detects and enrolls Codex, Claude Code, and Hermes; keeps one policy synchronized through their native instruction entry points. |
| **MCP servers** | Defines `agent-*` MCP tools centrally, generates secret-loading wrappers, repairs drift, and preserves every unrelated MCP entry. |
| **Secrets** | Stores tool credentials in one local mode-`0600` file; the macOS UI can add, update, reveal, hide, copy, and delete values. |
| **MCP servers** | Imports existing MCPs; adds, edits, enables, disables, removes, and targets them centrally; then repairs drift while preserving unrelated entries. |
| **Secrets** | Stores credentials once in a local mode-`0600` store and records which MCPs may consume each name. Every MCP receives only its declared credentials. |
| **Skills** | Reads an optional Skill Hub warehouse and separates dormant, project-active, global, and missing Skills. Downloading or updating a Skill never activates it. |
| **CLI tools** | Shows installed agent/tool CLIs, versions, package managers, executable paths, and Finder/file actions. |
| **Health and sync** | `doctor` previews drift; `reconcile` applies atomic, backed-up changes; the app exposes the same check-and-sync workflow. |
Expand Down Expand Up @@ -120,6 +123,21 @@ agent-switch doctor --json
# Repair managed MCP entries, wrappers, and shared instructions
agent-switch reconcile

# Inventory supported user-level stdio MCPs currently configured in supported agents
agent-switch mcp import --dry-run --json

# Back up native configs, migrate inline credentials, and adopt existing MCPs
agent-switch mcp import --adopt

# Manage the central registry
agent-switch mcp list
agent-switch mcp add filesystem --command npx \
--arg=-y --arg=@modelcontextprotocol/server-filesystem@1.0.0 \
--app codex --app claude
agent-switch mcp disable filesystem
agent-switch mcp enable filesystem
agent-switch mcp remove filesystem

# Inspect local integrations
agent-switch agents
agent-switch clis
Expand All @@ -142,14 +160,22 @@ Never substitute a literal secret for `secret-producing-command` in a recorded c
Agent Switch is local-first, but it is not a password vault:

- secret values are stored in `~/.config/agent-switch/secrets.env`, not in this repository, Git, app preferences, or generated agent configs;
- generated wrappers parse the store as data rather than sourcing it as shell code;
- a wrapper removes inherited sensitive variables and injects only the secret names declared by that MCP;
- the secrets file and instruction files use restrictive local permissions;
- secret writes use stdin or inherited file descriptors instead of process arguments;
- secret reads refuse stdout, stderr, terminal, and aliased descriptors;
- the macOS app reveals a value only after an explicit eye-button click, with no Touch ID dialog;
- diagnostics and audits report secret **names**, never secret values;
- wrappers fail closed when a required secret name is missing.
- `doctor` warns when an `npx` MCP package is not pinned to a version.

Read [MCP registry](docs/mcp-registry.md), [Secrets and wrappers](docs/secrets-and-wrappers.md), [Recovery](docs/recovery.md), and [Security Policy](SECURITY.md) before production use.

Read [Secrets and wrappers](docs/secrets-and-wrappers.md), [Recovery](docs/recovery.md), and [Security Policy](SECURITY.md) before production use.
Version 0.2 manages user-level, command/stdio MCP definitions. Native remote
HTTP/SSE and OAuth-session migration, project-scoped MCP discovery, additional
agent adapters, and signed distribution are tracked in the [roadmap](docs/roadmap.md)
rather than being presented as finished features.

## Skill Hub: warehouse first, activation second

Expand Down Expand Up @@ -214,6 +240,11 @@ python -m unittest discover -s tests/integration

The native application lives in [`macos-app/AgentSwitch`](macos-app/AgentSwitch) and targets macOS 14+.

The app uses the installed `agent-switch` CLI by default, exactly like an end
user installation. To run the app against a source checkout during development,
launch it with `AGENT_SWITCH_DEV_ROOT=/absolute/path/to/agent-switch`; source
code is never selected implicitly.

## License

[MIT](LICENSE) © 2026 JNHFlow21
8 changes: 8 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,21 @@ Please use [GitHub private vulnerability reporting](https://github.com/JNHFlow21
## Secret handling contract

- Never commit `~/.config/agent-switch/secrets.env` or copy it into a repository.
- The repository ignores `.env`, `*.env`, `secrets.env`, and `backups/`, but
ignore rules are only a last line of defense; credential values belong only
in the Agent Switch private store.
- Never include secret values in issues, screenshots, logs, or diagnostic output.
- Use the macOS app or `agent-switch secret set --stdin NAME` to write a value.
- Use `agent-switch secret list` for audits; it returns names only.
- Declare credential names on the MCP and keep their values out of the MCP's
ordinary `env` mapping. Generated wrappers grant only declared names.
- Pin package versions for MCPs launched through package runners such as `npx`.
- Rotate an affected provider credential immediately if exposure is suspected.

## Scope

Security reports should cover Agent Switch itself: secret storage and transport, generated wrappers, MCP config projection, instruction management, the native macOS app, and CC Switch compatibility behavior.

Third-party MCP servers, CLI tools, Skill sources, and providers keep their own security boundaries.
An MCP process can read the credentials explicitly granted to it; do not grant a
credential to code whose source or package version you do not trust.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.3
0.2.0
68 changes: 68 additions & 0 deletions docs/mcp-registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Unified MCP Registry

Agent Switch treats `~/.config/agent-switch/config.json` as the source of truth
for MCP definitions and `~/.config/agent-switch/secrets.env` as the source of
truth for credential values.

## Neutral first run

A new registry is empty. Agent Switch does not preinstall search, social, or
provider-specific MCPs and does not request unrelated credentials.

```bash
agent-switch write-default-config
agent-switch mcp list
```

## Import and adoption

Preview MCPs found in Claude Code, Claude Desktop, Codex, and Hermes:

```bash
agent-switch mcp import --dry-run --json
```

Adoption is explicit:

```bash
agent-switch mcp import --adopt
```

The adopt flow validates every source first, classifies credential-shaped
environment names, stores their values without printing them, backs up the
native files, removes the imported source entries, and reconciles wrapper-backed
`agent-*` projections. Non-secret environment values stay in central config.
The native app performs this same dry-run first and shows the MCP IDs and secret
names before the user can confirm adoption.

Version 0.2 imports user-level command/stdio entries. It deliberately does not
rewrite native HTTP/SSE or OAuth definitions into an unverified transport
bridge. Those transports need a dedicated adapter that preserves each client's
authentication semantics; see the roadmap. Discovery reports those entries as
`skipped` by app and ID, and adoption leaves them untouched.

## Registry lifecycle

```bash
agent-switch mcp add NAME --command COMMAND [--arg ARG] [--secret NAME] [--app APP]
agent-switch mcp set NAME --command COMMAND [options]
agent-switch mcp enable NAME
agent-switch mcp disable NAME
agent-switch mcp remove NAME
agent-switch mcp list --json
```

Supported app IDs are `claude`, `claude_desktop`, `codex`, and `hermes`.
Disabling an MCP removes its managed projections and stale wrapper on the next
reconcile without deleting stored credential values.

`--env NAME=VALUE` is only for non-secret settings. Names that look like keys,
tokens, passwords, credentials, or authentication values are rejected and must
be declared with `--secret NAME`; their values are written separately through
the Secret UI or `agent-switch secret set --stdin NAME`.

## Ownership

Agent Switch owns only `agent-*` entries and its marked instruction blocks.
Unrelated native configuration is preserved. Existing files are written
atomically and backups are kept in the private mode-`0700` backup directory.
16 changes: 16 additions & 0 deletions docs/recovery.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Recovery

Agent Switch writes atomically and stores backups under the Agent Switch backup directory when an existing file changes.
The backup directory is mode `0700` and backup files are mode `0600` because an
adopted native MCP config may have contained an inline credential.

## Failed Native Config Write

Expand Down Expand Up @@ -39,3 +41,17 @@ files are written atomically and backed up under `~/.config/agent-switch/backups

If enrollment does not converge, run `agent-switch agents --json` followed by
`agent-switch doctor --json` and restore only the affected target backup.

## MCP Import Or Adoption

Always preview first:

```bash
agent-switch mcp import --dry-run --json
```

`mcp import --adopt` validates all detected source formats before removing any
source entry. It then backs up each changed native file, migrates credential
values to the private store without printing them, and reconciles managed
projections. If adoption is interrupted, run `agent-switch doctor --json` and
restore only the affected private backup before retrying.
30 changes: 30 additions & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Roadmap

Agent Switch's product goal is one control plane for MCP definitions and static
credential values across local AI agents. The project documents incomplete
boundaries explicitly instead of treating a successful demo as a finished
distribution.

## 0.2 foundation

- Neutral first run with no maintainer-specific MCPs or credentials.
- Central lifecycle for user-level command/stdio MCPs.
- Explicit import preview and backed-up adoption from supported agents.
- One private credential store with per-MCP least-privilege wrappers.
- Detected-target-only reconciliation, strict health checks, CI, and package
build validation.

## Before stable 1.0

1. Normalize native Streamable HTTP and SSE MCP definitions without losing
client-specific OAuth behavior; migrate static header credentials without
printing or duplicating their values.
2. Discover project/local MCP scopes separately from user scope and require an
explicit ownership choice before adoption.
3. Add adapters through a documented contract and fixture suite rather than
guessing unknown agent configuration formats.
4. Ship a signed and notarized macOS release, a verified installer, published
Python packages, and a Homebrew path.
5. Add complete English and Chinese localization plus a first-run wizard that
previews targets, MCP IDs, and secret names before any write.
6. Add a first-class backup browser and guided restore flow.
Loading