@apify/mcpc 0.1.3 → 0.1.4

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 (97) hide show
  1. package/.claude/settings.local.json +30 -1
  2. package/.idea/codeStyles/Project.xml +4 -0
  3. package/.idea/workspace.xml +281 -277
  4. package/CONTRIBUTING.md +210 -0
  5. package/README.md +156 -367
  6. package/TODOs.md +27 -66
  7. package/dist/bridge/index.js +29 -17
  8. package/dist/bridge/index.js.map +1 -1
  9. package/dist/cli/commands/auth.d.ts.map +1 -1
  10. package/dist/cli/commands/auth.js +9 -4
  11. package/dist/cli/commands/auth.js.map +1 -1
  12. package/dist/cli/commands/clean.d.ts.map +1 -1
  13. package/dist/cli/commands/clean.js +13 -19
  14. package/dist/cli/commands/clean.js.map +1 -1
  15. package/dist/cli/commands/prompts.d.ts.map +1 -1
  16. package/dist/cli/commands/prompts.js +24 -1
  17. package/dist/cli/commands/prompts.js.map +1 -1
  18. package/dist/cli/commands/sessions.d.ts +5 -1
  19. package/dist/cli/commands/sessions.d.ts.map +1 -1
  20. package/dist/cli/commands/sessions.js +94 -139
  21. package/dist/cli/commands/sessions.js.map +1 -1
  22. package/dist/cli/commands/tools.d.ts.map +1 -1
  23. package/dist/cli/commands/tools.js +39 -1
  24. package/dist/cli/commands/tools.js.map +1 -1
  25. package/dist/cli/helpers.d.ts +2 -2
  26. package/dist/cli/helpers.d.ts.map +1 -1
  27. package/dist/cli/helpers.js +32 -68
  28. package/dist/cli/helpers.js.map +1 -1
  29. package/dist/cli/index.js +47 -13
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/output.d.ts +19 -3
  32. package/dist/cli/output.d.ts.map +1 -1
  33. package/dist/cli/output.js +370 -82
  34. package/dist/cli/output.js.map +1 -1
  35. package/dist/cli/parser.d.ts +4 -0
  36. package/dist/cli/parser.d.ts.map +1 -1
  37. package/dist/cli/parser.js +88 -1
  38. package/dist/cli/parser.js.map +1 -1
  39. package/dist/cli/shell.d.ts.map +1 -1
  40. package/dist/cli/shell.js +4 -5
  41. package/dist/cli/shell.js.map +1 -1
  42. package/dist/core/factory.d.ts +2 -4
  43. package/dist/core/factory.d.ts.map +1 -1
  44. package/dist/core/factory.js +2 -34
  45. package/dist/core/factory.js.map +1 -1
  46. package/dist/core/mcp-client.d.ts +2 -2
  47. package/dist/core/mcp-client.d.ts.map +1 -1
  48. package/dist/core/mcp-client.js +10 -10
  49. package/dist/core/mcp-client.js.map +1 -1
  50. package/dist/core/transports.d.ts +2 -2
  51. package/dist/core/transports.d.ts.map +1 -1
  52. package/dist/core/transports.js +36 -45
  53. package/dist/core/transports.js.map +1 -1
  54. package/dist/lib/auth/oauth-flow.d.ts.map +1 -1
  55. package/dist/lib/auth/oauth-flow.js +3 -0
  56. package/dist/lib/auth/oauth-flow.js.map +1 -1
  57. package/dist/lib/auth/oauth-provider.d.ts.map +1 -1
  58. package/dist/lib/auth/oauth-provider.js +5 -23
  59. package/dist/lib/auth/oauth-provider.js.map +1 -1
  60. package/dist/lib/auth/oauth-token-manager.d.ts.map +1 -1
  61. package/dist/lib/auth/oauth-token-manager.js +0 -10
  62. package/dist/lib/auth/oauth-token-manager.js.map +1 -1
  63. package/dist/lib/auth/profiles.d.ts +5 -1
  64. package/dist/lib/auth/profiles.d.ts.map +1 -1
  65. package/dist/lib/auth/profiles.js +80 -13
  66. package/dist/lib/auth/profiles.js.map +1 -1
  67. package/dist/lib/bridge-manager.d.ts +2 -2
  68. package/dist/lib/bridge-manager.d.ts.map +1 -1
  69. package/dist/lib/bridge-manager.js +18 -19
  70. package/dist/lib/bridge-manager.js.map +1 -1
  71. package/dist/lib/config.d.ts +3 -3
  72. package/dist/lib/config.d.ts.map +1 -1
  73. package/dist/lib/config.js.map +1 -1
  74. package/dist/lib/logger.d.ts +5 -1
  75. package/dist/lib/logger.d.ts.map +1 -1
  76. package/dist/lib/logger.js +10 -1
  77. package/dist/lib/logger.js.map +1 -1
  78. package/dist/lib/schema-validator.d.ts +36 -0
  79. package/dist/lib/schema-validator.d.ts.map +1 -0
  80. package/dist/lib/schema-validator.js +220 -0
  81. package/dist/lib/schema-validator.js.map +1 -0
  82. package/dist/lib/session-client.d.ts +2 -2
  83. package/dist/lib/session-client.d.ts.map +1 -1
  84. package/dist/lib/session-client.js +3 -3
  85. package/dist/lib/session-client.js.map +1 -1
  86. package/dist/lib/sessions.js +1 -1
  87. package/dist/lib/sessions.js.map +1 -1
  88. package/dist/lib/types.d.ts +13 -24
  89. package/dist/lib/types.d.ts.map +1 -1
  90. package/dist/lib/types.js.map +1 -1
  91. package/dist/lib/utils.d.ts +2 -0
  92. package/dist/lib/utils.d.ts.map +1 -1
  93. package/dist/lib/utils.js +8 -0
  94. package/dist/lib/utils.js.map +1 -1
  95. package/docs/claude-skill/SKILL.md +2 -2
  96. package/package.json +12 -8
  97. package/TESTING.md +0 -212
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # mcpc: Universal MCP command-line client
1
+ # `mcpc`: Universal MCP command-line client
2
2
 
