@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.
Files changed (63) hide show
  1. package/README.md +68 -7
  2. package/dist/commands/tunnel/index.d.ts +1 -1
  3. package/dist/commands/tunnel/index.d.ts.map +1 -1
  4. package/dist/commands/tunnel/index.js +26 -3
  5. package/dist/commands/tunnel/index.js.map +1 -1
  6. package/dist/commands/tunnel/lb.d.ts +6 -0
  7. package/dist/commands/tunnel/lb.d.ts.map +1 -0
  8. package/dist/commands/tunnel/lb.js +148 -0
  9. package/dist/commands/tunnel/lb.js.map +1 -0
  10. package/dist/commands/tunnel/types.d.ts +1 -1
  11. package/dist/commands/tunnel/types.d.ts.map +1 -1
  12. package/dist/mcp/code-mode/executor.d.ts +32 -0
  13. package/dist/mcp/code-mode/executor.d.ts.map +1 -0
  14. package/dist/mcp/code-mode/executor.js +173 -0
  15. package/dist/mcp/code-mode/executor.js.map +1 -0
  16. package/dist/mcp/code-mode/index.d.ts +12 -0
  17. package/dist/mcp/code-mode/index.d.ts.map +1 -0
  18. package/dist/mcp/code-mode/index.js +11 -0
  19. package/dist/mcp/code-mode/index.js.map +1 -0
  20. package/dist/mcp/code-mode/interface-generator.d.ts +38 -0
  21. package/dist/mcp/code-mode/interface-generator.d.ts.map +1 -0
  22. package/dist/mcp/code-mode/interface-generator.js +159 -0
  23. package/dist/mcp/code-mode/interface-generator.js.map +1 -0
  24. package/dist/mcp/code-mode/provider.d.ts +24 -0
  25. package/dist/mcp/code-mode/provider.d.ts.map +1 -0
  26. package/dist/mcp/code-mode/provider.js +93 -0
  27. package/dist/mcp/code-mode/provider.js.map +1 -0
  28. package/dist/mcp/code-mode/search.d.ts +32 -0
  29. package/dist/mcp/code-mode/search.d.ts.map +1 -0
  30. package/dist/mcp/code-mode/search.js +47 -0
  31. package/dist/mcp/code-mode/search.js.map +1 -0
  32. package/dist/mcp/code-mode/tool-registry.d.ts +44 -0
  33. package/dist/mcp/code-mode/tool-registry.d.ts.map +1 -0
  34. package/dist/mcp/code-mode/tool-registry.js +196 -0
  35. package/dist/mcp/code-mode/tool-registry.js.map +1 -0
  36. package/dist/mcp/code-mode/types.d.ts +41 -0
  37. package/dist/mcp/code-mode/types.d.ts.map +1 -0
  38. package/dist/mcp/code-mode/types.js +8 -0
  39. package/dist/mcp/code-mode/types.js.map +1 -0
  40. package/dist/mcp/daemon/entry.js +8 -1
  41. package/dist/mcp/daemon/entry.js.map +1 -1
  42. package/dist/mcp/providers/atlassian/tools/confluence.d.ts.map +1 -1
  43. package/dist/mcp/providers/atlassian/tools/confluence.js +17 -9
  44. package/dist/mcp/providers/atlassian/tools/confluence.js.map +1 -1
  45. package/dist/mcp/providers/atlassian/tools/jira.d.ts.map +1 -1
  46. package/dist/mcp/providers/atlassian/tools/jira.js +33 -14
  47. package/dist/mcp/providers/atlassian/tools/jira.js.map +1 -1
  48. package/dist/mcp/providers/gitlab/tools/issues.d.ts.map +1 -1
  49. package/dist/mcp/providers/gitlab/tools/issues.js +9 -5
  50. package/dist/mcp/providers/gitlab/tools/issues.js.map +1 -1
  51. package/dist/mcp/providers/gitlab/tools/merge-requests.js +31 -14
  52. package/dist/mcp/providers/gitlab/tools/merge-requests.js.map +1 -1
  53. package/dist/mcp/providers/gitlab/tools/pipelines.d.ts.map +1 -1
  54. package/dist/mcp/providers/gitlab/tools/pipelines.js +9 -5
  55. package/dist/mcp/providers/gitlab/tools/pipelines.js.map +1 -1
  56. package/dist/mcp/providers/gitlab/tools/repository.d.ts.map +1 -1
  57. package/dist/mcp/providers/gitlab/tools/repository.js +122 -96
  58. package/dist/mcp/providers/gitlab/tools/repository.js.map +1 -1
  59. package/dist/mcp/providers/tool-helpers.d.ts +33 -8
  60. package/dist/mcp/providers/tool-helpers.d.ts.map +1 -1
  61. package/dist/mcp/providers/tool-helpers.js +58 -4
  62. package/dist/mcp/providers/tool-helpers.js.map +1 -1
  63. 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 49 GitLab and Atlassian tools |
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 49 tools and 6 resource templates for GitLab and Atlassian. Any MCP-compatible client — Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, etc. — can call these tools directly.
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.23"
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 RDS databases via SSM Session Manager.
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
- ### Example Output
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;AAI3C;;GAEG;AACH,eAAO,MAAM,aAAa,SASH,CAAC;AAExB;;GAEG;AACH,iBAAe,YAAY,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CA8Cf;AAGD,OAAO,EAAE,YAAY,EAAE,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('<target>', 'Target service type (rds)')
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":"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"}
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,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,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,2DAA2D,CAAC;KACjF,QAAQ,CAAC,UAAU,EAAE,+BAA+B,CAAC;KACrD,MAAM,CAAC,sBAAsB,EAAE,oBAAoB,CAAC;KACpD,MAAM,CAAC,qBAAqB,EAAE,2BAA2B,CAAC;KAC1D,MAAM,CAAC,kBAAkB,EAAE,8BAA8B,CAAC;KAC1D,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC;KAC9C,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB;;GAEG;AACH,KAAK,UAAU,YAAY,CACzB,MAAc,EACd,MAA0B,EAC1B,OAAsB;IAEtB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;IAEzC,sBAAsB;IACtB,MAAM,QAAQ,GAAG,yBAAyB,EAAE,CAAC;IAC7C,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;YAC9E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,YAAY,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6EAA6E;IAC7E,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,MAAM,KAAK,SAAS,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACxE,MAAM,GAAG,MAAM,CAAC;QAChB,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,QAAQ,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7B,KAAK,KAAK;gBACR,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;gBAC/F,CAAC;gBACD,MAAM,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBACtC,MAAM;YACR,KAAK,IAAI;gBACP,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;gBAC7B,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAI,KAAe,CAAC,OAAO,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,sBAAsB;AACtB,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { TunnelOptions } from './types.js';
2
+ /**
3
+ * Start an LB tunnel via SSM Session Manager to the internal ALB
4
+ */
5
+ export declare function startLbTunnel(options: TunnelOptions): Promise<void>;
6
+ //# sourceMappingURL=lb.d.ts.map
@@ -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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"}
@@ -4,7 +4,7 @@
4
4
  /**
5
5
  * Tunnel target types
6
6
  */
7
- export type TunnelTarget = 'rds' | 'opensearch' | 'ec2';
7
+ export type TunnelTarget = 'rds' | 'opensearch' | 'ec2' | 'lb';
8
8
  /**
9
9
  * Options for the tunnel command
10
10
  */
@@ -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;AAExD;;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"}
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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"}