paygate-mcp 10.2.0 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,7 +32,10 @@ Monetize any MCP server with one command. Add API key auth, per-tool pricing, ra
32
32
  ## Quick Start
33
33
 
34
34
  ```bash
35
- # Wrap a local MCP server (stdio transport)
35
+ # Interactive setup wizard (generates paygate.json)
36
+ npx paygate-mcp init
37
+
38
+ # Or wrap directly with CLI flags
36
39
  npx paygate-mcp wrap --server "npx @modelcontextprotocol/server-filesystem /tmp"
37
40
 
38
41
  # Gate a remote MCP server (Streamable HTTP transport)
@@ -551,6 +554,42 @@ These MCP methods pass through without auth or billing:
551
554
 
552
555
  **Gated methods:** `tools/call` (single), `tools/call_batch` (batch — all-or-nothing billing, parallel execution). See [Batch Tool Calls](#batch-tool-calls).
553
556
 
557
+ ## CLI Commands
558
+
559
+ ```bash
560
+ paygate-mcp wrap [options] # Start a payment-gated MCP proxy
561
+ paygate-mcp init [--output] [--force] # Interactive setup wizard
562
+ paygate-mcp validate --config <path> # Validate config without starting
563
+ paygate-mcp completions <bash|zsh|fish> # Generate shell completions
564
+ paygate-mcp version [--json] # Print version
565
+ ```
566
+
567
+ ### Shell Completions
568
+
569
+ ```bash
570
+ # Bash
571
+ paygate-mcp completions bash > ~/.local/share/bash-completion/completions/paygate-mcp
572
+
573
+ # Zsh
574
+ paygate-mcp completions zsh > ~/.zfunc/_paygate-mcp
575
+ # Add to .zshrc: fpath=(~/.zfunc $fpath) && compinit
576
+
577
+ # Fish
578
+ paygate-mcp completions fish > ~/.config/fish/completions/paygate-mcp.fish
579
+ ```
580
+
581
+ ### Machine-Readable Output
582
+
583
+ ```bash
584
+ # Version as JSON (for CI/CD)
585
+ paygate-mcp version --json
586
+ # → {"version":"10.3.0"}
587
+
588
+ # Validate config with structured output
589
+ paygate-mcp validate --config paygate.json --json
590
+ # → {"valid":true,"diagnostics":[...],"errors":0,"warnings":0}
591
+ ```
592
+
554
593
  ## CLI Options
555
594
 
556
595
  ```
@@ -571,10 +610,22 @@ These MCP methods pass through without auth or billing:
571
610
  --refund-on-failure Refund credits when downstream tool call fails
572
611
  --redis-url <url> Redis URL for distributed state (e.g. "redis://localhost:6379")
573
612
  --config <path> Load settings from a JSON config file
