zero-config-cli-bridge 1.5.0 → 2.0.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.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * True server-side Human-in-the-Loop gate.
3
+ *
4
+ * The MCP connection stays pending (agent receives nothing) until a human
5
+ * physically types 'y' at the terminal where this server runs.
6
+ *
7
+ * Uses /dev/tty for input — stdin is occupied by the MCP protocol and must
8
+ * not be consumed. /dev/tty provides direct TTY access regardless of how
9
+ * stdin/stdout are redirected, exactly as sudo(8) and ssh(1) do.
10
+ *
11
+ * If no TTY is available (headless server, CI environment), the request is
12
+ * denied by default — fail-closed, not fail-open.
13
+ */
14
+ export declare function requestApproval(preview: string): Promise<boolean>;
15
+ //# sourceMappingURL=approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwCvE"}
@@ -0,0 +1,48 @@
1
+ import { createReadStream } from 'fs';
2
+ import { createInterface } from 'readline';
3
+ /**
4
+ * True server-side Human-in-the-Loop gate.
5
+ *
6
+ * The MCP connection stays pending (agent receives nothing) until a human
7
+ * physically types 'y' at the terminal where this server runs.
8
+ *
9
+ * Uses /dev/tty for input — stdin is occupied by the MCP protocol and must
10
+ * not be consumed. /dev/tty provides direct TTY access regardless of how
11
+ * stdin/stdout are redirected, exactly as sudo(8) and ssh(1) do.
12
+ *
13
+ * If no TTY is available (headless server, CI environment), the request is
14
+ * denied by default — fail-closed, not fail-open.
15
+ */
16
+ export async function requestApproval(preview) {
17
+ process.stderr.write('\n\x1b[33m━━━ APPROVAL REQUIRED ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m\n' +
18
+ '\x1b[33mAn agent wants to execute a write operation:\x1b[0m\n\n' +
19
+ ` \x1b[1m${preview}\x1b[0m\n\n` +
20
+ 'Type \x1b[32my\x1b[0m to approve, anything else to deny: ');
21
+ return new Promise((resolve) => {
22
+ let tty = null;
23
+ try {
24
+ tty = createReadStream('/dev/tty');
25
+ }
26
+ catch {
27
+ process.stderr.write('\x1b[31mNo TTY available — denied by default.\x1b[0m\n');
28
+ resolve(false);
29
+ return;
30
+ }
31
+ const rl = createInterface({ input: tty });
32
+ rl.once('line', (line) => {
33
+ rl.close();
34
+ tty?.destroy();
35
+ const approved = line.trim().toLowerCase() === 'y';
36
+ process.stderr.write(approved
37
+ ? '\x1b[32m✓ Approved — executing.\x1b[0m\n'
38
+ : '\x1b[31m✗ Denied — operation cancelled.\x1b[0m\n');
39
+ resolve(approved);
40
+ });
41
+ tty.on('error', () => {
42
+ rl.close();
43
+ process.stderr.write('\x1b[31mTTY error — denied by default.\x1b[0m\n');
44
+ resolve(false);
45
+ });
46
+ });
47
+ }
48
+ //# sourceMappingURL=approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,IAAI,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe;IACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6EAA6E;QAC7E,iEAAiE;QACjE,YAAY,OAAO,aAAa;QAChC,2DAA2D,CAC5D,CAAC;IAEF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,GAAG,GAA+C,IAAI,CAAC;QAE3D,IAAI,CAAC;YACH,GAAG,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;YAC/E,OAAO,CAAC,KAAK,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAE3C,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,EAAE,OAAO,EAAE,CAAC;YAEf,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC;YACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,QAAQ;gBACN,CAAC,CAAC,0CAA0C;gBAC5C,CAAC,CAAC,kDAAkD,CACvD,CAAC;YACF,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACxE,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/index.js CHANGED
@@ -3,16 +3,14 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
5
  import { executeCommand } from './executor.js';
