@padua/cli 2.0.24 → 2.2.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 +68 -7
- package/dist/commands/tunnel/index.d.ts +1 -1
- package/dist/commands/tunnel/index.d.ts.map +1 -1
- package/dist/commands/tunnel/index.js +26 -3
- package/dist/commands/tunnel/index.js.map +1 -1
- package/dist/commands/tunnel/lb.d.ts +6 -0
- package/dist/commands/tunnel/lb.d.ts.map +1 -0
- package/dist/commands/tunnel/lb.js +148 -0
- package/dist/commands/tunnel/lb.js.map +1 -0
- package/dist/commands/tunnel/types.d.ts +1 -1
- package/dist/commands/tunnel/types.d.ts.map +1 -1
- package/dist/mcp/code-mode/executor.d.ts +32 -0
- package/dist/mcp/code-mode/executor.d.ts.map +1 -0
- package/dist/mcp/code-mode/executor.js +173 -0
- package/dist/mcp/code-mode/executor.js.map +1 -0
- package/dist/mcp/code-mode/index.d.ts +12 -0
- package/dist/mcp/code-mode/index.d.ts.map +1 -0
- package/dist/mcp/code-mode/index.js +11 -0
- package/dist/mcp/code-mode/index.js.map +1 -0
- package/dist/mcp/code-mode/interface-generator.d.ts +38 -0
- package/dist/mcp/code-mode/interface-generator.d.ts.map +1 -0
- package/dist/mcp/code-mode/interface-generator.js +159 -0
- package/dist/mcp/code-mode/interface-generator.js.map +1 -0
- package/dist/mcp/code-mode/provider.d.ts +24 -0
- package/dist/mcp/code-mode/provider.d.ts.map +1 -0
- package/dist/mcp/code-mode/provider.js +93 -0
- package/dist/mcp/code-mode/provider.js.map +1 -0
- package/dist/mcp/code-mode/search.d.ts +32 -0
- package/dist/mcp/code-mode/search.d.ts.map +1 -0
- package/dist/mcp/code-mode/search.js +47 -0
- package/dist/mcp/code-mode/search.js.map +1 -0
- package/dist/mcp/code-mode/tool-registry.d.ts +44 -0
- package/dist/mcp/code-mode/tool-registry.d.ts.map +1 -0
- package/dist/mcp/code-mode/tool-registry.js +196 -0
- package/dist/mcp/code-mode/tool-registry.js.map +1 -0
- package/dist/mcp/code-mode/types.d.ts +41 -0
- package/dist/mcp/code-mode/types.d.ts.map +1 -0
- package/dist/mcp/code-mode/types.js +8 -0
- package/dist/mcp/code-mode/types.js.map +1 -0
- package/dist/mcp/daemon/entry.js +8 -1
- package/dist/mcp/daemon/entry.js.map +1 -1
- package/dist/mcp/providers/atlassian/tools/confluence.d.ts.map +1 -1
- package/dist/mcp/providers/atlassian/tools/confluence.js +17 -9
- package/dist/mcp/providers/atlassian/tools/confluence.js.map +1 -1
- package/dist/mcp/providers/atlassian/tools/jira.d.ts.map +1 -1
- package/dist/mcp/providers/atlassian/tools/jira.js +33 -14
- package/dist/mcp/providers/atlassian/tools/jira.js.map +1 -1
- package/dist/mcp/providers/gitlab/tools/issues.d.ts.map +1 -1
- package/dist/mcp/providers/gitlab/tools/issues.js +9 -5
- package/dist/mcp/providers/gitlab/tools/issues.js.map +1 -1
- package/dist/mcp/providers/gitlab/tools/merge-requests.js +31 -14
- package/dist/mcp/providers/gitlab/tools/merge-requests.js.map +1 -1
- package/dist/mcp/providers/gitlab/tools/pipelines.d.ts.map +1 -1
- package/dist/mcp/providers/gitlab/tools/pipelines.js +9 -5
- package/dist/mcp/providers/gitlab/tools/pipelines.js.map +1 -1
- package/dist/mcp/providers/gitlab/tools/repository.d.ts.map +1 -1
- package/dist/mcp/providers/gitlab/tools/repository.js +122 -96
- package/dist/mcp/providers/gitlab/tools/repository.js.map +1 -1
- package/dist/mcp/providers/tool-helpers.d.ts +33 -8
- package/dist/mcp/providers/tool-helpers.d.ts.map +1 -1
- package/dist/mcp/providers/tool-helpers.js +58 -4
- package/dist/mcp/providers/tool-helpers.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -54,15 +54,16 @@ The `init` command will:
|
|
|
54
54
|
| | Status | Health check for all authentication services |
|
|
55
55
|
| | Doctor | Configuration validation and diagnostics with fuzzy profile matching |
|
|
56
56
|
| **Tunnel** | RDS | Secure tunnels to RDS/Aurora databases via SSM |
|
|
57
|
+
| | LB | Port forwarding to internal ALB via SSM |
|
|
57
58
|
| **Exec** | ECS | Interactive shell in running ECS containers via SSM |
|
|
58
|
-
| **MCP** | Server | Built-in MCP server with
|
|
59
|
+
| **MCP** | Server | Built-in MCP server with 51 tools — GitLab, Atlassian, and code execution |
|
|
59
60
|
| | Daemon | Background process management via `padua login` |
|
|
60
61
|
| | Diagnostics | MCP health checks via `padua doctor` |
|
|
61
62
|
| | Migration | Token migration from legacy Go server |
|
|
62
63
|
|
|
63
64
|
## MCP Server
|
|
64
65
|
|
|
65
|
-
`@padua/cli` v2 includes a built-in [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server that exposes
|
|
66
|
+
`@padua/cli` v2 includes a built-in [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server that exposes 51 tools and 6 resource templates for GitLab, Atlassian, and code execution. Any MCP-compatible client — Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, etc. — can call these tools directly.
|
|
66
67
|
|
|
67
68
|
### Setup
|
|
68
69
|
|
|
@@ -107,6 +108,8 @@ Steps 5-7 are non-blocking — if a provider fails, the rest of Padua still work
|
|
|
107
108
|
- **Auth:** `Authorization: Bearer padua-mcp-local` (fixed token — the server only binds to localhost)
|
|
108
109
|
- **Tokens:** OAuth tokens persisted to `~/.padua/tokens.db` (AES-256-GCM encrypted), proactively refreshed before expiry and lazily refreshed on tool calls
|
|
109
110
|
- **Sessions:** Multi-session support — multiple Claude Code instances share the daemon concurrently, each with an independent session. Stale sessions are swept after 30 minutes, max 10 concurrent sessions with LRU eviction
|
|
111
|
+
- **Response format:** All tools default to TOON (Token-Oriented Object Notation) for 40-60% token savings on list/search responses. Pass `"format": "json"` on any tool call to receive raw JSON instead
|
|
112
|
+
- **Code mode:** `call_tool_chain` executes JavaScript in a secure V8 sandbox with all MCP tools available as synchronous namespaced functions (`gitlab.*`, `jira.*`, `confluence.*`). `search_tools` provides keyword search over all registered tools
|
|
110
113
|
|
|
111
114
|
### IDE Configuration
|
|
112
115
|
|
|
@@ -265,6 +268,13 @@ curl -X POST http://127.0.0.1:8919/mcp \
|
|
|
265
268
|
| `atlassian_confluence_get_space` | Get space details by key |
|
|
266
269
|
| `atlassian_confluence_search_content` | Search page content |
|
|
267
270
|
|
|
271
|
+
#### Code Mode (2 tools)
|
|
272
|
+
|
|
273
|
+
| Tool | Description |
|
|
274
|
+
|------|-------------|
|
|
275
|
+
| `call_tool_chain` | Execute JavaScript in a secure isolated-vm V8 sandbox with all MCP tools available as synchronous namespaced functions (`gitlab.*`, `jira.*`, `confluence.*`). Supports configurable timeout and memory limit. Use `__interfaces` or `__getToolInterface(name)` for tool schema introspection |
|
|
276
|
+
| `search_tools` | Search registered MCP tools by keyword — matches against name and description, returns full schema information |
|
|
277
|
+
|
|
268
278
|
### Resource Templates
|
|
269
279
|
|
|
270
280
|
Resources provide direct read access to specific entities by URI:
|
|
@@ -302,7 +312,7 @@ Returns:
|
|
|
302
312
|
"atlassian": "ready"
|
|
303
313
|
},
|
|
304
314
|
"uptime": 3600,
|
|
305
|
-
"version": "2.0
|
|
315
|
+
"version": "2.2.0"
|
|
306
316
|
}
|
|
307
317
|
```
|
|
308
318
|
|
|
@@ -789,15 +799,27 @@ paws clear
|
|
|
789
799
|
|
|
790
800
|
## Tunnel Command
|
|
791
801
|
|
|
792
|
-
Create secure tunnels to
|
|
802
|
+
Create secure tunnels to AWS resources via SSM Session Manager.
|
|
793
803
|
|
|
794
804
|
Automatically reads `AWS_PROFILE` environment variable when no `--profile` flag is provided (works with `paws`).
|
|
795
805
|
|
|
806
|
+
### Targets
|
|
807
|
+
|
|
808
|
+
| Target | Description | System Required |
|
|
809
|
+
|--------|-------------|-----------------|
|
|
810
|
+
| `rds` | Tunnel to RDS/Aurora databases | Yes (e.g., `roma`, `padua-iam`) |
|
|
811
|
+
| `lb` | Tunnel to internal ALB (`dev.int.paduasolutions.net:443`) | No |
|
|
812
|
+
|
|
796
813
|
### Basic Usage
|
|
797
814
|
|
|
798
815
|
```bash
|
|
816
|
+
# RDS tunnel (requires system argument)
|
|
799
817
|
padua tunnel roma rds # Interactive (prompts for port/cluster)
|
|
800
818
|
padua tunnel roma rds -p paduafg-development # Use specific profile
|
|
819
|
+
|
|
820
|
+
# Load balancer tunnel (no system needed)
|
|
821
|
+
padua tunnel lb # Interactive (prompts for port, default 8443)
|
|
822
|
+
padua tunnel lb --local-port 9443 # Use specific local port
|
|
801
823
|
```
|
|
802
824
|
|
|
803
825
|
### Options
|
|
@@ -806,11 +828,11 @@ padua tunnel roma rds -p paduafg-development # Use specific profile
|
|
|
806
828
|
|------|-------------|
|
|
807
829
|
| `-p, --profile <name>` | AWS profile to use |
|
|
808
830
|
| `--local-port <port>` | Local port for the tunnel |
|
|
809
|
-
| `--cluster <name>` | RDS cluster or instance name |
|
|
831
|
+
| `--cluster <name>` | RDS cluster or instance name (RDS only) |
|
|
810
832
|
| `-v, --verbose` | Show detailed output |
|
|
811
833
|
| `--no-color` | Disable colored output |
|
|
812
834
|
|
|
813
|
-
### System Configuration
|
|
835
|
+
### RDS System Configuration
|
|
814
836
|
|
|
815
837
|
Different systems use different EC2 instances as tunnel endpoints:
|
|
816
838
|
|
|
@@ -819,7 +841,22 @@ Different systems use different EC2 instances as tunnel endpoints:
|
|
|
819
841
|
| roma | bastion-host | 3306 (MySQL) | roma-backend |
|
|
820
842
|
| (others) | jumpbox | 5432 (PostgreSQL) | (none) |
|
|
821
843
|
|
|
822
|
-
###
|
|
844
|
+
### LB Tunnel Usage
|
|
845
|
+
|
|
846
|
+
The internal ALB uses path-based routing for most services. Once the tunnel is running:
|
|
847
|
+
|
|
848
|
+
```bash
|
|
849
|
+
# Path-based services (most services)
|
|
850
|
+
curl -k https://localhost:8443/echo/test
|
|
851
|
+
curl -k https://localhost:8443/wealth-summaries/healthz
|
|
852
|
+
curl -k https://localhost:8443/entity-management/api/v1/status
|
|
853
|
+
|
|
854
|
+
# Host-based services (permify)
|
|
855
|
+
curl -k https://localhost:8443/v1/permissions/check \
|
|
856
|
+
-H "Host: permify.dev.int.paduasolutions.net"
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
### Example Output (RDS)
|
|
823
860
|
|
|
824
861
|
```
|
|
825
862
|
Checking port 3306 availability...
|
|
@@ -839,6 +876,30 @@ Starting tunnel...
|
|
|
839
876
|
Press Ctrl+C to close the tunnel
|
|
840
877
|
```
|
|
841
878
|
|
|
879
|
+
### Example Output (LB)
|
|
880
|
+
|
|
881
|
+
```
|
|
882
|
+
Checking port 8443 availability...
|
|
883
|
+
✓ Port 8443 is available
|
|
884
|
+
Looking up jumpbox instance...
|
|
885
|
+
✓ Found instance: i-0abc123def456
|
|
886
|
+
|
|
887
|
+
Starting tunnel...
|
|
888
|
+
Profile: paduafg-development
|
|
889
|
+
Local port: 8443
|
|
890
|
+
Remote: dev.int.paduasolutions.net:443
|
|
891
|
+
Via: i-0abc123def456 (jumpbox)
|
|
892
|
+
|
|
893
|
+
Usage (path-based services):
|
|
894
|
+
curl -k https://localhost:8443/<service>/path
|
|
895
|
+
e.g. curl -k https://localhost:8443/echo/test
|
|
896
|
+
|
|
897
|
+
Usage (host-based services like permify):
|
|
898
|
+
curl -k https://localhost:8443/path -H "Host: <service>.dev.int.paduasolutions.net"
|
|
899
|
+
|
|
900
|
+
Press Ctrl+C to close the tunnel
|
|
901
|
+
```
|
|
902
|
+
|
|
842
903
|
## Exec Command
|
|
843
904
|
|
|
844
905
|
Open an interactive shell in a running ECS container via SSM Execute Command.
|
|
@@ -7,6 +7,6 @@ export declare const tunnelCommand: Command;
|
|
|
7
7
|
/**
|
|
8
8
|
* Handle the tunnel command
|
|
9
9
|
*/
|
|
10
|
-
declare function handleTunnel(system: string, target: string, options: TunnelOptions): Promise<void>;
|
|
10
|
+
declare function handleTunnel(system: string, target: string | undefined, options: TunnelOptions): Promise<void>;
|
|
11
11
|
export { handleTunnel };
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK3C;;GAEG;AACH,eAAO,MAAM,aAAa,SASH,CAAC;AAExB;;GAEG;AACH,iBAAe,YAAY,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAqEf;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { startRdsTunnel } from './rds.js';
|
|
4
|
+
import { startLbTunnel } from './lb.js';
|
|
4
5
|
import { checkSessionManagerPlugin } from '../init/prerequisites.js';
|
|
5
6
|
/**
|
|
6
7
|
* Tunnel command - create secure tunnels to AWS resources via SSM
|
|
7
8
|
*/
|
|
8
9
|
export const tunnelCommand = new Command('tunnel')
|
|
9
10
|
.description('Create secure tunnels to AWS resources via SSM Session Manager')
|
|
10
|
-
.argument('<system>', 'Target system (e.g., roma, padua-iam)')
|
|
11
|
-
.argument('
|
|
11
|
+
.argument('<system>', 'Target system (e.g., roma, padua-iam) or target type (lb)')
|
|
12
|
+
.argument('[target]', 'Target service type (rds, lb)')
|
|
12
13
|
.option('-p, --profile <name>', 'AWS profile to use')
|
|
13
14
|
.option('--local-port <port>', 'Local port for the tunnel')
|
|
14
15
|
.option('--cluster <name>', 'RDS cluster or instance name')
|
|
@@ -33,8 +34,24 @@ async function handleTunnel(system, target, options) {
|
|
|
33
34
|
}
|
|
34
35
|
process.exit(1);
|
|
35
36
|
}
|
|
37
|
+
// Smart target detection: if system is a valid target and no target provided
|
|
38
|
+
const validTargets = ['rds', 'lb'];
|
|
39
|
+
if (target === undefined && validTargets.includes(system.toLowerCase())) {
|
|
40
|
+
target = system;
|
|
41
|
+
system = '';
|
|
42
|
+
}
|
|
43
|
+
if (target === undefined) {
|
|
44
|
+
if (!noColor) {
|
|
45
|
+
console.error(chalk.red('Target is required.'));
|
|
46
|
+
console.error(chalk.gray(`Valid targets: ${validTargets.join(', ')}`));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.error('Target is required.');
|
|
50
|
+
console.error(`Valid targets: ${validTargets.join(', ')}`);
|
|
51
|
+
}
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
36
54
|
// Validate target type
|
|
37
|
-
const validTargets = ['rds'];
|
|
38
55
|
if (!validTargets.includes(target.toLowerCase())) {
|
|
39
56
|
if (!noColor) {
|
|
40
57
|
console.error(chalk.red(`Invalid target: ${target}`));
|
|
@@ -49,8 +66,14 @@ async function handleTunnel(system, target, options) {
|
|
|
49
66
|
try {
|
|
50
67
|
switch (target.toLowerCase()) {
|
|
51
68
|
case 'rds':
|
|
69
|
+
if (!system) {
|
|
70
|
+
throw new Error('System argument is required for RDS tunnels (e.g., padua tunnel roma rds)');
|
|
71
|
+
}
|
|
52
72
|
await startRdsTunnel(system, options);
|
|
53
73
|
break;
|
|
74
|
+
case 'lb':
|
|
75
|
+
await startLbTunnel(options);
|
|
76
|
+
break;
|
|
54
77
|
default:
|
|
55
78
|
throw new Error(`Unsupported target: ${target}`);
|
|
56
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAErE;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,gEAAgE,CAAC;KAC7E,QAAQ,CAAC,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lb.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/lb.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAW3C;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+IzE"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { getInstanceIdByTag } from './aws.js';
|
|
5
|
+
import { isPortAvailable, parsePort } from './port.js';
|
|
6
|
+
import { getSubprocessEnv, sanitizeOutput } from '../login/utils.js';
|
|
7
|
+
import { loadConfig } from '../login/config.js';
|
|
8
|
+
import { getEffectiveProfile } from '../login/types.js';
|
|
9
|
+
const ALB_REMOTE_HOST = 'dev.int.paduasolutions.net';
|
|
10
|
+
const ALB_REMOTE_PORT = 443;
|
|
11
|
+
const LB_DEFAULT_LOCAL_PORT = 8443;
|
|
12
|
+
/**
|
|
13
|
+
* Start an LB tunnel via SSM Session Manager to the internal ALB
|
|
14
|
+
*/
|
|
15
|
+
export async function startLbTunnel(options) {
|
|
16
|
+
const noColor = options.noColor ?? false;
|
|
17
|
+
// Load config and get profile
|
|
18
|
+
const config = await loadConfig();
|
|
19
|
+
const profile = getEffectiveProfile({ profile: options.profile }, config ?? undefined);
|
|
20
|
+
// Step 1: Resolve local port
|
|
21
|
+
let localPort;
|
|
22
|
+
if (options.localPort) {
|
|
23
|
+
const parsed = parsePort(options.localPort);
|
|
24
|
+
if (!parsed) {
|
|
25
|
+
throw new Error(`Invalid port: ${options.localPort}`);
|
|
26
|
+
}
|
|
27
|
+
localPort = parsed;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const portAnswer = await inquirer.prompt([
|
|
31
|
+
{
|
|
32
|
+
type: 'input',
|
|
33
|
+
name: 'port',
|
|
34
|
+
message: 'Local port for ALB tunnel:',
|
|
35
|
+
default: LB_DEFAULT_LOCAL_PORT.toString(),
|
|
36
|
+
validate: (input) => {
|
|
37
|
+
const p = parsePort(input);
|
|
38
|
+
if (!p)
|
|
39
|
+
return 'Please enter a valid port number (1-65535)';
|
|
40
|
+
return true;
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
localPort = parsePort(portAnswer.port);
|
|
45
|
+
}
|
|
46
|
+
// Step 2: Verify port availability
|
|
47
|
+
if (!noColor) {
|
|
48
|
+
console.log(chalk.gray(`Checking port ${localPort} availability...`));
|
|
49
|
+
}
|
|
50
|
+
const portAvailable = await isPortAvailable(localPort);
|
|
51
|
+
if (!portAvailable) {
|
|
52
|
+
throw new Error(`Port ${localPort} is already in use. Please choose a different port.`);
|
|
53
|
+
}
|
|
54
|
+
if (!noColor) {
|
|
55
|
+
console.log(chalk.green(`✓ Port ${localPort} is available`));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.log(`Port ${localPort} is available`);
|
|
59
|
+
}
|
|
60
|
+
// Step 3: Get jumpbox instance ID
|
|
61
|
+
if (!noColor) {
|
|
62
|
+
console.log(chalk.gray('Looking up jumpbox instance...'));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log('Looking up jumpbox instance...');
|
|
66
|
+
}
|
|
67
|
+
const instanceId = getInstanceIdByTag('jumpbox', profile, options.verbose);
|
|
68
|
+
if (!noColor) {
|
|
69
|
+
console.log(chalk.green(`✓ Found instance: ${instanceId}`));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(`Found instance: ${instanceId}`);
|
|
73
|
+
}
|
|
74
|
+
// Step 4: Print tunnel summary
|
|
75
|
+
console.log('');
|
|
76
|
+
if (!noColor) {
|
|
77
|
+
console.log(chalk.cyan.bold('Starting tunnel...'));
|
|
78
|
+
console.log(chalk.gray(` Profile: ${profile}`));
|
|
79
|
+
console.log(chalk.gray(` Local port: ${localPort}`));
|
|
80
|
+
console.log(chalk.gray(` Remote: ${ALB_REMOTE_HOST}:${ALB_REMOTE_PORT}`));
|
|
81
|
+
console.log(chalk.gray(` Via: ${instanceId} (jumpbox)`));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log('Starting tunnel...');
|
|
85
|
+
console.log(` Profile: ${profile}`);
|
|
86
|
+
console.log(` Local port: ${localPort}`);
|
|
87
|
+
console.log(` Remote: ${ALB_REMOTE_HOST}:${ALB_REMOTE_PORT}`);
|
|
88
|
+
console.log(` Via: ${instanceId} (jumpbox)`);
|
|
89
|
+
}
|
|
90
|
+
console.log('');
|
|
91
|
+
if (!noColor) {
|
|
92
|
+
console.log(chalk.cyan('Usage (path-based services):'));
|
|
93
|
+
console.log(chalk.gray(` curl -k https://localhost:${localPort}/<service>/path`));
|
|
94
|
+
console.log(chalk.gray(` e.g. curl -k https://localhost:${localPort}/echo/test`));
|
|
95
|
+
console.log('');
|
|
96
|
+
console.log(chalk.cyan('Usage (host-based services like permify):'));
|
|
97
|
+
console.log(chalk.gray(` curl -k https://localhost:${localPort}/path -H "Host: <service>.${ALB_REMOTE_HOST}"`));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.log('Usage (path-based services):');
|
|
101
|
+
console.log(` curl -k https://localhost:${localPort}/<service>/path`);
|
|
102
|
+
console.log(` e.g. curl -k https://localhost:${localPort}/echo/test`);
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log('Usage (host-based services like permify):');
|
|
105
|
+
console.log(` curl -k https://localhost:${localPort}/path -H "Host: <service>.${ALB_REMOTE_HOST}"`);
|
|
106
|
+
}
|
|
107
|
+
console.log('');
|
|
108
|
+
if (!noColor) {
|
|
109
|
+
console.log(chalk.yellow('Press Ctrl+C to close the tunnel'));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.log('Press Ctrl+C to close the tunnel');
|
|
113
|
+
}
|
|
114
|
+
console.log('');
|
|
115
|
+
// Step 5: Start SSM session
|
|
116
|
+
const child = spawn('aws', [
|
|
117
|
+
'ssm',
|
|
118
|
+
'start-session',
|
|
119
|
+
'--target', instanceId,
|
|
120
|
+
'--document-name', 'AWS-StartPortForwardingSessionToRemoteHost',
|
|
121
|
+
'--parameters', `host="${ALB_REMOTE_HOST}",portNumber="${ALB_REMOTE_PORT}",localPortNumber="${localPort}"`,
|
|
122
|
+
'--profile', profile,
|
|
123
|
+
], {
|
|
124
|
+
stdio: 'inherit',
|
|
125
|
+
env: { ...getSubprocessEnv(), AWS_PROFILE: profile },
|
|
126
|
+
});
|
|
127
|
+
// Handle process lifecycle
|
|
128
|
+
await new Promise((resolve, reject) => {
|
|
129
|
+
child.on('error', (error) => {
|
|
130
|
+
reject(new Error(`Failed to start SSM session: ${sanitizeOutput(error.message)}`));
|
|
131
|
+
});
|
|
132
|
+
child.on('exit', (code) => {
|
|
133
|
+
if (code !== 0 && code !== null) {
|
|
134
|
+
console.log('');
|
|
135
|
+
if (!noColor) {
|
|
136
|
+
console.log(chalk.red(`Tunnel closed with exit code: ${code}`));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.log(`Tunnel closed with exit code: ${code}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
child.on('close', () => {
|
|
144
|
+
resolve();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=lb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lb.js","sourceRoot":"","sources":["../../../src/commands/tunnel/lb.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,KAAK,GAAG,IAAI,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAMvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA2B/E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeExecutor — orchestrates the isolated-vm sandbox for code execution.
|
|
3
|
+
*
|
|
4
|
+
* Creates a fresh V8 isolate per execution, bridges all registered MCP tools
|
|
5
|
+
* as synchronous namespaced functions, captures console output, and disposes
|
|
6
|
+
* the isolate in a finally block.
|
|
7
|
+
*
|
|
8
|
+
* Security contract:
|
|
9
|
+
* - No filesystem access: isolated-vm provides no fs module by default
|
|
10
|
+
* - No network access: no require/import available inside the isolate
|
|
11
|
+
* - No Node.js built-ins: the sandbox only has JS builtins + bridged tools
|
|
12
|
+
*/
|
|
13
|
+
import type { ToolEntry, ExecutionResult, ExecutionOptions } from './types.js';
|
|
14
|
+
export declare class CodeExecutor {
|
|
15
|
+
private readonly tools;
|
|
16
|
+
constructor(tools: ToolEntry[]);
|
|
17
|
+
/**
|
|
18
|
+
* Execute caller-supplied JavaScript code in an isolated V8 sandbox.
|
|
19
|
+
*
|
|
20
|
+
* All registered MCP tools are available as synchronous functions inside
|
|
21
|
+
* the sandbox under their namespace (gitlab.*, jira.*, confluence.*).
|
|
22
|
+
*
|
|
23
|
+
* @param code JavaScript/TypeScript code to execute.
|
|
24
|
+
* @param options Execution options (timeout, memory limit).
|
|
25
|
+
* @returns Execution result and captured console logs.
|
|
26
|
+
*/
|
|
27
|
+
execute(code: string, options?: ExecutionOptions): Promise<ExecutionResult>;
|
|
28
|
+
private setupConsoleBridge;
|
|
29
|
+
private setupToolBridges;
|
|
30
|
+
private setupIntrospection;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/mcp/code-mode/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAM/E,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,SAAS,EAAE;IAE/C;;;;;;;;;OASG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;YAkEvE,kBAAkB;YAmClB,gBAAgB;YAqDhB,kBAAkB;CAoBjC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeExecutor — orchestrates the isolated-vm sandbox for code execution.
|
|
3
|
+
*
|
|
4
|
+
* Creates a fresh V8 isolate per execution, bridges all registered MCP tools
|
|
5
|
+
* as synchronous namespaced functions, captures console output, and disposes
|
|
6
|
+
* the isolate in a finally block.
|
|
7
|
+
*
|
|
8
|
+
* Security contract:
|
|
9
|
+
* - No filesystem access: isolated-vm provides no fs module by default
|
|
10
|
+
* - No network access: no require/import available inside the isolate
|
|
11
|
+
* - No Node.js built-ins: the sandbox only has JS builtins + bridged tools
|
|
12
|
+
*/
|
|
13
|
+
import ivm from 'isolated-vm';
|
|
14
|
+
import { InterfaceGenerator } from './interface-generator.js';
|
|
15
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
16
|
+
const DEFAULT_MEMORY_LIMIT_MB = 128;
|
|
17
|
+
export class CodeExecutor {
|
|
18
|
+
tools;
|
|
19
|
+
constructor(tools) {
|
|
20
|
+
this.tools = tools;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Execute caller-supplied JavaScript code in an isolated V8 sandbox.
|
|
24
|
+
*
|
|
25
|
+
* All registered MCP tools are available as synchronous functions inside
|
|
26
|
+
* the sandbox under their namespace (gitlab.*, jira.*, confluence.*).
|
|
27
|
+
*
|
|
28
|
+
* @param code JavaScript/TypeScript code to execute.
|
|
29
|
+
* @param options Execution options (timeout, memory limit).
|
|
30
|
+
* @returns Execution result and captured console logs.
|
|
31
|
+
*/
|
|
32
|
+
async execute(code, options = {}) {
|
|
33
|
+
const timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
34
|
+
const memoryLimit = options.memoryLimitMb ?? DEFAULT_MEMORY_LIMIT_MB;
|
|
35
|
+
const logs = [];
|
|
36
|
+
const isolate = new ivm.Isolate({ memoryLimit });
|
|
37
|
+
try {
|
|
38
|
+
const context = await isolate.createContext();
|
|
39
|
+
const jail = context.global;
|
|
40
|
+
// Self-reference so sandboxed code can access `global.x = ...`
|
|
41
|
+
await jail.set('global', jail.derefInto());
|
|
42
|
+
await this.setupConsoleBridge(isolate, context, jail, logs);
|
|
43
|
+
await this.setupToolBridges(isolate, context, jail);
|
|
44
|
+
await this.setupIntrospection(isolate, context, jail);
|
|
45
|
+
// Wrap user code so we can extract a return value across the isolate boundary.
|
|
46
|
+
// The result is serialised as JSON to avoid transferring non-transferable objects.
|
|
47
|
+
const wrappedCode = `
|
|
48
|
+
(function() {
|
|
49
|
+
var __result = (function() {
|
|
50
|
+
${code}
|
|
51
|
+
})();
|
|
52
|
+
return JSON.stringify({ __result: __result === undefined ? null : __result });
|
|
53
|
+
})()
|
|
54
|
+
`;
|
|
55
|
+
const script = await isolate.compileScript(wrappedCode);
|
|
56
|
+
const resultJson = await script.run(context, { timeout });
|
|
57
|
+
let result = null;
|
|
58
|
+
if (typeof resultJson === 'string') {
|
|
59
|
+
try {
|
|
60
|
+
result = JSON.parse(resultJson).__result;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
result = resultJson;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
result = resultJson;
|
|
68
|
+
}
|
|
69
|
+
return { result, logs };
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
73
|
+
return {
|
|
74
|
+
result: null,
|
|
75
|
+
logs: [...logs, `[ERROR] Code execution failed: ${msg}`],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
// Isolate may already be disposed (e.g. on OOM) — guard against double-dispose
|
|
80
|
+
try {
|
|
81
|
+
if (!isolate.isDisposed) {
|
|
82
|
+
isolate.dispose();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Ignore dispose errors — isolate is already gone
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Console bridge
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
async setupConsoleBridge(isolate, context, jail, logs) {
|
|
94
|
+
const makeHandler = (prefix) => new ivm.Reference((...args) => {
|
|
95
|
+
const parts = args.map(a => typeof a === 'object' && a !== null ? JSON.stringify(a, null, 2) : String(a));
|
|
96
|
+
const message = parts.join(' ');
|
|
97
|
+
logs.push(prefix ? `${prefix} ${message}` : message);
|
|
98
|
+
});
|
|
99
|
+
await jail.set('__logRef', makeHandler(''));
|
|
100
|
+
await jail.set('__warnRef', makeHandler('[WARN]'));
|
|
101
|
+
await jail.set('__errorRef', makeHandler('[ERROR]'));
|
|
102
|
+
const consoleScript = await isolate.compileScript(`
|
|
103
|
+
const __stringify = (a) => typeof a === 'object' && a !== null ? JSON.stringify(a, null, 2) : String(a);
|
|
104
|
+
global.console = {
|
|
105
|
+
log: (...args) => __logRef.applySync(undefined, args.map(__stringify)),
|
|
106
|
+
warn: (...args) => __warnRef.applySync(undefined, args.map(__stringify)),
|
|
107
|
+
error: (...args) => __errorRef.applySync(undefined, args.map(__stringify)),
|
|
108
|
+
info: (...args) => __logRef.applySync(undefined, args.map(__stringify)),
|
|
109
|
+
};
|
|
110
|
+
`);
|
|
111
|
+
await consoleScript.run(context);
|
|
112
|
+
}
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// Tool bridges
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
async setupToolBridges(isolate, context, jail) {
|
|
117
|
+
// Single reference handles all tool calls; tool name + args passed as JSON
|
|
118
|
+
const toolCallerRef = new ivm.Reference(async (toolName, argsJson) => {
|
|
119
|
+
const tool = this.tools.find(t => t.name === toolName);
|
|
120
|
+
if (!tool) {
|
|
121
|
+
return JSON.stringify({ success: false, error: `Tool '${toolName}' not found` });
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const args = JSON.parse(argsJson);
|
|
125
|
+
const result = await tool.handler(args);
|
|
126
|
+
return JSON.stringify({ success: true, result });
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
130
|
+
return JSON.stringify({ success: false, error: msg });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
await jail.set('__callToolRef', toolCallerRef);
|
|
134
|
+
// Build namespace initialisation + per-tool wrapper code
|
|
135
|
+
const setupParts = [];
|
|
136
|
+
const seenNamespaces = new Set();
|
|
137
|
+
for (const tool of this.tools) {
|
|
138
|
+
const { namespace, functionName } = tool;
|
|
139
|
+
if (!seenNamespaces.has(namespace)) {
|
|
140
|
+
seenNamespaces.add(namespace);
|
|
141
|
+
setupParts.push(`global.${namespace} = global.${namespace} || {};`);
|
|
142
|
+
}
|
|
143
|
+
setupParts.push(`
|
|
144
|
+
global.${namespace}.${functionName} = function(args) {
|
|
145
|
+
var resultJson = __callToolRef.applySyncPromise(undefined, [${JSON.stringify(tool.name)}, JSON.stringify(args || {})]);
|
|
146
|
+
var parsed = JSON.parse(resultJson);
|
|
147
|
+
if (!parsed.success) throw new Error(parsed.error);
|
|
148
|
+
return parsed.result;
|
|
149
|
+
};
|
|
150
|
+
`);
|
|
151
|
+
}
|
|
152
|
+
const toolSetupScript = await isolate.compileScript(setupParts.join('\n'));
|
|
153
|
+
await toolSetupScript.run(context);
|
|
154
|
+
}
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Introspection helpers
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
async setupIntrospection(isolate, context, jail) {
|
|
159
|
+
const generator = new InterfaceGenerator(this.tools);
|
|
160
|
+
const allInterfaces = generator.generateAll();
|
|
161
|
+
const interfaceMap = generator.buildInterfaceMap();
|
|
162
|
+
await jail.set('__interfaces', allInterfaces);
|
|
163
|
+
await jail.set('__interfaceMapJson', JSON.stringify(interfaceMap));
|
|
164
|
+
const utilScript = await isolate.compileScript(`
|
|
165
|
+
global.__getToolInterface = function(toolName) {
|
|
166
|
+
var map = JSON.parse(__interfaceMapJson);
|
|
167
|
+
return map[toolName] || null;
|
|
168
|
+
};
|
|
169
|
+
`);
|
|
170
|
+
await utilScript.run(context);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/mcp/code-mode/executor.ts"],"names":[],"mappings":"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"}
|