@alcyone-labs/arg-parser 1.2.0 → 2.1.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/README.md CHANGED
@@ -1,1499 +1,1021 @@
1
1
  # ArgParser - Type-Safe Command Line Argument Parser
2
2
 
3
- ArgParser is a powerful and flexible library for building command-line interfaces (CLIs) in TypeScript and JavaScript. It helps you define, parse, validate, and handle command-line arguments and sub-commands in a structured, type-safe way.
3
+ A modern, type-safe command line argument parser with built-in MCP (Model Context Protocol) integration and automatic Claude Desktop Extension (DXT) generation.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Features Overview](#features-overview)
8
+ - [Installation](#installation)
9
+ - [Quick Start: The Unified `addTool` API](#quick-start-the-unified-addtool-api)
10
+ - [How to Run It](#how-to-run-it)
11
+ - [Setting Up System-Wide CLI Access](#setting-up-system-wide-cli-access)
12
+ - [Parsing Command-Line Arguments](#parsing-command-line-arguments)
13
+ - [Cannonical Usage Pattern](#cannonical-usage-pattern)
14
+ - [Top-level await](#top-level-await)
15
+ - [Promise-based parsing](#promise-based-parsing)
16
+ - [Migrating from v1.x to the v2.0 `addTool` API](#migrating-from-v1x-to-the-v20-addtool-api)
17
+ - [Before v2.0: Separate Definitions](#before-v20-separate-definitions)
18
+ - [After v2.0: The Unified `addTool()` Method](#after-v20-the-unified-addtool-method)
19
+ - [Core Concepts](#core-concepts)
20
+ - [Defining Flags](#defining-flags)
21
+ - [Type Handling and Validation](#type-handling-and-validation)
22
+ - [Hierarchical CLIs (Sub-Commands)](#hierarchical-clis-sub-commands)
23
+ - [MCP Exposure Control](#mcp-exposure-control)
24
+ - [Flag Inheritance (`inheritParentFlags`)](#flag-inheritance-inheritparentflags)
25
+ - [MCP & Claude Desktop Integration](#mcp--claude-desktop-integration)
26
+ - [Output Schema Support](#output-schema-support)
27
+ - [Basic Usage](#basic-usage)
28
+ - [Predefined Schema Patterns](#predefined-schema-patterns)
29
+ - [Custom Zod Schemas](#custom-zod-schemas)
30
+ - [MCP Version Compatibility](#mcp-version-compatibility)
31
+ - [Automatic Error Handling](#automatic-error-handling)
32
+ - [Writing Effective MCP Tool Descriptions](#writing-effective-mcp-tool-descriptions)
33
+ - [Best Practices for Tool Descriptions](#best-practices-for-tool-descriptions)
34
+ - [Complete Example: Well-Documented Tool](#complete-example-well-documented-tool)
35
+ - [Parameter Description Guidelines](#parameter-description-guidelines)
36
+ - [Common Pitfalls to Avoid](#common-pitfalls-to-avoid)
37
+ - [Automatic MCP Server Mode (`--s-mcp-serve`)](#automatic-mcp-server-mode---s-mcp-serve)
38
+ - [MCP Transports](#mcp-transports)
39
+ - [Automatic Console Safety](#automatic-console-safety)
40
+ - [Generating DXT Packages (`--s-build-dxt`)](#generating-dxt-packages---s-build-dxt)
41
+ - [Logo Configuration](#logo-configuration)
42
+ - [Supported Logo Sources](#supported-logo-sources)
43
+ - [How DXT Generation Works](#how-dxt-generation-works)
44
+ - [System Flags & Configuration](#system-flags--configuration)
45
+ - [Changelog](#changelog)
46
+ - [v2.0.0](#v200)
47
+ - [v1.3.0](#v130)
48
+ - [v1.2.0](#v120)
49
+ - [v1.1.0](#v110)
50
+ - [Backlog](#backlog)
51
+ - [(known) Bugs / DX improvement points](#known-bugs--dx-improvement-points)
52
+
53
+ ## Features Overview
54
+
55
+ - **Unified Tool Architecture**: Define tools once with `addTool()` and they automatically function as both CLI subcommands and MCP tools.
56
+ - **Type-safe flag definitions** with full TypeScript support and autocompletion.
57
+ - **Automatic MCP Integration**: Transform any CLI into a compliant MCP server with a single command (`--s-mcp-serve`).
58
+ - **Console Safe**: `console.log` and other methods
59
+ are automatically handled in MCP mode to prevent protocol contamination, requiring no changes to your code.
60
+ - **DXT Package Generation**: Generate complete, ready-to-install Claude Desktop Extension (`.dxt`) packages with the `--s-build-dxt` command.
61
+ - **Hierarchical Sub-commands**: Create complex, nested sub-command structures (e.g., `git commit`, `docker container ls`) with flag inheritance.
62
+ - **Configuration Management**: Easily load (`--s-with-env`) and save (`--s-save-to-env`) configurations from/to `.env`, `.json`, `.yaml`, and `.toml` files.
63
+ - **Automatic Help & Error Handling**: Context-aware help text and user-friendly error messages are generated automatically.
64
+ - **Debugging Tools**: Built-in system flags like `--s-debug` and `--s-debug-print` for easy troubleshooting.
4
65
 
5
- Whether you're building a simple script, a complex nested CLI application, or an MCP (Model Context Protocol) server, ArgParser provides the tools to create robust and user-friendly interfaces with minimal boilerplate.
6
-
7
- ## What's New in v1.2.0
8
-
9
- ### **Critical MCP Fixes & Improvements**
10
-
11
- - **Fixed MCP Output Schema Support**: Resolved the critical issue where MCP tools with output schemas failed with `"Tool has an output schema but no structured content was provided"` error
12
- - **Enhanced Handler Context**: Added `isMcp` flag to handler context, enabling proper MCP mode detection in handlers
13
- - **Improved Response Format**: MCP tools now correctly return both `content` and `structuredContent` fields as required by the JSON-RPC 2.0 specification
14
- - **Better Integration**: Handlers can now reliably detect when they're being called from MCP mode vs CLI mode
66
+ ---
15
67
 
16
- ### **What Was Fixed**
68
+ ## Installation
17
69
 
18
- **Before v1.2.0**: MCP servers would fail when tools had output schemas defined:
19
- ```
20
- MCP error -32602: Tool canny-search has an output schema but no structured content was provided
70
+ ```bash
71
+ # Using PNPM (recommended)
72
+ pnpm add @alcyone-labs/arg-parser
21
73
  ```
22
74
 
23
- **After v1.2.0**: MCP tools with output schemas work correctly, returning proper JSON-RPC 2.0 responses:
24
- ```json
25
- {
26
- "jsonrpc": "2.0",
27
- "id": 3,
28
- "result": {
29
- "content": [{"type": "text", "text": "..."}],
30
- "structuredContent": { /* validated against output schema */ }
31
- }
32
- }
33
- ```
75
+ ---
34
76
 
35
- ### **Handler Context Enhancement**
77
+ ## Quick Start: The Unified `addTool` API
36
78
 
37
- Handlers now receive an `isMcp` flag to detect execution context:
79
+ The modern way to build with ArgParser is using the `.addTool()` method. It creates a single, self-contained unit that works as both a CLI subcommand and an MCP tool.
38
80
 
39
81
  ```typescript
82
+ import { z } from "zod";
83
+ import { ArgParser } from "@alcyone-labs/arg-parser";
84
+
85
+ // Use ArgParser.withMcp to enable MCP and DXT features
40
86
  const cli = ArgParser.withMcp({
41
- handler: async (ctx) => {
42
- if (ctx.isMcp) {
43
- // Running in MCP mode - return structured data
44
- return { success: true, data: processedData };
45
- } else {
46
- // Running in CLI mode - can use console output
47
- console.log("Processing complete!");
48
- return processedData;
49
- }
87
+ appName: "My Awesome CLI",
88
+ appCommandName: "mycli",
89
+ description: "A tool that works in both CLI and MCP mode",
90
+ mcp: {
91
+ serverInfo: { name: "my-awesome-mcp-server", version: "1.0.0" },
92
+ },
93
+ })
94
+ // Define a tool that works everywhere
95
+ .addTool({
96
+ name: "greet",
97
+ description: "A tool to greet someone",
98
+ flags: [
99
+ {
100
+ name: "name",
101
+ type: "string",
102
+ mandatory: true,
103
+ options: ["--name"],
104
+ description: "Name to greet",
105
+ },
106
+ {
107
+ name: "style",
108
+ type: "string",
109
+ enum: ["formal", "casual"],
110
+ defaultValue: "casual",
111
+ description: "Greeting style",
112
+ },
113
+ ],
114
+ // Optional: Define output schema for MCP clients (Claude Desktop, etc.)
115
+ // This only affects MCP mode - CLI mode works the same regardless
116
+ outputSchema: {
117
+ success: z.boolean().describe("Whether the greeting was successful"),
118
+ greeting: z.string().describe("The formatted greeting message"),
119
+ name: z.string().describe("The name that was greeted"),
120
+ },
121
+ handler: async (ctx) => {
122
+ // Use console.log freely - it's automatically safe in MCP mode!
123
+ console.log(`Greeting ${ctx.args.name} in a ${ctx.args.style} style...`);
124
+
125
+ const greeting =
126
+ ctx.args.style === "formal"
127
+ ? `Good day, ${ctx.args.name}.`
128
+ : `Hey ${ctx.args.name}!`;
129
+
130
+ console.log(greeting);
131
+ return { success: true, greeting, name: ctx.args.name };
132
+ },
133
+ });
134
+
135
+ // parse() is async and works with both sync and async handlers
136
+ async function main() {
137
+ try {
138
+ await cli.parse(process.argv.slice(2));
139
+ } catch (error) {
140
+ console.error("Error:", error.message);
141
+ process.exit(1);
50
142
  }
51
- });
52
- ```
143
+ }
53
144
 
54
- ## What's New in v1.1.0
145
+ main();
55
146
 
56
- ### **Major Features**
147
+ // Export if you want to test, use the CLI programmatically
148
+ // or use the --s-enable-fuzzing system flag to run fuzzy tests on your CLI
149
+ export default cli;
150
+ ```
57
151
 
58
- - **MCP (Model Context Protocol) Integration**: Transform any CLI into an MCP server with multiple transport support. Run MCP servers with stdio, SSE, and HTTP transports simultaneously, including streamable HTTP.
59
- - **System Flags**: Built-in `--s-debug-print`, `--s-with-env`, `--s-save-to-env`, `--s-enable-fuzzy`, and `--s-save-DXT` for enhanced debugging, configuration, testing, and MCP distribution
60
- - **Environment Loading**: Load configuration from `.env`, `.yaml`, `.json`, and `.toml` files
61
- - **Enhanced Debugging**: Comprehensive runtime debugging and configuration export tools
152
+ ## How to Run It
62
153
 
63
- ### **Quick Start with MCP**
154
+ ```bash
155
+ # This assumes `mycli` is your CLI's entry point
64
156
 
65
- ```typescript
66
- import { ArgParser } from "@alcyone-labs/arg-parser";
157
+ # 1. As a standard CLI subcommand
158
+ mycli greet --name Jane --style formal
67
159
 
68
- const cli = ArgParser.withMcp({
69
- appName: "My CLI Tool",
70
- appCommandName: "my-tool",
71
- description: "A powerful CLI that can also run as an MCP server",
72
- handler: async (ctx) => ({ result: "success", args: ctx.args }),
73
- })
74
- .addFlags([
75
- { name: "input", options: ["--input", "-i"], type: "string", mandatory: true },
76
- { name: "verbose", options: ["--verbose", "-v"], type: "boolean", flagOnly: true },
77
- ])
78
- .addMcpSubCommand("serve", {
79
- name: "my-mcp-server",
80
- version: "1.1.0",
81
- description: "Expose this CLI as an MCP server",
82
- }, {
83
- // Optional: Configure default transports (CLI flags take precedence)
84
- defaultTransports: [
85
- { type: "stdio" },
86
- { type: "sse", port: 3001, host: "0.0.0.0" }
87
- ]
88
- });
160
+ # 2. As an MCP server, exposing the 'greet' tool
161
+ mycli --s-mcp-serve
89
162
 
90
- // Use as CLI: my-tool --input data.txt --verbose
91
- // Use as MCP server with defaults: my-tool serve
92
- // Use as MCP server with CLI override: my-tool serve --transport sse --port 3002
93
- // Use with multiple transports: my-tool serve --transports '[{"type":"stdio"},{"type":"sse","port":3001}]'
163
+ # 3. Generate a DXT package for Claude Desktop (2-steps)
164
+ mycli --s-build-dxt ./my-dxt-package
94
165
  ```
95
166
 
96
- ## Features
97
-
98
- ### **Core CLI Features**
99
- - **Type Safety:** Define expected argument types (string, number, boolean, array, custom functions) and get type-safe parsed results
100
- - **Declarative API:** Configure your CLI structure, flags, and sub-commands using a clear, declarative syntax
101
- - **Automatic Help Generation:** Generate comprehensive and contextual help text based on your parser configuration
102
- - **Hierarchical Commands:** Easily define nested sub-commands to create complex command structures (e.g., `git commit`, `docker container ls`)
103
- - **Handler Execution:** Associate handler functions with commands and have them executed automatically upon successful parsing
104
- - **Validation:** Define custom validation rules for flag values with enum support and custom validators
105
- - **Conditional Requirements:** Make flags mandatory based on the presence or values of other arguments
106
- - **Default Values:** Specify default values for flags if they are not provided on the command line
107
- - **Flag Inheritance:** Share common flags between parent and child commands with an intuitive inheritance mechanism
108
- - **Error Handling:** Built-in, user-friendly error reporting for common parsing issues, with an option to handle errors manually
109
-
110
- ### **MCP Integration (v1.1.0+)**
111
- - **Automatic MCP Server Creation:** Transform any CLI into an MCP server with a single method call
112
- - **Multiple Transport Support:** Run stdio, SSE, and HTTP transports simultaneously on different ports
113
- - **Type-Safe Tool Generation:** Automatically generate MCP tools with Zod schema validation from CLI definitions
114
- - **Flexible Configuration:** Support for single transport or complex multi-transport JSON configurations
115
-
116
- ### **System & Configuration Features (v1.1.0+)**
117
- - **Environment Loading:** Load configuration from `.env`, `.yaml`, `.json`, and `.toml` files with `--s-with-env`
118
- - **Configuration Export:** Save current configuration to various formats with `--s-save-to-env`
119
- - **Advanced Debugging:** Runtime debugging with `--s-debug` and configuration inspection with `--s-debug-print`
120
- - **CLI Precedence:** Command line arguments always override file configuration
167
+ Read more on generating the DXT package here: [Generating DXT Packages](#generating-dxt-packages---s-build-dxt)
121
168
 
122
- ## Installation
169
+ ### Setting Up System-Wide CLI Access
123
170
 
124
- You can install ArgParser using your preferred package manager:
171
+ To make your CLI available system-wide as a binary command, you need to configure the `bin` field in your `package.json` and use package linking:
125
172
 
126
- ```bash
127
- pnpm add @alcyone-labs/arg-parser
128
- # or
129
- npm install @alcyone-labs/arg-parser
130
- # or
131
- yarn add @alcyone-labs/arg-parser
132
- # or
133
- bun add @alcyone-labs/arg-parser
134
- # or
135
- deno install npm:@alcyone-labs/arg-parser
136
- ```
173
+ **1. Configure your package.json:**
137
174
 
138
- ### **For MCP Integration (Optional)**
175
+ ```json
176
+ {
177
+ "name": "my-cli-app",
178
+ "version": "1.0.0",
179
+ "type": "module",
180
+ "bin": {
181
+ "mycli": "./cli.js"
182
+ }
183
+ }
184
+ ```
139
185
 
140
- If you plan to use MCP server features, install the additional dependencies:
186
+ **2. Make your CLI file executable:**
141
187
 
142
188
  ```bash
143
- pnpm add @modelcontextprotocol/sdk express
144
- # or
145
- npm install @modelcontextprotocol/sdk express
189
+ chmod +x cli.js
146
190
  ```
147
191
 
148
- **Note:** MCP dependencies are optional and only required if you use `ArgParser` with MCP features or MCP-related functionality.
192
+ **3. Add a shebang to your CLI file:**
149
193
 
150
- ## Runtime Compatibility
194
+ ```javascript
195
+ #!/usr/bin/env node
196
+ # or #!/usr/bin/env bun for native typescript runtime
151
197
 
152
- ArgParser is fully compatible with multiple JavaScript runtimes:
198
+ import { ArgParser } from '@alcyone-labs/arg-parser';
153
199
 
154
- ### **BunJS**
155
- ```bash
156
- # Run TypeScript directly
157
- bun your-cli.ts --flag value
200
+ const cli = ArgParser.withMcp({
201
+ appName: "My CLI",
202
+ appCommandName: "mycli",
203
+ // ... your configuration
204
+ });
158
205
 
159
- # Or compile and run
160
- bun build your-cli.ts --outdir ./dist
161
- bun ./dist/your-cli.js --flag value
206
+ // Parse command line arguments
207
+ await cli.parse(process.argv.slice(2));
162
208
  ```
163
209
 
164
- ### **Node.js**
165
- ```bash
166
- # Using tsx for TypeScript
167
- npx tsx your-cli.ts --flag value
210
+ **4. Link the package globally:**
168
211
 
169
- # Using ts-node
170
- npx ts-node your-cli.ts --flag value
212
+ ```bash
213
+ # Using npm
214
+ npm link
171
215
 
172
- # Or compile and run
173
- npx tsc your-cli.ts
174
- node your-cli.js --flag value
175
- ```
216
+ # Using pnpm
217
+ pnpm link --global
176
218
 
177
- ### **Deno**
178
- ```bash
179
- # Run with required permissions
180
- deno run --unstable-sloppy-imports --allow-read --allow-write --allow-env your-cli.ts --flag value
219
+ # Using bun
220
+ bun link
181
221
 
182
- # Or use the provided deno.json configuration for easier task management
183
- deno task example:simple-cli --env production --port 8080
222
+ # Using yarn
223
+ yarn link
184
224
  ```
185
225
 
186
- ### **Using the Library in Your Projects**
187
-
188
- Install the library and use it in your projects:
226
+ **5. Use your CLI from anywhere:**
189
227
 
190
228
  ```bash
191
- # Install the library
192
- pnpm add @alcyone-labs/arg-parser
229
+ # Now you can run your CLI from any directory
230
+ mycli --help
231
+ mycli greet --name "World"
193
232
 
194
- # Use in your project
195
- import { ArgParser } from '@alcyone-labs/arg-parser';
196
- // or
197
- const { ArgParser } = require('@alcyone-labs/arg-parser');
233
+ # Or use with npx/pnpx if you prefer
234
+ npx mycli --help
235
+ pnpx mycli greet --name "World"
198
236
  ```
199
237
 
200
- ### **Running Examples**
201
-
202
- Examples are provided as TypeScript source files for educational purposes. Run them directly with your preferred runtime:
238
+ **To unlink later:**
203
239
 
204
240
  ```bash
205
- # BunJS (recommended)
206
- bun examples/simple-cli.ts --env production --port 8080
241
+ # Using npm
242
+ npm unlink --global my-cli-app
243
+
244
+ # Using pnpm
245
+ pnpm unlink --global
207
246
 
208
- # Node.js with tsx
209
- npx tsx examples/simple-cli.ts --env production --port 8080
247
+ # Using bun
248
+ bun unlink
210
249
 
211
- # Deno (use predefined tasks)
212
- deno task example:simple-cli --env production --port 8080
250
+ # Using yarn
251
+ yarn unlink
213
252
  ```
214
253
 
215
- All examples work seamlessly across all three runtimes, ensuring maximum compatibility for your CLI applications.
254
+ ---
216
255
 
217
- ## Basic Usage
256
+ ## Parsing Command-Line Arguments
218
257
 
219
- ### **Standard CLI Usage**
258
+ ArgParser's `parse()` method is async and automatically handles both synchronous and asynchronous handlers:
220
259
 
221
- Here's a simple example demonstrating how to define flags and parse arguments:
260
+ ### Cannonical Usage Pattern
222
261
 
223
262
  ```typescript
224
- import { ArgParser } from "@alcyone-labs/arg-parser";
225
-
226
- const parser = new ArgParser({
227
- appName: "Data Processor",
228
- appCommandName: "data-proc", // Used in help text and error messages
229
- description: "A tool for processing data phases",
263
+ const cli = ArgParser.withMcp({
264
+ appName: "My CLI",
230
265
  handler: async (ctx) => {
231
- console.log("Processing data with phase:", ctx.args.phase);
232
- return { success: true, phase: ctx.args.phase };
233
- },
234
- }).addFlags([
235
- {
236
- name: "phase",
237
- options: ["--phase"],
238
- type: "string", // Use "string", "number", "boolean", or native types
239
- mandatory: true,
240
- enum: ["chunking", "pairing", "analysis"],
241
- description: "Processing phase to execute",
266
+ // Works with both sync and async operations
267
+ const result = await someAsyncOperation(ctx.args.input);
268
+ return { success: true, result };
242
269
  },
243
- {
244
- name: "batch",
245
- options: ["-b", "--batch-number"],
246
- type: "number",
247
- mandatory: (args) => args.phase !== "analysis", // Conditional requirement
248
- defaultValue: 0,
249
- description: "Batch number (required except for analysis phase)",
250
- },
251
- {
252
- name: "verbose",
253
- options: ["-v", "--verbose"],
254
- flagOnly: true, // This flag does not expect a value
255
- description: "Enable verbose logging",
256
- },
257
- ]);
270
+ });
258
271
 
259
- // Parse and execute
260
- const result = parser.parse(process.argv.slice(2));
261
- console.log("Result:", result);
272
+ // parse() is async and works with both sync and async handlers
273
+ async function main() {
274
+ try {
275
+ const result = await cli.parse(process.argv.slice(2));
276
+ // Handler results are automatically awaited and merged
277
+ console.log(result.success); // true
278
+ } catch (error) {
279
+ console.error("Error:", error.message);
280
+ process.exit(1);
281
+ }
282
+ }
262
283
  ```
263
284
 
264
- ### **MCP Server Usage (v1.1.0+)**
265
-
266
- Transform your CLI into an MCP server with minimal changes:
267
-
268
- ```typescript
269
- import { ArgParser } from "@alcyone-labs/arg-parser";
285
+ ### Top-level await
270
286
 
271
- const cli = ArgParser.withMcp({
272
- appName: "Data Processor",
273
- appCommandName: "data-proc",
274
- description: "A tool for processing data phases (CLI + MCP server)",
275
- handler: async (ctx) => {
276
- console.log("Processing data with phase:", ctx.args.phase);
277
- return { success: true, phase: ctx.args.phase, batch: ctx.args.batch };
278
- },
279
- })
280
- .addFlags([
281
- {
282
- name: "phase",
283
- options: ["--phase"],
284
- type: "string",
285
- mandatory: true,
286
- enum: ["chunking", "pairing", "analysis"],
287
- description: "Processing phase to execute",
288
- },
289
- {
290
- name: "batch",
291
- options: ["-b", "--batch-number"],
292
- type: "number",
293
- defaultValue: 0,
294
- description: "Batch number for processing",
295
- },
296
- ])
297
- .addMcpSubCommand("serve", {
298
- name: "data-processor-mcp",
299
- version: "1.1.0",
300
- description: "Data Processor MCP Server",
301
- });
287
+ Works in ES modules or Node.js >=18 with top-level await
302
288
 
303
- // Use as CLI: data-proc --phase chunking --batch 5
304
- // Use as MCP server: data-proc serve
305
- // Use with custom transport: data-proc serve --transport sse --port 3001
289
+ ```javascript
290
+ try {
291
+ const result = await cli.parse(process.argv.slice(2));
292
+ console.log("Success:", result);
293
+ } catch (error) {
294
+ console.error("Error:", error.message);
295
+ process.exit(1);
296
+ }
306
297
  ```
307
298
 
308
- ## MCP Integration (v1.1.0+)
299
+ ### Promise-based parsing
309
300
 
310
- ArgParser v1.1.0 introduces powerful Model Context Protocol (MCP) integration, allowing you to expose any CLI as an MCP server with minimal code changes.
301
+ If you need synchronous contexts, you can simply rely on promise-based APIs
311
302
 
312
- ### **Quick MCP Setup**
303
+ ```javascript
304
+ cli
305
+ .parse(process.argv.slice(2))
306
+ .then((result) => {
307
+ console.log("Success:", result);
308
+ })
309
+ .catch((error) => {
310
+ console.error("Error:", error.message);
311
+ process.exit(1);
312
+ });
313
+ ```
313
314
 
314
- 1. **Import the MCP-enabled class:**
315
- ```typescript
316
- import { ArgParser } from "@alcyone-labs/arg-parser";
317
- ```
315
+ ---
318
316
 
319
- 2. **Create your CLI with MCP support:**
320
- ```typescript
321
- const cli = ArgParser.withMcp({
322
- appName: "My Tool",
323
- appCommandName: "my-tool",
324
- handler: async (ctx) => ({ result: "success", args: ctx.args }),
325
- })
326
- .addFlags([/* your flags */])
327
- .addMcpSubCommand("serve", {
328
- name: "my-mcp-server",
329
- version: "1.0.0",
330
- });
331
- ```
317
+ ## Migrating from v1.x to the v2.0 `addTool` API
332
318
 
333
- 3. **Use as CLI or MCP server:**
334
- ```bash
335
- # CLI usage
336
- my-tool --input data.txt --verbose
319
+ Version 2.0 introduces the `addTool()` method to unify CLI subcommand and MCP tool creation. This simplifies development by removing boilerplate and conditional logic.
337
320
 
338
- # MCP server (stdio)
339
- my-tool serve
321
+ ### Before v2.0: Separate Definitions
340
322
 
341
- # MCP server (HTTP)
342
- my-tool serve --transport sse --port 3001
323
+ Previously, you had to define CLI handlers and MCP tools separately, often with conditional logic inside the handler to manage different output formats.
343
324
 
344
- # Multiple transports
345
- my-tool serve --transports '[{"type":"stdio"},{"type":"sse","port":3001}]'
346
- ```
325
+ ```javascript
326
+ const cli = ArgParser.withMcp({
327
+ appName: "My Awesome CLI",
328
+ appCommandName: "mycli",
329
+ description: "A tool that works in both CLI and MCP mode",
330
+ mcp: {
331
+ serverInfo: { name: "my-awesome-mcp-server", version: "1.0.0" },
332
+ },
333
+ });
347
334
 
348
- ### **MCP Transport Options**
335
+ // Old way: Separate CLI subcommands and MCP tools
336
+ cli
337
+ .addSubCommand({
338
+ name: "search",
339
+ handler: async (ctx) => {
340
+ // Manual MCP detection was required
341
+ if (ctx.isMcp) {
342
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
343
+ } else {
344
+ console.log("Search results...");
345
+ return result;
346
+ }
347
+ },
348
+ })
349
+ // And a separate command to start the server
350
+ .addMcpSubCommand("serve", {
351
+ /* MCP config */
352
+ });
353
+ ```
349
354
 
350
- - **`stdio`** (default): Standard input/output for CLI tools
351
- - **`sse`**: Server-Sent Events over HTTP for web applications
352
- - **`streamable-http`**: HTTP with streaming support for advanced integrations
355
+ ### After v2.0: The Unified `addTool()` Method
353
356
 
354
- ### **Multiple Transports Simultaneously**
357
+ Now, a single `addTool()` definition creates both the CLI subcommand and the MCP tool. Console output is automatically managed, flags are converted to MCP schemas, and the server is started with a universal system flag.
355
358
 
356
- Run multiple transport types at once for maximum flexibility:
359
+ ```javascript
360
+ const cli = ArgParser.withMcp({
361
+ appName: "My Awesome CLI",
362
+ appCommandName: "mycli",
363
+ description: "A tool that works in both CLI and MCP mode",
364
+ mcp: {
365
+ serverInfo: { name: "my-awesome-mcp-server", version: "1.0.0" },
366
+ },
367
+ });
357
368
 
358
- ```bash
359
- my-tool serve --transports '[
360
- {"type":"stdio"},
361
- {"type":"sse","port":3001,"path":"/sse"},
362
- {"type":"streamable-http","port":3002,"path":"/mcp","host":"0.0.0.0"}
363
- ]'
369
+ // New way: A single tool definition for both CLI and MCP
370
+ cli.addTool({
371
+ name: "search",
372
+ description: "Search for items",
373
+ flags: [
374
+ { name: "query", type: "string", mandatory: true },
375
+ { name: "apiKey", type: "string", env: "API_KEY" }, // For DXT integration
376
+ ],
377
+ handler: async (ctx) => {
378
+ // No more MCP detection! Use console.log freely.
379
+ console.log(`Searching for: ${ctx.args.query}`);
380
+ const results = await performSearch(ctx.args.query, ctx.args.apiKey);
381
+ console.log(`Found ${results.length} results`);
382
+ return { success: true, results };
383
+ },
384
+ });
385
+
386
+ // CLI usage: mycli search --query "test"
387
+ // MCP usage: mycli --s-mcp-serve
364
388
  ```
365
389
 
366
- ### **Automatic Tool Generation**
390
+ **Benefits of Migrating:**
391
+
392
+ - **Less Code**: A single definition replaces two or more complex ones.
393
+ - **Simpler Logic**: No more manual MCP mode detection or response formatting.
394
+ - **Automatic Schemas**: Flags are automatically converted into the `input_schema` for MCP tools.
395
+ - **Automatic Console Safety**: `console.log` is automatically redirected in MCP mode.
396
+ - **Optional Output Schemas**: Add `outputSchema` only if you want structured responses for MCP clients - CLI mode works perfectly without them.
367
397
 
368
- Your CLI flags are automatically converted to MCP tools with:
369
- - **Type-safe schemas** using Zod validation
370
- - **Automatic documentation** from flag descriptions
371
- - **Enum validation** for restricted values
372
- - **Error handling** with detailed messages
398
+ ---
373
399
 
374
400
  ## Core Concepts
375
401
 
376
402
  ### Defining Flags
377
403
 
378
- Flags are defined using the `.addFlag(flag)` method or by passing an array of flags as the second argument to the `ArgParser` constructor. Each flag is an object conforming to the `IFlag` interface:
404
+ Flags are defined using the `IFlag` interface within the `flags` array of a tool or command.
379
405
 
380
406
  ```typescript
381
407
  interface IFlag {
382
- name: string; // Internal name for accessing the value in parsed args
383
- options: string[]; // Array of command-line options (e.g., ["-v", "--verbose"])
384
- type:
385
- | "string"
386
- | "boolean"
387
- | "number"
388
- | "array"
389
- | "object"
390
- | ((value: string) => any)
391
- | Constructor; // Expected type or a parsing function
392
- description: string | string[]; // Text description for help output
393
- mandatory?: boolean | ((args: TParsedArgs) => boolean); // Whether the flag is required, or a function that determines this
394
- defaultValue?: any; // Default value if the flag is not provided
395
- default?: any; // Alias for defaultValue
396
- flagOnly?: boolean; // If true, the flag does not consume the next argument as its value (e.g., `--verbose`)
397
- allowMultiple?: boolean; // If true, the flag can be provided multiple times (values are collected in an array)
398
- enum?: any[]; // Array of allowed values. Parser validates input against this list.
399
- validate?: (value: any) => boolean | string | void; // Custom validation function
400
- required?: boolean | ((args: any) => boolean); // Alias for mandatory
408
+ name: string; // Internal name (e.g., 'verbose')
409
+ options: string[]; // Command-line options (e.g., ['--verbose', '-v'])
410
+ type: "string" | "number" | "boolean" | "array" | "object" | Function;
411
+ description?: string; // Help text
412
+ mandatory?: boolean | ((args: any) => boolean); // Whether the flag is required
413
+ defaultValue?: any; // Default value if not provided
414
+ flagOnly?: boolean; // A flag that doesn't consume a value (like --help)
415
+ enum?: any[]; // An array of allowed values
416
+ validate?: (value: any, parsedArgs?: any) => boolean | string | void; // Custom validation function
417
+ allowMultiple?: boolean; // Allow the flag to be provided multiple times
418
+ env?: string; // Links the flag to an environment variable for DXT packages, will automatically generate user_config entries in the DXT manifest and fill the flag value to the ENV value if found (process.env)
401
419
  }
402
420
  ```
403
421
 
404
422
  ### Type Handling and Validation
405
423
 
406
- ArgParser handles type conversion automatically based on the `type` property. You can use standard string types (`"string"`, `"number"`, `"boolean"`, `"array"`, `"object`), native constructors (`String`, `Number`, `Boolean`, `Array`, `Object`), or provide a custom function:
424
+ ArgParser provides **strong typing** for flag definitions with comprehensive validation at both compile-time and runtime. The `type` property accepts multiple formats and ensures type safety throughout your application.
407
425
 
408
- ```typescript
409
- .addFlag({
410
- name: "count",
411
- options: ["--count"],
412
- type: Number, // Automatically converts value to a number
413
- })
414
- .addFlag({
415
- name: "data",
416
- options: ["--data"],
417
- type: JSON.parse, // Use a function to parse complex types like JSON strings
418
- description: "JSON data to process"
419
- })
420
- .addFlag({
421
- name: "environment",
422
- options: ["--env"],
423
- type: "string",
424
- enum: ["dev", "staging", "prod"], // Validate value against this list
425
- description: "Deployment environment",
426
- })
427
- .addFlag({
428
- name: "id",
429
- options: ["--id"],
430
- type: "string",
431
- validate: (value) => /^[a-f0-9]+$/.test(value), // Custom validation function
432
- description: "Hexadecimal ID",
433
- })
434
- .addFlag({
435
- name: "config",
436
- options: ["-c"],
437
- allowMultiple: true,
438
- type: path => require(path), // Load config from path (example)
439
- description: "Load multiple configuration files"
440
- })
441
- ```
442
-
443
- ### Mandatory Flags
426
+ #### Supported Type Formats
444
427
 
445
- Flags can be made mandatory using the `mandatory` property, or its alias "required". This can be a boolean or a function that receives the currently parsed arguments and returns a boolean.
428
+ You can define flag types using either **constructor functions** or **string literals**:
446
429
 
447
430
  ```typescript
448
- .addFlag({
449
- name: "input",
450
- options: ["--in"],
451
- type: String,
452
- mandatory: true, // Always mandatory
453
- description: "Input file path",
454
- })
455
- .addFlag({
456
- name: "output",
457
- options: ["--out"],
458
- type: String,
459
- mandatory: (args) => args.format === "json", // Mandatory only if --format is "json"
460
- description: "Output file path (required for JSON output)",
461
- })
431
+ const parser = new ArgParser({ /* ... */ }).addFlags([
432
+ // Constructor functions (recommended for TypeScript)
433
+ { name: "count", options: ["--count"], type: Number },
434
+ { name: "enabled", options: ["--enabled"], type: Boolean, flagOnly: true },
435
+ { name: "files", options: ["--files"], type: Array, allowMultiple: true },
436
+
437
+ // String literals (case-insensitive)
438
+ { name: "name", options: ["--name"], type: "string" },
439
+ { name: "port", options: ["--port"], type: "number" },
440
+ { name: "verbose", options: ["-v"], type: "boolean", flagOnly: true },
441
+ { name: "tags", options: ["--tags"], type: "array", allowMultiple: true },
442
+ { name: "config", options: ["--config"], type: "object" },
443
+
444
+ // Custom parser functions
445
+ {
446
+ name: "date",
447
+ options: ["--date"],
448
+ type: (value: string) => new Date(value)
449
+ }
450
+ ]);
462
451
  ```
463
452
 
464
- If a mandatory flag is missing and default error handling is enabled (`handleErrors: true`), the parser will print an error and exit.
465
-
466
- ### Default Values
453
+ #### Runtime Type Validation
467
454
 
468
- Set a `defaultValue` (or its alias `default`) for flags to provide a fallback value if the flag is not present in the arguments.
455
+ The type system validates flag definitions at runtime and throws descriptive errors for invalid configurations:
469
456
 
470
457
  ```typescript
471
- .addFlag({
472
- name: "port",
473
- options: ["-p", "--port"],
474
- type: Number,
475
- defaultValue: 3000, // Default port is 3000 if -p or --port is not used
476
- description: "Server port",
477
- })
458
+ // ✅ Valid - these work
459
+ { name: "count", options: ["--count"], type: Number }
460
+ { name: "count", options: ["--count"], type: "number" }
461
+ { name: "count", options: ["--count"], type: "NUMBER" } // case-insensitive
462
+
463
+ // Invalid - these throw ZodError
464
+ { name: "count", options: ["--count"], type: "invalid-type" }
465
+ { name: "count", options: ["--count"], type: 42 } // primitive instead of constructor
466
+ { name: "count", options: ["--count"], type: null }
478
467
  ```
479
468
 
480
- ### Flag-Only Flags
469
+ #### Automatic Type Processing
481
470
 
482
- Flags that do not expect a value (like `--verbose` or `--force`) should have `flagOnly: true`. When `flagOnly` is false (the default), the parser expects the next argument to be the flag's value.
471
+ - **String literals** are automatically converted to constructor functions internally
472
+ - **Constructor functions** are preserved as-is
473
+ - **Custom parser functions** allow complex transformations
474
+ - **undefined** falls back to the default `"string"` type
483
475
 
484
- ```typescript
485
- .addFlag({
486
- name: "verbose",
487
- options: ["-v"],
488
- type: Boolean, // Typically boolean for flag-only flags
489
- flagOnly: true,
490
- description: "Enable verbose output",
491
- })
492
- ```
476
+ #### Type Conversion Examples
493
477
 
494
- ### Alias Properties
478
+ ```typescript
479
+ // String flags
480
+ --name value → "value"
481
+ --name="quoted value" → "quoted value"
495
482
 
496
- For convenience, `ArgParser` supports aliases for some flag properties:
483
+ // Number flags
484
+ --count 42 → 42
485
+ --port=8080 → 8080
497
486
 
498
- - `default` is an alias for `defaultValue`.
499
- - `required` is an alias for `mandatory`.
500
- If both the original property and its alias are provided, the original property (`defaultValue`, `mandatory`) takes precedence.
487
+ // Boolean flags (flagOnly: true)
488
+ --verbose → true
489
+ (no flag) false
501
490
 
502
- ## Hierarchical CLIs (Sub-Commands)
491
+ // Array flags (allowMultiple: true)
492
+ --tags tag1,tag2,tag3 → ["tag1", "tag2", "tag3"]
493
+ --file file1.txt --file file2.txt → ["file1.txt", "file2.txt"]
503
494
 
504
- ArgParser excels at building CLIs with nested commands, like `git clone` or `docker build`.
495
+ // Custom parser functions
496
+ --date "2023-01-01" → Date object
497
+ --json '{"key":"val"}' → parsed JSON object
498
+ ```
505
499
 
506
- ### Defining Sub-Commands
500
+ ### Hierarchical CLIs (Sub-Commands)
507
501
 
508
- Define sub-commands using the `subCommands` option in the `ArgParser` constructor or the `.addSubCommand(subCommand)` method. Each sub-command requires a `name`, `description`, and a dedicated `ArgParser` instance for its own flags and nested sub-commands.
502
+ While `addTool()` is the recommended way to create subcommands that are also MCP-compatible, you can use `.addSubCommand()` for traditional CLI hierarchies.
509
503
 
510
- Note that each flag name set is debounced to make sure there are no duplicates, but the flags are sandboxed within their respective sub-commands. So it's ok to use the same flag on different sub-commands.
504
+ > **Note**: By default, subcommands created with `.addSubCommand()` are exposed to MCP as tools. If you want to create CLI-only subcommands, set `includeSubCommands: false` when adding tools.
511
505
 
512
506
  ```typescript
513
- import {
514
- ArgParser,
515
- HandlerContext,
516
- ISubCommand,
517
- } from "@alcyone-labs/arg-parser";
518
-
519
- const deployParser = new ArgParser().addFlags([
520
- { name: "target", options: ["-t"], type: String, mandatory: true },
521
- ]);
522
-
523
- const monitorLogsParser = new ArgParser().addFlags([
524
- { name: "follow", options: ["-f"], flagOnly: true, type: Boolean },
507
+ // Create a parser for a nested command
508
+ const logsParser = new ArgParser().addFlags([
509
+ { name: "follow", options: ["-f"], type: "boolean", flagOnly: true },
525
510
  ]);
526
511
 
512
+ // This creates a command group: `my-cli monitor`
527
513
  const monitorParser = new ArgParser().addSubCommand({
528
514
  name: "logs",
529
- description: "Show logs",
530
- parser: monitorLogsParser,
531
- handler: ({ args }) => {
532
- console.log(`Showing logs... Follow: ${args.follow}`);
533
- },
515
+ description: "Show application logs",
516
+ parser: logsParser,
517
+ handler: ({ args }) => console.log(`Following logs: ${args.follow}`),
534
518
  });
535
519
 
536
- const cli = new ArgParser({
537
- appName: "My CLI",
538
- appCommandName: "my-cli",
539
- description: "Manage application resources",
540
- subCommands: [
541
- {
542
- name: "deploy",
543
- description: "Deploy resources",
544
- parser: deployParser,
545
- handler: ({ args }) => {
546
- console.log(`Deploying to ${args.target}`);
547
- },
548
- },
549
- {
550
- name: "monitor",
551
- description: "Monitoring commands",
552
- parser: monitorParser,
553
- },
554
- ],
520
+ // Attach the command group to the main CLI
521
+ const cli = new ArgParser().addSubCommand({
522
+ name: "monitor",
523
+ description: "Monitoring commands",
524
+ parser: monitorParser,
555
525
  });
556
526
 
557
- // Example usage:
558
- // my-cli deploy -t production
559
- // my-cli monitor logs -f
527
+ // Usage: my-cli monitor logs -f
560
528
  ```
561
529
 
562
- ### Handler Execution
563
-
564
- A core feature is associating handler functions with commands. Handlers are functions (`(ctx: HandlerContext) => void`) that contain the logic to be executed when a specific command (root or sub-command) is successfully parsed and matched.
565
-
566
- Handlers can be defined in the `ISubCommand` object or set/updated later using the `.setHandler()` method on the command's parser instance.
567
-
568
- **By default, after successful parsing, ArgParser will execute the handler associated with the _final command_ matched in the argument chain.** For example, running `my-cli service start` will execute the handler for the `start` command, not `my-cli` or `service`.
569
-
570
- If you need to parse arguments but _prevent_ handler execution, you can pass the `skipHandlers: true` option to the `parse()` method:
530
+ #### MCP Exposure Control
571
531
 
572
532
  ```typescript
573
- const args = parser.parse(process.argv.slice(2), { skipHandlers: true });
574
- // Handlers will NOT be executed, you can inspect 'args' and decide what to do
575
- ```
533
+ // By default, subcommands are exposed to MCP
534
+ const mcpTools = parser.toMcpTools(); // Includes all subcommands
576
535
 
577
- ### Handler Context
536
+ // To exclude subcommands from MCP (CLI-only)
537
+ const mcpToolsOnly = parser.toMcpTools({ includeSubCommands: false });
578
538
 
579
- Handler functions receive a single argument, a `HandlerContext` object, containing information about the parsing result and the command chain:
580
-
581
- ```typescript
582
- type HandlerContext = {
583
- args: TParsedArgs<any>; // Arguments parsed by and defined for the FINAL command's parser
584
- parentArgs?: TParsedArgs<any>; // Combined arguments from PARENT parsers (less relevant with inheritParentFlags)
585
- commandChain: string[]; // Array of command names from root to final command
586
- };
587
- ```
588
-
589
- The `args` property is the most commonly used, containing flags and their values relevant to the handler's specific command. If `inheritParentFlags` is used, inherited flags appear directly in `args`.
590
-
591
- ### Setting Handlers with `.setHandler()`
592
-
593
- You can define or override a parser instance's handler after its creation:
594
-
595
- ```typescript
596
- const myCommandParser = new ArgParser().addFlags(/* ... */);
597
-
598
- myCommandParser.setHandler((ctx) => {
599
- console.log(`Executing handler for ${ctx.commandChain.join(" -> ")}`);
600
- // ... command logic ...
601
- });
602
-
603
- // You can also retrieve a sub-parser and set its handler:
604
- const subParser = cli.getSubCommand("deploy")?.parser;
605
- if (subParser) {
606
- subParser.setHandler((ctx) => {
607
- console.log("Overridden deploy handler!");
608
- // ... new deploy logic ...
609
- });
610
- }
611
- ```
612
-
613
- ### Accessing Sub-Parsers with `.getSubCommand()`
614
-
615
- Use the `.getSubCommand(name)` method on a parser instance to retrieve the `ISubCommand` definition for a specific sub-command by name. This allows you to access its parser instance to set handlers, add flags dynamically, or inspect its configuration.
616
-
617
- ```typescript
618
- const deploySubCommand = cli.getSubCommand("deploy");
619
- if (deploySubCommand) {
620
- console.log(`Description of deploy command: ${deploySubCommand.description}`);
621
- // Access the parser instance:
622
- const deployParserInstance = deploySubCommand.parser;
623
- // Add a flag specifically to the deploy command after initial setup:
624
- deployParserInstance.addFlag({
625
- name: "force",
626
- options: ["--force"],
627
- flagOnly: true,
628
- type: Boolean,
629
- });
630
- }
539
+ // Name conflicts: You cannot have both addSubCommand("name") and addTool({ name: "name" })
540
+ // This will throw an error:
541
+ parser.addSubCommand({ name: "process", parser: subParser });
542
+ parser.addTool({ name: "process", handler: async () => {} }); // ❌ Error: Sub-command 'process' already exists
631
543
  ```
632
544
 
633
545
  ### Flag Inheritance (`inheritParentFlags`)
634
546
 
635
- Enable `inheritParentFlags: true` in a child parser's constructor options to automatically copy flags from its direct parent when added as a sub-command. This is useful for sharing common flags like `--verbose` across your CLI.
636
-
637
- If a flag with the same name exists in both the parent and the child, the child's definition takes precedence. The built-in `--help` flag is never inherited.
547
+ To share common flags (like `--verbose` or `--config`) across sub-commands, set `inheritParentFlags: true` in the sub-command's parser.
638
548
 
639
549
  ```typescript
640
550
  const parentParser = new ArgParser().addFlags([
641
- { name: "verbose", options: ["-v"], type: Boolean, flagOnly: true },
642
- { name: "config", options: ["-c"], type: String }, // Common config flag
551
+ { name: "verbose", options: ["-v"], type: "boolean" },
643
552
  ]);
644
553
 
554
+ // This child parser will automatically have the --verbose flag
645
555
  const childParser = new ArgParser({ inheritParentFlags: true }).addFlags([
646
- { name: "local", options: ["-l"], type: String }, // Child-specific flag
647
- { name: "config", options: ["--child-config"], type: Number }, // Override config flag
556
+ { name: "target", options: ["-t"], type: "string" },
648
557
  ]);
649
558
 
650
- parentParser.addSubCommand({
651
- name: "child",
652
- description: "A child command",
653
- parser: childParser,
654
- });
655
-
656
- // The 'child' parser now effectively has flags: --help, -v, -l, --child-config
657
- // Running `parent child -v -l value --child-config 123` will parse all these flags.
559
+ parentParser.addSubCommand({ name: "deploy", parser: childParser });
658
560
  ```
659
561
 
660
- ## Automatic Help
661
-
662
- ArgParser provides robust automatic help generation.
562
+ ---
663
563
 
664
- ### Global Help Flag (`--help`, `-h`)
564
+ ## MCP & Claude Desktop Integration
665
565
 
666
- A `--help` (and `-h`) flag is automatically added to every parser instance (root and sub-commands). When this flag is encountered during parsing:
566
+ ### Output Schema Support
667
567
 
668
- 1. ArgParser stops processing arguments.
669
- 2. Generates and prints the help text relevant to the current command/sub-command context.
670
- 3. Exits the process with code 0.
568
+ Output schemas are **completely optional** and **only affect MCP mode** (Claude Desktop, MCP clients). They have **zero impact** on CLI usage - your CLI will work exactly the same with or without them.
671
569
 
672
- This behavior is triggered automatically unless `skipHelpHandling: true` is passed to the `parse()` method.
570
+ **When do I need output schemas?**
673
571
 
674
- ```bash
675
- # Shows help for the root command
676
- my-cli --help
572
+ - ❌ **CLI-only usage**: Never needed - skip this section entirely
573
+ - **MCP integration**: Optional but recommended for better structured responses
574
+ - ✅ **Claude Desktop**: Helpful for Claude to understand your tool's output format
677
575
 
678
- # Shows help for the 'deploy' sub-command
679
- my-cli deploy --help
680
- ```
576
+ **Key Points:**
681
577
 
682
- ### `helpText()` Method
578
+ - **CLI works perfectly without them**: Your command-line interface is unaffected
579
+ - ✅ **MCP-only feature**: Only used when running with `--s-mcp-serve`
580
+ - ✅ **Version-aware**: Automatically included only for compatible MCP clients (v2025-06-18+)
581
+ - ✅ **Flexible**: Use predefined patterns or custom Zod schemas
683
582
 
684
- You can manually generate the help text for any parser instance at any time using the `helpText()` method. This returns a string containing the formatted help output.
583
+ #### Basic Usage
685
584
 
686
585
  ```typescript
687
- console.log(parser.helpText());
688
- ```
586
+ import { z } from "zod";
689
587
 
690
- ### Auto-Help on Empty Invocation
588
+ .addTool({
589
+ name: "process-file",
590
+ description: "Process a file",
591
+ flags: [
592
+ { name: "path", options: ["--path"], type: "string", mandatory: true }
593
+ ],
594
+ // Optional: Only needed if you want structured MCP responses
595
+ // CLI mode works exactly the same whether this is present or not
596
+ outputSchema: {
597
+ success: z.boolean().describe("Whether processing succeeded"),
598
+ filePath: z.string().describe("Path to the processed file"),
599
+ size: z.number().describe("File size in bytes"),
600
+ lastModified: z.string().describe("Last modification timestamp")
601
+ },
602
+ handler: async (ctx) => {
603
+ // Your logic here - same code for both CLI and MCP
604
+ // The outputSchema doesn't change how this function works
605
+ return {
606
+ success: true,
607
+ filePath: ctx.args.path,
608
+ size: 1024,
609
+ lastModified: new Date().toISOString()
610
+ };
611
+ }
612
+ })
691
613
 
692
- For the root command, if you invoke the script **without any arguments** and the root parser **does not have a handler defined**, ArgParser will automatically display the root help text and exit cleanly (code 0). This provides immediate guidance for users who just type the script name.
614
+ // CLI usage (outputSchema ignored): mycli process-file --path /my/file.txt
615
+ // MCP usage (outputSchema provides structure): mycli --s-mcp-serve
616
+ ```
693
617
 
694
- If the root parser _does_ have a handler, it's assumed that the handler will manage the empty invocation case, and auto-help will not trigger.
618
+ #### Predefined Schema Patterns
695
619
 
696
- ## Error Handling
620
+ For common use cases, use predefined patterns:
697
621
 
698
- ArgParser includes built-in error handling for common parsing errors like missing mandatory flags, invalid types, or unknown commands.
622
+ ```typescript
623
+ // For simple success/error responses
624
+ outputSchema: "successError";
699
625
 
700
- By default (`handleErrors: true`):
626
+ // For operations that return data
627
+ outputSchema: "successWithData";
701
628
 
702
- 1. A descriptive, colored error message is printed to `stderr`.
703
- 2. A suggestion to use `--help` is included, showing the correct command path.
704
- 3. The process exits with status code 1.
629
+ // For file operations
630
+ outputSchema: "fileOperation";
705
631
 
706
- ```typescript
707
- // Example (assuming 'data-proc' is appCommandName and 'phase' is mandatory)
708
- // Running `data-proc` would output:
632
+ // For process execution
633
+ outputSchema: "processExecution";
709
634
 
710
- // Error: Missing mandatory flags: phase
711
- //
712
- // Try 'data-proc --help' for usage details.
635
+ // For list operations
636
+ outputSchema: "list";
713
637
  ```
714
638
 
715
- You can disable this behavior by setting `handleErrors: false` in the `ArgParser` constructor options. When disabled, ArgParser will throw an `ArgParserError` exception on parsing errors, allowing you to catch and handle them programmatically.
639
+ #### Custom Zod Schemas
716
640
 
717
- ```typescript
718
- import { ArgParser, ArgParserError } from "@alcyone-labs/arg-parser";
641
+ For complex data structures:
719
642
 
720
- const parser = new ArgParser({
721
- appCommandName: "my-app",
722
- handleErrors: false, // Disable default handling
643
+ ```typescript
644
+ outputSchema: z.object({
645
+ analysis: z.object({
646
+ summary: z.string(),
647
+ wordCount: z.number(),
648
+ sentiment: z.enum(["positive", "negative", "neutral"]),
649
+ }),
650
+ metadata: z.object({
651
+ timestamp: z.string(),
652
+ processingTime: z.number(),
653
+ }),
723
654
  });
724
-
725
- try {
726
- const args = parser.parse(process.argv.slice(2));
727
- // Process args if parsing succeeded
728
- } catch (error) {
729
- if (error instanceof ArgParserError) {
730
- console.error(`\nCustom Parse Error: ${error.message}`);
731
- // Implement custom logic (e.g., logging, different exit codes)
732
- process.exit(1);
733
- } else {
734
- // Handle unexpected errors
735
- console.error("An unexpected error occurred:", error);
736
- process.exit(1);
737
- }
738
- }
739
655
  ```
740
656
 
741
- ## Environment Configuration Export
657
+ #### MCP Version Compatibility
742
658
 
743
- ArgParser includes a built-in system flag `--s-save-to-env` that allows you to export the current parser's configuration and parsed arguments to various file formats. This is useful for creating configuration templates, documenting CLI usage, or generating environment files for deployment.
659
+ Output schemas are automatically handled based on MCP client version:
744
660
 
745
- ### Usage
661
+ - **MCP v2025-06-18+**: Full output schema support with `structuredContent`
662
+ - **Earlier versions**: Schemas ignored, standard JSON text response only
746
663
 
747
- ```bash
748
- # Export to .env format (default for no extension)
749
- your-cli --flag1 value1 --flag2 --s-save-to-env config.env
664
+ To explicitly set the MCP version for testing:
750
665
 
751
- # Export to YAML format
752
- your-cli --flag1 value1 --flag2 --s-save-to-env config.yaml
753
-
754
- # Export to JSON format
755
- your-cli --flag1 value1 --flag2 --s-save-to-env config.json
756
-
757
- # Export to TOML format
758
- your-cli --flag1 value1 --flag2 --s-save-to-env config.toml
666
+ ```typescript
667
+ const cli = ArgParser.withMcp({
668
+ // ... your config
669
+ }).setMcpProtocolVersion("2025-06-18"); // Enable output schema support
759
670
  ```
760
671
 
761
- ### Supported Formats
762
-
763
- The format is automatically detected based on the file extension:
764
-
765
- - **`.env`** (or no extension): Bash environment variable format
766
- - **`.yaml` / `.yml`**: YAML format
767
- - **`.json` / `.jsonc`**: JSON format with metadata
768
- - **`.toml` / `.tml`**: TOML format
672
+ **Important**:
769
673
 
770
- ### Behavior
674
+ - **CLI users**: You can ignore MCP versions entirely - they don't affect command-line usage
675
+ - **MCP users**: ArgParser handles version detection automatically based on client capabilities
771
676
 
772
- - **Works at any parser level**: Can be used with root commands or sub-commands
773
- - **Includes inherited flags**: Shows flags from the current parser and all parent parsers in the chain
774
- - **Comments optional flags**: Flags that are optional and not set are commented out but still documented
775
- - **Preserves values**: Set flags show their actual values, unset flags show default values or are commented out
776
- - **Rich documentation**: Each flag includes its description, options, type, and constraints
677
+ #### Automatic Error Handling
777
678
 
778
- ### Example Output
679
+ ArgParser automatically handles errors differently based on execution context, so your handlers can simply throw errors without worrying about CLI vs MCP mode:
779
680
 
780
- For a CLI with flags `--verbose`, `--output file.txt`, and `--count 5`:
781
-
782
- **`.env` format:**
783
- ```bash
784
- # Environment configuration generated by ArgParser
785
- # Format: Bash .env style
786
-
787
- # verbose: Enable verbose output
788
- # Options: -v, --verbose
789
- # Type: Boolean
790
- # Default: false
791
- VERBOSE="true"
792
-
793
- # output: Output file path
794
- # Options: -o, --output
795
- # Type: String
796
- OUTPUT="file.txt"
797
-
798
- # count: Number of items to process
799
- # Options: -c, --count
800
- # Type: Number
801
- # Default: 10
802
- COUNT="5"
803
- ```
804
-
805
- **`.yaml` format:**
806
- ```yaml
807
- # Environment configuration generated by ArgParser
808
- # Format: YAML
809
-
810
- # verbose: Enable verbose output
811
- # Options: -v, --verbose
812
- # Type: Boolean
813
- # Default: false
681
+ ```typescript
682
+ const cli = ArgParser.withMcp({
683
+ // ... config
684
+ }).addTool({
685
+ name: "process-data",
686
+ handler: async (ctx) => {
687
+ // Simply throw errors - ArgParser handles the rest automatically
688
+ if (!ctx.args.apiKey) {
689
+ throw new Error("API key is required");
690
+ }
814
691
 
815
- verbose: true
816
- output: "file.txt"
817
- count: 5
692
+ // Do your work and return results
693
+ return { success: true, data: processedData };
694
+ },
695
+ });
818
696
  ```
819
697
 
820
- ## System Flags (v1.1.0+)
821
-
822
- ArgParser includes several built-in system flags that provide debugging, configuration management, and introspection capabilities. These flags are processed before normal argument parsing and will cause the program to exit after execution.
698
+ **How it works:**
823
699
 
824
- ### **Overview**
700
+ - **CLI mode**: Thrown errors cause the process to exit with error code 1
701
+ - **MCP mode**: Thrown errors are automatically converted to structured MCP error responses
702
+ - **No manual checks needed**: Handlers don't need to check `ctx.isMcp` or handle different response formats
825
703
 
826
- System flags use the `--s-*` pattern and provide powerful development and deployment tools:
704
+ ### Writing Effective MCP Tool Descriptions
827
705
 
828
- - **`--s-debug`**: Runtime debugging with step-by-step parsing analysis
829
- - **`--s-with-env <file>`**: Load configuration from files (`.env`, `.yaml`, `.json`, `.toml`)
830
- - **`--s-save-to-env <file>`**: Export current configuration to various formats
831
- - **`--s-debug-print`**: Export complete parser configuration for inspection
832
- - **`--s-enable-fuzzy`**: Enable fuzzy testing mode (dry-run with no side effects)
833
- - **`--s-save-DXT [dir]`**: Generate DXT packages for MCP servers (Desktop Extensions)
706
+ **Why descriptions matter**: When your tools are exposed to Claude Desktop or other MCP clients, the `description` field is the primary way LLMs understand what your tool does and when to use it. A well-written description significantly improves tool selection accuracy and user experience.
834
707
 
835
- ### `--s-save-to-env <file>`
836
-
837
- Exports the current parser's configuration and parsed arguments to various file formats.
838
-
839
- ```bash
840
- # Export to .env format (default for no extension)
841
- your-cli --flag1 value1 --flag2 --s-save-to-env config.env
708
+ #### Best Practices for Tool Descriptions
842
709
 
843
- # Export to YAML format
844
- your-cli --flag1 value1 --flag2 --s-save-to-env config.yaml
710
+ **1. Start with the action** - Begin with a clear verb describing what the tool does:
845
711
 
846
- # Export to JSON format
847
- your-cli --flag1 value1 --flag2 --s-save-to-env config.json
712
+ ```typescript
713
+ // Good: Action-first, specific
714
+ description: "Analyzes text files and returns detailed statistics including word count, character count, and sentiment analysis";
848
715
 
849
- # Export to TOML format
850
- your-cli --flag1 value1 --flag2 --s-save-to-env config.toml
716
+ // Avoid: Vague or noun-heavy
717
+ description: "File analysis tool";
851
718
  ```
852
719
 
853
- **Features:**
854
- - Works at any parser level (root command or sub-commands)
855
- - Includes inherited flags from parent parsers in the chain
856
- - Comments out optional flags that are not set
857
- - Rich documentation for each flag (description, options, type, constraints)
858
- - Automatic format detection based on file extension
859
-
860
- ### `--s-with-env <file>`
861
-
862
- Loads configuration from a file and merges it with command line arguments. CLI arguments take precedence over file configuration.
863
-
864
- ```bash
865
- # Load from .env format (default for no extension)
866
- your-cli --s-with-env config.env
867
-
868
- # Load from YAML format
869
- your-cli --s-with-env config.yaml
720
+ **2. Include context and use cases** - Explain when and why to use the tool:
870
721
 
871
- # Load from JSON format
872
- your-cli --s-with-env config.json
873
-
874
- # Load from TOML format
875
- your-cli --s-with-env config.toml
722
+ ```typescript
723
+ // Good: Provides context
724
+ description: "Converts image files between formats (PNG, JPEG, WebP). Use this when you need to change image format, resize images, or optimize file sizes. Supports batch processing of multiple files.";
876
725
 
877
- # Combine with CLI arguments (CLI args override file config)
878
- your-cli --s-with-env config.yaml --verbose --output override.txt
726
+ // Avoid: No context
727
+ description: "Converts images";
879
728
  ```
880
729
 
881
- **Supported Formats:**
882
-
883
- The format is automatically detected based on the file extension:
884
-
885
- - **`.env`** (or no extension): Dotenv format with `KEY=value` pairs
886
- - **`.yaml` / `.yml`**: YAML format
887
- - **`.json` / `.jsonc`**: JSON format (metadata is ignored if present)
888
- - **`.toml` / `.tml`**: TOML format
889
-
890
- **Behavior:**
891
-
892
- - **File validation**: Checks if the file exists and can be parsed
893
- - **Type conversion**: Automatically converts values to match flag types (boolean, number, string, array)
894
- - **Enum validation**: Validates values against allowed enum options
895
- - **CLI precedence**: Command line arguments override file configuration
896
- - **Error handling**: Exits with error code 1 if file cannot be loaded or parsed
897
- - **Flag matching**: Only loads values for flags that exist in the current parser chain
730
+ **3. Mention key parameters and constraints** - Reference important inputs and limitations:
898
731
 
899
- **Example Configuration Files:**
900
-
901
- **.env format:**
902
- ```bash
903
- VERBOSE=true
904
- OUTPUT=file.txt
905
- COUNT=5
906
- TAGS=tag1,tag2,tag3
907
- ```
908
-
909
- **YAML format:**
910
- ```yaml
911
- verbose: true
912
- output: file.txt
913
- count: 5
914
- tags:
915
- - tag1
916
- - tag2
917
- - tag3
918
- ```
732
+ ```typescript
733
+ // ✅ Good: Mentions key parameters and constraints
734
+ description: "Searches through project files using regex patterns. Specify the search pattern and optionally filter by file type. Supports JavaScript, TypeScript, Python, and text files up to 10MB.";
919
735
 
920
- **JSON format:**
921
- ```json
922
- {
923
- "verbose": true,
924
- "output": "file.txt",
925
- "count": 5,
926
- "tags": ["tag1", "tag2", "tag3"]
927
- }
736
+ // ❌ Avoid: No parameter guidance
737
+ description: "Searches files";
928
738
  ```
929
739
 
930
- ### `--s-debug-print`
740
+ **4. Be specific about outputs** - Describe what the tool returns:
931
741
 
932
- Prints the complete parser configuration to a JSON file and console for debugging complex parser setups.
742
+ ```typescript
743
+ // ✅ Good: Clear output description
744
+ description: "Analyzes code complexity and returns metrics including cyclomatic complexity, lines of code, and maintainability index. Results include detailed breakdown by function and overall file scores.";
933
745
 
934
- ```bash
935
- your-cli --s-debug-print
746
+ // ❌ Avoid: Unclear output
747
+ description: "Analyzes code";
936
748
  ```
937
749
 
938
- **Output:**
939
- - Creates `ArgParser.full.json` with the complete parser structure
940
- - Shows all flags, sub-commands, handlers, and configuration
941
- - Useful for debugging complex parser hierarchies
942
- - Human-readable console output with syntax highlighting
943
-
944
- ### `--s-debug`
750
+ #### Complete Example: Well-Documented Tool
945
751
 
946
- Provides detailed runtime debugging information showing how arguments are parsed step-by-step.
947
-
948
- ```bash
949
- your-cli --flag1 value1 sub-command --flag2 value2 --s-debug
752
+ ```typescript
753
+ .addTool({
754
+ name: "analyze-repository",
755
+ description: "Analyzes a Git repository and generates comprehensive statistics including commit history, contributor activity, code quality metrics, and dependency analysis. Use this to understand project health, identify bottlenecks, or prepare reports. Supports Git repositories up to 1GB with history up to 5 years.",
756
+ flags: [
757
+ {
758
+ name: "path",
759
+ description: "Path to the Git repository root directory",
760
+ options: ["--path", "-p"],
761
+ type: "string",
762
+ mandatory: true,
763
+ },
764
+ {
765
+ name: "include-dependencies",
766
+ description: "Include analysis of package.json dependencies and security vulnerabilities",
767
+ options: ["--include-dependencies", "-d"],
768
+ type: "boolean",
769
+ flagOnly: true,
770
+ },
771
+ {
772
+ name: "output-format",
773
+ description: "Output format for the analysis report",
774
+ options: ["--output-format", "-f"],
775
+ type: "string",
776
+ choices: ["json", "markdown", "html"],
777
+ defaultValue: "json",
778
+ }
779
+ ],
780
+ handler: async (ctx) => {
781
+ // Implementation here
782
+ }
783
+ })
950
784
  ```
951
785
 
952
- **Output:**
953
- - Shows command chain identification process
954
- - Step-by-step argument parsing simulation
955
- - Final parser identification
956
- - Accumulated arguments at each level
957
- - Remaining arguments after parsing
958
- - Complete static configuration of the final parser
786
+ #### Parameter Description Guidelines
959
787
 
960
- **Useful for:**
961
- - Understanding complex command chains
962
- - Debugging argument parsing issues
963
- - Seeing how flags are inherited between parsers
964
- - Troubleshooting sub-command resolution
965
-
966
- ### Usage Notes
967
-
968
- - System flags are processed before normal argument parsing
969
- - They cause the program to exit after execution (exit code 0 for success)
970
- - Can be used with any combination of regular flags and sub-commands
971
- - Particularly useful during development and debugging
972
-
973
- ## Debugging
974
-
975
- ### Programmatic Debugging
976
-
977
- The `printAll(filePath?: string)` method is useful for debugging complex parser configurations programmatically. It recursively outputs the structure, options, flags, and handlers of a parser instance and its sub-commands.
978
-
979
- - `parser.printAll()`: Prints a colored, human-readable output to the console.
980
- - `parser.printAll('./config.json')`: Writes the configuration as a pretty-printed JSON file.
981
- - `parser.printAll('./config.log')`: Writes a plain text version to a file.
788
+ Each flag should have a clear, concise description:
982
789
 
983
790
  ```typescript
984
- import { ArgParser } from "@alcyone-labs/arg-parser";
791
+ // Good parameter descriptions
792
+ {
793
+ name: "timeout",
794
+ description: "Maximum execution time in seconds (default: 30, max: 300)",
795
+ options: ["--timeout", "-t"],
796
+ type: "number",
797
+ }
985
798
 
986
- const parser = new ArgParser({ appName: "Debug App" })
987
- .addFlags([
988
- /* ... */
989
- ])
990
- .addSubCommand(/* ... */);
799
+ {
800
+ name: "verbose",
801
+ description: "Enable detailed logging output including debug information",
802
+ options: ["--verbose", "-v"],
803
+ type: "boolean",
804
+ flagOnly: true,
805
+ }
991
806
 
992
- parser.printAll(); // Output to console
807
+ {
808
+ name: "format",
809
+ description: "Output format for results (json: structured data, csv: spreadsheet-friendly, pretty: human-readable)",
810
+ options: ["--format"],
811
+ type: "string",
812
+ choices: ["json", "csv", "pretty"],
813
+ }
993
814
  ```
994
815
 
995
- ### Runtime Debugging
816
+ #### Common Pitfalls to Avoid
996
817
 
997
- For runtime debugging, use the system flags documented above:
818
+ - **Don't be overly technical**: Avoid jargon that doesn't help with tool selection
819
+ - **Don't repeat the tool name**: The name is already visible, focus on functionality
820
+ - **Don't use generic terms**: "Process data" or "handle files" are too vague
821
+ - **Don't forget constraints**: Mention important limitations or requirements
822
+ - **Don't ignore parameter descriptions**: Each flag should have a helpful description
998
823
 
999
- - `--s-debug-print`: Export complete parser configuration
1000
- - `--s-debug`: Show step-by-step argument parsing process
1001
- - `--s-save-to-env <file>`: Export current configuration to various formats
1002
- - `--s-with-env <file>`: Load configuration from file and merge with CLI arguments
824
+ **Remember**: A good description helps the LLM choose the right tool for the task and use it correctly. Invest time in writing clear, comprehensive descriptions - it directly impacts the user experience in Claude Desktop and other MCP clients.
1003
825
 
1004
- ### `--s-enable-fuzzy`
826
+ ### Automatic MCP Server Mode (`--s-mcp-serve`)
1005
827
 
1006
- Enables fuzzy testing mode, which acts as a dry-run mode for safe testing without side effects. **No boilerplate code required** - the system automatically prevents CLI execution during fuzzy testing.
828
+ You don't need to write any server logic. Run your application with the `--s-mcp-serve` flag, and ArgParser will automatically start a compliant MCP server, exposing all tools defined with `.addTool()` and subcommands created with `.addSubCommand()` (unless `includeSubCommands: false` is set).
1007
829
 
1008
830
  ```bash
1009
- # Enable fuzzy mode for testing
1010
- your-cli --s-enable-fuzzy --input test.txt --format json
1011
- ```
1012
-
1013
- **Features:**
1014
- - **Automatic execution prevention**: No need for complex conditional logic in your CLI code
1015
- - **Zero boilerplate**: Simply export your CLI with `export default cli` and call `cli.parse()`
1016
- - Disables error handling to allow error collection
1017
- - Skips mandatory flag validation for comprehensive testing
1018
- - **Prevents handler function execution** (no side effects)
1019
- - **Logs what each handler would receive** for testing visibility
1020
- - Recursively applies to all subcommand parsers
1021
- - Safe for testing production CLIs with database operations, file modifications, or API calls
1022
-
1023
- **Example Output:**
1024
- ```
1025
- [--s-enable-fuzzy] handler() skipped for command chain: (root)
1026
- Input args: [--s-enable-fuzzy --input test.txt --format json]
1027
- Parsed args: {"input":"test.txt","format":"json"}
1028
- ```
1029
-
1030
- **Use Cases:**
1031
- - Fuzzy testing CLI argument parsing
1032
- - Validating CLI configuration without executing business logic
1033
- - Testing complex command hierarchies safely
1034
- - Automated testing of CLI interfaces
1035
-
1036
- These system flags are particularly useful when you need to debug a CLI application without modifying the source code.
1037
-
1038
- ## Fuzzy Testing
1039
-
1040
- ArgParser includes comprehensive fuzzy testing capabilities to automatically test CLI configurations and catch edge cases that manual testing might miss. The fuzzy testing utility systematically explores command paths and generates various flag combinations to ensure robustness.
831
+ # This single command starts a fully compliant MCP server
832
+ my-cli-app --s-mcp-serve
1041
833
 
1042
- ### **Quick Start**
1043
-
1044
- Test any ArgParser configuration using the built-in fuzzy testing CLI:
1045
-
1046
- ```bash
1047
- # Test an ArgParser file
1048
- bun src/fuzzy-test-cli.ts --file examples/getting-started.ts
1049
-
1050
- # Test with custom options and save results
1051
- bun src/fuzzy-test-cli.ts \
1052
- --file examples/getting-started.ts \
1053
- --output test-results.json \
1054
- --format json \
1055
- --max-depth 3 \
1056
- --random-tests 20 \
1057
- --verbose
834
+ # You can also override transports and ports using system flags
835
+ my-cli-app --s-mcp-serve --s-mcp-transport sse --s-mcp-port 3001
1058
836
  ```
1059
837
 
1060
- **Important Note**: Make sure that the `examples/getting-started.ts` file exports the parser instance using `export default` for the fuzzy testing CLI to work correctly.
838
+ ### MCP Transports
1061
839
 
1062
- ### **System Flag Integration**
1063
-
1064
- The `--s-enable-fuzzy` system flag makes any CLI fuzzy-test compatible **without any code modifications or boilerplate**:
840
+ You can define the transports directly in the .withMcp() settings, or override them via the `--s-mcp-transport(s)` flags.
1065
841
 
1066
842
  ```bash
1067
- # Enable fuzzy mode for safe testing (dry-run with no side effects)
1068
- your-cli --s-enable-fuzzy --input test.txt --format json
1069
-
1070
- # The fuzzy testing CLI automatically uses this flag
1071
- bun src/fuzzy-test-cli.ts --file your-cli.ts
1072
- ```
1073
-
1074
- **Fuzzy mode features:**
1075
- - **Zero boilerplate**: No conditional logic needed - just `export default cli` and `cli.parse()`
1076
- - **Automatic prevention**: System automatically prevents CLI execution during fuzzy testing
1077
- - **Dry-run execution**: Prevents handler function execution (no side effects)
1078
- - **Error collection**: Disables error handling to collect all parsing errors
1079
- - **Argument logging**: Shows what each handler would receive for testing visibility
1080
- - **Safe testing**: Test production CLIs with database operations, file modifications, or API calls
1081
-
1082
- ### **Testing Capabilities**
1083
-
1084
- The fuzzy tester automatically tests:
843
+ # Single transport
844
+ my-tool --s-mcp-serve --s-mcp-transport stdio
1085
845
 
1086
- - **Valid combinations**: Proper flag usage with correct types and values
1087
- - **Invalid combinations**: Wrong inputs to verify error handling
1088
- - **Random combinations**: Pseudo-random flag combinations for edge cases
1089
- - **Command paths**: All subcommand combinations up to configurable depth
1090
- - **Performance**: Execution timing for different input complexities
846
+ # Multiple transports via JSON
847
+ my-tool --s-mcp-serve --s-mcp-transports '[{"type":"stdio"},{"type":"sse","port":3001}]'
1091
848
 
1092
- ### **Programmatic Usage**
849
+ # Single transport with custom options
850
+ my-tool --s-mcp-serve --s-mcp-transport sse --s-mcp-port 3000 --s-mcp-host 0.0.0.0
1093
851
 
1094
- ```typescript
1095
- import { ArgParserFuzzyTester } from "@alcyone-labs/arg-parser/fuzzy-tester";
1096
- import { myArgParser } from "./my-cli";
1097
-
1098
- const tester = new ArgParserFuzzyTester(myArgParser, {
1099
- maxDepth: 5,
1100
- randomTestCases: 10,
1101
- includePerformance: true,
1102
- testErrorCases: true,
1103
- verbose: false,
852
+ # Multiple transports (configured via --s-mcp-serve system flag)
853
+ const cli = ArgParser.withMcp({
854
+ appName: 'multi-tool',
855
+ appCommandName: 'multi-tool',
856
+ mcp: {
857
+ serverInfo: {
858
+ name: 'multi-tool-mcp',
859
+ version: '1.0.0'
860
+ },
861
+ transports: [
862
+ // Can be a single string...
863
+ "stdio",
864
+ // or one of the other transport types supported by @modelcontextprotocol/sdk
865
+ { type: "sse", port: 3000, host: "0.0.0.0" },
866
+ { type: "websocket", port: 3001, path: "/ws" }
867
+ ]
868
+ }
1104
869
  });
1105
-
1106
- const report = await tester.runFuzzyTest();
1107
- console.log(`Success rate: ${(report.successfulTests / report.totalTests * 100).toFixed(1)}%`);
1108
870
  ```
1109
871
 
1110
- ### **Output Formats**
872
+ ### Automatic Console Safety
1111
873
 
1112
- Generate reports in multiple formats:
874
+ A major challenge in MCP is preventing `console.log` from corrupting the JSON-RPC communication over `STDOUT`. ArgParser solves this automatically.
1113
875
 
1114
- ```bash
1115
- # Human-readable console output
1116
- bun src/fuzzy-test-cli.ts --file my-cli.ts --format text
1117
-
1118
- # Machine-readable JSON
1119
- bun src/fuzzy-test-cli.ts --file my-cli.ts --format json --output results.json
1120
-
1121
- # Documentation-friendly Markdown
1122
- bun src/fuzzy-test-cli.ts --file my-cli.ts --format markdown --output report.md
1123
- ```
876
+ - **How it works**: When `--s-mcp-serve` is active, ArgParser hijacks the global `console` object.
877
+ - **What it does**: It redirects `console.log`, `.info`, `.warn`, and `.debug` to `STDERR` with a prefix, making them visible for debugging without interfering with the protocol. `console.error` is preserved on `STDERR` as expected.
878
+ - **Your benefit**: You can write `console.log` statements freely in your handlers. They will work as expected in CLI mode and be safely handled in MCP mode with **zero code changes**.
1124
879
 
1125
- For complete documentation, examples, and advanced usage patterns, see the [Fuzzy Testing Documentation](docs/fuzzy-testing.md).
880
+ ### Generating DXT Packages (`--s-build-dxt`)
1126
881
 
1127
- ### `--s-save-DXT [directory]`
1128
-
1129
- Generates Desktop Extension (DXT) packages for all MCP servers defined in your ArgParser instance. DXT files are zip archives containing a manifest.json and server files, enabling single-click installation of MCP servers in compatible applications like Claude Desktop.
882
+ A Desktop Extension (`.dxt`) is a standardized package for installing your tools into Claude Desktop. ArgParser automates this process.
1130
883
 
1131
884
  ```bash
1132
- # Generate DXT packages in current directory
1133
- your-cli --s-save-DXT
1134
-
1135
- # Generate DXT packages in specific directory
1136
- your-cli --s-save-DXT ./dxt-packages
885
+ # 1. Generate the DXT package contents into a directory
886
+ my-cli-app --s-build-dxt ./my-dxt-package
1137
887
 
1138
- # Example with multiple MCP servers
1139
- my-tool --s-save-DXT ./extensions
1140
- ```
888
+ # The output folder contains everything needed: manifest.json, entry point, etc.
889
+ # A default logo will be applied if you don't provide one.
1141
890
 
1142
- **Features:**
1143
- - **Automatic detection**: Finds all MCP servers added via `addMcpSubCommand()`
1144
- - **Multiple servers**: Generates separate DXT files for each MCP server
1145
- - **Complete tool listing**: Includes all MCP tools in the manifest
1146
- - **Proper metadata**: Uses actual server names, versions, and descriptions
1147
- - **Ready to install**: Generated DXT files work with DXT-compatible applications
891
+ # 2. (Optional) Pack the folder into a .dxt file for distribution
892
+ npx @anthropic-ai/dxt pack ./my-dxt-package
1148
893
 
1149
- **Generated Structure:**
1150
- ```
1151
- your-server.dxt (ZIP file)
1152
- ├── manifest.json # Server metadata and tool definitions
1153
- └── server/
1154
- └── index.js # Server entry point
1155
- ```
894
+ # 3. (Optional) Sign the DXT package
895
+ npx @anthropic-ai/dxt sign ./my-dxt-package.dxt
1156
896
 
1157
- **Example Output:**
1158
- ```
1159
- 🔧 Generating DXT packages for 2 MCP server(s)...
1160
- ✓ Generated: primary-server.dxt
1161
- Server: primary-server v1.0.0
1162
- Tools: 3 tool(s)
1163
- ✓ Generated: analytics-server.dxt
1164
- Server: analytics-server v2.1.0
1165
- Tools: 5 tool(s)
1166
-
1167
- ✅ DXT package generation completed!
1168
- Output directory: /path/to/dxt-packages
897
+ # Then drag & drop the .dxt file into Claude Desktop to install it, in the Settings > Extensions screen.
1169
898
  ```
1170
899
 
1171
- **Use Cases:**
1172
- - **Distribution**: Package MCP servers for easy sharing and installation
1173
- - **Development**: Create test packages during MCP server development
1174
- - **Deployment**: Generate production-ready DXT files for distribution
1175
- - **Integration**: Prepare MCP servers for Claude Desktop or other DXT-compatible applications
1176
-
1177
- ## Changelog
1178
-
1179
- ### v1.2.0 (2025-01-02)
1180
-
1181
- **🔧 Critical MCP Fixes & Improvements**
1182
-
1183
- - **Fixed MCP Output Schema Support**: Resolved the critical issue where MCP tools with output schemas failed with `"Tool has an output schema but no structured content was provided"` error
1184
- - **Enhanced Handler Context**: Added `isMcp` flag to handler context for proper MCP mode detection
1185
- - **Improved Response Format**: MCP tools now correctly return both `content` and `structuredContent` fields as required by JSON-RPC 2.0
1186
- - **Better Integration**: Handlers can reliably detect when they're being called from MCP mode vs CLI mode
1187
-
1188
- **What was broken before v1.2.0:**
1189
- - MCP servers would fail when tools had output schemas defined
1190
- - Handlers couldn't reliably detect MCP execution context
1191
- - Response format didn't comply with MCP specification for structured content
1192
-
1193
- **What works now:**
1194
- - ✅ MCP tools with output schemas work correctly
1195
- - ✅ Proper JSON-RPC 2.0 response format with both `content` and `structuredContent`
1196
- - ✅ Handler context includes `isMcp` flag for mode detection
1197
- - ✅ Full compatibility with MCP clients and the Model Context Protocol specification
1198
-
1199
- ### v1.1.0 (2024-12-XX)
1200
-
1201
- **Major Features**
1202
- - MCP (Model Context Protocol) Integration with multiple transport support
1203
- - System Flags: `--s-debug-print`, `--s-with-env`, `--s-save-to-env`, `--s-enable-fuzzy`, `--s-save-DXT`
1204
- - Environment Loading from `.env`, `.yaml`, `.json`, and `.toml` files
1205
- - Enhanced Debugging and configuration export tools
1206
-
1207
- ## API Reference
1208
-
1209
- This section provides a quick overview of the main components. See the sections above for detailed explanations and examples.
1210
-
1211
- ### **Core Classes**
900
+ ### Logo Configuration
1212
901
 
1213
- #### `ArgParserBase`
902
+ The logo will appear in Claude Desktop's Extensions settings and when users interact with your MCP tools. Note that neither ArgParser nor Anthropic packer will modify the logo, so make sure to use a reasonable size, such as 256x256 pixels or 512x512 pixels maximum. Any image type that can display in a browser is supported.
1214
903
 
1215
- Base class providing core CLI parsing functionality without MCP features. Use this for lightweight CLIs that don't need MCP server capabilities.
904
+ You can customize the logo/icon that appears in Claude Desktop for your DXT package by configuring the `logo` property in your `serverInfo`:
1216
905
 
1217
- **Constructor:**
1218
- - `new ArgParserBase(options?, initialFlags?)`: Create basic parser instance
1219
-
1220
- #### `ArgParser` (v1.1.0+)
1221
-
1222
- Main class with built-in MCP server capabilities. Extends `ArgParserBase` with MCP integration.
1223
-
1224
- **Constructors:**
1225
- - `new ArgParser(options?, initialFlags?)`: Create parser with MCP capabilities
1226
- - `ArgParser.withMcp(options?, initialFlags?)`: Factory method for MCP-enabled parser (same as constructor)
1227
- - `ArgParser.fromArgParser(parser)`: Convert existing ArgParserBase to MCP-enabled
1228
-
1229
- **MCP Methods:**
1230
- - `toMcpTools(options?)`: Generate MCP tool structures from CLI definition
1231
- - `createMcpServer(serverInfo, toolOptions?)`: Create MCP server instance
1232
- - `startMcpServer(serverInfo, toolOptions?)`: Start MCP server with stdio transport
1233
- - `startMcpServerWithTransport(serverInfo, transportType, transportOptions?, toolOptions?)`: Start with specific transport
1234
- - `startMcpServerWithMultipleTransports(serverInfo, transports, toolOptions?)`: Start with multiple transports (manual approach)
1235
- - `addMcpSubCommand(name, serverInfo, options?)`: Add MCP server sub-command with optional preset transports (recommended approach)
1236
- - `parse(args, options?)`: Async version supporting async handlers
1237
-
1238
- **MCP Types:**
1239
- - `McpTransportConfig`: Configuration for a single transport (`{ type, port?, host?, path?, sessionIdGenerator? }`)
1240
- - `McpSubCommandOptions`: Options for MCP sub-command (`{ defaultTransport?, defaultTransports?, toolOptions? }`)
1241
-
1242
- **Transport Types:**
1243
- - `"stdio"`: Standard input/output
1244
- - `"sse"`: Server-Sent Events over HTTP
1245
- - `"streamable-http"`: HTTP with streaming support
1246
-
1247
- **Example:**
1248
906
  ```typescript
1249
907
  const cli = ArgParser.withMcp({
1250
908
  appName: "My CLI",
1251
- handler: async (ctx) => ({ result: ctx.args }),
1252
- })
1253
- .addFlags([/* flags */])
1254
- .addMcpSubCommand("serve", {
1255
- name: "my-mcp-server",
1256
- version: "1.0.0",
1257
- });
1258
-
1259
- // Elegant approach: Configure default transports in addMcpSubCommand
1260
- const cli = ArgParser.withMcp({
1261
- appName: "My Tool",
1262
- handler: async (ctx) => ({ result: ctx.args }),
1263
- })
1264
- .addFlags([/* your flags */])
1265
- .addMcpSubCommand("serve", {
1266
- name: "my-server",
1267
- version: "1.0.0",
1268
- }, {
1269
- // Default multiple transports - used when no CLI flags provided
1270
- defaultTransports: [
1271
- { type: "stdio" },
1272
- { type: "sse", port: 3001 },
1273
- { type: "streamable-http", port: 3002 }
1274
- ]
909
+ appCommandName: "mycli",
910
+ mcp: {
911
+ // This will appear in Claude Desktop's Extensions settings
912
+ serverInfo: {
913
+ name: "my-mcp-server",
914
+ version: "1.0.0",
915
+ description: "My CLI as an MCP server",
916
+ logo: "./assets/my-logo.png", // Local file path
917
+ },
918
+ },
1275
919
  });
1276
-
1277
- // Usage: my-tool serve (uses all default transports)
1278
- // Usage: my-tool serve --transports '[{"type":"sse","port":4000}]' (overrides defaults)
1279
920
  ```
1280
921
 
1281
- ### Constructors
1282
-
1283
- #### `new ArgParserBase(options?, initialFlags?)`
1284
-
1285
- Constructor for creating a basic parser instance without MCP capabilities.
1286
-
1287
- #### `new ArgParser(options?, initialFlags?)`
1288
-
1289
- Constructor for creating a parser instance with MCP capabilities.
1290
-
1291
- - `options`: An object (`IArgParserParams`) configuring the parser.
1292
- - `appName?: string`: Display name.
1293
- - `appCommandName?: string`: Command name for help/errors.
1294
- - `description?: string`: Parser description.
1295
- - `handler?: (ctx: HandlerContext) => void`: Handler function for this parser.
1296
- - `subCommands?: ISubCommand[]`: Array of sub-command definitions.
1297
- - `handleErrors?: boolean`: Enable/disable default error handling (default: `true`).
1298
- - `throwForDuplicateFlags?: boolean`: Throw error for duplicate flags (default: `false`).
1299
- - `inheritParentFlags?: boolean`: Enable flag inheritance when this parser is a sub-command (default: `false`).
1300
- - `initialFlags`: Optional array of `IFlag` objects to add during initialization.
1301
-
1302
- ### `parse(args, options?)`
1303
-
1304
- Parses an array of command-line arguments.
1305
-
1306
- - `args`: `string[]` - Array of arguments (usually `process.argv.slice(2)`).
1307
- - `options`: Optional object (`IParseOptions`).
1308
- - `skipHelpHandling?: boolean`: Prevents automatic help display/exit on `--help` (default: `false`).
1309
- - `skipHandlers?: boolean`: Prevents execution of any matched command handlers (default: `false`).
1310
- - Returns: `TParsedArgs & { $commandChain?: string[] }` - An object containing the parsed arguments and optionally the `$commandChain`. Throws `ArgParserError` if `handleErrors` is `false`.
1311
-
1312
- ### `.addFlag(flag)`
922
+ If no custom logo is provided or loading fails, a default ArgParser logo is included
1313
923
 
1314
- Adds a single flag definition.
924
+ #### Supported Logo Sources
1315
925
 
1316
- - `flag`: `IFlag` - The flag object.
1317
- - Returns: `this` for chaining.
926
+ **Local File Path:**
1318
927
 
1319
- ### `.addFlags(flags)`
1320
-
1321
- Adds multiple flag definitions.
1322
-
1323
- - `flags`: `IFlag[]` - Array of flag objects.
1324
- - Returns: `this` for chaining.
1325
-
1326
- ### `.addSubCommand(subCommand)`
1327
-
1328
- Adds a sub-command definition.
1329
-
1330
- - `subCommand`: `ISubCommand` - The sub-command object.
1331
- - Returns: `this` for chaining.
1332
-
1333
- ### `.setHandler(handler)`
1334
-
1335
- Sets or overrides the handler function for this parser instance.
1336
-
1337
- - `handler`: `(ctx: HandlerContext) => void` - The handler function.
1338
- - Returns: `this` for chaining.
1339
-
1340
- ### `.getSubCommand(name)`
1341
-
1342
- Retrieves a defined sub-command by name.
1343
-
1344
- - `name`: `string` - The name of the sub-command.
1345
- - Returns: `ISubCommand | undefined` - The sub-command definition or `undefined` if not found.
1346
-
1347
- ### `.hasFlag(name)`
1348
-
1349
- Checks if a flag with the given name exists on this parser instance.
1350
-
1351
- - `name`: `string` - The name of the flag.
1352
- - Returns: `boolean`.
1353
-
1354
- ### `helpText()`
1355
-
1356
- Generates the formatted help text for this parser instance.
928
+ ```typescript
929
+ logo: "./assets/my-logo.png"; // Relative to your project
930
+ logo: "/absolute/path/to/logo.jpg"; // Absolute path
931
+ ```
1357
932
 
1358
- - Returns: `string` - The generated help text.
933
+ **HTTP/HTTPS URL:**
1359
934
 
1360
- ### `printAll(filePath?)`
935
+ ```typescript
936
+ logo: "https://example.com/logo.png"; // Downloaded automatically
937
+ logo: "https://cdn.example.com/icon.svg";
938
+ ```
1361
939
 
1362
- Recursively prints the parser configuration.
940
+ ### How DXT Generation Works
1363
941
 
1364
- - `filePath`: `string?` - Optional path to write output to file. `.json` extension saves as JSON.
942
+ When you run `--s-build-dxt`, ArgParser performs several steps to create a self-contained, autonomous package:
1365
943
 
1366
- ### Interfaces
944
+ 1. **Introspection**: It analyzes all tools defined with `.addTool()`.
945
+ 2. **Manifest Generation**: It creates a `manifest.json` file.
946
+ - Tool flags are converted into a JSON Schema for the `input_schema`.
947
+ - Flags with an `env` property (e.g., `{ name: 'apiKey', env: 'API_KEY' }`) are automatically added to the `user_config` section, prompting the user for the value upon installation and making it available as an environment variable to your tool.
948
+ 3. **Autonomous Build**: It bundles your CLI's source code and its dependencies into a single entry point (e.g., `server.js`) that can run without `node_modules`. This ensures the DXT is portable and reliable.
949
+ 4. **Packaging**: It assembles all necessary files (manifest, server bundle, logo, etc.) into the specified output directory, ready to be used by Claude Desktop or packed with `npx @anthropic-ai/dxt`.
1367
950
 
1368
- - `IFlag`: Defines the structure of a command-line flag.
1369
- - `ISubCommand`: Defines the structure of a sub-command.
1370
- - `HandlerContext`: The object passed to handler functions.
1371
- - `IParseOptions`: Options for the `parse()` method.
1372
- - `IArgParserParams`: Options for the `ArgParser` constructor.
1373
- - `ArgParserError`: Custom error class thrown on parsing failures when `handleErrors` is `false`.
951
+ ---
1374
952
 
1375
- ## Quick Reference
953
+ ## System Flags & Configuration
954
+
955
+ ArgParser includes built-in `--s-*` flags for development, debugging, and configuration. They are processed before normal arguments and will cause the program to exit after their task is complete.
956
+
957
+ | Flag | Description |
958
+ | --------------------------- | ---------------------------------------------------------------------------------------------- |
959
+ | **MCP & DXT** | |
960
+ | `--s-mcp-serve` | Starts the application in MCP server mode, exposing all tools. |
961
+ | `--s-build-dxt [dir]` | Generates a complete, autonomous DXT package for Claude Desktop. |
962
+ | `--s-mcp-transport <type>` | Overrides the MCP transport (`stdio`, `sse`, `streamable-http`). |
963
+ | `--s-mcp-transports <json>` | Overrides transports with a JSON array for multi-transport setups. |
964
+ | `--s-mcp-port <number>` | Sets the port for HTTP-based transports (`sse`, `streamable-http`). |
965
+ | `--s-mcp-host <string>` | Sets the host address for HTTP-based transports. |
966
+ | **Configuration** | |
967
+ | `--s-with-env <file>` | Loads configuration from a file (`.env`, `.json`, `.yaml`, `.toml`). CLI args take precedence. |
968
+ | `--s-save-to-env <file>` | Saves the current arguments to a configuration file, perfect for templates. |
969
+ | **Debugging** | |
970
+ | `--s-debug` | Prints a detailed, step-by-step log of the argument parsing process. |
971
+ | `--s-debug-print` | Exports the entire parser configuration to a JSON file for inspection. |
972
+ | `--s-enable-fuzzy` | Enables fuzzy testing mode—a dry run that parses args but skips handler execution. |
1376
973
 
1377
- ### **Basic CLI Setup**
1378
- ```typescript
1379
- import { ArgParser } from "@alcyone-labs/arg-parser";
974
+ ---
1380
975
 
1381
- const cli = new ArgParser({
1382
- appName: "My Tool",
1383
- appCommandName: "my-tool",
1384
- handler: async (ctx) => ({ result: ctx.args }),
1385
- })
1386
- .addFlags([
1387
- { name: "input", options: ["--input", "-i"], type: "string", mandatory: true },
1388
- { name: "verbose", options: ["--verbose", "-v"], type: "boolean", flagOnly: true },
1389
- ])
1390
- .addSubCommand({
1391
- name: "process",
1392
- description: "Process data",
1393
- handler: async (ctx) => ({ processed: true }),
1394
- parser: new ArgParser({}, [
1395
- { name: "format", options: ["--format"], type: "string", enum: ["json", "xml"] },
1396
- ]),
1397
- });
1398
- ```
976
+ ## Changelog
1399
977
 
1400
- ### **MCP Integration**
1401
- ```typescript
1402
- import { ArgParser } from "@alcyone-labs/arg-parser";
978
+ ### v2.1.0
1403
979
 
1404
- const mcpCli = ArgParser.withMcp({ /* same options */ })
1405
- .addFlags([/* same flags */])
1406
- .addMcpSubCommand("serve", {
1407
- name: "my-mcp-server",
1408
- version: "1.0.0",
1409
- });
980
+ **Feat**
1410
981
 
1411
- // CLI: my-tool --input data.txt process --format json
1412
- // MCP: my-tool serve --transport sse --port 3001
1413
- ```
982
+ - IFlag function-based `type` handling must now define the type it returns, this unlocks nice features such as providing nicer Intellisense, `output schemas` support and makes it easier to upgrade to Zod V4
983
+ - Add support for MCP output_schema field for clients that support it, CLI isn't impacted by it, this helps a lot the interactivity, self-documentation, and improves the API guarantees
1414
984
 
1415
- ### **MCP Preset Transport Configuration**
1416
- Configure default transports that will be used when no CLI transport flags are provided:
985
+ **Fixes and changes**
986
+ - Fix missing missing types
987
+ - Improved MCP version compliance
1417
988
 
1418
- ```typescript
1419
- import { ArgParser, McpTransportConfig } from "@alcyone-labs/arg-parser";
989
+ ### v2.0.0
1420
990
 
1421
- // Single preset transport
1422
- const cliWithPreset = ArgParser.withMcp({
1423
- appName: "My Tool",
1424
- handler: async (ctx) => ({ result: ctx.args }),
1425
- })
1426
- .addMcpSubCommand("serve", {
1427
- name: "my-server",
1428
- version: "1.0.0",
1429
- }, {
1430
- defaultTransport: {
1431
- type: "sse",
1432
- port: 3001,
1433
- host: "0.0.0.0"
1434
- }
1435
- });
991
+ - **Unified Tool Architecture**: Introduced `.addTool()` to define CLI subcommands and MCP tools in a single declaration.
992
+ - **Environment Variables Support**: The `env` property on any IFlag now automatically pull value from the `process.env[${ENV}]` key and generates `user_config` entries in the DXT manifest and fills the flag value to the ENV value if found (process.env).
993
+ - **Enhanced DXT Generation**: The `env` property on flags now automatically generates `user_config` entries in the DXT manifest.
994
+ - **Automatic Console Safety**: Console output is automatically and safely redirected in MCP mode to prevent protocol contamination.
995
+ - **Breaking Changes**: The `addMcpSubCommand()` and separate `addSubCommand()` for MCP tools are deprecated in favor of `addTool()` and `--s-mcp-serve`.
1436
996
 
1437
- // Multiple preset transports
1438
- const cliWithMultiplePresets = ArgParser.withMcp({
1439
- appName: "Multi-Transport Tool",
1440
- handler: async (ctx) => ({ result: ctx.args }),
1441
- })
1442
- .addMcpSubCommand("serve", {
1443
- name: "multi-server",
1444
- version: "1.0.0",
1445
- }, {
1446
- defaultTransports: [
1447
- { type: "stdio" },
1448
- { type: "sse", port: 3001 },
1449
- { type: "streamable-http", port: 3002, path: "/api/mcp" }
1450
- ],
1451
- toolOptions: {
1452
- includeSubCommands: true
1453
- }
1454
- });
997
+ ### v1.3.0
1455
998
 
1456
- // CLI flags always take precedence over presets
1457
- // my-tool serve -> Uses preset transports
1458
- // my-tool serve --transport sse -> Overrides preset with CLI flags
1459
- ```
999
+ - **Plugin System & Architecture**: Refactored to a dependency-injection model, making the core library dependency-free. Optional plugins for TOML/YAML.
1000
+ - **Global Console Replacement**: Implemented the first version of automatic console suppression for MCP compliance.
1001
+ - **Autonomous Build Improvements**: Significantly reduced DXT bundle size and removed dynamic `require` issues.
1460
1002
 
1461
- ### **System Flags**
1462
- ```bash
1463
- # Debug parsing
1464
- my-tool --s-debug --input data.txt process
1003
+ ### v1.2.0
1465
1004
 
1466
- # Load configuration
1467
- my-tool --s-with-env config.yaml --input override.txt
1005
+ - **Critical MCP Fixes**: Resolved issues where MCP tools with output schemas would fail. Ensured correct JSON-RPC 2.0 response formatting.
1006
+ - **Enhanced Handler Context**: Added `isMcp` flag to the handler context for more reliable mode detection.
1468
1007
 
1469
- # Save configuration
1470
- my-tool --input data.txt --s-save-to-env template.yaml
1471
- ```
1008
+ ### v1.1.0
1472
1009
 
1473
- ### **Multiple MCP Transports**
1474
- ```bash
1475
- # Single transport
1476
- my-tool serve --transport sse --port 3001
1477
-
1478
- # Multiple transports
1479
- my-tool serve --transports '[
1480
- {"type":"stdio"},
1481
- {"type":"sse","port":3001},
1482
- {"type":"streamable-http","port":3002}
1483
- ]'
1484
- ```
1010
+ - **Major Features**: First release with MCP Integration, System Flags (`--s-debug`, `--s-with-env`, etc.), and environment loading from files.
1485
1011
 
1486
1012
  ---
1487
1013
 
1488
- **📖 For complete examples and tutorials, see the [`examples/`](./examples/) directory.**
1489
-
1490
- ---
1491
-
1492
1014
  ## Backlog
1493
1015
 
1494
1016
  - [x] Publish as an open-source library
1495
1017
  - [x] Make ArgParser compatible with MCP out-of-the-box
1496
- - [x] Rename --LIB-* flags to --s-*
1018
+ - [x] Rename --LIB-\* flags to --s-\*
1497
1019
  - [x] Make it possible to pass a `--s-save-to-env /path/to/file` parameter that saves all the parameters to a file (works with Bash-style .env, JSON, YAML, TOML)
1498
1020
  - [x] Make it possible to pass a `--s-with-env /path/to/file` parameter that loads all the parameters from a file (works with Bash-style .env, JSON, YAML, TOML)
1499
1021
  - [ ] Add System flags to args.systemArgs
@@ -1506,4 +1028,3 @@ my-tool serve --transports '[
1506
1028
  ### (known) Bugs / DX improvement points
1507
1029
 
1508
1030
  - [ ] When a flag with `flagOnly: false` is going to consume a value that appears like a valid flag from the set, raise the appropriate warning
1509
- - [ ] When a flag with `allowMultiple: false` and `flagOnly: true` is passed multiple times (regardless of the options, for example "-1" and later "--one", both being valid), raise the correct error