6
- import { validateSubcommand, validateArgs } from './security.js';
7
- import { buildToolDefinitions, buildGhArgs } from './schema.js';
6
+ import { getOperationTier, validateArgs } from './security.js';
7
+ import { buildToolDefinitions, buildGhArgs, buildCommandPreview } from './schema.js';
8
+ import { requestApproval } from './approval.js';
8
9
  const MAX_JSON_ITEMS = 30;
9
- const MAX_SERIALISED_CHARS = 200_000; // 200 KB cap for non-array JSON objects
10
+ const MAX_SERIALISED_CHARS = 200_000;
10
11
  /**
11
- * Converts gh stdout (JSON) into a bounded, always-valid envelope.
12
- * Called only when exitCode === 0.
13
- *
14
- * stdout is passed unmodified from executor — no byte-level truncation
15
- * has occurred. item-level truncation is the sole guard here.
12
+ * Converts gh stdout (always JSON when --json flag is used) into a bounded envelope.
13
+ * Called only on exitCode === 0.
16
14
  */
17
15
  function stdoutToEnvelope(stdout) {
18
16
  if (!stdout.trim()) {
@@ -23,16 +21,11 @@ function stdoutToEnvelope(stdout) {
23
21
  parsed = JSON.parse(stdout);
24
22
  }
25
23
  catch {
26
- // gh returned non-JSON despite --json flag (should not happen in normal operation)
27
24
  return {
28
25
  data: null,
29
- meta: {
30
- truncated: false,
31
- error: `Unexpected non-JSON output from gh: ${stdout.slice(0, 200)}`,
32
- },
26
+ meta: { truncated: false, error: `Unexpected non-JSON output: ${stdout.slice(0, 200)}` },
33
27
  };
34
28
  }
35
- // Array response: truncate at item level — primary case for list commands
36
29
  if (Array.isArray(parsed)) {
37
30
  const truncated = parsed.length > MAX_JSON_ITEMS;
38
31
  const data = truncated ? parsed.slice(0, MAX_JSON_ITEMS) : parsed;
@@ -47,37 +40,33 @@ function stdoutToEnvelope(stdout) {
47
40
  },
48
41
  };
49
42
  }
50
- // Non-array JSON object: guard against unbounded size
43
+ // Non-array (e.g. single created resource from write command)
51
44
  const serialised = JSON.stringify(parsed);
52
45
  if (serialised.length > MAX_SERIALISED_CHARS) {
53
46
  return {
54
47
  data: null,
55
- meta: {
56
- truncated: true,
57
- error: `Response object too large (${serialised.length} chars). Use filters to narrow results.`,
58
- },
48
+ meta: { truncated: true, error: `Response too large (${serialised.length} chars).` },
59
49
  };
60
50
  }
61
51
  return { data: parsed, meta: { truncated: false } };
62
52
  }
63
- /**
64
- * Wraps an error string in the standard envelope.
65
- * stderr is already bounded to 4KB by executor.
66
- */
67
53
  function stderrToEnvelope(stderr, stdout) {
68
54
  const error = (stderr || stdout || 'Command failed with no output').trim();
69
55
  return { data: null, meta: { truncated: false, error } };
70
56
  }
