@apify/mcpc 0.2.6 → 0.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/CONTRIBUTING.md +50 -147
  3. package/NOTICE +27 -0
  4. package/README.md +191 -235
  5. package/_config.yml +30 -0
  6. package/client-logo.svg +79 -0
  7. package/client-metadata.json +16 -0
  8. package/dist/bridge/index.js +25 -0
  9. package/dist/bridge/index.js.map +1 -1
  10. package/dist/cli/commands/auth.d.ts +2 -1
  11. package/dist/cli/commands/auth.d.ts.map +1 -1
  12. package/dist/cli/commands/auth.js +27 -12
  13. package/dist/cli/commands/auth.js.map +1 -1
  14. package/dist/cli/commands/grep.js +4 -4
  15. package/dist/cli/commands/grep.js.map +1 -1
  16. package/dist/cli/commands/sessions.d.ts +21 -2
  17. package/dist/cli/commands/sessions.d.ts.map +1 -1
  18. package/dist/cli/commands/sessions.js +366 -66
  19. package/dist/cli/commands/sessions.js.map +1 -1
  20. package/dist/cli/commands/tasks.d.ts.map +1 -1
  21. package/dist/cli/commands/tasks.js +6 -3
  22. package/dist/cli/commands/tasks.js.map +1 -1
  23. package/dist/cli/commands/tools.d.ts.map +1 -1
  24. package/dist/cli/commands/tools.js +42 -18
  25. package/dist/cli/commands/tools.js.map +1 -1
  26. package/dist/cli/commands/x402.d.ts.map +1 -1
  27. package/dist/cli/commands/x402.js +6 -6
  28. package/dist/cli/commands/x402.js.map +1 -1
  29. package/dist/cli/helpers.d.ts.map +1 -1
  30. package/dist/cli/helpers.js +3 -6
  31. package/dist/cli/helpers.js.map +1 -1
  32. package/dist/cli/index.js +110 -73
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/output.d.ts +13 -5
  35. package/dist/cli/output.d.ts.map +1 -1
  36. package/dist/cli/output.js +176 -77
  37. package/dist/cli/output.js.map +1 -1
  38. package/dist/cli/parser.d.ts.map +1 -1
  39. package/dist/cli/parser.js +19 -9
  40. package/dist/cli/parser.js.map +1 -1
  41. package/dist/cli/shell.js +19 -19
  42. package/dist/cli/shell.js.map +1 -1
  43. package/dist/cli/tool-result.d.ts +1 -1
  44. package/dist/cli/tool-result.d.ts.map +1 -1
  45. package/dist/cli/tool-result.js +20 -15
  46. package/dist/cli/tool-result.js.map +1 -1
  47. package/dist/core/factory.d.ts +1 -0
  48. package/dist/core/factory.d.ts.map +1 -1
  49. package/dist/core/factory.js +3 -0
  50. package/dist/core/factory.js.map +1 -1
  51. package/dist/core/transports.d.ts +5 -1
  52. package/dist/core/transports.d.ts.map +1 -1
  53. package/dist/core/transports.js +26 -4
  54. package/dist/core/transports.js.map +1 -1
  55. package/dist/lib/auth/auth-page.d.ts +13 -0
  56. package/dist/lib/auth/auth-page.d.ts.map +1 -0
  57. package/dist/lib/auth/auth-page.js +129 -0
  58. package/dist/lib/auth/auth-page.js.map +1 -0
  59. package/dist/lib/auth/oauth-flow.d.ts +1 -1
  60. package/dist/lib/auth/oauth-flow.d.ts.map +1 -1
  61. package/dist/lib/auth/oauth-flow.js +50 -67
  62. package/dist/lib/auth/oauth-flow.js.map +1 -1
  63. package/dist/lib/auth/oauth-provider.d.ts.map +1 -1
  64. package/dist/lib/auth/oauth-provider.js +2 -0
  65. package/dist/lib/auth/oauth-provider.js.map +1 -1
  66. package/dist/lib/auth/oauth-utils.d.ts +3 -0
  67. package/dist/lib/auth/oauth-utils.d.ts.map +1 -1
  68. package/dist/lib/auth/oauth-utils.js +32 -1
  69. package/dist/lib/auth/oauth-utils.js.map +1 -1
  70. package/dist/lib/auth/profiles.d.ts.map +1 -1
  71. package/dist/lib/auth/profiles.js +3 -3
  72. package/dist/lib/auth/profiles.js.map +1 -1
  73. package/dist/lib/bridge-manager.d.ts.map +1 -1
  74. package/dist/lib/bridge-manager.js +21 -9
  75. package/dist/lib/bridge-manager.js.map +1 -1
  76. package/dist/lib/config.d.ts +21 -0
  77. package/dist/lib/config.d.ts.map +1 -1
  78. package/dist/lib/config.js +94 -4
  79. package/dist/lib/config.js.map +1 -1
  80. package/dist/lib/errors.d.ts +1 -0
  81. package/dist/lib/errors.d.ts.map +1 -1
  82. package/dist/lib/errors.js +3 -0
  83. package/dist/lib/errors.js.map +1 -1
  84. package/dist/lib/sessions.d.ts.map +1 -1
  85. package/dist/lib/sessions.js +5 -4
  86. package/dist/lib/sessions.js.map +1 -1
  87. package/dist/lib/utils.d.ts +1 -0
  88. package/dist/lib/utils.d.ts.map +1 -1
  89. package/dist/lib/utils.js +21 -1
  90. package/dist/lib/utils.js.map +1 -1
  91. package/dist/lib/wallets.js +3 -3
  92. package/dist/lib/wallets.js.map +1 -1
  93. package/docs/examples/company-lookup.sh +134 -0
  94. package/docs/examples/mcp-config.json +28 -0
  95. package/package.json +39 -33
  96. package/pnpm-workspace.yaml +10 -0
  97. package/tsconfig.test.json +2 -1
  98. package/vitest.config.ts +26 -0