3
3
  `mcpc` is a CLI for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/),
4
4
  which maps MCP operations to intuitive commands for interactive shell use, scripts, and AI coding agents.
5
5
 
6
6
  `mcpc` can connect to any MCP server over Streamable HTTP or stdio transports,
7
7
  securely login via OAuth credentials and store credentials,
8
- and keep long-term sessions to multiple servers in parallel.
8
+ and keep long-term sessions to multiple servers.
9
9
  It supports all major MCP features, including tools, resources, prompts, asynchronous tasks, and notifications.
10
10
 
11
11
  `mcpc` is handy for manual testing of MCP servers, scripting,
@@ -13,23 +13,29 @@ and AI coding agents to use MCP in ["code mode"](https://www.anthropic.com/engin
13
13
  for better accuracy and lower token compared to traditional tool function calling.
14
14
  After all, UNIX-compatible shell script is THE most universal coding language, for people and LLMs alike.
15
15
 
16
- Note that `mcpc` is deterministic and does not use any LLM on its own; that's left for the higher layer.
16
+ Note that `mcpc` does not use LLMs on its own; that's a job for the higher layer.
17
17
 
18
- <!--
19
- ## Table of contents
18
+ **Key features**
19
+
20
+ - 🔌 **Super compatible** - Works with any MCP server over Streamable HTTP or stdio.
21
+ - 🔄 **Persistent sessions** - Keep multiple server connections alive simultaneously.
22
+ - 🚀 **Zero setup** - Connect to remote servers instantly with just a URL.
23
+ - 🔧 **Full protocol support** - Tools, resources, prompts, dynamic discovery, and async notifications.
24
+ - 📊 **JSON output** - Easy integration with `jq`, scripts, and other CLI tools.
25
+ - 🤖 **AI-friendly** - Designed for code generation and automated workflows.
26
+ - 🔒 **Secure** - OS keychain integration for credentials, encrypted auth storage.
20
27
 
21
- TODO: Simplify README - there are too many top-level sections, and then show just the second level ones
22
- -->
28
+
29
+ ## Table of contents
23
30
 
24
31
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
25
32
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
26
- <!--
27
- - [Features](#features)
33
+
28
34
  - [Install](#install)
29
35
  - [Quickstart](#quickstart)
30
36
  - [Usage](#usage)
31
37
  - [MCP command arguments](#mcp-command-arguments)
32
- - [Global flags](#global-flags)
38
+ - [Global flags](#global-flags)
33
39
  - [Authentication](#authentication)
34
40
  - [No authentication](#no-authentication)
35
41
  - [Bearer token authentication](#bearer-token-authentication)
@@ -42,7 +48,11 @@ TODO: Simplify README - there are too many top-level sections, and then show jus
42
48
  - [Sessions](#sessions)
43
49
  - [Managing sessions](#managing-sessions)
44
50
  - [Piping between sessions](#piping-between-sessions)
51
+ - [Output format](#output-format)
52
+ - [Human-readable (default)](#human-readable-default)
53
+ - [JSON mode](#json-mode)
45
54
  - [Scripting](#scripting)
55
+ - [MCP server schema changes](#mcp-server-schema-changes)
46
56
  - [Session failover](#session-failover)
47
57
  - [Logging](#logging)
48
58
  - [Cleanup](#cleanup)
@@ -50,10 +60,8 @@ TODO: Simplify README - there are too many top-level sections, and then show jus
50
60
  - [MCP config JSON file](#mcp-config-json-file)
51
61
  - [Environment variables](#environment-variables)
52
62
  - [MCP protocol notes](#mcp-protocol-notes)
53
- - [Output format](#output-format)
54
- - [Human-readable (default)](#human-readable-default)
55
- - [JSON mode (`--json`)](#json-mode---json)
56
63
  - [Security](#security)
64
+ - [Authentication](#authentication-1)
57
65
  - [Credential storage](#credential-storage)
58
66
  - [Bridge process authentication](#bridge-process-authentication)
59
67
  - [File permissions](#file-permissions)
@@ -64,36 +72,14 @@ TODO: Simplify README - there are too many top-level sections, and then show jus
64
72
  - [Interactive shell](#interactive-shell)
65
73
  - [Claude Code skill](#claude-code-skill)
66
74
  - [Troubleshooting](#troubleshooting)
67
- - [Common issues](#common-issues)
68
- - [Debug mode](#debug-mode)
69
75
  - [Logs](#logs)
70
- - [Development](#development)
71
- - [Design principles](#design-principles)
72
- - [Architecture overview](#architecture-overview)
73
- - [Core module (runtime-agnostic)](#core-module-runtime-agnostic)
74
- - [Bridge process](#bridge-process)
75
- - [CLI executable](#cli-executable)
76
- - [Session lifecycle](#session-lifecycle)
77
- - [Error recovery](#error-recovery)
78
- - [Testing strategy](#testing-strategy)
76
+ - [Common issues](#common-issues)
79
77
  - [Contributing](#contributing)
80
- - [Development setup](#development-setup)
81
- - [Release process](#release-process)
82
- - [References](#references)
83
78
  - [Authors](#authors)
84
79
  - [License](#license)
85
- -->
86
- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
87
80
 
88
- ## Features
81
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
89
82
 
90
- - 🔌 **Universal MCP client** - Works with any MCP server over Streamable HTTP or stdio.
91
- - 🔄 **Persistent sessions** - Keep multiple server connections alive simultaneously.
92
- - 🚀 **Zero setup** - Connect to remote servers instantly with just a URL.
93
- - 🔧 **Full protocol support** - Tools, resources, prompts, dynamic discovery, and async notifications.
94
- - 📊 **`--json` output** - Easy integration with `jq`, scripts, and other CLI tools.
95
- - 🤖 **AI-friendly** - Designed for code generation and automated workflows.
96
- - 🔒 **Secure** - OS keychain integration for credentials, encrypted auth storage.
97
83
 
98
84
  ## Install
99
85
 
@@ -107,69 +93,55 @@ npm install -g @apify/mcpc
107
93
  # List all active sessions and saved authentication profiles
108
94
  mcpc
109
95
 
110
- # Use a local server package referenced by MCP config file
111
- mcpc --config ~/.vscode/mcp.json filesystem tools-list
112
-
113
- # Login to OAuth-enabled MCP server and save authentication for future use
96
+ # Login to remote MCP server and save OAuth credentials for future use
114
97
  mcpc mcp.apify.com login
115
98
 
116
- # Show information about a remote MCP server and open interactive shell
99
+ # Show information about a remote MCP server
117
100
  mcpc mcp.apify.com
118
- mcpc mcp.apify.com shell
119
101
 
120
102
  # Use JSON mode for scripting
121
- mcpc --json mcp.apify.com tools-list
103
+ mcpc mcp.apify.com tools-list --json
122
104
 
123
- # Create a persistent session (or reconnect if it exists but bridge is dead)
105
+ # Create and use persistent MCP session
124
106
  mcpc mcp.apify.com session @test
125
- mcpc @test tools-call search-actors --args query="web crawler"
107
+ mcpc @test tools-call search-actors --args keywords="web crawler"
126
108
  mcpc @test shell
109
+
110
+ # Interact with a local MCP server package (stdio) referenced from config file
111
+ mcpc --config ~/.vscode/mcp.json filesystem tools-list
127
112
  ```
128
113
 
129
114
  ## Usage
130
115
 
131
116
  ```bash
132
- mcpc [--json] [--config <file>] [-H|--header "K: V"] [-v|--verbose]
133
- [--schema <file>] [--schema-mode <mode>] [--timeout <seconds>]
134
- [--clean|--clean=sessions,logs,profiles,all]
135
- <target> <command...>
136
-
137
- # Lists all active sessions and saved authentication profiles
138
- mcpc
139
-
140
- # Shows server or session info, instructions, and capabilities
141
- mcpc <target>
142
-
143
- # MCP commands
144
- mcpc <target> tools
145
- mcpc <target> tools-list
146
- mcpc <target> tools-schema <tool-name>
147
- mcpc <target> tools-call <tool-name> [--args key=val key2:=json ...] [--args-file <file>]
148
-
149
- mcpc <target> prompts
150
- mcpc <target> prompts-list
151
- mcpc <target> prompts-get <prompt-name> [--args key=val key2:=json ...] [--args-file <file>]
152
-
153
- mcpc <target> resources
154
- mcpc <target> resources-list
155
- mcpc <target> resources-read <uri>
156
- mcpc <target> resources-subscribe <uri>
157
- mcpc <target> resources-unsubscribe <uri>
158
- mcpc <target> resources-templates-list
159
-
160
- mcpc <target> logging-set-level <level>
161
-
162
- # Interactive MCP shell
163
- mcpc <target> shell
164
-
165
- # Persistent sessions
166
- mcpc <server> session @<session-name> [--profile <name>]
167
- mcpc @<session-name> <command...>
168
- mcpc @<session-name> close
169
-
170
- # Saved OAuth profiles for remote MCP servers
171
- mcpc <server> login [--profile <name>]
172
- mcpc <server> logout [--profile <name>]
117
+ Usage: mcpc [options] [target] [command]
118
+
119
+ Options:
120
+ -v, --version Output the version number
121
+ -j, --json Output in JSON format for scripting
122
+ --verbose Enable verbose logging
123
+ -c, --config <file> Path to MCP config JSON file (e.g. ".vscode/mcp.json")
124
+ -H, --header <header> Add HTTP header (can be repeated)
125
+ --timeout <seconds> Request timeout in seconds (default: 300)
126
+ --profile <name> Authentication profile to use (default: "default")
127
+ --schema <file> Validate against expected tool/prompt schema
128
+ --schema-mode <mode> Schema validation mode: "strict", "compatible" (default), or "ignore"
129
+ --clean[=types] Clean up mcpc data (types: "sessions,logs,profiles,all")
130
+ -h, --help Display general help
131
+
132
+ Targets:
133
+ <server-url> Remote MCP server URL (e.g. "mcp.apify.com")
134
+ <config-entry> Entry from MCP config file specified in --config (e.g. "fs")
135
+ @<session> Named persistent session (e.g. "@apify")
136
+
137
+ Commands:
138
+ help Show server info, instructions, and capabilities
139
+ shell Open interactive shell to run MCP commands)
140
+ login Create OAuth profile with credentials to access remote server
141
+ logout Remove OAuth profile
142
+ session @<session> Create a named persistent session
143
+ restart @<session> Kill and restart a session
144
+ close @<session> Close a session
173
145
  ```
174
146
 
175
147
  where `<target>` can be one of (in this order of precedence):
@@ -216,16 +188,6 @@ echo '{"query":"hello","count":10}' | mcpc @server tools-call my-tool
216
188
  - `=` assigns as string, `:=` parses as JSON
217
189
  - Stdin is automatically detected when input is piped (not interactive terminal)
218
190
 
219
- ## Global flags
220
-
221
- - `--json` - Input and output in JSON format for scripting
222
- - `--config <file>` - Use MCP config JSON file (e.g., `.vscode/mcp.json`)
223
- - `-H, --header "Key: Value"` - Add HTTP header (can be repeated)
224
- - `-v, --verbose` - Enable verbose logging (shows protocol details)
225
- - `--timeout <seconds>` - Request timeout in seconds (default: 300)
226
- - `--schema <file>` - Validate against expected tool/prompt schema
227
- - `--schema-mode <mode>` - Schema validation mode: `strict`, `compatible`, or `ignore` (default: `compatible`)
228
-
229
191
  ## Authentication
230
192
 
231
193
  `mcpc` supports all standard [authentication methods](https://modelcontextprotocol.io/specification/latest/basic/authorization) for MCP servers,
@@ -468,6 +430,9 @@ mcpc
468
430
  mcpc @apify tools-list
469
431
  mcpc @apify shell
470
432
 
433
+ # Restart the session (kills and restarts the bridge process)
434
+ mcpc @apify restart
435
+
471
436
  # Close the session (terminates bridge process, but keeps authentication profile)
472
437
  mcpc @apify close
473
438
  ```
@@ -480,28 +445,66 @@ mcpc --json @apify tools-call search-actors --args query="tiktok scraper" \
480
445
  | mcpc @playwright tools-call run-browser
481
446
  ```
482
447
 
448
+ ### Output format
449
+
450
+ #### Human-readable (default)
451
+
452
+ Default output is formatted for human and AI readability with plain text, colors, and Markdown-like formatting.
453
+ The text is formatted in Markdown-compatible format for AIs with colors for easy human readability.
454
+
455
+ #### JSON mode
456
+
457
+ If `--json` option is provided, `mcpc` always emits only a single JSON object, in order to enable scripting.
458
+ For MCP commands, the returned objects are always consistent with the [MCP protocol specification](https://modelcontextprotocol.io/specification/latest).
459
+ On success, the JSON object is printed to stdout, otherwise to stderr.
460
+
483
461
  ### Scripting
484
462
 
485
- `mcpc` is designed to be easily usable in (AI-generated) scripts. To ensure consistency
486
- of your scripts with the current MCP server interface, you can use `--schema <file>` argument
487
- to pass `mcpc` the expected schema. If the MCP server's current schema is incompatible,
488
- the command returns an error.
463
+ `mcpc` is designed for us in (AI-generated) scripts.
464
+ With the `--json` option, `mcpc` returns a single JSON object (object or array) as follows:
465
+
466
+ - On success, the JSON object is printed to stdout
467
+ - On error, the JSON object is printed to stderr
468
+
469
+ You can use tools like `jq` to process the output.
470
+
471
+ Note that `--json` option has no effect on `--help` command,
472
+ or if there are invalid arguments, as those take precedence.
473
+
474
+ For all MCP operations, the **returned JSON is and always will be strictly consistent
475
+ with the [MCP specification](https://modelcontextprotocol.io/specification/latest)**,
476
+ based to the protocol version negotiated between client and server in the initial handshake.
477
+
478
+ Additionally, one of the core [design principles](CONTRIBUTING.md#design-principles) of `mcpc`
479
+ is to keep backwards compatibility to maximum extent possible, to ensure the scripts using `mcpc`
480
+ will not break over time.
481
+
482
+ #### MCP server schema changes
483
+
484
+ MCP is a fluid protocol, and MCP servers can change operations and their schema at any time.
485
+ To ensure your scripts fail fast whenever such schema change occurs, rather than fail silently later,
486
+ you can use the `--schema <file>` option to pass `mcpc` the expected operation schema.
487
+ If the MCP server's current schema is incompatible, the command returns an error.
489
488
 
490
489
  ```bash
491
490
  # Save tool schema for future validation
492
- mcpc --json @apify tools-schema search-actors > search-actors-schema.json
491
+ mcpc --json @apify tools-get search-actors > search-actors-schema.json
493
492
 
494
493
  # Use schema to ensure compatibility (fails if schema changed)
495
494
  mcpc @apify tools-call search-actors \
496
495
  --schema search-actors-schema.json \
497
496
  --schema-mode strict \
498
- --args query="tiktok scraper"
497
+ --args keywords="tiktok scraper"
499
498
  ```
500
499
 
501
- **Schema validation modes using the `--schema-mode` parameter:**
502
- - `strict` - Exact schema match required (all fields, types must be identical)
503
- - `compatible` (default) - Backwards compatible (new optional fields OK, required fields and types must match)
504
- - `ignore` - Skip schema validation
500
+ The `--schema-mode <mode>` parameter determines how `mcpc` validates the schema:
501
+
502
+ - `compatible` (default) - Backwards compatible (new optional fields OK, types of required
503
+ fields and passed arguments must match, descriptions are ignored). For tools, the output schema
504
+ is ignored.
505
+ - `strict` - Exact schema match required (all fields, their types and descriptions must be
506
+ identical). For tools, the output schema must match exactly.
507
+ - `ignore` - Skip schema validation altogether
505
508
 
506
509
  ### Session failover
507
510
 
@@ -536,6 +539,8 @@ mcpc https://mcp.apify.com session @apify
536
539
 
537
540
  ## Logging
538
541
 
542
+ TODO: Move this to MPC features section
543
+
539
544
  The background bridge process logs to `~/.mcpc/logs/bridge-<session-name>.log`.
540
545
  The main `mcpc` process doesn't save log files, but you can use `--verbose` flag to print all logs to stderr.
541
546
 
@@ -681,6 +686,8 @@ Config files support environment variable substitution using `${VAR_NAME}` synta
681
686
 
682
687
  ## MCP protocol notes
683
688
 
689
+ TODO: explain in detail how MCP concepts work in mcpc
690
+
684
691
  **Protocol initialization:**
685
692
  - `mcpc` follows the MCP initialization handshake: sends `initialize` request with protocol version and capabilities, receives server capabilities and instructions, then sends `initialized` notification
686
693
  - Protocol version negotiation: client proposes latest supported version (currently `2025-11-25`), server responds with version to use
@@ -695,10 +702,12 @@ Config files support environment variable substitution using `${VAR_NAME}` synta
695
702
  **Protocol features:**
696
703
  - `mcpc` supports all MCP primitives in both Streamable HTTP and stdio transports:
697
704
  - **Instructions**: Fetches and stores MCP server-provided `instructions`
698
- - **Tools**: Executable functions with JSON Schema-validated arguments.
705
+ - **Tools**: Executable functions with JSON Schema-validated arguments.
699
706
  - **Resources**: Data sources identified by URIs (e.g., `file:///path/to/file`, `https://example.com/data`), with optional subscriptions for change notifications
700
707
  - **Prompts**: Reusable message templates with customizable arguments
701
708
  - **Completion**: Provides access to Completion API for tools and resources
709
+ - **Asynchronous tasks**: Not implemented yet
710
+ - **Roots**: Not implemented yet
702
711
  - Supports server logging settings (`logging/setLevel`) and messages (`notifications/message`), and prints them to stderr or stdout based on verbosity level.
703
712
  - Handles server notifications: progress tracking, logging, and change notifications (`notifications/tools/list_changed`, `notifications/resources/list_changed`, `notifications/prompts/list_changed`)
704
713
  - Request multiplexing: supports up to 10 concurrent requests, queues up to 100 additional requests
@@ -706,27 +715,28 @@ Config files support environment variable substitution using `${VAR_NAME}` synta
706
715
  - Pings: `mcpc` periodically issues the MCP `ping` request to keep the connection alive
707
716
  - Sampling is not supported as `mcpc` has no access to an LLM
708
717
 
709
- ## Output format
710
-
711
- ### Human-readable (default)
712
-
713
- Default output is formatted for human and AI readability with plain text, colors, and Markdown-like formatting.
714
-
715
- ### JSON mode (`--json`)
716
-
717
- In JSON mode, `mcpc` always emits only a single JSON object to enable scripting.
718
- For MCP commands, the object is always consistent with the MCP protocol specification.
719
- On success, the JSON object is printed to stdout, otherwise to stderr.
720
-
721
718
  ## Security
722
719
 
723
- MCP enables arbitrary tool execution and data access; treat servers like you treat shells:
720
+ `mcpc` implements the [MCP security best practices](https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices) specification. MCP enables arbitrary tool execution and data access; treat servers like you treat shells:
724
721
 
725
722
  * Use least-privilege tokens/headers
726
723
  * Prefer trusted endpoints
727
724
  * Audit what tools do before running them
728
725
  * Review server permissions in interactive mode
729
726
 
727
+ ### Authentication
728
+
729
+ **OAuth 2.1 with PKCE:**
730
+ - Full OAuth 2.1 flow with PKCE (Proof Key for Code Exchange) via the MCP SDK
731
+ - OAuth callback server binds to `127.0.0.1` only (not `0.0.0.0`)
732
+ - Warning displayed for OAuth over plain HTTP (except localhost)
733
+ - Dynamic client registration supported
734
+
735
+ **Input validation:**
736
+ - Session names validated: `^@[a-zA-Z0-9_-]{1,64}$`
737
+ - Profile names validated: `^[a-zA-Z0-9_-]{1,64}$`
738
+ - URLs normalized and validated (HTTPS enforced, credentials stripped)
739
+
730
740
  ### Credential storage
731
741
 
732
742
  **OS keychain integration:**
@@ -736,8 +746,8 @@ MCP enables arbitrary tool execution and data access; treat servers like you tre
736
746
  - The `~/.mcpc/profiles.json` file only contains metadata (server URL, scopes, timestamps) - never tokens
737
747
 
738
748
  **Keychain entries:**
739
- - OAuth tokens: `mcpc:auth:<serverUrl>:<profileName>:oauth-tokens`
740
- - OAuth client: `mcpc:auth:<serverUrl>:<profileName>:oauth-client`
749
+ - OAuth tokens: `mcpc:auth-profile:<host>:<profileName>:tokens`
750
+ - OAuth client: `mcpc:auth-profile:<host>:<profileName>:client`
741
751
  - HTTP headers: `mcpc:session:<sessionName>:headers`
742
752
 
743
753
  ### Bridge process authentication
@@ -768,17 +778,18 @@ This architecture ensures:
768
778
 
769
779
  ### File permissions
770
780
 
771
- - `~/.mcpc/sessions.json` is set to `0600` (user-only read/write)
772
- - `~/.mcpc/profiles.json` is set to `0600` (user-only read/write)
773
- - Bridge sockets in `~/.mcpc/bridges/` are created with `0700` permissions
774
- - Log files in `~/.mcpc/logs/` are created with `0600` permissions
781
+ - `~/.mcpc/sessions.json` is created with `0600` permissions (user-only read/write)
782
+ - `~/.mcpc/profiles.json` is created with `0600` permissions (user-only read/write)
783
+ - Bridge sockets in `~/.mcpc/bridges/` use default umask (typically user-only)
784
+ - File locking via `proper-lockfile` prevents race conditions on concurrent access
775
785
 
776
786
  ### Network security
777
787
 
778
- - HTTPS enforced for remote servers (HTTP auto-upgraded)
779
- - `Origin` header validation to prevent DNS rebinding attacks
780
- - Local servers bind to localhost (127.0.0.1) only
788
+ - HTTPS enforced for remote servers (HTTP auto-upgraded when no scheme provided)
789
+ - URL normalization removes username, password, and hash from URLs
790
+ - Local OAuth callback server binds to `127.0.0.1` only
781
791
  - No credentials logged even in verbose mode
792
+ - `MCP-Protocol-Version` and `MCP-Session-Id` headers handled per MCP spec
782
793
 
783
794
  ## Error handling
784
795
 
@@ -860,25 +871,7 @@ See [`claude-skill/README.md`](./claude-skill/README.md) for details.
860
871
 
861
872
  ## Troubleshooting
862
873
 
863
- ### Common issues
864
-
865
- **"Cannot connect to bridge"**
866
- - Bridge may have crashed. Try: `mcpc <server> session @<session-name>`
867
- - Check bridge is running: `ps aux | grep -e 'mcpc-bridge' -e '[m]cpc/dist/bridge'`
868
- - Check socket exists: `ls ~/.mcpc/bridges/`
869
-
870
- **"Session not found"**
871
- - Session may have expired. Create new session: `mcpc <target> session @<session-name>`
872
- - List existing sessions: `mcpc`
873
-
874
- **"Authentication failed"**
875
- - List saved profiles: `mcpc`
876
- - Re-authenticate: `mcpc <server> login [--profile <name>]`
877
- - For bearer tokens: provide `--header "Authorization: Bearer ${TOKEN}"` again
878
-
879
- ### Debug mode
880
-
881
- Enable detailed logging with `--verbose`:
874
+ To see what's happening, enable detailed logging with `--verbose`:
882
875
 
883
876
  ```bash
884
877
  mcpc --verbose @apify tools-list
@@ -899,234 +892,30 @@ Bridge processes log to:
899
892
 
900
893
  Log rotation: Keep last 10MB per session, max 5 files.
901
894
 
902
- ## Development
903
-
904
- `mcpc` is under active development and some things might not work 100% yet. You have been warned.
905
-
906
- ### Design principles
895
+ ### Common issues
907
896
 
908
- - Delightful for humans and AI agents alike (interactive + scripting)
909
- - Avoid unnecessary interaction loops, provide sufficient context, yet be concise (save tokens)
910
- - One clear way to do things (orthogonal commands, no surprises)
911
- - Do not ask for user input (except `shell` and `login`, no unexpected OAuth flows)
912
- - Be forgiving, always help users make progress (great errors + guidance)
913
- - Be consistent with the [MCP specification](https://modelcontextprotocol.io/specification/latest), with `--json` strictly
914
- - Minimal and portable (few deps, cross-platform)
915
- - No slop!
897
+ **"Cannot connect to bridge"**
898
+ - Bridge may have crashed. Try: `mcpc @<session-name> tools-list` to restart the bridge
899
+ - Check bridge is running: `ps aux | grep -e 'mcpc-bridge' -e '[m]cpc/dist/bridge'`
900
+ - Check socket exists: `ls ~/.mcpc/bridges/`
916
901
 
917
- ### Architecture overview
902
+ **"Session not found"**
903
+ - List existing sessions: `mcpc`
904
+ - Create new session if expired: `mcpc @<session-name> close` and `mcpc <target> session @<session-name>`
918
905
 
919
- ```
920
- TODO: add interaction diagram
921
- mcpc ──> cli ├──> bridge (UNIX socket) ──> MCP server (stdio/HTTP)
922
- ├──> MCP server (stdio/HTTP)
923
-
924
- mcpc (single package)
925
- ├── src/
926
- │ ├── core/ # Core MCP protocol implementation
927
- │ ├── bridge/ # Bridge process logic
928
- │ ├── cli/ # CLI interface
929
- │ └── lib/ # Shared utilities
930
- ├── bin/
931
- │ ├── mcpc # Main CLI executable
932
- │ └── mcpc-bridge # Bridge process executable
933
- ```
906
+ **"Authentication failed"**
907
+ - List saved OAuth profiles: `mcpc`
908
+ - Re-authenticate: `mcpc <server> login [--profile <name>]`
909
+ - For bearer tokens: provide `--header "Authorization: Bearer ${TOKEN}"` again
934
910
 
935
- ### Core module (runtime-agnostic)
936
-
937
- Implemented with minimal dependencies to support both Node.js (≥18.0.0) and Bun (≥1.0.0).
938
-
939
- **Core responsibilities:**
940
- - Transport selection and initialization (Streamable HTTP vs stdio)
941
- - MCP protocol implementation and version negotiation
942
- - Session state machine management
943
- - Streamable HTTP connection management (reconnection with exponential backoff)
944
- - Request/response correlation (JSON-RPC style with request IDs)
945
- - Multiplexing concurrent requests (up to 10 concurrent)
946
- - Event emitter for async notifications
947
-
948
- **Key dependencies:**
949
- - Native `fetch` API (available in Node.js 18+ and Bun)
950
- - Native process APIs for stdio transport
951
- - Minimal: UUID generation, event emitter abstraction
952
-
953
- ### Bridge process
954
-
955
- Implemented as a separate executable (`mcpc-bridge`) that maintains persistent connections.
956
-
957
- **Bridge responsibilities:**
958
- - Session persistence (reads/writes `~/.mcpc/sessions.json` with file locking)
959
- - Process lifecycle management for local package servers
960
- - Stdio framing and protocol handling
961
- - Unix domain socket server for CLI communication
962
- - Heartbeat mechanism for health monitoring
963
- - Orphaned process cleanup on startup
964
-
965
- **IPC protocol:**
966
- - Unix domain sockets (located in `~/.mcpc/bridges/<session-name>.sock`)
967
- - Named pipes on Windows
968
- - JSON-RPC style messages over socket
969
- - Control messages: init, request, cancel, close, health-check
970
-
971
- **Bridge discovery:**
972
- - CLI reads `~/.mcpc/sessions.json` to find socket path and PID
973
- - Validates bridge is alive (connect to socket + health-check)
974
- - Auto-restarts crashed bridges (detected via socket connection failure)
975
- - Cleanup: removes stale socket files for dead processes
976
-
977
- **Concurrency safety:**
978
- - `~/.mcpc/sessions.json` protected with file locking (`proper-lockfile` package)
979
- - Atomic writes (write to temp file, then rename)
980
- - Lock timeout: 5 seconds (fails if can't acquire lock)
981
-
982
- ### CLI executable
983
-
984
- The main `mcpc` command provides the user interface.
985
-
986
- **CLI responsibilities:**
987
- - Argument parsing using Commander.js
988
- - Output formatting (human-readable vs `--json`)
989
- - Bridge lifecycle: start/connect/stop
990
- - Communication with bridge via socket
991
- - Interactive shell (REPL using Node.js `readline`)
992
- - Configuration file loading (standard MCP JSON format)
993
- - Credential management (OS keychain via `keytar` package)
994
-
995
- **Shell implementation:**
996
- - Built on Node.js `readline` module for input handling with history support
997
- - Command history using `~/.mcpc/history` (last 1000 commands)
998
- - Real-time notification display during shell sessions
999
- - Graceful exit handling (cleanup on Ctrl+C/Ctrl+D)
1000
-
1001
- ### Session lifecycle
1002
-
1003
- 1. User: `mcpc https://mcp.apify.com session @apify`
1004
- 2. CLI: Atomically creates session entry in `~/.mcpc/sessions.json`
1005
- 3. CLI: Spawns bridge process (`mcpc-bridge`)
1006
- 4. Bridge: Creates Unix socket at `~/.mcpc/bridges/apify.sock`
1007
- 5. Bridge: Performs MCP initialization handshake with server:
1008
- - Sends initialize request with protocol version and capabilities
1009
- - Receives server info, version, and capabilities
1010
- - Sends initialized notification to activate session
1011
- 6. Bridge: Updates session in `~/.mcpc/sessions.json` (adds PID, socket path, protocol version)
1012
- 7. CLI: Confirms session created
1013
-
1014
- Later...
1015
-
1016
- 8. User: mcpc @apify tools-list
1017
- 9. CLI: Reads `~/.mcpc/sessions.json`, finds socket path
1018
- 10. CLI: Connects to bridge socket
1019
- 11. CLI: Sends `tools/list` JSON-RPC request via socket
1020
- 12. Bridge: Forwards to MCP server via Streamable HTTP
1021
- 13. Bridge: Returns response via socket
1022
- 14. CLI: Formats and displays to user
1023
-
1024
-
1025
- ### Error recovery
1026
-
1027
- **Bridge crashes:**
1028
- 1. CLI detects socket connection failure
1029
- 2. Reads `~/.mcpc/sessions.json` for last known config
1030
- 3. Spawns new bridge process
1031
- 4. Bridge re-initializes connection to MCP server
1032
- 5. Continues request
1033
-
1034
- **Network failures:**
1035
- 1. Bridge detects connection error
1036
- 2. Begins exponential backoff reconnection
1037
- 3. Queues incoming requests (up to 100, max 3min)
1038
- 4. On reconnect: drains queue
1039
- 5. On timeout: fails queued requests with network error
1040
-
1041
- **Orphaned processes:**
1042
- 1. On startup, CLI scans `~/.mcpc/bridges/` directory
1043
- 2. For each socket file, attempts connection
1044
- 3. If connection fails, reads PID from sessions.json
1045
- 4. Checks if process exists (via `kill -0` or similar)
1046
- 5. If dead: removes socket file and session entry
1047
- 6. If alive but unresponsive: kills process, removes entries
1048
-
1049
- ## Testing strategy
1050
-
1051
- **Unit tests:**
1052
- - Core protocol implementation (mocked transports)
1053
- - Argument parsing and validation
1054
- - Output formatting (human and JSON modes)
1055
-
1056
- **Integration tests:**
1057
- - Mock MCP server (simple Streamable HTTP + stdio servers)
1058
- - Bridge lifecycle (start, connect, restart, cleanup)
1059
- - Session management with file locking
1060
- - Stream reconnection logic
1061
-
1062
- **E2E tests:**
1063
- - Real MCP server implementations
1064
- - Cross-runtime (Node.js and Bun)
1065
- - Interactive shell workflows
1066
-
1067
- **Test utilities:**
1068
- - `examples/test-server/` - Reference MCP server for testing
1069
- - `test/mock-keychain.ts` - Mock OS keychain for testing
1070
911
 
1071
912
  ## Contributing
1072
913
 
1073
- Contributions are welcome!
1074
-
1075
- ### Development setup
1076
-
1077
- ```bash
1078
- # Clone repository
1079
- git clone https://github.com/apify/mcpc.git
1080
- cd mcpc
1081
-
1082
- # Install dependencies
1083
- npm install
1084
-
1085
- # Run tests
1086
- npm test
1087
-
1088
- # Build
1089
- npm run build
1090
-
1091
- # Test locally
1092
- npm link
1093
- mcpc --help
1094
- ```
1095
-
1096
- ### Release process
1097
-
1098
- Use the release script to publish a new version (must be on `main` branch):
1099
-
1100
- ```bash
1101
- npm run release # patch version bump (0.1.2 → 0.1.3)
1102
- npm run release:minor # minor version bump (0.1.2 → 0.2.0)
1103
- npm run release:major # major version bump (0.1.2 → 1.0.0)
1104
- ```
1105
-
1106
- The script automatically:
1107
- - Ensures you're on `main` branch
1108
- - Ensures working directory is clean (no uncommitted changes)
1109
- - Ensures branch is up-to-date with remote
1110
- - Runs lint, build, and tests
1111
- - Bumps the version in package.json
1112
- - Creates a git commit and annotated tag (`v{version}`)
1113
- - Pushes the commit and tag to origin
1114
- - Publishes to npm
1115
-
1116
- After publishing, create a GitHub release at the provided link.
1117
-
1118
- Please open an issue or pull request on [GitHub](https://github.com/apify/mcpc).
1119
-
1120
-
1121
- ### References
1122
-
1123
- - [Official MCP documentation](https://modelcontextprotocol.io/llms.txt)
1124
- - [Official TypeScript SDK for MCP servers and clients](https://www.npmjs.com/package/@modelcontextprotocol/sdk)
1125
- - [MCP Inspector](https://github.com/modelcontextprotocol/inspector) - CLI client implementation for reference
914
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup, architecture overview, and contribution guidelines.
1126
915
 
1127
916
  ## Authors
1128
917
 
1129
- Built by [Jan Curn](https://x.com/jancurn), [Apify](https://apify.com), and contributors welcome.
918
+ Built by [Jan Curn](https://x.com/jancurn) / [Apify](https://apify.com).
1130
919
 
1131
920
  ## License
1132
921