71
- function envelopeToResponse(envelope, isError) {
57
+ function envelopeResponse(envelope, isError) {
72
58
  return {
73
59
  content: [{ type: 'text', text: JSON.stringify(envelope, null, 2) }],
74
60
  isError,
75
61
  };
76
62
  }
77
- // Tool registry is synchronously populated at startup — no subprocess calls.
63
+ function errorEnvelope(message) {
64
+ return envelopeResponse({ data: null, meta: { truncated: false, error: message } }, true);
65
+ }
66
+ // Tool registry populated synchronously at startup — no subprocess overhead.
78
67
  const tools = buildToolDefinitions();
79
68
  const toolRegistry = new Map(tools.map((t) => [t.name, t]));
80
- const server = new Server({ name: 'zero-config-cli-bridge', version: '1.4.0' }, { capabilities: { tools: {} } });
69
+ const server = new Server({ name: 'zero-config-cli-bridge', version: '2.0.0' }, { capabilities: { tools: {} } });
81
70
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
82
71
  tools: Array.from(toolRegistry.values()).map(({ name, description, inputSchema }) => ({
83
72
  name,
@@ -89,33 +78,42 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
89
78
  const { name: toolName, arguments: rawArgs } = request.params;
90
79
  const args = (rawArgs ?? {});
91
80
  const tool = toolRegistry.get(toolName);
92
- if (!tool) {
93
- return envelopeToResponse({ data: null, meta: { truncated: false, error: `Unknown tool "${toolName}".` } }, true);
94
- }
95
- // Security: whitelist subcommand + validate arg values
81
+ if (!tool)
82
+ return errorEnvelope(`Unknown tool "${toolName}".`);
83
+ // Security: verify subcommand is in allow-list and get its tier
84
+ let tier;
96
85
  try {
97
- validateSubcommand(tool.subcommand.join(' '));
98
86
  validateArgs(args);
87
+ tier = getOperationTier(tool.subcommand.join(' '));
99
88
  }
100
89
  catch (err) {
101
- return envelopeToResponse({ data: null, meta: { truncated: false, error: err instanceof Error ? err.message : String(err) } }, true);
90
+ return errorEnvelope(err instanceof Error ? err.message : String(err));
91
+ }
92
+ // Tier 3: never executes (not exposed as tools, but guard defensively)
93
+ if (tier === 3) {
94
+ return errorEnvelope('Irreversible operations are not permitted.');
95
+ }
96
+ // Tier 2: block until human physically approves at the terminal
97
+ if (tier === 2) {
98
+ const preview = buildCommandPreview(tool, args);
99
+ const approved = await requestApproval(preview);
100
+ if (!approved) {
101
+ return errorEnvelope('Operation denied by human operator.');
102
+ }
102
103
  }
103
- // Direct spawn no shell, no injection surface
104
+ // Executedirect spawn, no shell
104
105
  const ghArgs = buildGhArgs(tool, args);
105
106
  let result;
106
107
  try {
107
108
  result = await executeCommand('gh', ghArgs);
108
109
  }
109
110
  catch (err) {
110
- return envelopeToResponse({ data: null, meta: { truncated: false, error: `Execution error: ${err instanceof Error ? err.message : String(err)}` } }, true);
111
+ return errorEnvelope(`Execution error: ${err instanceof Error ? err.message : String(err)}`);
111
112
  }
112
- // stdout and stderr are semantically distinct:
113
- // exitCode === 0 → stdout is structured JSON data; stderr is ignored warnings
114
- // exitCode !== 0 → stderr is the error message; stdout is typically empty
115
113
  if (result.exitCode !== 0) {
116
- return envelopeToResponse(stderrToEnvelope(result.stderr, result.stdout), true);
114
+ return envelopeResponse(stderrToEnvelope(result.stderr, result.stdout), true);
117
115
  }
118
- return envelopeToResponse(stdoutToEnvelope(result.stdout), false);
116
+ return envelopeResponse(stdoutToEnvelope(result.stdout), false);
119
117
  });
120
118
  async function main() {
121
119
  const transport = new StdioServerTransport();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/schema.d.ts CHANGED
@@ -1,17 +1,4 @@
1
- /**
2
- * Schema definitions for exposed gh tools.
3
- *
4
- * Field list design:
5
- * STATIC_FIELDS is the authoritative source of truth.
6
- * It contains only fields that work with the standard `repo` OAuth scope
7
- * and have been stable across gh major versions.
8
- *
9
- * The probe (detectJsonFields) is NOT called at startup.
10
- * Rationale: the probe has no reliability guarantee — gh's output format
11
- * is human-readable and can change with any release. Running an unreliable
12
- * subprocess at every server start adds latency and timeout risk for zero
13
- * guaranteed gain. Static fields are the correct default.
14
- */
1
+ import type { OperationTier } from './security.js';
15
2
  export interface ToolDefinition {
16
3
  name: string;
17
4
  description: string;
@@ -24,7 +11,9 @@ export interface ToolDefinition {
24
11
  required?: string[];
25
12
  };
26
13
  subcommand: string[];
27
- jsonFields: string[];
14
+ tier: OperationTier;
15
+ /** For read (Tier 0) tools: --json fields to request */
16
+ jsonFields?: string[];
28
17
  }
29
18
  export declare function buildToolDefinitions(): ToolDefinition[];
30
19
  /**
@@ -33,4 +22,6 @@ export declare function buildToolDefinitions(): ToolDefinition[];
33
22
  * misinterpreted as a separate flag by gh's argument parser.
34
23
  */
35
24
  export declare function buildGhArgs(tool: ToolDefinition, args: Record<string, unknown>): string[];
25
+ /** Human-readable preview of the command an agent intends to execute */
26
+ export declare function buildCommandPreview(tool: ToolDefinition, args: Record<string, unknown>): string;
36
27
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAiBD,wBAAgB,oBAAoB,IAAI,cAAc,EAAE,CAyCvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAWzF"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,aAAa,CAAC;IACpB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAwBD,wBAAgB,oBAAoB,IAAI,cAAc,EAAE,CA0GvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAkDzF;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAE/F"}
package/dist/schema.js CHANGED
@@ -1,20 +1,6 @@
1
- /**
2
- * Schema definitions for exposed gh tools.
3
- *
4
- * Field list design:
5
- * STATIC_FIELDS is the authoritative source of truth.
6
- * It contains only fields that work with the standard `repo` OAuth scope
7
- * and have been stable across gh major versions.
8
- *
9
- * The probe (detectJsonFields) is NOT called at startup.
10
- * Rationale: the probe has no reliability guarantee — gh's output format
11
- * is human-readable and can change with any release. Running an unreliable
12
- * subprocess at every server start adds latency and timeout risk for zero
13
- * guaranteed gain. Static fields are the correct default.
14
- */
15
- // Fields verified against `gh issue list --json` and `gh pr list --json` output.
1
+ // Fields verified against `gh issue list --json` and `gh pr list --json`.
16
2
  // Excludes: `id` (requires read:project scope), `body` (unbounded text).
17
- const STATIC_FIELDS = {
3
+ const READ_FIELDS = {
18
4
  'issue list': [
19
5
  'number', 'title', 'state', 'labels', 'assignees',
20
6
  'author', 'createdAt', 'updatedAt', 'closedAt', 'url',
@@ -26,15 +12,22 @@ const STATIC_FIELDS = {
26
12
  'baseRefName', 'headRefName', 'isDraft', 'mergedAt', 'reviewDecision',
27
13
  ],
28
14
  };
15
+ // Fields returned by write commands (small, bounded — single created resource)
16
+ const WRITE_RESPONSE_FIELDS = {
17
+ 'issue create': ['number', 'url', 'title', 'state'],
18
+ 'pr create': ['number', 'url', 'title', 'state', 'baseRefName', 'headRefName'],
19
+ 'issue comment': ['url', 'body'],
20
+ };
29
21
  export function buildToolDefinitions() {
30
22
  return [
23
+ // ── Tier 0: Read ────────────────────────────────────────────────────────
31
24
  {
32
25
  name: 'gh_issue_list',
33
26
  description: 'List GitHub issues as structured JSON. ' +
34
- 'Uses the local `gh` CLI and its existing authentication no API key required. ' +
35
- 'Read-only. Does not create, edit, or delete issues.',
27
+ 'Read-onlyexecutes immediately without approval.',
36
28
  subcommand: ['issue', 'list'],
37
- jsonFields: STATIC_FIELDS['issue list'],
29
+ tier: 0,
30
+ jsonFields: READ_FIELDS['issue list'],
38
31
  inputSchema: {
39
32
  type: 'object',
40
33
  properties: {
@@ -49,10 +42,10 @@ export function buildToolDefinitions() {
49
42
  {
50
43
  name: 'gh_pr_list',
51
44
  description: 'List GitHub pull requests as structured JSON. ' +
52
- 'Uses the local `gh` CLI and its existing authentication no API key required. ' +
53
- 'Read-only. Does not create, edit, merge, or close pull requests.',
45
+ 'Read-onlyexecutes immediately without approval.',
54
46
  subcommand: ['pr', 'list'],
55
- jsonFields: STATIC_FIELDS['pr list'],
47
+ tier: 0,
48
+ jsonFields: READ_FIELDS['pr list'],
56
49
  inputSchema: {
57
50
  type: 'object',
58
51
  properties: {
@@ -64,6 +57,66 @@ export function buildToolDefinitions() {
64
57
  },
65
58
  },
66
59
  },
60
+ // ── Tier 2: Write (requires human TTY approval) ──────────────────────────
61
+ {
62
+ name: 'gh_issue_create',
63
+ description: 'Create a GitHub issue. ' +
64
+ '⚠️ WRITE OPERATION — blocks until a human approves at the terminal. ' +
65
+ 'Uses local `gh` authentication. Requires title.',
66
+ subcommand: ['issue', 'create'],
67
+ tier: 2,
68
+ jsonFields: WRITE_RESPONSE_FIELDS['issue create'],
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ title: { type: 'string', description: 'Issue title (required).' },
73
+ body: { type: 'string', description: 'Issue body text.' },
74
+ repo: { type: 'string', description: 'OWNER/REPO. Omit to use current directory.' },
75
+ label: { type: 'string', description: 'Label name to apply.' },
76
+ assignee: { type: 'string', description: 'Assignee login.' },
77
+ },
78
+ required: ['title'],
79
+ },
80
+ },
81
+ {
82
+ name: 'gh_pr_create',
83
+ description: 'Create a GitHub pull request. ' +
84
+ '⚠️ WRITE OPERATION — blocks until a human approves at the terminal. ' +
85
+ 'Uses local `gh` authentication. Requires title.',
86
+ subcommand: ['pr', 'create'],
87
+ tier: 2,
88
+ jsonFields: WRITE_RESPONSE_FIELDS['pr create'],
89
+ inputSchema: {
90
+ type: 'object',
91
+ properties: {
92
+ title: { type: 'string', description: 'PR title (required).' },
93
+ body: { type: 'string', description: 'PR body text.' },
94
+ base: { type: 'string', description: 'Base branch (default: repo default branch).' },
95
+ head: { type: 'string', description: 'Head branch (default: current branch).' },
96
+ repo: { type: 'string', description: 'OWNER/REPO. Omit to use current directory.' },
97
+ draft: { type: 'boolean', description: 'Open as draft PR.' },
98
+ },
99
+ required: ['title'],
100
+ },
101
+ },
102
+ {
103
+ name: 'gh_issue_comment',
104
+ description: 'Add a comment to a GitHub issue. ' +
105
+ '⚠️ WRITE OPERATION — blocks until a human approves at the terminal. ' +
106
+ 'Uses local `gh` authentication. Requires issue number and body.',
107
+ subcommand: ['issue', 'comment'],
108
+ tier: 2,
109
+ jsonFields: WRITE_RESPONSE_FIELDS['issue comment'],
110
+ inputSchema: {
111
+ type: 'object',
112
+ properties: {
113
+ issue: { type: 'number', description: 'Issue number (required).' },
114
+ body: { type: 'string', description: 'Comment text (required).' },
115
+ repo: { type: 'string', description: 'OWNER/REPO. Omit to use current directory.' },
116
+ },
117
+ required: ['issue', 'body'],
118
+ },
119
+ },
67
120
  ];
68
121
  }
69
122
  /**
@@ -72,19 +125,71 @@ export function buildToolDefinitions() {
72
125
  * misinterpreted as a separate flag by gh's argument parser.
73
126
  */
74
127
  export function buildGhArgs(tool, args) {
75
- const parts = [...tool.subcommand, `--json=${tool.jsonFields.join(',')}`];
76
- if (args['repo'] !== undefined)
77
- parts.push(`--repo=${String(args['repo'])}`);
78
- if (args['limit'] !== undefined)
79
- parts.push(`--limit=${String(args['limit'])}`);
80
- if (args['state'] !== undefined)
81
- parts.push(`--state=${String(args['state'])}`);
82
- if (args['label'] !== undefined && tool.name === 'gh_issue_list')
83
- parts.push(`--label=${String(args['label'])}`);
84
- if (args['assignee'] !== undefined)
85
- parts.push(`--assignee=${String(args['assignee'])}`);
86
- if (args['base'] !== undefined && tool.name === 'gh_pr_list')
87
- parts.push(`--base=${String(args['base'])}`);
128
+ const parts = [...tool.subcommand];
129
+ // All tools request JSON output for structured responses
130
+ if (tool.jsonFields && tool.jsonFields.length > 0) {
131
+ parts.push(`--json=${tool.jsonFields.join(',')}`);
132
+ }
133
+ switch (tool.name) {
134
+ case 'gh_issue_list':
135
+ if (args['repo'])
136
+ parts.push(`--repo=${String(args['repo'])}`);
137
+ if (args['limit'])
138
+ parts.push(`--limit=${String(args['limit'])}`);
139
+ if (args['state'])
140
+ parts.push(`--state=${String(args['state'])}`);
141
+ if (args['label'])
142
+ parts.push(`--label=${String(args['label'])}`);
143
+ if (args['assignee'])
144
+ parts.push(`--assignee=${String(args['assignee'])}`);
145
+ break;
146
+ case 'gh_pr_list':
147
+ if (args['repo'])
148
+ parts.push(`--repo=${String(args['repo'])}`);
149
+ if (args['limit'])
150
+ parts.push(`--limit=${String(args['limit'])}`);
151
+ if (args['state'])
152
+ parts.push(`--state=${String(args['state'])}`);
153
+ if (args['base'])
154
+ parts.push(`--base=${String(args['base'])}`);
155
+ if (args['assignee'])
156
+ parts.push(`--assignee=${String(args['assignee'])}`);
157
+ break;
158
+ case 'gh_issue_create':
159
+ parts.push(`--title=${String(args['title'])}`);
160
+ if (args['body'])
161
+ parts.push(`--body=${String(args['body'])}`);
162
+ if (args['repo'])
163
+ parts.push(`--repo=${String(args['repo'])}`);
164
+ if (args['label'])
165
+ parts.push(`--label=${String(args['label'])}`);
166
+ if (args['assignee'])
167
+ parts.push(`--assignee=${String(args['assignee'])}`);
168
+ break;
169
+ case 'gh_pr_create':
170
+ parts.push(`--title=${String(args['title'])}`);
171
+ if (args['body'])
172
+ parts.push(`--body=${String(args['body'])}`);
173
+ if (args['base'])
174
+ parts.push(`--base=${String(args['base'])}`);
175
+ if (args['head'])
176
+ parts.push(`--head=${String(args['head'])}`);
177
+ if (args['repo'])
178
+ parts.push(`--repo=${String(args['repo'])}`);
179
+ if (args['draft'])
180
+ parts.push('--draft');
181
+ break;
182
+ case 'gh_issue_comment':
183
+ parts.push(String(args['issue']));
184
+ parts.push(`--body=${String(args['body'])}`);
185
+ if (args['repo'])
186
+ parts.push(`--repo=${String(args['repo'])}`);
187
+ break;
188
+ }
88
189
  return parts;
89
190
  }
191
+ /** Human-readable preview of the command an agent intends to execute */
192
+ export function buildCommandPreview(tool, args) {
193
+ return 'gh ' + buildGhArgs(tool, args).join(' ');
194
+ }
90
195
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,17 @@
2
2
  * Security layer.
3
3
  *
4
4
  * With direct spawn(bin, args[]) there is no shell to inject into.
5
- * This layer provides defense-in-depth by:
6
- * 1. Whitelisting the exact subcommand paths allowed to execute.
7
- * 2. Validating individual argument values for anomalous content.
5
+ * This layer provides defence-in-depth:
6
+ * 1. Whitelists the exact subcommand paths allowed to execute.
7
+ * 2. Associates each subcommand with an operation tier.
8
+ * 3. Validates individual argument values for anomalous content.
9
+ *
10
+ * Tiers:
11
+ * 0 READ — executes immediately, no approval
12
+ * 2 WRITE — blocks until human approves via TTY
13
+ * 3 IRREVERSIBLE — never executes; not exposed as tools
8
14
  */
9
- export declare function validateSubcommand(subcommand: string): void;
15
+ export type OperationTier = 0 | 2 | 3;
16
+ export declare function getOperationTier(subcommand: string): OperationTier;
10
17
  export declare function validateArgs(args: Record<string, unknown>): void;
11
18
  //# sourceMappingURL=security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAM3D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWhE"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAUtC,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAMlE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWhE"}
package/dist/security.js CHANGED
@@ -2,19 +2,29 @@
2
2
  * Security layer.
3
3
  *
4
4
  * With direct spawn(bin, args[]) there is no shell to inject into.
5
- * This layer provides defense-in-depth by:
6
- * 1. Whitelisting the exact subcommand paths allowed to execute.
7
- * 2. Validating individual argument values for anomalous content.
5
+ * This layer provides defence-in-depth:
6
+ * 1. Whitelists the exact subcommand paths allowed to execute.
7
+ * 2. Associates each subcommand with an operation tier.
8
+ * 3. Validates individual argument values for anomalous content.
9
+ *
10
+ * Tiers:
11
+ * 0 READ — executes immediately, no approval
12
+ * 2 WRITE — blocks until human approves via TTY
13
+ * 3 IRREVERSIBLE — never executes; not exposed as tools
8
14
  */
9
- /** Only these gh subcommand paths may execute. */
10
- const ALLOWED_SUBCOMMANDS = new Set([
11
- 'issue list',
12
- 'pr list',
15
+ const SUBCOMMAND_TIERS = new Map([
16
+ ['issue list', 0],
17
+ ['pr list', 0],
18
+ ['issue create', 2],
19
+ ['pr create', 2],
20
+ ['issue comment', 2],
13
21
  ]);
14
- export function validateSubcommand(subcommand) {
15
- if (!ALLOWED_SUBCOMMANDS.has(subcommand)) {
16
- throw new Error(`Error: Subcommand "${subcommand}" is not in the read-only allow-list.`);
22
+ export function getOperationTier(subcommand) {
23
+ const tier = SUBCOMMAND_TIERS.get(subcommand);
24
+ if (tier === undefined) {
25
+ throw new Error(`Error: Subcommand "${subcommand}" is not in the allow-list.`);
17
26
  }
27
+ return tier;
18
28
  }
19
29
  export function validateArgs(args) {
20
30
  for (const [, val] of Object.entries(args)) {
@@ -1 +1 @@
1
- {"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,kDAAkD;AAClD,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IACvD,YAAY;IACZ,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CACb,sBAAsB,UAAU,uCAAuC,CACxE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAA6B;IACxD,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,gBAAgB,GAAuC,IAAI,GAAG,CAAC;IACnE,CAAC,YAAY,EAAK,CAAC,CAAC;IACpB,CAAC,SAAS,EAAQ,CAAC,CAAC;IACpB,CAAC,cAAc,EAAG,CAAC,CAAC;IACpB,CAAC,WAAW,EAAM,CAAC,CAAC;IACpB,CAAC,eAAe,EAAE,CAAC,CAAC;CACrB,CAAC,CAAC;AAEH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,sBAAsB,UAAU,6BAA6B,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAA6B;IACxD,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zero-config-cli-bridge",
3
- "version": "1.5.0",
3
+ "version": "2.0.0",
4
4
  "description": "Zero Setup. Zero API Keys. Expose your local authenticated CLIs as MCP tools.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",