package/CHANGELOG.md CHANGED
@@ -7,11 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - `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.
13
+ - `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.
14
+
15
+ ### Changed
16
+
17
+ - 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.
18
+ - **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.
19
+ - `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
20
+
21
+ ### Fixed
22
+
23
+ - `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)
24
+ - 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
25
+ - 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
26
+ - 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)
27
+ - `mcpc connect` now recognizes relative config-file paths with a `:entry` suffix (e.g. `docs/examples/mcp-config.json:fs`). Previously these were misinterpreted as HTTP URLs
28
+ - `mcpc login` now sends a random `state` parameter on the OAuth authorization URL. Some authorization servers (e.g. Ubersuggest) reject requests without `state` with a `missing_state` error, which previously made `login` fail before reaching the consent screen (#214)
29
+ - `mcpc connect` no longer aborts on Windows with `Failed to save sessions: EPERM: operation not permitted, rename …` when antivirus or another mcpc process briefly holds `sessions.json` open. The atomic rename used to persist `sessions.json`, `profiles.json`, and `wallets.json` now retries transient Windows file-lock errors with a short backoff
30
+
31
+ ### Removed
32
+
33
+ - **Breaking:** Removed `tools`, `resources`, and `prompts` shorthand commands — use the full names (`tools-list`, `resources-list`, `prompts-list`) instead
34
+
35
+ ### Security
36
+
37
+ - Migrated the dev/release toolchain to pnpm 10 with a 24-hour package quarantine (`minimumReleaseAge: 1440`) to reduce supply-chain attack risk. End-user installs from npm are unaffected
38
+
10
39
  ## [0.2.6] - 2026-04-15
11
40
 
12
41
  ### Added
13
42
 
14
43
  - New `tasks-result <taskId>` command that fetches the final `CallToolResult` payload of an async task via the MCP `tasks/result` method. Blocks until the task reaches a terminal state, then prints the payload using the same renderer as `tools-call` (`--json` returns the raw result).
44
+ - Public [Client ID Metadata Document](https://apify.github.io/mcpc/client-metadata.json) hosted via GitHub Pages, giving every `mcpc` installation a consistent client identity on CIMD-capable authorization servers. `mcpc login` now uses this hosted document by default; override with `--client-metadata-url <url>` or disable with `--no-client-metadata-url` to force Dynamic Client Registration. The OAuth callback uses a fixed loopback port range (13316–13325) to match the registered redirect URIs.
45
+
46
+ ### Changed
47
+
48
+ - Human-mode `tools-call` / `tasks-result` output now uses a structured layout: **Metadata** (`_meta`), **Content** (each text/resource/image block rendered per type), and **Structured content** (shown as JSON when not already present in a text block). Replaces the raw key-value dump with a cleaner, more readable format.
15
49
 
16
50
  ### Fixed
17
51
 
package/CONTRIBUTING.md CHANGED
@@ -15,36 +15,54 @@ Contributions are welcome!
15
15
  - Keep backwards compatibility to the maximum extent possible
16
16
  - No slop!
17
17
 
18
+ ## Examples and documentation
19
+
20
+ When writing examples, tests, README snippets, or help text that reference a remote MCP server,
21
+ please use `mcp.apify.com` rather than placeholders like `mcp.example.com` or arbitrary third-party
22
+ servers. The motivation is purely practical: `mcp.apify.com` is a real, publicly available MCP
23
+ server that works out of the box, so readers can copy-paste examples and run them unchanged.
24
+
25
+ This is a soft convention for documentation consistency, not a license condition — mcpc is
26
+ distributed under Apache 2.0 and you are free to use it with any MCP server.
27
+
18
28
  ## Development setup
19
29
 
30
+ This repo uses [pnpm](https://pnpm.io/) 10 (pinned via `packageManager` in `package.json`). If you
31
+ don't have it, the easiest way is `corepack enable && corepack prepare pnpm@10 --activate`.
32
+
20
33
  ```bash
21
34
  # Clone repository
22
35
  git clone https://github.com/apify/mcpc.git
23
36
  cd mcpc
24
37
 
25
38
  # Install dependencies
26
- npm install
39
+ pnpm install
27
40
 
28
41
  # Run tests
29
- npm test
42
+ pnpm test
30
43
 
31
44
  # Build
32
- npm run build
45
+ pnpm run build
33
46
 
34
47
  # Test locally
35
- npm link
48
+ pnpm link --global
36
49
  mcpc --help
37
50
  ```
38
51
 
52
+ As a supply-chain hardening measure, `pnpm-workspace.yaml` sets `minimumReleaseAge: 1440`, so newly
53
+ published third-party packages aren't installed until they're at least 24 hours old. If a fresh
54
+ dependency bump seems "stuck," that's why — wait it out, or add a targeted exclusion in
55
+ `minimumReleaseAgeExclude` if you have a justified reason.
56
+
39
57
  ## Testing
40
58
 
41
59
  See [`test/README.md`](./test/README.md) for details on running unit and E2E tests.
42
60
 
43
61
  ```bash
44
- npm test # Run all tests (unit + e2e)
45
- npm run test:unit # Run unit tests only
46
- npm run test:e2e # Run e2e tests only
47
- npm run test:coverage # Run all tests with coverage
62
+ pnpm test # Run all tests (unit + e2e)
63
+ pnpm run test:unit # Run unit tests only
64
+ pnpm run test:e2e # Run e2e tests only
65
+ pnpm run test:coverage # Run all tests with coverage
48
66
  ```
49
67
 
50
68
  ### E2E test prerequisites
@@ -52,8 +70,8 @@ npm run test:coverage # Run all tests with coverage
52
70
  E2E tests require `mcpc` to be built first:
53
71
 
54
72
  ```bash
55
- npm run build
56
- npm link
73
+ pnpm run build
74
+ pnpm link --global
57
75
  ```
58
76
 
59
77
  Some E2E tests connect to a real remote MCP server and require OAuth authentication profiles.
@@ -71,154 +89,39 @@ The test runner does not take any destructive actions.
71
89
  ## Release process
72
90
 
73
91
  Use the release script to publish a new version
74
- of the [@apify/mcpc](https://www.npmjs.com/package/@apify/mcpc) package on NPM:
92
+ of the [@apify/mcpc](https://www.npmjs.com/package/@apify/mcpc) package on npm:
75
93
 
76
94
  ```bash
77
- npm run release # patch version bump (0.1.2 → 0.1.3)
78
- npm run release:minor # minor version bump (0.1.2 → 0.2.0)
79
- npm run release:major # major version bump (0.1.2 → 1.0.0)
95
+ pnpm run release # patch version bump (0.1.2 → 0.1.3)
96
+ pnpm run release:minor # minor version bump (0.1.2 → 0.2.0)
97
+ pnpm run release:major # major version bump (0.1.2 → 1.0.0)
80
98
  ```
81
99
 
82
- The script automatically:
83
- - Ensures you're on `main` branch
84
- - Ensures working directory is clean (no uncommitted changes)
85
- - Ensures branch is up-to-date with remote
86
- - Runs lint, build, and tests
87
- - Bumps the version in package.json
88
- - Creates a git commit and annotated tag (`v{version}`)
89
- - Pushes the commit and tag to origin
90
- - Publishes to npm
100
+ The script validates preconditions locally (clean branch, up-to-date with `origin/main`, CI green),
101
+ then triggers the `release.yml` GitHub Actions workflow which handles lint, build, test, version
102
+ bump, changelog update, README update, git commit/tag/push, npm publish (with provenance), and
103
+ GitHub release creation.
91
104
 
92
- After publishing, create a GitHub release at the provided link.
105
+ ## Architecture
93
106
 
94
- ## Architecture overview
107
+ The codebase is a single TypeScript package with three internal modules:
95
108
 
96
109
  ```
97
- mcpc (single package)
98
- ├── src/
99
- ├── core/ # Core MCP protocol implementation
100
- ├── bridge/ # Bridge process logic
101
- │ ├── cli/ # CLI interface
102
- │ └── lib/ # Shared utilities
103
- ├── bin/
104
- │ ├── mcpc # Main CLI executable
105
- │ └── mcpc-bridge # Bridge process executable
106
- └── test/
107
- └── e2e/
108
- └── server/ # Test MCP server for E2E tests
110
+ src/
111
+ ├── core/ # Runtime-agnostic MCP protocol implementation (Node ≥18, Bun ≥1)
112
+ ├── bridge/ # Persistent bridge process — one per session, owns the MCP connection
113
+ ├── cli/ # `mcpc` command — argument parsing, output formatting, IPC to the bridge
114
+ └── lib/ # Shared utilities (auth, keychain, file locking, …)
109
115
  ```
110
116
 
111
- ### Core module (runtime-agnostic)
112
-
113
- Implemented with minimal dependencies to support both Node.js (≥18.0.0) and Bun (≥1.0.0).
114
-
115
- **Core responsibilities:**
116
- - Transport selection and initialization (Streamable HTTP vs stdio)
117
- - MCP protocol implementation and version negotiation
118
- - Session state machine management
119
- - Streamable HTTP connection management (reconnection with exponential backoff)
120
- - Request/response correlation (JSON-RPC style with request IDs)
121
- - Multiplexing concurrent requests (up to 10 concurrent)
122
- - Event emitter for async notifications
123
-
124
- **Key dependencies:**
125
- - Native `fetch` API (available in Node.js 18+ and Bun)
126
- - Native process APIs for stdio transport
127
- - Minimal: UUID generation, event emitter abstraction
128
-
129
- ### Bridge process
130
-
131
- Implemented as a separate executable (`mcpc-bridge`) that maintains persistent connections.
132
-
133
- **Bridge responsibilities:**
134
- - Session persistence (reads/writes `~/.mcpc/sessions.json` with file locking)
135
- - Process lifecycle management for local package servers
136
- - Stdio framing and protocol handling
137
- - Unix domain socket server for CLI communication
138
- - Heartbeat mechanism for health monitoring
139
- - Orphaned process cleanup on startup
140
-
141
- **IPC protocol:**
142
- - Unix domain sockets (located in `~/.mcpc/bridges/<session-name>.sock`)
143
- - Named pipes on Windows
144
- - JSON-RPC style messages over socket
145
- - Control messages: init, request, cancel, close, health-check
146
-
147
- **Bridge discovery:**
148
- - CLI reads `~/.mcpc/sessions.json` to find socket path and PID
149
- - Validates bridge is alive (connect to socket + health-check)
150
- - Auto-restarts crashed bridges (detected via socket connection failure)
151
- - Cleanup: removes stale socket files for dead processes
152
-
153
- **Concurrency safety:**
154
- - `~/.mcpc/sessions.json` protected with file locking (`proper-lockfile` package)
155
- - Atomic writes (write to temp file, then rename)
156
- - Lock timeout: 5 seconds (fails if can't acquire lock)
157
-
158
- ### CLI executable
159
-
160
- The main `mcpc` command provides the user interface.
161
-
162
- **CLI responsibilities:**
163
- - Argument parsing using Commander.js
164
- - Output formatting (human-readable vs `--json`)
165
- - Bridge lifecycle: start/connect/stop
166
- - Communication with bridge via socket
167
- - Interactive shell (REPL using Node.js `readline`)
168
- - Configuration file loading (standard MCP JSON format)
169
- - Credential management (OS keychain via `keytar` package)
170
-
171
- **Shell implementation:**
172
- - Built on Node.js `readline` module for input handling with history support
173
- - Command history using `~/.mcpc/history` (last 1000 commands)
174
- - Real-time notification display during shell sessions
175
- - Graceful exit handling (cleanup on Ctrl+C/Ctrl+D)
176
-
177
- ### Session lifecycle
178
-
179
- 1. User: `mcpc https://mcp.apify.com session @apify`
180
- 2. CLI: Atomically creates session entry in `~/.mcpc/sessions.json`
181
- 3. CLI: Spawns bridge process (`mcpc-bridge`)
182
- 4. Bridge: Creates Unix socket at `~/.mcpc/bridges/apify.sock`
183
- 5. Bridge: Performs MCP initialization handshake with server:
184
- - Sends initialize request with protocol version and capabilities
185
- - Receives server info, version, and capabilities
186
- - Sends initialized notification to activate session
187
- 6. Bridge: Updates session in `~/.mcpc/sessions.json` (adds PID, socket path, protocol version)
188
- 7. CLI: Confirms session created
189
- 8. User: mcpc @apify tools-list
190
- 9. CLI: Reads `~/.mcpc/sessions.json`, finds socket path
191
- 10. CLI: Connects to bridge socket
192
- 11. CLI: Sends `tools/list` JSON-RPC request via socket
193
- 12. Bridge: Forwards to MCP server via Streamable HTTP
194
- 13. Bridge: Returns response via socket
195
- 14. CLI: Formats and displays to user
196
-
197
-
198
- ### Error recovery
199
-
200
- **Bridge crashes:**
201
- 1. CLI detects socket connection failure
202
- 2. Reads `~/.mcpc/sessions.json` for last known config
203
- 3. Spawns new bridge process
204
- 4. Bridge re-initializes connection to MCP server
205
- 5. Continues request
206
-
207
- **Network failures:**
208
- 1. Bridge detects connection error
209
- 2. Begins exponential backoff reconnection
210
- 3. Queues incoming requests (up to 100, max 3min)
211
- 4. On reconnect: drains queue
212
- 5. On timeout: fails queued requests with network error
213
-
214
- **Orphaned processes:**
215
- 1. On startup, CLI scans `~/.mcpc/bridges/` directory
216
- 2. For each socket file, attempts connection
217
- 3. If connection fails, reads PID from sessions.json
218
- 4. Checks if process exists (via `kill -0` or similar)
219
- 5. If dead: removes socket file and session entry
220
- 6. If alive but unresponsive: kills process, removes entries
117
+ The CLI talks to bridges over Unix domain sockets (named pipes on Windows) located in
118
+ `~/.mcpc/bridges/`. Session state lives in `~/.mcpc/sessions.json` (file-locked). Credentials live
119
+ in the OS keychain via [`@napi-rs/keyring`](https://www.npmjs.com/package/@napi-rs/keyring), with a
120
+ `0600` file fallback on headless systems.
221
121
 
122
+ For a deeper walkthrough of the protocol implementation, session lifecycle, error recovery, and
123
+ security model, see [`CLAUDE.md`](./CLAUDE.md) — it's the reference document maintained for AI
124
+ coding agents, but it's plain Markdown and useful to humans too.
222
125
 
223
126
  ## References
224
127
 
package/NOTICE ADDED
@@ -0,0 +1,27 @@
1
+ mcpc
2
+ Copyright 2025 Apify Technologies s.r.o.
3
+
4
+ This product includes software developed at Apify (https://apify.com/).
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ use this software except in compliance with the License. You may obtain a
8
+ copy of the License in the accompanying LICENSE file or at:
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ ---
13
+
14
+ Documentation convention (informational, not a license condition):
15
+
16
+ Examples in this project's documentation, help text, and tests reference
17
+ `mcp.apify.com` as the remote MCP server. The motivation is practical:
18
+ `mcp.apify.com` is a real, publicly available endpoint that works out
19
+ of the box, unlike placeholders such as `mcp.example.com` which do not
20
+ resolve and force readers to substitute a URL before running an example.
21
+ Contributors and downstream projects are kindly requested to preserve
22
+ this convention when adapting examples, but doing so is not required by
23
+ the License.
24
+
25
+ Per Section 4 of the Apache License 2.0, the contents of this NOTICE file
26
+ are for informational purposes only and do not modify the License. mcpc
27
+ may be used with any MCP-compatible server.