@alcyone-labs/arg-parser 2.5.0 → 2.7.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 +376 -95
- package/dist/core/ArgParser.d.ts +60 -0
- package/dist/core/ArgParser.d.ts.map +1 -1
- package/dist/core/ArgParserBase.d.ts +20 -0
- package/dist/core/ArgParserBase.d.ts.map +1 -1
- package/dist/core/FlagManager.d.ts.map +1 -1
- package/dist/core/dxt-path-resolver.d.ts +100 -0
- package/dist/core/dxt-path-resolver.d.ts.map +1 -0
- package/dist/core/log-path-utils.d.ts.map +1 -1
- package/dist/core/types.d.ts +69 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/dxt/DxtGenerator.d.ts +6 -0
- package/dist/dxt/DxtGenerator.d.ts.map +1 -1
- package/dist/index.cjs +849 -203
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.min.mjs +6080 -5615
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +849 -203
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ A modern, type-safe command line argument parser with built-in MCP (Model Contex
|
|
|
27
27
|
- [Async Custom Parser Support](#async-custom-parser-support)
|
|
28
28
|
- [Zod Schema Flags (Structured JSON Validation)](#zod-schema-flags-structured-json-validation)
|
|
29
29
|
- [Type Conversion Examples](#type-conversion-examples)
|
|
30
|
+
- [DXT Package User Configuration & Path Handling](#dxt-package-user-configuration--path-handling)
|
|
30
31
|
- [Hierarchical CLIs (Sub-Commands)](#hierarchical-clis-sub-commands)
|
|
31
32
|
- [MCP Exposure Control](#mcp-exposure-control)
|
|
32
33
|
- [Flag Inheritance (`inheritParentFlags`)](#flag-inheritance-inheritparentflags)
|
|
@@ -44,6 +45,9 @@ A modern, type-safe command line argument parser with built-in MCP (Model Contex
|
|
|
44
45
|
- [Common Pitfalls to Avoid](#common-pitfalls-to-avoid)
|
|
45
46
|
- [Automatic MCP Server Mode (`--s-mcp-serve`)](#automatic-mcp-server-mode---s-mcp-serve)
|
|
46
47
|
- [MCP Transports](#mcp-transports)
|
|
48
|
+
- [Adding custom HTTP routes (e.g., /health)](#adding-custom-http-routes-eg-health)
|
|
49
|
+
- [CORS and Authentication for streamable-http](#cors-and-authentication-for-streamable-http)
|
|
50
|
+
- [Multiple transports and improved logging](#multiple-transports-and-improved-logging)
|
|
47
51
|
- [MCP Logging Configuration](#mcp-logging-configuration)
|
|
48
52
|
- [Enhanced Logging (Recommended)](#enhanced-logging-recommended)
|
|
49
53
|
- [Simple Logging Configuration](#simple-logging-configuration)
|
|
@@ -70,6 +74,8 @@ A modern, type-safe command line argument parser with built-in MCP (Model Contex
|
|
|
70
74
|
- [Typical Errors](#typical-errors)
|
|
71
75
|
- [System Flags & Configuration](#system-flags--configuration)
|
|
72
76
|
- [Changelog](#changelog)
|
|
77
|
+
- [v2.7.0](#v270)
|
|
78
|
+
- [v2.6.0](#v260)
|
|
73
79
|
- [v2.5.0](#v250)
|
|
74
80
|
- [v2.4.2](#v242)
|
|
75
81
|
- [v2.4.1](#v241)
|
|
@@ -86,70 +92,6 @@ A modern, type-safe command line argument parser with built-in MCP (Model Contex
|
|
|
86
92
|
- [Backlog](#backlog)
|
|
87
93
|
- [(known) Bugs / DX improvement points](#known-bugs--dx-improvement-points)
|
|
88
94
|
|
|
89
|
-
- [Features Overview](#features-overview)
|
|
90
|
-
- [Installation](#installation)
|
|
91
|
-
- [Quick Start: The Unified `addTool` API](#quick-start-the-unified-addtool-api)
|
|
92
|
-
- [How to Run It](#how-to-run-it)
|
|
93
|
-
- [Setting Up System-Wide CLI Access](#setting-up-system-wide-cli-access)
|
|
94
|
-
- [Parsing Command-Line Arguments](#parsing-command-line-arguments)
|
|
95
|
-
- [Automatic Argument Detection](#automatic-argument-detection)
|
|
96
|
-
- [Cannonical Usage Pattern](#cannonical-usage-pattern)
|
|
97
|
-
- [Top-level await](#top-level-await)
|
|
98
|
-
- [Promise-based parsing](#promise-based-parsing)
|
|
99
|
-
- [Migrating from v1.x to the v2.0 `addTool` API](#migrating-from-v1x-to-the-v20-addtool-api)
|
|
100
|
-
- [Before v2.0: Separate Definitions](#before-v20-separate-definitions)
|
|
101
|
-
- [After v2.0: The Unified `addTool()` Method](#after-v20-the-unified-addtool-method)
|
|
102
|
-
- [Core Concepts](#core-concepts)
|
|
103
|
-
- [Defining Flags](#defining-flags)
|
|
104
|
-
- [Type Handling and Validation](#type-handling-and-validation)
|
|
105
|
-
- [Supported Type Formats](#supported-type-formats)
|
|
106
|
-
- [Runtime Type Validation](#runtime-type-validation)
|
|
107
|
-
- [Automatic Type Processing](#automatic-type-processing)
|
|
108
|
-
- [Async Custom Parser Support](#async-custom-parser-support)
|
|
109
|
-
- [Zod Schema Flags (Structured JSON Validation)](#zod-schema-flags-structured-json-validation)
|
|
110
|
-
- [Type Conversion Examples](#type-conversion-examples)
|
|
111
|
-
- [Hierarchical CLIs (Sub-Commands)](#hierarchical-clis-sub-commands)
|
|
112
|
-
- [MCP Exposure Control](#mcp-exposure-control)
|
|
113
|
-
- [Flag Inheritance (`inheritParentFlags`)](#flag-inheritance-inheritparentflags)
|
|
114
|
-
- [MCP & Claude Desktop Integration](#mcp--claude-desktop-integration)
|
|
115
|
-
- [Output Schema Support](#output-schema-support)
|
|
116
|
-
- [Basic Usage](#basic-usage)
|
|
117
|
-
- [Predefined Schema Patterns](#predefined-schema-patterns)
|
|
118
|
-
- [Custom Zod Schemas](#custom-zod-schemas)
|
|
119
|
-
- [MCP Version Compatibility](#mcp-version-compatibility)
|
|
120
|
-
- [Automatic Error Handling](#automatic-error-handling)
|
|
121
|
-
- [Writing Effective MCP Tool Descriptions](#writing-effective-mcp-tool-descriptions)
|
|
122
|
-
- [Best Practices for Tool Descriptions](#best-practices-for-tool-descriptions)
|
|
123
|
-
- [Complete Example: Well-Documented Tool](#complete-example-well-documented-tool)
|
|
124
|
-
- [Parameter Description Guidelines](#parameter-description-guidelines)
|
|
125
|
-
- [Common Pitfalls to Avoid](#common-pitfalls-to-avoid)
|
|
126
|
-
- [Automatic MCP Server Mode (`--s-mcp-serve`)](#automatic-mcp-server-mode---s-mcp-serve)
|
|
127
|
-
- [MCP Transports](#mcp-transports)
|
|
128
|
-
- [MCP Log Path Configuration](#mcp-log-path-configuration)
|
|
129
|
-
- [MCP Resources - Real-Time Data Feeds](#mcp-resources---real-time-data-feeds) ⭐
|
|
130
|
-
- [Automatic Console Safety](#automatic-console-safety)
|
|
131
|
-
- [Generating DXT Packages (`--s-build-dxt`)](#generating-dxt-packages---s-build-dxt)
|
|
132
|
-
- [Logo Configuration](#logo-configuration)
|
|
133
|
-
- [Supported Logo Sources](#supported-logo-sources)
|
|
134
|
-
- [How DXT Generation Works](#how-dxt-generation-works)
|
|
135
|
-
- [DXT Bundling Strategies](#dxt-bundling-strategies)
|
|
136
|
-
- [Standard Approach (Recommended for Most Projects)](#standard-approach-recommended-for-most-projects)
|
|
137
|
-
- [Native Dependencies Approach](#native-dependencies-approach)
|
|
138
|
-
- [Typical Errors](#typical-errors)
|
|
139
|
-
- [System Flags & Configuration](#system-flags--configuration)
|
|
140
|
-
- [Changelog](#changelog)
|
|
141
|
-
- [v2.3.0](#v230)
|
|
142
|
-
- [v2.2.1](#v221)
|
|
143
|
-
- [v2.2.0](#v220)
|
|
144
|
-
- [v2.1.1](#v211)
|
|
145
|
-
- [v2.1.0](#v210)
|
|
146
|
-
- [v2.0.0](#v200)
|
|
147
|
-
- [v1.3.0](#v130)
|
|
148
|
-
- [v1.2.0](#v120)
|
|
149
|
-
- [v1.1.0](#v110)
|
|
150
|
-
- [Backlog](#backlog)
|
|
151
|
-
- [(known) Bugs / DX improvement points](#known-bugs--dx-improvement-points)
|
|
152
|
-
|
|
153
95
|
## Features Overview
|
|
154
96
|
|
|
155
97
|
- **Unified Tool Architecture**: Define tools once with `addTool()` and they automatically function as both CLI subcommands and MCP tools.
|
|
@@ -399,9 +341,9 @@ yarn unlink
|
|
|
399
341
|
|
|
400
342
|
ArgParser's `parse()` method is async and automatically handles both synchronous and asynchronous handlers:
|
|
401
343
|
|
|
402
|
-
###
|
|
344
|
+
### Auto-Execution versus Import: No More Boilerplate
|
|
403
345
|
|
|
404
|
-
|
|
346
|
+
ArgParser now provides auto-execution ability that eliminates the need for boilerplate code to check if your script is being run directly vs. imported. This enables use cases such as programmatically loading the CLI and scanning for tools or testing it from another script via the --s-enable-fuzzy flag or your own script.
|
|
405
347
|
|
|
406
348
|
```typescript
|
|
407
349
|
const cli = ArgParser.withMcp({
|
|
@@ -410,32 +352,27 @@ const cli = ArgParser.withMcp({
|
|
|
410
352
|
handler: async (ctx) => ({ success: true, data: ctx.args }),
|
|
411
353
|
});
|
|
412
354
|
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const result = await cli.parse(); // No arguments needed!
|
|
418
|
-
console.log("Success:", result);
|
|
419
|
-
} catch (error) {
|
|
420
|
-
console.error("Error:", error.message);
|
|
421
|
-
process.exit(1);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
```
|
|
355
|
+
// Now, this will NOT automatically execute the parser if the script is imported, but will execute if called directly:
|
|
356
|
+
await cli.parse(undefined, {
|
|
357
|
+
importMetaUrl: import.meta.url
|
|
358
|
+
}).catch(handleError);
|
|
425
359
|
|
|
426
|
-
**How it works:**
|
|
427
360
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
361
|
+
// Or, using the manual APIs:
|
|
362
|
+
await cli.parseIfExecutedDirectly(import.meta.url).catch((error) => {
|
|
363
|
+
console.error("Fatal error:", error instanceof Error ? error.message : String(error));
|
|
364
|
+
process.exit(1);
|
|
365
|
+
});
|
|
366
|
+
```
|
|
433
367
|
|
|
434
|
-
**
|
|
368
|
+
**Replaces previously confusing patterns:**
|
|
435
369
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
370
|
+
```typescript
|
|
371
|
+
// Brittle and breaks in sandboxes
|
|
372
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
373
|
+
await cli.parse().catch(handleError);
|
|
374
|
+
}
|
|
375
|
+
```
|
|
439
376
|
|
|
440
377
|
### Cannonical Usage Pattern
|
|
441
378
|
|
|
@@ -609,7 +546,14 @@ Flags are defined using the `IFlag` interface within the `flags` array of a tool
|
|
|
609
546
|
interface IFlag {
|
|
610
547
|
name: string; // Internal name (e.g., 'verbose')
|
|
611
548
|
options: string[]; // Command-line options (e.g., ['--verbose', '-v'])
|
|
612
|
-
type:
|
|
549
|
+
type:
|
|
550
|
+
| "string"
|
|
551
|
+
| "number"
|
|
552
|
+
| "boolean"
|
|
553
|
+
| "array"
|
|
554
|
+
| "object"
|
|
555
|
+
| Function
|
|
556
|
+
| ZodSchema;
|
|
613
557
|
description?: string; // Help text
|
|
614
558
|
mandatory?: boolean | ((args: any) => boolean); // Whether the flag is required
|
|
615
559
|
defaultValue?: any; // Default value if not provided
|
|
@@ -618,9 +562,153 @@ interface IFlag {
|
|
|
618
562
|
validate?: (value: any, parsedArgs?: any) => boolean | string | void; // Custom validation function
|
|
619
563
|
allowMultiple?: boolean; // Allow the flag to be provided multiple times
|
|
620
564
|
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)
|
|
565
|
+
dxtOptions?: DxtOptions; // Customizes how this flag appears in DXT package user_config
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
interface DxtOptions {
|
|
569
|
+
type?: "string" | "directory" | "file" | "boolean" | "number"; // UI input type in Claude Desktop
|
|
570
|
+
title?: string; // Display name in Claude Desktop (defaults to formatted flag name)
|
|
571
|
+
sensitive?: boolean; // Whether to hide the value in UI (defaults to true for security)
|
|
572
|
+
default?: any; // Default value for the user_config entry
|
|
573
|
+
min?: number; // Minimum value (for number types)
|
|
574
|
+
max?: number; // Maximum value (for number types)
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### DXT Package User Configuration & Path Handling
|
|
579
|
+
|
|
580
|
+
ArgParser v2.5.0 introduces comprehensive DXT (Desktop Extension Toolkit) support with rich user interfaces, automatic path resolution, and context-aware development tools.
|
|
581
|
+
|
|
582
|
+
#### Enhanced dxtOptions
|
|
583
|
+
|
|
584
|
+
When generating DXT packages with `--s-build-dxt`, you can create rich user configuration interfaces using `dxtOptions`:
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
import { ArgParser, DxtPathResolver } from "@alcyone-labs/arg-parser";
|
|
588
|
+
|
|
589
|
+
const parser = new ArgParser()
|
|
590
|
+
.withMcp({
|
|
591
|
+
name: "file-processor",
|
|
592
|
+
version: "1.0.0",
|
|
593
|
+
logPath: "${HOME}/logs/file-processor.log", // DXT variables supported!
|
|
594
|
+
})
|
|
595
|
+
.addFlag({
|
|
596
|
+
name: "input-file",
|
|
597
|
+
description: "File to process",
|
|
598
|
+
type: "string",
|
|
599
|
+
mandatory: true,
|
|
600
|
+
dxtOptions: {
|
|
601
|
+
type: "file",
|
|
602
|
+
title: "Select Input File",
|
|
603
|
+
},
|
|
604
|
+
})
|
|
605
|
+
.addFlag({
|
|
606
|
+
name: "output-dir",
|
|
607
|
+
description: "Output directory for processed files",
|
|
608
|
+
type: "string",
|
|
609
|
+
dxtOptions: {
|
|
610
|
+
type: "directory",
|
|
611
|
+
localDefault: "${DOCUMENTS}/processed-files", // Smart defaults with DXT variables
|
|
612
|
+
title: "Output Directory",
|
|
613
|
+
},
|
|
614
|
+
})
|
|
615
|
+
.addFlag({
|
|
616
|
+
name: "api-key",
|
|
617
|
+
description: "API authentication key",
|
|
618
|
+
type: "string",
|
|
619
|
+
env: "API_KEY",
|
|
620
|
+
dxtOptions: {
|
|
621
|
+
type: "string",
|
|
622
|
+
sensitive: true, // Excluded from DXT manifest for security
|
|
623
|
+
title: "API Key",
|
|
624
|
+
},
|
|
625
|
+
})
|
|
626
|
+
.addFlag({
|
|
627
|
+
name: "quality",
|
|
628
|
+
description: "Processing quality (1-100)",
|
|
629
|
+
type: "number",
|
|
630
|
+
dxtOptions: {
|
|
631
|
+
type: "number",
|
|
632
|
+
min: 1,
|
|
633
|
+
max: 100,
|
|
634
|
+
localDefault: 85,
|
|
635
|
+
title: "Quality (%)",
|
|
636
|
+
},
|
|
637
|
+
})
|
|
638
|
+
.addFlag({
|
|
639
|
+
name: "parallel",
|
|
640
|
+
description: "Enable parallel processing",
|
|
641
|
+
type: "boolean",
|
|
642
|
+
dxtOptions: {
|
|
643
|
+
type: "boolean",
|
|
644
|
+
localDefault: true,
|
|
645
|
+
title: "Parallel Processing",
|
|
646
|
+
},
|
|
647
|
+
});
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
#### DXT Variables & Path Resolution
|
|
651
|
+
|
|
652
|
+
ArgParser automatically resolves paths based on your runtime environment:
|
|
653
|
+
|
|
654
|
+
```typescript
|
|
655
|
+
// DXT variables work everywhere - in flags, MCP config, and code
|
|
656
|
+
const logPath = "${HOME}/logs/app.log";
|
|
657
|
+
const configPath = "${DOCUMENTS}/myapp/config.json";
|
|
658
|
+
const resourcePath = "${__dirname}/templates/default.hbs";
|
|
659
|
+
|
|
660
|
+
// Helper functions for common patterns
|
|
661
|
+
const userDataPath = DxtPathResolver.createUserDataPath("cache.db");
|
|
662
|
+
const tempPath = DxtPathResolver.createTempPath("processing.tmp");
|
|
663
|
+
const configPath = DxtPathResolver.createConfigPath("settings.json");
|
|
664
|
+
|
|
665
|
+
// Context detection
|
|
666
|
+
const context = DxtPathResolver.detectContext();
|
|
667
|
+
if (context.isDxt) {
|
|
668
|
+
console.log("Running in DXT environment");
|
|
669
|
+
} else {
|
|
670
|
+
console.log("Running in development");
|
|
621
671
|
}
|
|
622
672
|
```
|
|
623
673
|
|
|
674
|
+
**Supported DXT Variables:**
|
|
675
|
+
|
|
676
|
+
- `${HOME}` - User's home directory
|
|
677
|
+
- `${DOCUMENTS}` - Documents folder
|
|
678
|
+
- `${DOWNLOADS}` - Downloads folder
|
|
679
|
+
- `${DESKTOP}` - Desktop folder
|
|
680
|
+
- `${__dirname}` - Entry point directory (DXT package root in DXT)
|
|
681
|
+
- `${pathSeparator}` - Platform-specific path separator
|
|
682
|
+
- `${DXT_DIR}` - DXT package directory (DXT only)
|
|
683
|
+
- `${EXTENSION_DIR}` - Extension root directory (DXT only)
|
|
684
|
+
|
|
685
|
+
#### dxtOptions Properties
|
|
686
|
+
|
|
687
|
+
| Property | Type | Description |
|
|
688
|
+
| -------------- | ------------------------------------------------------------ | ------------------------------------------------ |
|
|
689
|
+
| `type` | `'string' \| 'file' \| 'directory' \| 'boolean' \| 'number'` | UI component type |
|
|
690
|
+
| `sensitive` | `boolean` | Mark as sensitive (excluded from manifest) |
|
|
691
|
+
| `localDefault` | `string \| number \| boolean` | Default for development (supports DXT variables) |
|
|
692
|
+
| `multiple` | `boolean` | Allow multiple values |
|
|
693
|
+
| `min` / `max` | `number` | Validation constraints |
|
|
694
|
+
| `title` | `string` | Custom display name |
|
|
695
|
+
|
|
696
|
+
#### Security & Best Practices
|
|
697
|
+
|
|
698
|
+
- **Sensitive Data**: Use `sensitive: true` for passwords, API keys, tokens
|
|
699
|
+
- **Smart Defaults**: Use DXT variables in `localDefault` for portable paths
|
|
700
|
+
- **Type Safety**: Match `dxtOptions.type` with flag `type` for validation
|
|
701
|
+
- **Cross-Platform**: Use `${pathSeparator}` for platform-independent paths
|
|
702
|
+
|
|
703
|
+
#### Comprehensive Documentation
|
|
704
|
+
|
|
705
|
+
For detailed guides and examples:
|
|
706
|
+
|
|
707
|
+
- **[DXT Path Handling Guide](./docs/DXT_PATH_HANDLING.md)** - Complete path resolution guide
|
|
708
|
+
- **[dxtOptions API Documentation](./docs/DXT_OPTIONS_API.md)** - Full API reference with examples
|
|
709
|
+
- **[DXT Migration Guide](./docs/DXT_MIGRATION.md)** - Migrate existing applications
|
|
710
|
+
- **[DXT Practical Examples](./docs/DXT_EXAMPLES.md)** - Real-world usage patterns
|
|
711
|
+
|
|
624
712
|
### Type Handling and Validation
|
|
625
713
|
|
|
626
714
|
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.
|
|
@@ -1207,6 +1295,14 @@ my-tool --s-mcp-serve --s-mcp-transports '[{"type":"stdio"},{"type":"sse","port"
|
|
|
1207
1295
|
# Single transport with custom options
|
|
1208
1296
|
my-tool --s-mcp-serve --s-mcp-transport sse --s-mcp-port 3000 --s-mcp-host 0.0.0.0
|
|
1209
1297
|
|
|
1298
|
+
# Streamable HTTP CORS/auth via CLI flags (JSON strings)
|
|
1299
|
+
my-tool --s-mcp-serve \
|
|
1300
|
+
--s-mcp-transport streamable-http \
|
|
1301
|
+
--s-mcp-port 3002 --s-mcp-path /api/mcp \
|
|
1302
|
+
--s-mcp-cors '{"origins":["http://localhost:5173"],"credentials":true,"methods":["GET","POST","OPTIONS"],"maxAge":600}' \
|
|
1303
|
+
--s-mcp-auth '{"required":true,"scheme":"jwt","jwt":{"algorithms":["HS256"],"secret":"$MY_JWT_SECRET"},"publicPaths":["/health"]}'
|
|
1304
|
+
|
|
1305
|
+
|
|
1210
1306
|
# Custom log path via CLI flag (logs to specified file instead of ./logs/mcp.log)
|
|
1211
1307
|
my-tool --s-mcp-serve --s-mcp-log-path /var/log/my-mcp-server.log
|
|
1212
1308
|
|
|
@@ -1214,6 +1310,130 @@ my-tool --s-mcp-serve --s-mcp-log-path /var/log/my-mcp-server.log
|
|
|
1214
1310
|
const parser = ArgParser.withMcp({
|
|
1215
1311
|
mcp: {
|
|
1216
1312
|
serverInfo: { name: 'my-tool', version: '1.0.0' },
|
|
1313
|
+
|
|
1314
|
+
```
|
|
1315
|
+
|
|
1316
|
+
### CORS and Authentication for streamable-http
|
|
1317
|
+
|
|
1318
|
+
CORS is often required when connecting a Web UI to an MCP server over HTTP.
|
|
1319
|
+
|
|
1320
|
+
- Programmatic transport config:
|
|
1321
|
+
|
|
1322
|
+
```ts
|
|
1323
|
+
import type { McpTransportConfig } from "@alcyone-labs/arg-parser";
|
|
1324
|
+
|
|
1325
|
+
const defaultTransports: McpTransportConfig[] = [{
|
|
1326
|
+
type: "streamable-http",
|
|
1327
|
+
port: 3002,
|
|
1328
|
+
path: "/api/mcp",
|
|
1329
|
+
cors: {
|
|
1330
|
+
origins: ["http://localhost:5173", /^https?:\/\/example\.com$/],
|
|
1331
|
+
methods: ["GET","POST","OPTIONS"],
|
|
1332
|
+
headers: ["Content-Type","Authorization","MCP-Session-Id"],
|
|
1333
|
+
exposedHeaders: ["MCP-Session-Id"],
|
|
1334
|
+
credentials: true,
|
|
1335
|
+
maxAge: 600,
|
|
1336
|
+
},
|
|
1337
|
+
auth: {
|
|
1338
|
+
required: true,
|
|
1339
|
+
scheme: "jwt", // or "bearer"
|
|
1340
|
+
// Bearer allowlist:
|
|
1341
|
+
// allowedTokens: ["token1","token2"],
|
|
1342
|
+
// JWT verification (HS256):
|
|
1343
|
+
// jwt: { algorithms: ["HS256"], secret: process.env.JWT_SECRET },
|
|
1344
|
+
// JWT verification (RS256 with static public key):
|
|
1345
|
+
// jwt: { algorithms: ["RS256"], publicKey: process.env.RS256_PUBLIC_KEY },
|
|
1346
|
+
// JWT verification (RS256 with dynamic JWKS):
|
|
1347
|
+
// jwt: { algorithms: ["RS256"], getPublicKey: async (header)=>{ /* fetch JWKS and return PEM */ } },
|
|
1348
|
+
publicPaths: ["/health"],
|
|
1349
|
+
protectedPaths: undefined, // if set, only listed paths require auth
|
|
1350
|
+
// Optional custom validator to add extra checks
|
|
1351
|
+
validator: async (req, token) => true,
|
|
1352
|
+
},
|
|
1353
|
+
}];
|
|
1354
|
+
```
|
|
1355
|
+
|
|
1356
|
+
- CLI flags (JSON strings):
|
|
1357
|
+
|
|
1358
|
+
```bash
|
|
1359
|
+
my-tool --s-mcp-serve \
|
|
1360
|
+
--s-mcp-transport streamable-http \
|
|
1361
|
+
--s-mcp-port 3002 --s-mcp-path /api/mcp \
|
|
1362
|
+
--s-mcp-cors '{"origins":["http://localhost:5173"],"credentials":true,"methods":["GET","POST","OPTIONS"],"maxAge":600}' \
|
|
1363
|
+
--s-mcp-auth '{"required":true,"scheme":"jwt","jwt":{"algorithms":["HS256"],"secret":"'$JWT_SECRET'"},"publicPaths":["/health"]}'
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
- Express hook for custom routes:
|
|
1367
|
+
|
|
1368
|
+
```ts
|
|
1369
|
+
httpServer: {
|
|
1370
|
+
configureExpress: (app) => {
|
|
1371
|
+
app.get("/health", (_req, res) => res.json({ ok: true }));
|
|
1372
|
+
},
|
|
1373
|
+
}
|
|
1374
|
+
```
|
|
1375
|
+
|
|
1376
|
+
See examples:
|
|
1377
|
+
- examples/streamable-http/secure-mcp.ts (HS256)
|
|
1378
|
+
- examples/streamable-http/rs256-mcp.ts (RS256)
|
|
1379
|
+
- examples/streamable-http/jwks-mcp.ts (JWKS)
|
|
1380
|
+
- examples/streamable-http/bearer-mcp.ts (Bearer)
|
|
1381
|
+
- examples/streamable-http/productized-mcp.ts (token + session usage)
|
|
1382
|
+
|
|
1383
|
+
#### TypeScript types
|
|
1384
|
+
|
|
1385
|
+
- CorsOptions
|
|
1386
|
+
|
|
1387
|
+
```ts
|
|
1388
|
+
export type CorsOptions = {
|
|
1389
|
+
origins?: "*" | string | RegExp | Array<string | RegExp>;
|
|
1390
|
+
methods?: string[];
|
|
1391
|
+
headers?: string[];
|
|
1392
|
+
exposedHeaders?: string[];
|
|
1393
|
+
credentials?: boolean;
|
|
1394
|
+
maxAge?: number;
|
|
1395
|
+
};
|
|
1396
|
+
```
|
|
1397
|
+
|
|
1398
|
+
- AuthOptions and JwtVerifyOptions
|
|
1399
|
+
|
|
1400
|
+
```ts
|
|
1401
|
+
export type JwtVerifyOptions = {
|
|
1402
|
+
algorithms?: ("HS256" | "RS256")[];
|
|
1403
|
+
secret?: string; // HS256
|
|
1404
|
+
publicKey?: string; // RS256 static
|
|
1405
|
+
getPublicKey?: (header: Record<string, unknown>, payload: Record<string, unknown>) => Promise<string> | string; // RS256 dynamic
|
|
1406
|
+
audience?: string | string[];
|
|
1407
|
+
issuer?: string | string[];
|
|
1408
|
+
clockToleranceSec?: number;
|
|
1409
|
+
};
|
|
1410
|
+
|
|
1411
|
+
export type AuthOptions = {
|
|
1412
|
+
required?: boolean; // default true for MCP endpoint
|
|
1413
|
+
scheme?: "bearer" | "jwt";
|
|
1414
|
+
allowedTokens?: string[]; // simple bearer allowlist
|
|
1415
|
+
validator?: (req: any, token: string | undefined) => boolean | Promise<boolean>;
|
|
1416
|
+
jwt?: JwtVerifyOptions;
|
|
1417
|
+
publicPaths?: string[]; // paths that skip auth
|
|
1418
|
+
protectedPaths?: string[]; // if provided, only these paths require auth
|
|
1419
|
+
customMiddleware?: (req: any, res: any, next: any) => any; // full control hook
|
|
1420
|
+
};
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
- HttpServerOptions
|
|
1424
|
+
|
|
1425
|
+
```ts
|
|
1426
|
+
export type HttpServerOptions = {
|
|
1427
|
+
configureExpress?: (app: any) => void;
|
|
1428
|
+
};
|
|
1429
|
+
```
|
|
1430
|
+
|
|
1431
|
+
Notes:
|
|
1432
|
+
- When credentials are true, Access-Control-Allow-Origin echoes the request Origin rather than using "*".
|
|
1433
|
+
- You can manage CORS for non-MCP routes in configureExpress.
|
|
1434
|
+
- Use publicPaths to allow some routes without auth; use protectedPaths to only require auth for certain routes.
|
|
1435
|
+
|
|
1436
|
+
|
|
1217
1437
|
log: {
|
|
1218
1438
|
level: 'debug', // Capture all log levels
|
|
1219
1439
|
logToFile: '/var/log/my-mcp-server.log',
|
|
@@ -1221,9 +1441,28 @@ const parser = ArgParser.withMcp({
|
|
|
1221
1441
|
}
|
|
1222
1442
|
// LEGACY: logPath: '/var/log/my-mcp-server.log' // Still works
|
|
1223
1443
|
}
|
|
1444
|
+
|
|
1445
|
+
### Adding custom HTTP routes (e.g., /health)
|
|
1446
|
+
|
|
1447
|
+
Use the httpServer.configureExpress(app) hook to register routes before MCP endpoints are bound. Example:
|
|
1448
|
+
|
|
1449
|
+
```ts
|
|
1450
|
+
const cli = ArgParser.withMcp({
|
|
1451
|
+
mcp: {
|
|
1452
|
+
serverInfo: { name: "my-mcp", version: "1.0.0" },
|
|
1453
|
+
defaultTransports: [
|
|
1454
|
+
{ type: "streamable-http", port: 3002, path: "/api/mcp", auth: { required: true, publicPaths: ["/health"] } }
|
|
1455
|
+
],
|
|
1456
|
+
httpServer: { configureExpress: (app) => app.get("/health", (_req, res) => res.json({ ok: true })) },
|
|
1457
|
+
}
|
|
1224
1458
|
});
|
|
1459
|
+
```
|
|
1460
|
+
|
|
1461
|
+
- To make a route public (no auth), add it to auth.publicPaths.
|
|
1462
|
+
- CORS headers for non-MCP paths can be applied by your own middleware inside the hook if desired.
|
|
1463
|
+
|
|
1464
|
+
### Multiple transports and improved logging
|
|
1225
1465
|
|
|
1226
|
-
# Multiple transports and improved logging (configured via --s-mcp-serve system flag)
|
|
1227
1466
|
const cli = ArgParser.withMcp({
|
|
1228
1467
|
appName: 'multi-tool',
|
|
1229
1468
|
appCommandName: 'multi-tool',
|
|
@@ -1407,9 +1646,9 @@ const cli = ArgParser.withMcp({
|
|
|
1407
1646
|
ctx.logger.mcpError(`Shutting down: ${ctx.reason}`);
|
|
1408
1647
|
await cleanupResources();
|
|
1409
1648
|
await closeDatabase();
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1649
|
+
},
|
|
1650
|
+
},
|
|
1651
|
+
},
|
|
1413
1652
|
});
|
|
1414
1653
|
```
|
|
1415
1654
|
|
|
@@ -1422,6 +1661,7 @@ const cli = ArgParser.withMcp({
|
|
|
1422
1661
|
**Context Properties:**
|
|
1423
1662
|
|
|
1424
1663
|
Each lifecycle event receives a context object with:
|
|
1664
|
+
|
|
1425
1665
|
- `getFlag(name)`: Access parsed CLI flags and environment variables
|
|
1426
1666
|
- `logger`: MCP-compliant logger instance for the current context
|
|
1427
1667
|
- `serverInfo`: Server information (name, version, description)
|
|
@@ -1824,6 +2064,47 @@ ArgParser includes built-in `--s-*` flags for development, debugging, and config
|
|
|
1824
2064
|
|
|
1825
2065
|
## Changelog
|
|
1826
2066
|
|
|
2067
|
+
### v2.7.0
|
|
2068
|
+
|
|
2069
|
+
**Feat**
|
|
2070
|
+
|
|
2071
|
+
**MCP**:
|
|
2072
|
+
|
|
2073
|
+
- Add support for CORS and authentication options, enabling powerful tools to serve Web UIs and publicly exposed APIs
|
|
2074
|
+
- Add supports for configuring express by exposing the app before it runs
|
|
2075
|
+
|
|
2076
|
+
**CLI**:
|
|
2077
|
+
|
|
2078
|
+
- Add support for NOT automatically executing the CLI if the script is imported, but will execute if called directly as a CLI. This enables use cases such as programmatically loading the CLI and scanning for tools or testing it from another script via the --s-enable-fuzzy flag or your own script.
|
|
2079
|
+
|
|
2080
|
+
### v2.6.0
|
|
2081
|
+
|
|
2082
|
+
**Feat**
|
|
2083
|
+
|
|
2084
|
+
**DXT**:
|
|
2085
|
+
|
|
2086
|
+
- Improve how paths and dynamic variables are handled when bundling into a DXT, to improve compatibility and reduce paths that will fail in a sandbox when the CLI / MCP expects path available on the system. Dynamic path resolution with `${VARIABLE}` syntax supporting `${HOME}`, `${DOCUMENTS}`, `${__dirname}`, `${DXT_DIR}`, and more. Context-aware path resolution with `DxtPathResolver.createUserDataPath()`, `createTempPath()`, `createConfigPath()`.
|
|
2087
|
+
- Add new IFlag.dxtOption set of options for each flag to allow finer control on how the flags are perceived on the DXT manifest / Claude Desktop.
|
|
2088
|
+
|
|
2089
|
+
Read more her: [DXT Package User Configuration & Path Handling](#dxt-package-user-configuration--path-handling)
|
|
2090
|
+
|
|
2091
|
+
**Fixes and Changes**
|
|
2092
|
+
|
|
2093
|
+
**DXT**:
|
|
2094
|
+
|
|
2095
|
+
- Improve handling of sensitive env variable, they were previously always showing as sensitive.
|
|
2096
|
+
|
|
2097
|
+
**Known Limitations**
|
|
2098
|
+
|
|
2099
|
+
**DXT**:
|
|
2100
|
+
|
|
2101
|
+
The DXT bundling / packing / unpacking / launching process is notoriously early and brittle. There are many reasons something is not working, but **MOST** importantly it will not work if:
|
|
2102
|
+
|
|
2103
|
+
1. You are bundling a package in a mono-repo (you will need to temporarily create a pnpm-workspace.yaml file for example to break the hierarchy)
|
|
2104
|
+
2. You do _not_ hard-install your node_modules as detailed in the documentation (it will only work if the node_modules are hard installed)
|
|
2105
|
+
3. In some cases if your CLI entrypoint does not run a main loop (see documentation for working examples)
|
|
2106
|
+
4. If you use PATH-dependent variables (for example relying on ~/.config/path/to/some.json). This has been addressed in v2.6.0, but you have to make sure you use the correct patterns (see documentation)
|
|
2107
|
+
|
|
1827
2108
|
### v2.5.0
|
|
1828
2109
|
|
|
1829
2110
|
**Feat**
|
|
@@ -1852,7 +2133,7 @@ ArgParser includes built-in `--s-*` flags for development, debugging, and config
|
|
|
1852
2133
|
- MCP client now sanitizes the method names to ensure spec-compliants MCP behavior, names that collision will be logged
|
|
1853
2134
|
- There were some use-cases where the DXT bundling failed, this new release addresses all of them, namely:
|
|
1854
2135
|
1. Output structure will match that of the input so relative files (for example DB migrations) will work
|
|
1855
|
-
2.
|
|
2136
|
+
2. Deeper folder structure was previously not working
|
|
1856
2137
|
- DXT bundling now supports including resources via options: `{dxt: {include: ['TSDown blob-like paths']}`
|
|
1857
2138
|
- Logger was improved to support log level via `options:{ log: {} }` so you can set it to level: 'debug' and the MCP log will contain 100% of the console output, logPath setting was not impacted
|
|
1858
2139
|
|
|
@@ -1946,8 +2227,8 @@ Make sure to clearly identify if you need to include the node_modules or not. In
|
|
|
1946
2227
|
- [x] Upgrade to Zod/V4 (V4 does not support functions well, this will take more time, not a priority)
|
|
1947
2228
|
- [ ] Add System flags to args.systemArgs
|
|
1948
2229
|
- [ ] Improve flag options collision prevention
|
|
1949
|
-
- [ ] Add support for locales / translations
|
|
1950
2230
|
- [ ] (potentially) add support for fully typed parsed output, this has proven very challenging
|
|
2231
|
+
- [ ] Add support for locales / translations
|
|
1951
2232
|
|
|
1952
2233
|
### (known) Bugs / DX improvement points
|
|
1953
2234
|
|