@apify/mcpc 0.3.0-beta.0 → 0.3.0
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.
- package/CHANGELOG.md +8 -1
- package/CONTRIBUTING.md +40 -149
- package/README.md +22 -68
- package/docs/examples/company-lookup.sh +134 -0
- package/docs/examples/mcp-config.json +28 -0
- package/package.json +39 -34
- package/pnpm-workspace.yaml +10 -0
- package/tsconfig.test.json +2 -1
- package/vitest.config.ts +26 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-05-20
|
|
11
|
+
|
|
10
12
|
### Added
|
|
11
13
|
|
|
12
14
|
- `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.
|
|
@@ -32,6 +34,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
32
34
|
|
|
33
35
|
- **Breaking:** Removed `tools`, `resources`, and `prompts` shorthand commands — use the full names (`tools-list`, `resources-list`, `prompts-list`) instead
|
|
34
36
|
|
|
37
|
+
### Security
|
|
38
|
+
|
|
39
|
+
- 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
|
|
40
|
+
|
|
35
41
|
## [0.2.6] - 2026-04-15
|
|
36
42
|
|
|
37
43
|
### Added
|
|
@@ -265,7 +271,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
265
271
|
- Interactive shell mode
|
|
266
272
|
- JSON output mode for scripting
|
|
267
273
|
|
|
268
|
-
[Unreleased]: https://github.com/apify/mcpc/compare/v0.
|
|
274
|
+
[Unreleased]: https://github.com/apify/mcpc/compare/v0.3.0...HEAD
|
|
275
|
+
[0.3.0]: https://github.com/apify/mcpc/compare/v0.2.6...v0.3.0
|
|
269
276
|
[0.2.6]: https://github.com/apify/mcpc/compare/v0.2.5...v0.2.6
|
|
270
277
|
[0.2.5]: https://github.com/apify/mcpc/compare/v0.2.4...v0.2.5
|
|
271
278
|
[0.2.4]: https://github.com/apify/mcpc/compare/v0.2.3...v0.2.4
|
package/CONTRIBUTING.md
CHANGED
|
@@ -21,42 +21,48 @@ When writing examples, tests, README snippets, or help text that reference a rem
|
|
|
21
21
|
please use `mcp.apify.com` rather than placeholders like `mcp.example.com` or arbitrary third-party
|
|
22
22
|
servers. The motivation is purely practical: `mcp.apify.com` is a real, publicly available MCP
|
|
23
23
|
server that works out of the box, so readers can copy-paste examples and run them unchanged.
|
|
24
|
-
Placeholders like `mcp.example.com` don't resolve to anything, which forces every reader to
|
|
25
|
-
substitute a URL before they can try an example.
|
|
26
24
|
|
|
27
25
|
This is a soft convention for documentation consistency, not a license condition — mcpc is
|
|
28
26
|
distributed under Apache 2.0 and you are free to use it with any MCP server.
|
|
29
27
|
|
|
30
28
|
## Development setup
|
|
31
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
|
+
|
|
32
33
|
```bash
|
|
33
34
|
# Clone repository
|
|
34
35
|
git clone https://github.com/apify/mcpc.git
|
|
35
36
|
cd mcpc
|
|
36
37
|
|
|
37
38
|
# Install dependencies
|
|
38
|
-
|
|
39
|
+
pnpm install
|
|
39
40
|
|
|
40
41
|
# Run tests
|
|
41
|
-
|
|
42
|
+
pnpm test
|
|
42
43
|
|
|
43
44
|
# Build
|
|
44
|
-
|
|
45
|
+
pnpm run build
|
|
45
46
|
|
|
46
47
|
# Test locally
|
|
47
|
-
|
|
48
|
+
pnpm link --global
|
|
48
49
|
mcpc --help
|
|
49
50
|
```
|
|
50
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
|
+
|
|
51
57
|
## Testing
|
|
52
58
|
|
|
53
59
|
See [`test/README.md`](./test/README.md) for details on running unit and E2E tests.
|
|
54
60
|
|
|
55
61
|
```bash
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
60
66
|
```
|
|
61
67
|
|
|
62
68
|
### E2E test prerequisites
|
|
@@ -64,8 +70,8 @@ npm run test:coverage # Run all tests with coverage
|
|
|
64
70
|
E2E tests require `mcpc` to be built first:
|
|
65
71
|
|
|
66
72
|
```bash
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
pnpm run build
|
|
74
|
+
pnpm link --global
|
|
69
75
|
```
|
|
70
76
|
|
|
71
77
|
Some E2E tests connect to a real remote MCP server and require OAuth authentication profiles.
|
|
@@ -83,154 +89,39 @@ The test runner does not take any destructive actions.
|
|
|
83
89
|
## Release process
|
|
84
90
|
|
|
85
91
|
Use the release script to publish a new version
|
|
86
|
-
of the [@apify/mcpc](https://www.npmjs.com/package/@apify/mcpc) package on
|
|
92
|
+
of the [@apify/mcpc](https://www.npmjs.com/package/@apify/mcpc) package on npm:
|
|
87
93
|
|
|
88
94
|
```bash
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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)
|
|
92
98
|
```
|
|
93
99
|
|
|
94
|
-
The script
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Runs lint, build, and tests
|
|
99
|
-
- Bumps the version in package.json
|
|
100
|
-
- Creates a git commit and annotated tag (`v{version}`)
|
|
101
|
-
- Pushes the commit and tag to origin
|
|
102
|
-
- 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.
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
## Architecture
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
The codebase is a single TypeScript package with three internal modules:
|
|
107
108
|
|
|
108
109
|
```
|
|
109
|
-
|
|
110
|
-
├──
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
│ └── lib/ # Shared utilities
|
|
115
|
-
├── bin/
|
|
116
|
-
│ ├── mcpc # Main CLI executable
|
|
117
|
-
│ └── mcpc-bridge # Bridge process executable
|
|
118
|
-
└── test/
|
|
119
|
-
└── e2e/
|
|
120
|
-
└── 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, …)
|
|
121
115
|
```
|
|
122
116
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
**Core responsibilities:**
|
|
128
|
-
- Transport selection and initialization (Streamable HTTP vs stdio)
|
|
129
|
-
- MCP protocol implementation and version negotiation
|
|
130
|
-
- Session state machine management
|
|
131
|
-
- Streamable HTTP connection management (reconnection with exponential backoff)
|
|
132
|
-
- Request/response correlation (JSON-RPC style with request IDs)
|
|
133
|
-
- Multiplexing concurrent requests (up to 10 concurrent)
|
|
134
|
-
- Event emitter for async notifications
|
|
135
|
-
|
|
136
|
-
**Key dependencies:**
|
|
137
|
-
- Native `fetch` API (available in Node.js 18+ and Bun)
|
|
138
|
-
- Native process APIs for stdio transport
|
|
139
|
-
- Minimal: UUID generation, event emitter abstraction
|
|
140
|
-
|
|
141
|
-
### Bridge process
|
|
142
|
-
|
|
143
|
-
Implemented as a separate executable (`mcpc-bridge`) that maintains persistent connections.
|
|
144
|
-
|
|
145
|
-
**Bridge responsibilities:**
|
|
146
|
-
- Session persistence (reads/writes `~/.mcpc/sessions.json` with file locking)
|
|
147
|
-
- Process lifecycle management for local package servers
|
|
148
|
-
- Stdio framing and protocol handling
|
|
149
|
-
- Unix domain socket server for CLI communication
|
|
150
|
-
- Heartbeat mechanism for health monitoring
|
|
151
|
-
- Orphaned process cleanup on startup
|
|
152
|
-
|
|
153
|
-
**IPC protocol:**
|
|
154
|
-
- Unix domain sockets (located in `~/.mcpc/bridges/<session-name>.sock`)
|
|
155
|
-
- Named pipes on Windows
|
|
156
|
-
- JSON-RPC style messages over socket
|
|
157
|
-
- Control messages: init, request, cancel, close, health-check
|
|
158
|
-
|
|
159
|
-
**Bridge discovery:**
|
|
160
|
-
- CLI reads `~/.mcpc/sessions.json` to find socket path and PID
|
|
161
|
-
- Validates bridge is alive (connect to socket + health-check)
|
|
162
|
-
- Auto-restarts crashed bridges (detected via socket connection failure)
|
|
163
|
-
- Cleanup: removes stale socket files for dead processes
|
|
164
|
-
|
|
165
|
-
**Concurrency safety:**
|
|
166
|
-
- `~/.mcpc/sessions.json` protected with file locking (`proper-lockfile` package)
|
|
167
|
-
- Atomic writes (write to temp file, then rename)
|
|
168
|
-
- Lock timeout: 5 seconds (fails if can't acquire lock)
|
|
169
|
-
|
|
170
|
-
### CLI executable
|
|
171
|
-
|
|
172
|
-
The main `mcpc` command provides the user interface.
|
|
173
|
-
|
|
174
|
-
**CLI responsibilities:**
|
|
175
|
-
- Argument parsing using Commander.js
|
|
176
|
-
- Output formatting (human-readable vs `--json`)
|
|
177
|
-
- Bridge lifecycle: start/connect/stop
|
|
178
|
-
- Communication with bridge via socket
|
|
179
|
-
- Interactive shell (REPL using Node.js `readline`)
|
|
180
|
-
- Configuration file loading (standard MCP JSON format)
|
|
181
|
-
- Credential management (OS keychain via `keytar` package)
|
|
182
|
-
|
|
183
|
-
**Shell implementation:**
|
|
184
|
-
- Built on Node.js `readline` module for input handling with history support
|
|
185
|
-
- Command history using `~/.mcpc/history` (last 1000 commands)
|
|
186
|
-
- Real-time notification display during shell sessions
|
|
187
|
-
- Graceful exit handling (cleanup on Ctrl+C/Ctrl+D)
|
|
188
|
-
|
|
189
|
-
### Session lifecycle
|
|
190
|
-
|
|
191
|
-
1. User: `mcpc https://mcp.apify.com session @apify`
|
|
192
|
-
2. CLI: Atomically creates session entry in `~/.mcpc/sessions.json`
|
|
193
|
-
3. CLI: Spawns bridge process (`mcpc-bridge`)
|
|
194
|
-
4. Bridge: Creates Unix socket at `~/.mcpc/bridges/apify.sock`
|
|
195
|
-
5. Bridge: Performs MCP initialization handshake with server:
|
|
196
|
-
- Sends initialize request with protocol version and capabilities
|
|
197
|
-
- Receives server info, version, and capabilities
|
|
198
|
-
- Sends initialized notification to activate session
|
|
199
|
-
6. Bridge: Updates session in `~/.mcpc/sessions.json` (adds PID, socket path, protocol version)
|
|
200
|
-
7. CLI: Confirms session created
|
|
201
|
-
8. User: mcpc @apify tools-list
|
|
202
|
-
9. CLI: Reads `~/.mcpc/sessions.json`, finds socket path
|
|
203
|
-
10. CLI: Connects to bridge socket
|
|
204
|
-
11. CLI: Sends `tools/list` JSON-RPC request via socket
|
|
205
|
-
12. Bridge: Forwards to MCP server via Streamable HTTP
|
|
206
|
-
13. Bridge: Returns response via socket
|
|
207
|
-
14. CLI: Formats and displays to user
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
### Error recovery
|
|
211
|
-
|
|
212
|
-
**Bridge crashes:**
|
|
213
|
-
1. CLI detects socket connection failure
|
|
214
|
-
2. Reads `~/.mcpc/sessions.json` for last known config
|
|
215
|
-
3. Spawns new bridge process
|
|
216
|
-
4. Bridge re-initializes connection to MCP server
|
|
217
|
-
5. Continues request
|
|
218
|
-
|
|
219
|
-
**Network failures:**
|
|
220
|
-
1. Bridge detects connection error
|
|
221
|
-
2. Begins exponential backoff reconnection
|
|
222
|
-
3. Queues incoming requests (up to 100, max 3min)
|
|
223
|
-
4. On reconnect: drains queue
|
|
224
|
-
5. On timeout: fails queued requests with network error
|
|
225
|
-
|
|
226
|
-
**Orphaned processes:**
|
|
227
|
-
1. On startup, CLI scans `~/.mcpc/bridges/` directory
|
|
228
|
-
2. For each socket file, attempts connection
|
|
229
|
-
3. If connection fails, reads PID from sessions.json
|
|
230
|
-
4. Checks if process exists (via `kill -0` or similar)
|
|
231
|
-
5. If dead: removes socket file and session entry
|
|
232
|
-
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.
|
|
233
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.
|
|
234
125
|
|
|
235
126
|
## References
|
|
236
127
|
|
package/README.md
CHANGED
|
@@ -127,54 +127,6 @@ mcpc @fs tools-list
|
|
|
127
127
|
<!-- AUTO-GENERATED: mcpc --help -->
|
|
128
128
|
|
|
129
129
|
```
|
|
130
|
-
Usage: mcpc [<@session>] [<command>] [options]
|
|
131
|
-
|
|
132
|
-
Universal command-line client for the Model Context Protocol (MCP).
|
|
133
|
-
|
|
134
|
-
Commands:
|
|
135
|
-
connect <server> [@session] Connect to an MCP server and start a new named @session
|
|
136
|
-
close <@session> Close a session
|
|
137
|
-
restart <@session> Restart a session (losing all state)
|
|
138
|
-
shell <@session> Open interactive shell for a session
|
|
139
|
-
login <server> Interactively login to a server using OAuth and save profile
|
|
140
|
-
logout <server> Delete an OAuth profile for a server
|
|
141
|
-
clean [resources...] Clean up mcpc data (sessions, profiles, logs, all)
|
|
142
|
-
grep <pattern> Search tools and instructions across all active sessions
|
|
143
|
-
x402 [subcommand] [args...] Configure an x402 payment wallet (EXPERIMENTAL)
|
|
144
|
-
help [command] [subcommand] Show help for a specific command
|
|
145
|
-
|
|
146
|
-
Options:
|
|
147
|
-
--json Output in JSON format for scripting
|
|
148
|
-
--verbose Enable debug logging
|
|
149
|
-
--profile <name> OAuth profile for the server ("default" if not provided)
|
|
150
|
-
--timeout <seconds> Request timeout in seconds (default: 300)
|
|
151
|
-
--max-chars <n> Truncate output to n characters (ignored in --json mode)
|
|
152
|
-
--insecure Skip TLS certificate verification (for self-signed certs)
|
|
153
|
-
-v, --version Output the version number
|
|
154
|
-
-h, --help Display help
|
|
155
|
-
|
|
156
|
-
MCP session commands (after connecting):
|
|
157
|
-
<@session> Show MCP server info, capabilities, and tools overview
|
|
158
|
-
<@session> grep <pattern> Search tools and instructions
|
|
159
|
-
<@session> tools-list List all server tools
|
|
160
|
-
<@session> tools-get <name> Get tool details and schema
|
|
161
|
-
<@session> tools-call <name> [arg:=val ... | <json> | <stdin]
|
|
162
|
-
<@session> prompts-list
|
|
163
|
-
<@session> prompts-get <name> [arg:=val ... | <json> | <stdin]
|
|
164
|
-
<@session> resources-list
|
|
165
|
-
<@session> resources-read <uri>
|
|
166
|
-
<@session> resources-subscribe <uri>
|
|
167
|
-
<@session> resources-unsubscribe <uri>
|
|
168
|
-
<@session> resources-templates-list
|
|
169
|
-
<@session> tasks-list
|
|
170
|
-
<@session> tasks-get <taskId>
|
|
171
|
-
<@session> tasks-result <taskId>
|
|
172
|
-
<@session> tasks-cancel <taskId>
|
|
173
|
-
<@session> logging-set-level <level>
|
|
174
|
-
<@session> ping
|
|
175
|
-
|
|
176
|
-
Run "mcpc" without arguments to show active sessions and OAuth profiles.
|
|
177
|
-
Run "mcpc --json" to get the same data as `{ sessions: [...], profiles: [...] }`.
|
|
178
130
|
```
|
|
179
131
|
|
|
180
132
|
### General actions
|
|
@@ -349,19 +301,21 @@ and auto-reconnects on network failures or its own crashes (10s cooldown on fail
|
|
|
349
301
|
|
|
350
302
|
**Session states:**
|
|
351
303
|
|
|
352
|
-
| State
|
|
353
|
-
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
|
|
|
357
|
-
|
|
|
358
|
-
|
|
|
359
|
-
|
|
|
360
|
-
|
|
|
304
|
+
| State | Meaning |
|
|
305
|
+
|------------------| ----------------------------------------------------------------------------------------------- |
|
|
306
|
+
| 🟢`live` | Bridge process running and server responding |
|
|
307
|
+
| 🟡`connecting` | Initial bridge startup in progress (`mcpc connect`) |
|
|
308
|
+
| 🟡`reconnecting` | Bridge crashed or lost auth; auto-reconnecting in the background |
|
|
309
|
+
| 🟡`disconnected` | Bridge process running but server unreachable; auto-recovers when server responds |
|
|
310
|
+
| 🟡`crashed` | Bridge process crashed or was killed; auto-reconnects in the background |
|
|
311
|
+
| 🔴`unauthorized` | Server rejected authentication (401/403) or token refresh failed; re-run `login` then `restart` |
|
|
312
|
+
| 🔴`expired` | Server rejected session ID (404); requires `restart` |
|
|
361
313
|
|
|
362
314
|
`mcpc` never removes sessions automatically — failed ones stay flagged with a recovery hint
|
|
363
315
|
in the error message. Use `mcpc @apify restart` to kill the bridge and open a fresh
|
|
364
316
|
`MCP-Session-Id`, or `mcpc @apify close` to remove the session entirely.
|
|
317
|
+
You can also remove dead sessions by running `mcpc clean`,
|
|
318
|
+
and all sessions by running `mcpc clean all` (see [Cleanup](#cleanup)).
|
|
365
319
|
|
|
366
320
|
## Authentication
|
|
367
321
|
|
|
@@ -1208,22 +1162,22 @@ See [CONTRIBUTING](./CONTRIBUTING.md) for development setup, architecture overvi
|
|
|
1208
1162
|
|
|
1209
1163
|
### MCP CLI clients
|
|
1210
1164
|
|
|
1211
|
-
<!-- Stars, contributors, commits, and activity as of
|
|
1165
|
+
<!-- Stars, contributors, commits, and activity as of May 2026. -->
|
|
1212
1166
|
|
|
1213
1167
|
| Tool | Lang | Stars | Contrib / Commits | Active | Tools | Resources | Prompts | Tasks | Code mode | Sessions | OAuth | Stdio | HTTP | Tool search | x402 | LLM |
|
|
1214
1168
|
| ----------------------------------------------------------------------- | ------ | ----: | ----------------: | ------ | ----- | --------- | ------- | ----- | --------- | -------- | ----- | ----- | ---- | ----------- | ---- | --- |
|
|
1215
|
-
| **[apify/mcpc](https://github.com/apify/mcpc)** | TS | ~
|
|
1216
|
-
| [steipete/mcporter](https://github.com/steipete/mcporter) | TS | ~
|
|
1217
|
-
| [
|
|
1218
|
-
| [
|
|
1219
|
-
| [f/mcptools](https://github.com/f/mcptools) | Go | ~1.
|
|
1220
|
-
| [philschmid/mcp-cli](https://github.com/philschmid/mcp-cli) | TS | ~1.1k |
|
|
1169
|
+
| **[apify/mcpc](https://github.com/apify/mcpc)** | TS | ~590 | 8 / ~640 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
|
|
1170
|
+
| [steipete/mcporter](https://github.com/steipete/mcporter) | TS | ~4.4k | 29 / ~650 | ✅ | ✅ | — | — | — | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | — |
|
|
1171
|
+
| [knowsuchagency/mcp2cli](https://github.com/knowsuchagency/mcp2cli) | Python | ~2.1k | 11 / ~91 | ✅ | ✅ | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — |
|
|
1172
|
+
| [IBM/mcp-cli](https://github.com/IBM/mcp-cli) | Python | ~2.0k | 24 / ~790 | ✅ | ✅ | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ✅ |
|
|
1173
|
+
| [f/mcptools](https://github.com/f/mcptools) | Go | ~1.6k | 15 / ~175 | ⚠️ | ✅ | ✅ | ✅ | — | ✅ | — | — | ✅ | ✅ | — | — | — |
|
|
1174
|
+
| [philschmid/mcp-cli](https://github.com/philschmid/mcp-cli) | TS | ~1.1k | 3 / ~30 | ⚠️ | ✅ | — | — | — | ✅ | ✅ | — | ✅ | ✅ | ✅ | — | — |
|
|
1221
1175
|
| [adhikasp/mcp-client-cli](https://github.com/adhikasp/mcp-client-cli) | Python | ~670 | 6 / ~110 | ⚠️ | ✅ | ✅ | ✅ | — | — | — | — | ✅ | — | — | — | ✅ |
|
|
1222
|
-
| [thellimist/clihub](https://github.com/thellimist/clihub) | Go | ~
|
|
1176
|
+
| [thellimist/clihub](https://github.com/thellimist/clihub) | Go | ~670 | 1 / ~60 | ✅ | ✅ | — | — | — | — | — | ✅ | ✅ | ✅ | ✅ | — | — |
|
|
1223
1177
|
| [wong2/mcp-cli](https://github.com/wong2/mcp-cli) | JS | ~430 | 4 / ~63 | ⚠️ | ✅ | ✅ | ✅ | — | — | — | ✅ | — | ✅ | — | — | — |
|
|
1224
|
-
| [mcpshim/mcpshim](https://github.com/mcpshim/mcpshim) | Go | ~
|
|
1225
|
-
| [evantahler/mcpx](https://github.com/evantahler/mcpx) | TS | ~
|
|
1226
|
-
| [EstebanForge/mcp-cli-ent](https://github.com/EstebanForge/mcp-cli-ent) | Go | ~15 |
|
|
1178
|
+
| [mcpshim/mcpshim](https://github.com/mcpshim/mcpshim) | Go | ~58 | 1 / ~13 | ✅ | ✅ | — | — | — | ✅ | ✅ | ✅ | — | ✅ | ✅ | — | — |
|
|
1179
|
+
| [evantahler/mcpx](https://github.com/evantahler/mcpx) | TS | ~32 | 2 / ~100 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | — | — |
|
|
1180
|
+
| [EstebanForge/mcp-cli-ent](https://github.com/EstebanForge/mcp-cli-ent) | Go | ~15 | 3 / ~46 | ✅ | ✅ | — | — | — | ✅ | ✅ | — | ✅ | ✅ | ✅ | — | — |
|
|
1227
1181
|
|
|
1228
1182
|
**Legend:** ✅ = supported, ⚠️ = stale (no commits in 3+ months), **Contrib / Commits** = contributors / total commits, **Tasks** = [async tasks](https://modelcontextprotocol.io/specification/latest/server/utilities/tasks), **x402** = [x402 payment protocol](https://www.x402.org/) support, **LLM** = requires/uses an LLM.
|
|
1229
1183
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Company Lookup Script using mcpc + Apify RAG Web Browser
|
|
4
|
+
#
|
|
5
|
+
# This is an example of an AI-generated "code mode" script that uses mcpc
|
|
6
|
+
# to call MCP tools programmatically. It was generated by Claude Code + Opus 4.5.
|
|
7
|
+
#
|
|
8
|
+
# Prerequisites:
|
|
9
|
+
# 1. Install mcpc: npm install -g @apify/mcpc
|
|
10
|
+
# 2. Login to Apify MCP server: mcpc mcp.apify.com login
|
|
11
|
+
# 3. Create a session: mcpc mcp.apify.com connect @apify
|
|
12
|
+
#
|
|
13
|
+
# Usage:
|
|
14
|
+
# ./company-lookup.sh "Company Name"
|
|
15
|
+
#
|
|
16
|
+
# Example:
|
|
17
|
+
# ./company-lookup.sh "Stripe"
|
|
18
|
+
# ./company-lookup.sh "Anthropic"
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
set -e
|
|
22
|
+
|
|
23
|
+
# Configuration
|
|
24
|
+
SESSION="${MCPC_SESSION:-@apify}"
|
|
25
|
+
REQUIRED_TOOL="apify-slash-rag-web-browser"
|
|
26
|
+
|
|
27
|
+
# Colors for output
|
|
28
|
+
RED='\033[0;31m'
|
|
29
|
+
GREEN='\033[0;32m'
|
|
30
|
+
YELLOW='\033[0;33m'
|
|
31
|
+
BLUE='\033[0;34m'
|
|
32
|
+
NC='\033[0m' # No Color
|
|
33
|
+
|
|
34
|
+
# Helper functions
|
|
35
|
+
error() { echo -e "${RED}❌ Error: $1${NC}" >&2; exit 1; }
|
|
36
|
+
info() { echo -e "${BLUE}$1${NC}"; }
|
|
37
|
+
success() { echo -e "${GREEN}$1${NC}"; }
|
|
38
|
+
warn() { echo -e "${YELLOW}$1${NC}"; }
|
|
39
|
+
|
|
40
|
+
# Check if mcpc is installed
|
|
41
|
+
if ! command -v mcpc &> /dev/null; then
|
|
42
|
+
error "mcpc is not installed. Install it with: npm install -g @apify/mcpc"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Parse arguments
|
|
46
|
+
COMPANY="${1:-}"
|
|
47
|
+
if [ -z "$COMPANY" ]; then
|
|
48
|
+
echo "Usage: $0 \"Company Name\""
|
|
49
|
+
echo ""
|
|
50
|
+
echo "Examples:"
|
|
51
|
+
echo " $0 \"Stripe\""
|
|
52
|
+
echo " $0 \"Anthropic\""
|
|
53
|
+
echo ""
|
|
54
|
+
echo "Environment variables:"
|
|
55
|
+
echo " MCPC_SESSION Session to use (default: @apify)"
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# Check if the session exists and is live
|
|
60
|
+
info "🔌 Checking session ${SESSION}..."
|
|
61
|
+
|
|
62
|
+
SESSION_STATUS=$(mcpc --json 2>/dev/null | jq -r ".sessions[] | select(.name == \"${SESSION}\") | .status" 2>/dev/null || echo "")
|
|
63
|
+
|
|
64
|
+
if [ -z "$SESSION_STATUS" ]; then
|
|
65
|
+
echo ""
|
|
66
|
+
error "Session ${SESSION} not found.
|
|
67
|
+
|
|
68
|
+
To set up the required session:
|
|
69
|
+
1. Login to Apify: mcpc mcp.apify.com login
|
|
70
|
+
2. Create session: mcpc mcp.apify.com connect ${SESSION}
|
|
71
|
+
|
|
72
|
+
Or use a different session by setting MCPC_SESSION environment variable."
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
if [ "$SESSION_STATUS" = "expired" ]; then
|
|
76
|
+
error "Session ${SESSION} has expired. Please recreate it:
|
|
77
|
+
mcpc ${SESSION} close
|
|
78
|
+
mcpc mcp.apify.com connect ${SESSION}"
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
if [ "$SESSION_STATUS" = "crashed" ]; then
|
|
82
|
+
warn "⚠️ Session ${SESSION} has crashed, will attempt to restart..."
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Verify the required tool is available
|
|
86
|
+
info "🔧 Checking for required tool..."
|
|
87
|
+
|
|
88
|
+
TOOL_EXISTS=$(mcpc --json "${SESSION}" tools-list 2>/dev/null | jq -r ".[] | select(.name == \"${REQUIRED_TOOL}\") | .name" 2>/dev/null || echo "")
|
|
89
|
+
|
|
90
|
+
if [ -z "$TOOL_EXISTS" ]; then
|
|
91
|
+
error "Required tool '${REQUIRED_TOOL}' not found on server.
|
|
92
|
+
Make sure you're connected to the correct MCP server (mcp.apify.com)."
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# All checks passed, proceed with the lookup
|
|
96
|
+
echo ""
|
|
97
|
+
info "🔍 Looking up: $COMPANY"
|
|
98
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
99
|
+
echo ""
|
|
100
|
+
info "⏳ Searching the web..."
|
|
101
|
+
echo ""
|
|
102
|
+
|
|
103
|
+
# Build the query - company name + search terms
|
|
104
|
+
QUERY="${COMPANY} company headquarters address"
|
|
105
|
+
|
|
106
|
+
# Use mcpc with the RAG web browser to fetch results as JSON
|
|
107
|
+
RESULT=$(mcpc "${SESSION}" tools-call "${REQUIRED_TOOL}" \
|
|
108
|
+
query:="$QUERY" \
|
|
109
|
+
maxResults:=1 \
|
|
110
|
+
outputFormats:='["markdown"]' \
|
|
111
|
+
--json 2>/dev/null) || error "Failed to call tool. Check your session and try again."
|
|
112
|
+
|
|
113
|
+
# Parse the markdown from the result
|
|
114
|
+
MARKDOWN=$(echo "$RESULT" \
|
|
115
|
+
| jq -r '.content[0].text // empty' 2>/dev/null \
|
|
116
|
+
| jq -r '.[0].markdown // empty' 2>/dev/null)
|
|
117
|
+
|
|
118
|
+
# Check if we got results
|
|
119
|
+
if [ -z "$MARKDOWN" ]; then
|
|
120
|
+
warn "⚠️ No results found for '$COMPANY'"
|
|
121
|
+
echo ""
|
|
122
|
+
echo "Raw response:"
|
|
123
|
+
echo "$RESULT" | jq '.' 2>/dev/null || echo "$RESULT"
|
|
124
|
+
exit 1
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
echo "📄 Company Information:"
|
|
128
|
+
echo "────────────────────────────────────────────────────"
|
|
129
|
+
# Show first 50 lines of markdown
|
|
130
|
+
echo "$MARKDOWN" | head -50
|
|
131
|
+
|
|
132
|
+
echo ""
|
|
133
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
134
|
+
success "✅ Done"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"playwright": {
|
|
4
|
+
"command": "npx",
|
|
5
|
+
"args": ["@playwright/mcp@latest"]
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
"fs": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "${PWD}"]
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
"apify-public": {
|
|
14
|
+
"url": "https://mcp.apify.com/?tools=docs,search-actors"
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
"apify-bearer": {
|
|
18
|
+
"url": "https://mcp.apify.com",
|
|
19
|
+
"headers": {
|
|
20
|
+
"Authorization": "Bearer ${APIFY_TOKEN}"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
"apify-oauth": {
|
|
25
|
+
"url": "https://mcp.apify.com"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apify/mcpc",
|
|
3
|
-
"version": "0.3.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Universal command-line client for the Model Context Protocol (MCP).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -28,32 +28,6 @@
|
|
|
28
28
|
"engines": {
|
|
29
29
|
"node": ">=20.0.0"
|
|
30
30
|
},
|
|
31
|
-
"scripts": {
|
|
32
|
-
"build": "tsc",
|
|
33
|
-
"build:watch": "tsc --watch",
|
|
34
|
-
"build:readme": "./scripts/update-readme.sh",
|
|
35
|
-
"test": "npm run build && npm run test:unit && ./test/e2e/run.sh --no-build --parallel 8 && ./test/e2e/run.sh --no-build --parallel 8 --runtime bun",
|
|
36
|
-
"test:unit": "jest",
|
|
37
|
-
"test:watch": "jest --watch",
|
|
38
|
-
"test:coverage": "npm run test:coverage:unit && npm run test:coverage:e2e && npm run test:coverage:merge",
|
|
39
|
-
"test:coverage:unit": "jest --coverage && find test/coverage/unit -name '*.html' -exec sed -i '' -e 's/Code coverage report for All files/mcpc Coverage (Unit Tests)/g' -e 's/<h1>All files<\\/h1>/<h1>Unit Test Coverage<\\/h1>/g' {} \\;",
|
|
40
|
-
"test:coverage:e2e": "./test/e2e/run.sh --coverage",
|
|
41
|
-
"test:coverage:merge": "test/coverage/coverage-merge.sh",
|
|
42
|
-
"test:e2e": "./test/e2e/run.sh --keep",
|
|
43
|
-
"test:e2e:bun": "./test/e2e/run.sh --no-build --runtime bun",
|
|
44
|
-
"test:conformance": "npm run build && npx -y @modelcontextprotocol/conformance client --command \"node test/conformance/client.mjs\" --scenario initialize",
|
|
45
|
-
"lint": "eslint src/**/*.ts && prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
46
|
-
"lint:fix": "eslint src/**/*.ts --fix && prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
47
|
-
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
48
|
-
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
49
|
-
"clean": "rm -rf dist",
|
|
50
|
-
"prebuild": "npm run clean",
|
|
51
|
-
"prepublishOnly": "if [ -z \"$MCPC_RELEASE\" ]; then echo '\\n❌ Direct npm publish is not allowed.\\n Please use: npm run release\\n' && exit 1; fi",
|
|
52
|
-
"release": "bash scripts/publish.sh",
|
|
53
|
-
"release:minor": "bash scripts/publish.sh minor",
|
|
54
|
-
"release:major": "bash scripts/publish.sh major",
|
|
55
|
-
"release:pre": "bash scripts/publish.sh --pre-release"
|
|
56
|
-
},
|
|
57
31
|
"dependencies": {
|
|
58
32
|
"@inquirer/input": "^5.0.3",
|
|
59
33
|
"@inquirer/select": "^5.0.3",
|
|
@@ -69,23 +43,54 @@
|
|
|
69
43
|
"viem": "^2.46.3"
|
|
70
44
|
},
|
|
71
45
|
"devDependencies": {
|
|
72
|
-
"@types/jest": "^30.0.0",
|
|
73
46
|
"@types/node": "^25.0.3",
|
|
74
47
|
"@types/proper-lockfile": "^4.1.4",
|
|
75
48
|
"@types/qrcode-terminal": "^0.12.2",
|
|
76
49
|
"@types/uuid": "^11.0.0",
|
|
77
|
-
"@typescript-eslint/eslint-plugin": "
|
|
78
|
-
"@typescript-eslint/parser": "
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "8.57.2",
|
|
51
|
+
"@typescript-eslint/parser": "8.57.2",
|
|
52
|
+
"@vitest/coverage-v8": "4.1.5",
|
|
79
53
|
"c8": "^11.0.0",
|
|
80
54
|
"doctoc": "^2.2.1",
|
|
81
55
|
"eslint": "^8.57.1",
|
|
82
|
-
"jest": "^30.2.0",
|
|
83
56
|
"markdown-link-check": "^3.14.2",
|
|
84
57
|
"nyc": "^18.0.0",
|
|
85
58
|
"prettier": "^3.7.4",
|
|
86
59
|
"proxy-chain": "^2.7.1",
|
|
87
|
-
"ts-jest": "^29.4.6",
|
|
88
60
|
"tsx": "^4.21.0",
|
|
89
|
-
"typescript": "^5.9.3"
|
|
61
|
+
"typescript": "^5.9.3",
|
|
62
|
+
"vitest": "4.1.5"
|
|
63
|
+
},
|
|
64
|
+
"devEngines": {
|
|
65
|
+
"packageManager": {
|
|
66
|
+
"name": "pnpm",
|
|
67
|
+
"version": "10.33.4",
|
|
68
|
+
"onFail": "warn"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build": "tsc",
|
|
73
|
+
"build:watch": "tsc --watch",
|
|
74
|
+
"build:readme": "./scripts/update-readme.sh",
|
|
75
|
+
"test": "pnpm run build && pnpm run test:unit && ./test/e2e/run.sh --no-build --parallel 8 && ./test/e2e/run.sh --no-build --parallel 8 --runtime bun",
|
|
76
|
+
"test:unit": "vitest run",
|
|
77
|
+
"test:watch": "vitest",
|
|
78
|
+
"test:coverage": "pnpm run test:coverage:unit && pnpm run test:coverage:e2e && pnpm run test:coverage:merge",
|
|
79
|
+
"test:coverage:unit": "vitest run --coverage",
|
|
80
|
+
"test:coverage:e2e": "./test/e2e/run.sh --coverage",
|
|
81
|
+
"test:coverage:merge": "test/coverage/coverage-merge.sh",
|
|
82
|
+
"test:e2e": "./test/e2e/run.sh --keep",
|
|
83
|
+
"test:e2e:bun": "./test/e2e/run.sh --no-build --runtime bun",
|
|
84
|
+
"test:conformance": "pnpm run build && npx -y @modelcontextprotocol/conformance client --command \"node test/conformance/client.mjs\" --scenario initialize",
|
|
85
|
+
"lint": "eslint src/**/*.ts && prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
86
|
+
"lint:fix": "eslint src/**/*.ts --fix && prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
87
|
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
88
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
89
|
+
"clean": "rm -rf dist",
|
|
90
|
+
"prebuild": "pnpm run clean",
|
|
91
|
+
"release": "bash scripts/publish.sh",
|
|
92
|
+
"release:minor": "bash scripts/publish.sh minor",
|
|
93
|
+
"release:major": "bash scripts/publish.sh major",
|
|
94
|
+
"release:pre": "bash scripts/publish.sh --pre-release"
|
|
90
95
|
}
|
|
91
|
-
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Supply-chain protection: require packages to be at least X days old before pnpm will install them.
|
|
2
|
+
# Mitigates compromised npm packages discovered and yanked within the first day (shai-hulud worm,
|
|
3
|
+
# nx self-replicator, etc.). 7200 minutes = 5 days.
|
|
4
|
+
minimumReleaseAge: 7200
|
|
5
|
+
|
|
6
|
+
# @napi-rs/keyring ships a native node binding that needs to be built/copied
|
|
7
|
+
# into place on install. Without this entry pnpm v10 refuses to run its
|
|
8
|
+
# postinstall script and the keychain feature breaks at runtime.
|
|
9
|
+
onlyBuiltDependencies:
|
|
10
|
+
- "@napi-rs/keyring"
|
package/tsconfig.test.json
CHANGED
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
// Coverage thresholds match the previous Jest setup (70% across the board).
|
|
4
|
+
// See test/README.md for the test layout.
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
test: {
|
|
7
|
+
include: ['test/unit/**/*.test.ts', 'test/unit/**/*.spec.ts'],
|
|
8
|
+
environment: 'node',
|
|
9
|
+
// `globals: true` keeps the existing test bodies (`describe`/`it`/`expect`)
|
|
10
|
+
// working without changing every file's imports. Jest-compatible API.
|
|
11
|
+
globals: true,
|
|
12
|
+
coverage: {
|
|
13
|
+
provider: 'v8',
|
|
14
|
+
reportsDirectory: 'test/coverage/unit',
|
|
15
|
+
reporter: ['text', 'lcov', 'html', 'json'],
|
|
16
|
+
include: ['src/**/*.ts'],
|
|
17
|
+
exclude: ['src/**/*.d.ts', 'src/**/index.ts'],
|
|
18
|
+
thresholds: {
|
|
19
|
+
branches: 70,
|
|
20
|
+
functions: 70,
|
|
21
|
+
lines: 70,
|
|
22
|
+
statements: 70,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|