613
+ --discovery <mode> Tool discovery mode: static (default) or dynamic
614
+ --json Machine-readable JSON output
574
615
  ```
575
616
 
576
617
  > **Note:** Use `--server` OR `--remote-url` for single-server mode. Use `servers` in a config file for multi-server mode.
577
618
 
619
+ ### Dynamic Tool Discovery
620
+
621
+ For servers with many tools, dynamic discovery mode reduces agent context window bloat by exposing 3 meta-tools instead of the full tool list:
622
+
623
+ ```bash
624
+ npx paygate-mcp wrap --server "your-server" --discovery dynamic
625
+ ```
626
+
627
+ Agents see 3 tools: `paygate_list_tools` (paginated listing), `paygate_search_tools` (keyword search), and `paygate_call_tool` (proxy any tool). This reduces N tools to 3 in the context window while preserving full functionality.
628
+
578
629
  ### Persistent Storage
579
630
 
580
631
  Add `--state-file` to save API keys and credits to disk. Data survives server restarts.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shell Completions — Generate tab completion scripts for bash, zsh, and fish.
3
+ *
4
+ * Usage:
5
+ * paygate-mcp completions bash > ~/.local/share/bash-completion/completions/paygate-mcp
6
+ * paygate-mcp completions zsh > ~/.zfunc/_paygate-mcp
7
+ * paygate-mcp completions fish > ~/.config/fish/completions/paygate-mcp.fish
8
+ */
9
+ export declare function generateCompletions(shell: string): string;
10
+ //# sourceMappingURL=cli-completions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-completions.d.ts","sourceRoot":"","sources":["../src/cli-completions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQzD"}
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ /**
3
+ * Shell Completions — Generate tab completion scripts for bash, zsh, and fish.
4
+ *
5
+ * Usage:
6
+ * paygate-mcp completions bash > ~/.local/share/bash-completion/completions/paygate-mcp
7
+ * paygate-mcp completions zsh > ~/.zfunc/_paygate-mcp
8
+ * paygate-mcp completions fish > ~/.config/fish/completions/paygate-mcp.fish
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.generateCompletions = generateCompletions;
12
+ const COMMANDS = ['wrap', 'init', 'validate', 'completions', 'version', 'help'];
13
+ const WRAP_FLAGS = [
14
+ '--server', '--remote-url', '--config', '--port', '--price',
15
+ '--rate-limit', '--name', '--shadow', '--admin-key', '--tool-price',
16
+ '--import-key', '--state-file', '--stripe-secret', '--webhook-url',
17
+ '--webhook-secret', '--webhook-retries', '--refund-on-failure',
18
+ '--redis-url', '--header', '--trusted-proxies', '--dry-run',
19
+ '--log-level', '--log-format', '--request-timeout', '--headers-timeout',
20
+ '--keepalive-timeout', '--max-requests-per-socket', '--admin-rate-limit',
21
+ '--discovery', '--json',
22
+ ];
23
+ const INIT_FLAGS = ['--output', '--force'];
24
+ const VALIDATE_FLAGS = ['--config', '--json'];
25
+ const LOG_LEVELS = ['debug', 'info', 'warn', 'error', 'silent'];
26
+ const LOG_FORMATS = ['text', 'json'];
27
+ function generateCompletions(shell) {
28
+ switch (shell.toLowerCase()) {
29
+ case 'bash': return generateBash();
30
+ case 'zsh': return generateZsh();
31
+ case 'fish': return generateFish();
32
+ default:
33
+ throw new Error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
34
+ }
35
+ }
36
+ function generateBash() {
37
+ return `# paygate-mcp bash completion
38
+ # Install: paygate-mcp completions bash > ~/.local/share/bash-completion/completions/paygate-mcp
39
+ # Or: paygate-mcp completions bash >> ~/.bashrc
40
+
41
+ _paygate_mcp() {
42
+ local cur prev words cword
43
+ _init_completion || return
44
+
45
+ local commands="${COMMANDS.join(' ')}"
46
+ local wrap_flags="${WRAP_FLAGS.join(' ')}"
47
+ local init_flags="${INIT_FLAGS.join(' ')}"
48
+ local validate_flags="${VALIDATE_FLAGS.join(' ')}"
49
+ local log_levels="${LOG_LEVELS.join(' ')}"
50
+ local log_formats="${LOG_FORMATS.join(' ')}"
51
+ local shells="bash zsh fish"
52
+
53
+ # Complete commands at position 1
54
+ if [[ \${cword} -eq 1 ]]; then
55
+ COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
56
+ return
57
+ fi
58
+
59
+ local cmd="\${words[1]}"
60
+
61
+ # Complete based on previous flag
62
+ case "\${prev}" in
63
+ --log-level)
64
+ COMPREPLY=( $(compgen -W "\${log_levels}" -- "\${cur}") )
65
+ return
66
+ ;;
67
+ --log-format)
68
+ COMPREPLY=( $(compgen -W "\${log_formats}" -- "\${cur}") )
69
+ return
70
+ ;;
71
+ --config|--state-file|--output)
72
+ COMPREPLY=( $(compgen -f -- "\${cur}") )
73
+ return
74
+ ;;
75
+ --discovery)
76
+ COMPREPLY=( $(compgen -W "static dynamic" -- "\${cur}") )
77
+ return
78
+ ;;
79
+ esac
80
+
81
+ # Complete flags based on command
82
+ case "\${cmd}" in
83
+ wrap)
84
+ COMPREPLY=( $(compgen -W "\${wrap_flags}" -- "\${cur}") )
85
+ ;;
86
+ init)
87
+ COMPREPLY=( $(compgen -W "\${init_flags}" -- "\${cur}") )
88
+ ;;
89
+ validate)
90
+ COMPREPLY=( $(compgen -W "\${validate_flags}" -- "\${cur}") )
91
+ ;;
92
+ completions)
93
+ COMPREPLY=( $(compgen -W "\${shells}" -- "\${cur}") )
94
+ ;;
95
+ esac
96
+ }
97
+
98
+ complete -F _paygate_mcp paygate-mcp
99
+ `;
100
+ }
101
+ function generateZsh() {
102
+ const wrapFlagDefs = WRAP_FLAGS.map(f => `'${f}[${flagDescription(f)}]'`).join('\n ');
103
+ return `#compdef paygate-mcp
104
+ # paygate-mcp zsh completion
105
+ # Install: paygate-mcp completions zsh > ~/.zfunc/_paygate-mcp
106
+ # Then add: fpath=(~/.zfunc $fpath) and run: compinit
107
+
108
+ _paygate_mcp() {
109
+ local -a commands
110
+ commands=(
111
+ 'wrap:Start a payment-gated MCP proxy'
112
+ 'init:Interactive setup wizard'
113
+ 'validate:Validate a config file'
114
+ 'completions:Generate shell completions'
115
+ 'version:Print version'
116
+ 'help:Show help'
117
+ )
118
+
119
+ _arguments -C \\
120
+ '1:command:->command' \\
121
+ '*::arg:->args'
122
+
123
+ case $state in
124
+ command)
125
+ _describe 'command' commands
126
+ ;;
127
+ args)
128
+ case $words[1] in
129
+ wrap)
130
+ _arguments \\
131
+ '--server[MCP server command to wrap]:command:' \\
132
+ '--remote-url[Remote MCP server URL]:url:' \\
133
+ '--config[Config file path]:file:_files' \\
134
+ '--port[HTTP port]:port:' \\
135
+ '--price[Default credits per call]:credits:' \\
136
+ '--rate-limit[Max calls/min per key]:limit:' \\
137
+ '--name[Server display name]:name:' \\
138
+ '--shadow[Shadow mode]' \\
139
+ '--admin-key[Admin key]:key:' \\
140
+ '--tool-price[Per-tool pricing]:pricing:' \\
141
+ '--state-file[State persistence file]:file:_files' \\
142
+ '--stripe-secret[Stripe webhook secret]:secret:' \\
143
+ '--webhook-url[Webhook URL]:url:' \\
144
+ '--webhook-secret[Webhook HMAC secret]:secret:' \\
145
+ '--redis-url[Redis URL]:url:' \\
146
+ '--dry-run[Discover tools and exit]' \\
147
+ '--log-level[Log level]:level:(debug info warn error silent)' \\
148
+ '--log-format[Log format]:format:(text json)' \\
149
+ '--json[JSON output mode]' \\
150
+ '--refund-on-failure[Refund on downstream failure]' \\
151
+ '--discovery[Tool discovery mode]:mode:(static dynamic)'
152
+ ;;
153
+ init)
154
+ _arguments \\
155
+ '--output[Output file path]:file:_files' \\
156
+ '--force[Overwrite existing file]'
157
+ ;;
158
+ validate)
159
+ _arguments \\
160
+ '--config[Config file path]:file:_files' \\
161
+ '--json[JSON output mode]'
162
+ ;;
163
+ completions)
164
+ _arguments '1:shell:(bash zsh fish)'
165
+ ;;
166
+ esac
167
+ ;;
168
+ esac
169
+ }
170
+
171
+ _paygate_mcp "$@"
172
+ `;
173
+ }
174
+ function generateFish() {
175
+ return `# paygate-mcp fish completion
176
+ # Install: paygate-mcp completions fish > ~/.config/fish/completions/paygate-mcp.fish
177
+
178
+ # Disable file completions by default
179
+ complete -c paygate-mcp -f
180
+
181
+ # Commands
182
+ complete -c paygate-mcp -n "__fish_use_subcommand" -a "wrap" -d "Start a payment-gated MCP proxy"
183
+ complete -c paygate-mcp -n "__fish_use_subcommand" -a "init" -d "Interactive setup wizard"
184
+ complete -c paygate-mcp -n "__fish_use_subcommand" -a "validate" -d "Validate a config file"
185
+ complete -c paygate-mcp -n "__fish_use_subcommand" -a "completions" -d "Generate shell completions"
186
+ complete -c paygate-mcp -n "__fish_use_subcommand" -a "version" -d "Print version"
187
+ complete -c paygate-mcp -n "__fish_use_subcommand" -a "help" -d "Show help"
188
+
189
+ # wrap flags
190
+ ${WRAP_FLAGS.map(f => `complete -c paygate-mcp -n "__fish_seen_subcommand_from wrap" -l "${f.slice(2)}" -d "${flagDescription(f)}"`).join('\n')}
191
+
192
+ # init flags
193
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from init" -l "output" -d "Output file path" -r -F
194
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from init" -l "force" -d "Overwrite existing file"
195
+
196
+ # validate flags
197
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from validate" -l "config" -d "Config file path" -r -F
198
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from validate" -l "json" -d "JSON output mode"
199
+
200
+ # completions shells
201
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from completions" -a "bash zsh fish"
202
+
203
+ # log-level values
204
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from wrap; and __fish_prev_arg_in --log-level" -a "debug info warn error silent"
205
+
206
+ # log-format values
207
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from wrap; and __fish_prev_arg_in --log-format" -a "text json"
208
+
209
+ # discovery mode values
210
+ complete -c paygate-mcp -n "__fish_seen_subcommand_from wrap; and __fish_prev_arg_in --discovery" -a "static dynamic"
211
+ `;
212
+ }
213
+ function flagDescription(flag) {
214
+ const descriptions = {
215
+ '--server': 'MCP server command',
216
+ '--remote-url': 'Remote MCP server URL',
217
+ '--config': 'Config file path',
218
+ '--port': 'HTTP port',
219
+ '--price': 'Default credits per call',
220
+ '--rate-limit': 'Max calls/min per key',
221
+ '--name': 'Server display name',
222
+ '--shadow': 'Shadow mode',
223
+ '--admin-key': 'Admin key',
224
+ '--tool-price': 'Per-tool pricing',
225
+ '--import-key': 'Import API key with credits',
226
+ '--state-file': 'State persistence file',
227
+ '--stripe-secret': 'Stripe webhook secret',
228
+ '--webhook-url': 'Webhook URL',
229
+ '--webhook-secret': 'Webhook HMAC secret',
230
+ '--webhook-retries': 'Max webhook retries',
231
+ '--refund-on-failure': 'Refund on downstream failure',
232
+ '--redis-url': 'Redis URL',
233
+ '--header': 'Custom response header',
234
+ '--trusted-proxies': 'Trusted proxy IPs',
235
+ '--dry-run': 'Discover tools and exit',
236
+ '--log-level': 'Log level',
237
+ '--log-format': 'Log format',
238
+ '--request-timeout': 'Max request time (ms)',
239
+ '--headers-timeout': 'Max header receive time (ms)',
240
+ '--keepalive-timeout': 'Idle connection timeout (ms)',
241
+ '--max-requests-per-socket': 'Max requests per socket',
242
+ '--admin-rate-limit': 'Admin rate limit per IP',
243
+ '--json': 'JSON output mode',
244
+ '--discovery': 'Tool discovery mode (static/dynamic)',
245
+ };
246
+ return descriptions[flag] || flag.slice(2);
247
+ }
248
+ //# sourceMappingURL=cli-completions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-completions.js","sourceRoot":"","sources":["../src/cli-completions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CLI Init Wizard — Interactive setup for paygate-mcp.
3
+ *
4
+ * Generates a paygate.json config file with guided prompts.
5
+ * Uses only Node.js built-in readline — zero dependencies.
6
+ */
7
+ export declare function runInit(flags: Record<string, string>): Promise<void>;
8
+ //# sourceMappingURL=cli-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-init.d.ts","sourceRoot":"","sources":["../src/cli-init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0FH,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAyI1E"}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ /**
3
+ * CLI Init Wizard — Interactive setup for paygate-mcp.
4
+ *
5
+ * Generates a paygate.json config file with guided prompts.
6
+ * Uses only Node.js built-in readline — zero dependencies.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.runInit = runInit;
10
+ const readline_1 = require("readline");
11
+ const fs_1 = require("fs");
12
+ const path_1 = require("path");
13
+ // ─── Readline helpers ─────────────────────────────────────────────────────────
14
+ function createRl() {
15
+ return (0, readline_1.createInterface)({ input: process.stdin, output: process.stdout });
16
+ }
17
+ function ask(rl, question, defaultValue) {
18
+ const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
19
+ return new Promise((resolve) => {
20
+ rl.question(prompt, (answer) => {
21
+ resolve(answer.trim() || defaultValue || '');
22
+ });
23
+ });
24
+ }
25
+ function askYesNo(rl, question, defaultYes = false) {
26
+ const hint = defaultYes ? '[Y/n]' : '[y/N]';
27
+ return new Promise((resolve) => {
28
+ rl.question(`${question} ${hint}: `, (answer) => {
29
+ const a = answer.trim().toLowerCase();
30
+ if (!a)
31
+ return resolve(defaultYes);
32
+ resolve(a === 'y' || a === 'yes');
33
+ });
34
+ });
35
+ }
36
+ function askChoice(rl, question, choices, defaultIndex = 0) {
37
+ return new Promise((resolve) => {
38
+ console.log(`\n ${question}`);
39
+ choices.forEach((c, i) => {
40
+ const marker = i === defaultIndex ? '>' : ' ';
41
+ console.log(` ${marker} ${i + 1}. ${c}`);
42
+ });
43
+ rl.question(` Choice [${defaultIndex + 1}]: `, (answer) => {
44
+ const idx = parseInt(answer.trim(), 10) - 1;
45
+ if (idx >= 0 && idx < choices.length) {
46
+ resolve(choices[idx]);
47
+ }
48
+ else {
49
+ resolve(choices[defaultIndex]);
50
+ }
51
+ });
52
+ });
53
+ }
54
+ const TEMPLATES = [
55
+ {
56
+ name: 'filesystem',
57
+ description: 'Wrap the MCP filesystem server',
58
+ serverCommand: 'npx',
59
+ serverArgs: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
60
+ defaultPrice: 1,
61
+ rateLimit: 60,
62
+ },
63
+ {
64
+ name: 'custom-stdio',
65
+ description: 'Wrap a custom stdio MCP server',
66
+ serverCommand: '',
67
+ serverArgs: [],
68
+ defaultPrice: 1,
69
+ rateLimit: 60,
70
+ },
71
+ {
72
+ name: 'remote-http',
73
+ description: 'Gate a remote MCP server (Streamable HTTP)',
74
+ serverCommand: '',
75
+ serverArgs: [],
76
+ defaultPrice: 1,
77
+ rateLimit: 60,
78
+ },
79
+ ];
80
+ // ─── Init Command ─────────────────────────────────────────────────────────────
81
+ async function runInit(flags) {
82
+ const outputPath = (0, path_1.resolve)(flags['output'] || flags['o'] || 'paygate.json');
83
+ // Check if file already exists
84
+ if ((0, fs_1.existsSync)(outputPath) && !flags['force']) {
85
+ console.error(`\n Error: ${outputPath} already exists. Use --force to overwrite.\n`);
86
+ process.exit(1);
87
+ }
88
+ console.log(`
89
+ ╔══════════════════════════════════════════════════╗
90
+ ║ PayGate MCP — Interactive Setup ║
91
+ ║ Monetize any MCP server in seconds ║
92
+ ╚══════════════════════════════════════════════════╝
93
+ `);
94
+ const rl = createRl();
95
+ try {
96
+ // Step 1: Choose template
97
+ const templateChoice = await askChoice(rl, 'What type of MCP server do you want to gate?', TEMPLATES.map(t => `${t.name} — ${t.description}`), 0);
98
+ const templateIdx = TEMPLATES.findIndex(t => templateChoice.startsWith(t.name));
99
+ const template = TEMPLATES[templateIdx >= 0 ? templateIdx : 0];
100
+ const config = {};
101
+ // Step 2: Server command or remote URL
102
+ if (template.name === 'remote-http') {
103
+ const url = await ask(rl, 'Remote MCP server URL', 'https://my-server.example.com/mcp');
104
+ config.remoteUrl = url;
105
+ }
106
+ else if (template.name === 'filesystem') {
107
+ const dir = await ask(rl, 'Directory to serve', '/tmp');
108
+ config.serverCommand = 'npx';
109
+ config.serverArgs = ['-y', '@modelcontextprotocol/server-filesystem', dir];
110
+ }
111
+ else {
112
+ const cmd = await ask(rl, 'Server command (e.g., "node server.js" or "python server.py")');
113
+ if (!cmd) {
114
+ console.error('\n Error: server command is required.\n');
115
+ process.exit(1);
116
+ }
117
+ const parts = cmd.split(/\s+/);
118
+ config.serverCommand = parts[0];
119
+ config.serverArgs = parts.slice(1);
120
+ }
121
+ // Step 3: Port
122
+ const portStr = await ask(rl, 'Port', '3402');
123
+ config.port = parseInt(portStr, 10) || 3402;
124
+ // Step 4: Pricing
125
+ const priceStr = await ask(rl, 'Default credits per tool call', String(template.defaultPrice));
126
+ config.defaultCreditsPerCall = parseInt(priceStr, 10) || 1;
127
+ // Step 5: Rate limit
128
+ const rateStr = await ask(rl, 'Rate limit (calls/min per key, 0=unlimited)', String(template.rateLimit));
129
+ config.globalRateLimitPerMin = parseInt(rateStr, 10);
130
+ // Step 6: Shadow mode
131
+ const shadow = await askYesNo(rl, 'Enable shadow mode? (log without enforcing)', false);
132
+ if (shadow) {
133
+ config.shadowMode = true;
134
+ }
135
+ // Step 7: State persistence
136
+ const persist = await askYesNo(rl, 'Persist state to disk? (survives restarts)', true);
137
+ if (persist) {
138
+ const stateFile = await ask(rl, 'State file path', 'paygate-state.json');
139
+ config.stateFile = stateFile;
140
+ }
141
+ // Step 8: Stripe integration
142
+ const stripe = await askYesNo(rl, 'Enable Stripe integration for credit purchases?', false);
143
+ if (stripe) {
144
+ const stripeSecret = await ask(rl, 'Stripe webhook signing secret (whsec_...)');
145
+ if (stripeSecret) {
146
+ config.stripeWebhookSecret = stripeSecret;
147
+ }
148
+ // Add credit packages placeholder
149
+ config.creditPackages = [
150
+ { id: 'starter', credits: 100, priceInCents: 999, currency: 'usd', name: 'Starter Pack' },
151
+ { id: 'pro', credits: 1000, priceInCents: 4999, currency: 'usd', name: 'Pro Pack' },
152
+ ];
153
+ }
154
+ // Step 9: Webhook
155
+ const webhook = await askYesNo(rl, 'Send usage events to a webhook?', false);
156
+ if (webhook) {
157
+ const webhookUrl = await ask(rl, 'Webhook URL');
158
+ if (webhookUrl) {
159
+ config.webhookUrl = webhookUrl;
160
+ const webhookSecret = await ask(rl, 'Webhook HMAC secret (optional)');
161
+ if (webhookSecret) {
162
+ config.webhookSecret = webhookSecret;
163
+ }
164
+ }
165
+ }
166
+ // Step 10: Log format
167
+ const jsonLogs = await askYesNo(rl, 'Use JSON log format? (recommended for production)', false);
168
+ if (jsonLogs) {
169
+ config.logFormat = 'json';
170
+ }
171
+ // Write config file
172
+ const configJson = JSON.stringify(config, null, 2);
173
+ (0, fs_1.writeFileSync)(outputPath, configJson + '\n', 'utf-8');
174
+ console.log(`
175
+ ✓ Config written to ${outputPath}
176
+
177
+ Next steps:
178
+ 1. Start PayGate:
179
+ paygate-mcp wrap --config ${outputPath.endsWith('paygate.json') ? 'paygate.json' : outputPath}
180
+
181
+ 2. Create an API key:
182
+ curl -X POST http://localhost:${config.port}/keys \\
183
+ -H "X-Admin-Key: <admin-key>" \\
184
+ -H "Content-Type: application/json" \\
185
+ -d '{"name":"my-client","credits":100}'
186
+
187
+ 3. Make a tool call:
188
+ curl http://localhost:${config.port}/mcp \\
189
+ -H "X-API-Key: <api-key>" \\
190
+ -H "Content-Type: application/json" \\
191
+ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"tool_name","arguments":{}},"id":1}'
192
+
193
+ Admin dashboard: http://localhost:${config.port}/dashboard
194
+ API docs: http://localhost:${config.port}/docs
195
+ `);
196
+ }
197
+ finally {
198
+ rl.close();
199
+ }
200
+ }
201
+ //# sourceMappingURL=cli-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-init.js","sourceRoot":"","sources":["../src/cli-init.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAkOH;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6B9C,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AA2OH;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6B9C,CAAC"}