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
12 changes: 12 additions & 0 deletions cmd/mcpproxy/connect_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,19 @@ func runDisconnect(cmd *cobra.Command, args []string) error {
}

func printConnectStatus(svc *connect.Service, formatter clioutput.OutputFormatter, format string) error {
// Spec 075: GetAllStatus is content-read-free and leaves Connected/AccessState
// unresolved. Running `mcpproxy connect` is an explicit user action, so resolve
// each supported+installed client's connected state on demand via GetStatus to
// preserve the CONNECTED column. Unsupported/absent clients keep the cheap
// metadata-only listing (no content read).
statuses := svc.GetAllStatus()
for i := range statuses {
if statuses[i].Supported && statuses[i].Exists {
if st, err := svc.GetStatus(statuses[i].ID); err == nil {
statuses[i] = st
}
}
}

if format == "table" {
headers := []string{"CLIENT", "STATUS", "CONFIG PATH", "CONNECTED"}
Expand Down
26 changes: 26 additions & 0 deletions docs/api/rest-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,32 @@ Success returns `data.server` (`name`, `protocol`, `command`, `args`, `url`,
Drop a registry's cached server lists. Returns
`{ "registry_id": "...", "cleared": <n> }`.

### Connect (client wizard)

#### GET /api/v1/connect

Lists the connection status of every known MCP client (Claude Desktop, Cursor,
VS Code, Codex, Gemini, OpenCode, …).

As of Spec 075, the overall listing determines each client's installed state
using **file-existence metadata only** (`os.Stat`) and performs **zero config
content reads** — so simply viewing status never triggers the macOS
"wants to access data from other apps" privacy prompt. Each per-client object is
additive-compatible and gains two fields:

| Field | Type | Meaning |
|-------|------|---------|
| `exists` | bool | Config file present (metadata only). |
| `connected` | bool | mcpproxy registered in the config. Authoritative **only** when `access_state == "accessible"`; `false`/unresolved in the overall listing. |
| `access_state` | string | `"unknown"` in the overall listing (not content-checked); resolved to `"accessible"`, `"absent"`, or `"malformed"` by an on-demand single-client read. |
| `remediation` | string | Present only when access is denied (populated by later stories). |

A client that is installed but not yet content-checked reads as
`exists=true, connected=false, access_state="unknown"`. Resolving `connected`
requires an explicit per-client read (connect/disconnect, or the CLI
`mcpproxy connect` command), which is the only place a privacy prompt may
legitimately appear.

### Real-time Updates

#### GET /events
Expand Down
Loading
Loading