Skip to content
Draft
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `mcpc connect` (with no arguments) now auto-discovers standard MCP config files (`.mcp.json`, `mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`, `~/.claude.json`, Claude Desktop, Windsurf, Kiro, etc.) in the current directory and home directory, and connects every server defined across them. Entries with duplicate session names are deduplicated (project-scoped files win over global ones). VS Code's `"servers"` key is also supported.
- `mcpc connect` auto-connects to `mcp.apify.com` as `@apify` when the `APIFY_API_TOKEN` environment variable is set, using it as a Bearer token. Existing live sessions are reused without restart.
- `mcpc x402 sign` supports the x402 `upto` scheme alongside `exact`. Use `--scheme <auto|upto|exact>` to pick a preference (default `auto` prefers `upto`, falls back to `exact`). The signer auto-grants a one-time `USDC.approve(PERMIT2, MAX_UINT256)` allowance on first upto sign; pass `--no-approve` to skip.
- `mcpc connect --x402 [auto|upto|exact]` enables x402 auto-payment with an optional scheme preference. Bare `--x402` defaults to `auto` (prefer upto, fall back to exact). The choice is persisted to `sessions.json` and reused on `mcpc restart`. Use `--x402=<scheme>` when the flag is followed by positional arguments to avoid Commander's greedy parsing of the next token.
- Sessions using x402 auto-payment now show a yellow `[x402]` marker in session listings, alongside the existing OAuth and proxy markers.

### Changed

- Stdio (command-based) config entries are now skipped by default when connecting from a config file (`mcpc connect <file>`). Pass `--stdio` to include them. Single-entry connects (`mcpc connect file:entry @session`) are not affected.
- x402 debug logs now announce the selected scheme (`scheme=upto` / `scheme=exact`) up front and print USD amounts with 6-decimal precision (USDC atomic unit). Enable with `--verbose` or `MCPC_VERBOSE=1`.
- **Breaking:** `mcpc connect --json` now always returns an array of `InitializeResult` objects (extended with `toolNames` and `_mcpc` metadata), regardless of whether you connect a single server, a config file, or auto-discover all configs. Skipped/failed entries carry `_mcpc.status` (`created` | `active` | `failed` | `skipped`) and `_mcpc.skipReason` / `_mcpc.error`. The previous wrapper-object shapes (`{configFile, results, skipped}` and `{discovered, results, skipped}`) have been removed.
- `tools-call --task` now prints the task ID and recovery commands when interrupted with Ctrl+C, so you can fetch or cancel the server-side task later

### Fixed

- `mcpc connect` and `mcpc restart` no longer fail with `ENOENT` when the macOS Keychain prompts for a password. Credentials are now read from the keychain *before* the bridge process is spawned, so the bridge's IPC startup timer no longer races a foreground password dialog (#55)
- `mcpc connect` and `mcpc restart` no longer fail with `ENOENT` when the macOS Keychain prompts for a password. Credentials are now read from the keychain _before_ the bridge process is spawned, so the bridge's IPC startup timer no longer races a foreground password dialog (#55)
- Background auto-reconnect now correctly marks sessions as `unauthorized` when the server returns 401/403, instead of leaving them stuck in `connecting` after the bridge crashed on an unhandled rejection
- Sessions using a static bearer token (via `--header "Authorization: ..."`) no longer flip between `unauthorized` and `connecting` on every `mcpc` invocation — they stay `unauthorized` until you `mcpc login` or reconnect. OAuth-profile sessions still auto-retry because tokens may have been refreshed by another session
- Stdio servers no longer fail silently: the bridge now captures the child's stderr, writes it to `~/.mcpc/logs/bridge-<session>.log`, and appends a tail of the most recent lines to `mcpc connect` errors. This makes it obvious when a stdio server crashes on startup due to e.g. missing TLS trust (`NODE_EXTRA_CA_CERTS`), missing proxy vars, or missing credentials (#195)
Expand Down
63 changes: 40 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ and auto-reconnects on network failures or its own crashes (10s cooldown on fail
**Session states:**

| State | Meaning |
|------------------| ----------------------------------------------------------------------------------------------- |
| ---------------- | ----------------------------------------------------------------------------------------------- |
| 🟢`live` | Bridge process running and server responding |
| 🟡`connecting` | Initial bridge startup in progress (`mcpc connect`) |
| 🟡`reconnecting` | Bridge crashed or lost auth; auto-reconnecting in the background |
Expand Down Expand Up @@ -485,13 +485,13 @@ always win over stored profiles, and credentials are never silently downgraded.
is missing, expired, or invalid, `mcpc` fails with an error that includes the right
`mcpc login` command to recover.

| Flag | Behavior |
| ------------------------------- | ------------------------------------------------------------------------------------------- |
| `--header "Authorization: ..."` | Use explicit header; skip OAuth auto-detection. Cannot combine with `--profile`. |
| `--profile <name>` | Require the named profile to exist. |
| `--no-profile` | Connect anonymously even if a `default` profile exists. |
| `--x402` | Skip OAuth auto-detection; use x402 payments instead. Combine with `--profile` to use both. |
| _(none)_ | Use `default` profile if it exists; otherwise connect anonymously. |
| Flag | Behavior |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `--header "Authorization: ..."` | Use explicit header; skip OAuth auto-detection. Cannot combine with `--profile`. |
| `--profile <name>` | Require the named profile to exist. |
| `--no-profile` | Connect anonymously even if a `default` profile exists. |
| `--x402 [scheme]` | Skip OAuth auto-detection; use x402 payments instead. Optional scheme: `auto` (default), `upto`, `exact`. Combine with `--profile` to use both. |
| _(none)_ | Use `default` profile if it exists; otherwise connect anonymously. |

Config file headers (from `--config`) apply to servers loaded from that file.

Expand Down Expand Up @@ -681,13 +681,20 @@ This is entirely **opt-in**: existing functionality is unaffected unless you exp

### How it works

1. **Server returns HTTP 402** with a `PAYMENT-REQUIRED` header describing the price and payment details.
2. `mcpc` parses the header, signs an [EIP-3009](https://eips.ethereum.org/EIPS/eip-3009) `TransferWithAuthorization` using your local wallet.
3. `mcpc` retries the request with a `PAYMENT-SIGNATURE` header containing the signed payment.
The x402 protocol defines different payment **schemes**:

- **`exact`** (Standard EIP-3009): The client signs an exact `TransferWithAuthorization` on USDC. Settles on-chain immediately at call-time.
- **`upto`** (Permit2): The client signs a maximum authorization cap using Uniswap's `Permit2` witness signatures. The facilitator verifies the signature off-chain immediately, and settles the actual accumulated usage later (asynchronously).

Regardless of the scheme, the general flow is:

1. **Server returns HTTP 402** with a `PAYMENT-REQUIRED` header advertising its supported schemes and details.
2. `mcpc` parses the header, picks the best scheme, and signs the payment payload using your local wallet.
- For `upto`, `mcpc` automatically checks and grants the one-time on-chain Permit2 allowance if needed (requires a small native ETH float for gas).
3. `mcpc` retries the request with a `PAYMENT-SIGNATURE` header containing the signed payload.
4. The server verifies the signature and fulfills the request.

For tools that advertise pricing in their `_meta.x402` metadata, `mcpc` can **proactively sign** payments
on the first request, avoiding the 402 round-trip entirely.
For tools that advertise pricing in their `_meta.x402` metadata, `mcpc` can **proactively sign** payments on the first request, avoiding the 402 round-trip entirely. This path is fully scheme-aware and respects your configured session preference.

### Wallet setup

Expand Down Expand Up @@ -731,31 +738,41 @@ mcpc x402 sign <base64-payment-required> --amount 1.00 --expiry 3600 --json

**Options:**

| Option | Description |
| -------------------- | ------------------------------------------------------------- |
| `--amount <usd>` | Override the payment amount in USD (e.g. `0.50` for $0.50) |
| `--expiry <seconds>` | Override the payment expiry in seconds from now (e.g. `3600`) |
| Option | Description |
| -------------------- | ----------------------------------------------------------------------- |
| `--amount <usd>` | Override the payment amount in USD (e.g. `0.50` for $0.50) |
| `--expiry <seconds>` | Override the payment expiry in seconds from now (e.g. `3600`) |
| `--scheme <val>` | Scheme preference: `auto` (default, upto > exact), `upto`, or `exact` |
| `--no-approve` | For `upto`, skip checking and auto-approving on-chain Permit2 allowance |

The command outputs the signed `PAYMENT-SIGNATURE` header value and an MCP config snippet
that can be used directly with other MCP clients.

### Using x402 with MCP servers

Pass the `--x402` flag when connecting to a session or running direct commands:
Pass the `--x402` flag when connecting to a session. It accepts an optional scheme preference
(`auto`, `upto`, or `exact`); bare `--x402` defaults to `auto`.

```bash
# Create a session with x402 payment support
# Create a session with x402 payment support (auto picks the best advertised scheme)
mcpc connect mcp.apify.com @apify --x402

# The session now automatically handles 402 responses
# Pin a specific scheme — value goes after the flag
mcpc connect mcp.apify.com @apify --x402 exact

# When --x402 precedes positional args, use the equals form to avoid Commander's
# greedy [optional] argument parser eating the URL/session as the value.
mcpc connect --x402=upto mcp.apify.com @apify

# The session now automatically handles 402 responses using your preference
mcpc @apify tools-call expensive-tool query:="hello"

# Restart a session with x402 enabled
mcpc @apify restart --x402
# Restart re-uses the saved scheme from sessions.json — no need to repeat the flag
mcpc @apify restart
```

When `--x402` is active, a fetch middleware wraps all HTTP requests to the MCP server.
If any request returns HTTP 402, the middleware transparently signs and retries.
If any request returns HTTP 402, the middleware transparently signs and retries. Your scheme preference is persisted in `sessions.json` and reused on every reconnect or restart.

### Supported networks

Expand Down
Loading
Loading