hermes-action-bridge 0.4.0 → 0.5.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/CHANGELOG.md +35 -0
- package/README.md +111 -14
- package/dist/adapters/hermes-cli.d.ts +14 -0
- package/dist/adapters/hermes-cli.js +80 -19
- package/dist/adapters/hermes-cli.js.map +1 -1
- package/dist/approvals.d.ts +35 -0
- package/dist/approvals.js +96 -0
- package/dist/approvals.js.map +1 -0
- package/dist/audit-log.d.ts +21 -0
- package/dist/audit-log.js +31 -0
- package/dist/audit-log.js.map +1 -0
- package/dist/capabilities.d.ts +29 -0
- package/dist/capabilities.js +24 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cli.js +205 -18
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +8 -1
- package/dist/doctor.js +76 -13
- package/dist/doctor.js.map +1 -1
- package/dist/execution-gate.d.ts +5 -0
- package/dist/execution-gate.js +20 -0
- package/dist/execution-gate.js.map +1 -0
- package/dist/http-server.d.ts +18 -0
- package/dist/http-server.js +310 -0
- package/dist/http-server.js.map +1 -0
- package/dist/install/launcher.d.ts +3 -0
- package/dist/install/launcher.js +7 -0
- package/dist/install/launcher.js.map +1 -0
- package/dist/install/mcp-service.d.ts +44 -0
- package/dist/install/mcp-service.js +172 -0
- package/dist/install/mcp-service.js.map +1 -0
- package/dist/install/templates.js +38 -32
- package/dist/install/templates.js.map +1 -1
- package/dist/install/types.d.ts +1 -0
- package/dist/jobs.d.ts +51 -0
- package/dist/jobs.js +244 -0
- package/dist/jobs.js.map +1 -0
- package/dist/mcp-server.d.ts +32 -0
- package/dist/mcp-server.js +382 -25
- package/dist/mcp-server.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/validation.d.ts +1 -0
- package/dist/validation.js +8 -0
- package/dist/validation.js.map +1 -0
- package/docs/ARCHITECTURE.md +67 -7
- package/docs/FUNCTIONAL-TESTS.md +27 -12
- package/examples/claude-code/SKILL.md +35 -29
- package/examples/codex/SKILL.md +35 -29
- package/package.json +5 -3
- package/plugins/hermes-action/.codex-plugin/plugin.json +30 -0
- package/plugins/hermes-action/.mcp.json +8 -0
- package/plugins/hermes-action/assets/app-icon.png +0 -0
- package/plugins/hermes-action/skills/hermes-action-bridge/SKILL.md +61 -0
package/dist/mcp-server.js
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
1
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
5
|
import { z } from "zod";
|
|
6
|
+
import { appendAuditEvent, fingerprintPrompt } from "./audit-log.js";
|
|
7
|
+
import { createApprovalStore } from "./approvals.js";
|
|
8
|
+
import { startHermesCli } from "./adapters/hermes-cli.js";
|
|
9
|
+
import { getBridgeCapabilities } from "./capabilities.js";
|
|
4
10
|
import { loadConfig } from "./config.js";
|
|
11
|
+
import { createExecutionGate } from "./execution-gate.js";
|
|
12
|
+
import { createJobStore, defaultJobMaxOutputBytes } from "./jobs.js";
|
|
5
13
|
import { buildEffectiveRun } from "./run.js";
|
|
6
|
-
import { runHermesCli } from "./adapters/hermes-cli.js";
|
|
7
14
|
import { checkHermesStatus } from "./status.js";
|
|
8
15
|
import { version } from "./version.js";
|
|
9
16
|
const modeSchema = z.enum(["plan", "draft", "execute", "request-approval"]);
|
|
17
|
+
const idSchema = z.string().uuid();
|
|
18
|
+
const serverInstructions = [
|
|
19
|
+
"Use Hermes for capabilities owned by the Hermes runtime: configured skills, connected services, messaging, schedules, browser workflows, and persistent external automation.",
|
|
20
|
+
"Call hermes_capabilities before assuming that a Hermes preset, skill, or toolset is configured.",
|
|
21
|
+
"Prefer hermes_plan or hermes_prepare before an action with external side effects.",
|
|
22
|
+
"Do not delegate ordinary local code edits or repository inspection when the host agent can perform them directly.",
|
|
23
|
+
].join(" ");
|
|
10
24
|
/**
|
|
11
|
-
* Single error boundary for every tool handler:
|
|
12
|
-
*
|
|
13
|
-
*
|
|
25
|
+
* Single error boundary for every tool handler: bad presets, missing context,
|
|
26
|
+
* process errors, storage errors, and serialization become structured MCP
|
|
27
|
+
* errors instead of terminating the server.
|
|
14
28
|
*/
|
|
15
29
|
async function guard(produce) {
|
|
16
30
|
try {
|
|
@@ -21,33 +35,133 @@ async function guard(produce) {
|
|
|
21
35
|
return { content: [{ type: "text", text: `Bridge error: ${message}` }], isError: true };
|
|
22
36
|
}
|
|
23
37
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const run = buildEffectiveRun(config, {
|
|
38
|
+
function effectiveRun(config, options) {
|
|
39
|
+
return buildEffectiveRun(config, {
|
|
27
40
|
prompt: options.prompt,
|
|
28
41
|
mode: options.mode,
|
|
29
42
|
preset: options.preset,
|
|
30
43
|
contextFiles: options.contextFiles ?? [],
|
|
31
44
|
yolo: options.yolo ?? false,
|
|
32
|
-
dryRun,
|
|
45
|
+
dryRun: options.dryRun ?? false,
|
|
33
46
|
json: false,
|
|
34
47
|
provider: options.provider,
|
|
35
48
|
model: options.model,
|
|
36
49
|
maxTurns: options.maxTurns,
|
|
37
50
|
timeoutSeconds: options.timeoutSeconds,
|
|
38
51
|
});
|
|
39
|
-
|
|
52
|
+
}
|
|
53
|
+
async function delegate(config, options) {
|
|
54
|
+
const dryRun = options.dryRun ?? false;
|
|
55
|
+
const run = effectiveRun(config, options);
|
|
56
|
+
const result = await startHermesCli(config, run, dryRun, { maxOutputBytes: defaultJobMaxOutputBytes }).result;
|
|
40
57
|
const sections = [result.stdout, result.stderr].filter((section) => section.trim().length > 0);
|
|
58
|
+
if (result.outputTruncated)
|
|
59
|
+
sections.push(`[Hermes output truncated at ${defaultJobMaxOutputBytes} bytes]`);
|
|
41
60
|
const text = sections.length > 0 ? sections.join("\n") : `Hermes exited with code ${result.exitCode}`;
|
|
42
61
|
const content = [{ type: "text", text }];
|
|
43
62
|
return result.ok ? { content } : { content, isError: true };
|
|
44
63
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
64
|
+
function jsonResult(value) {
|
|
65
|
+
return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
|
|
66
|
+
}
|
|
67
|
+
function defaultAuditFile() {
|
|
68
|
+
if (process.env.HERMES_ACTION_AUDIT_FILE)
|
|
69
|
+
return process.env.HERMES_ACTION_AUDIT_FILE;
|
|
70
|
+
const stateHome = process.env.XDG_STATE_HOME || join(homedir(), ".local", "state");
|
|
71
|
+
return join(stateHome, "hermes-action", "audit.jsonl");
|
|
72
|
+
}
|
|
73
|
+
function auditContext(run, transport, principalId) {
|
|
74
|
+
return {
|
|
75
|
+
principalId,
|
|
76
|
+
transport,
|
|
77
|
+
promptFingerprint: fingerprintPrompt(run.prompt),
|
|
78
|
+
requestedMode: run.requestedMode,
|
|
79
|
+
effectiveMode: run.mode,
|
|
80
|
+
presetName: run.presetName,
|
|
81
|
+
detectedRisks: [...run.detectedRisks],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function auditEvent(phase, requestId, context, terminal) {
|
|
85
|
+
return {
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
phase,
|
|
88
|
+
requestId,
|
|
89
|
+
principalId: context.principalId,
|
|
90
|
+
transport: context.transport,
|
|
91
|
+
requestedMode: context.requestedMode,
|
|
92
|
+
effectiveMode: context.effectiveMode,
|
|
93
|
+
presetName: context.presetName,
|
|
94
|
+
detectedRisks: [...context.detectedRisks],
|
|
95
|
+
promptFingerprint: context.promptFingerprint,
|
|
96
|
+
...(terminal?.exitCode === undefined ? {} : { exitCode: terminal.exitCode }),
|
|
97
|
+
...(terminal?.outcome === undefined ? {} : { outcome: terminal.outcome }),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function terminalOutcome(job) {
|
|
101
|
+
switch (job.status) {
|
|
102
|
+
case "succeeded":
|
|
103
|
+
return "succeeded";
|
|
104
|
+
case "cancelled":
|
|
105
|
+
return "cancelled";
|
|
106
|
+
case "timed_out":
|
|
107
|
+
return "timed_out";
|
|
108
|
+
default:
|
|
109
|
+
return "failed";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export function createBridgeRuntime(config, auditFile = defaultAuditFile()) {
|
|
113
|
+
const jobAudit = new Map();
|
|
114
|
+
const approvalAudit = new Map();
|
|
115
|
+
const jobs = createJobStore((run) => startHermesCli(config, run, false, { maxOutputBytes: defaultJobMaxOutputBytes }), {
|
|
116
|
+
onSettled: (job) => {
|
|
117
|
+
const context = jobAudit.get(job.id);
|
|
118
|
+
if (!context)
|
|
119
|
+
return;
|
|
120
|
+
if (job.status === "timed_out" && !job.startedAt) {
|
|
121
|
+
appendAuditEvent(auditFile, auditEvent("expired", job.id, context));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
appendAuditEvent(auditFile, auditEvent(job.status === "cancelled" ? "cancelled" : "completed", job.id, context, {
|
|
125
|
+
exitCode: job.exitCode,
|
|
126
|
+
outcome: terminalOutcome(job),
|
|
127
|
+
}));
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
const approvals = createApprovalStore({
|
|
131
|
+
onExpired: (approval) => {
|
|
132
|
+
const context = approvalAudit.get(approval.id);
|
|
133
|
+
if (context)
|
|
134
|
+
appendAuditEvent(auditFile, auditEvent("expired", approval.id, context));
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
const cleanupTimer = setInterval(() => {
|
|
138
|
+
jobs.cleanup();
|
|
139
|
+
approvals.cleanup();
|
|
140
|
+
pruneAuditContexts(jobAudit, (id) => jobs.get(id) !== undefined);
|
|
141
|
+
pruneAuditContexts(approvalAudit, (id) => approvals.get(id) !== undefined);
|
|
142
|
+
}, 60_000);
|
|
143
|
+
cleanupTimer.unref();
|
|
144
|
+
return {
|
|
145
|
+
jobs,
|
|
146
|
+
approvals,
|
|
147
|
+
auditFile,
|
|
148
|
+
jobAudit,
|
|
149
|
+
approvalAudit,
|
|
150
|
+
directExecutions: createExecutionGate(),
|
|
151
|
+
dispose: async () => {
|
|
152
|
+
clearInterval(cleanupTimer);
|
|
153
|
+
await jobs.shutdown();
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
export function createBridgeMcpServer(config, options = {}) {
|
|
158
|
+
const transport = options.transport ?? "stdio";
|
|
159
|
+
const principalId = options.principalId ?? transport;
|
|
160
|
+
const runtime = options.runtime ?? createBridgeRuntime(config);
|
|
161
|
+
const server = new McpServer({ name: "hermes-action-bridge", version }, { instructions: serverInstructions });
|
|
48
162
|
server.registerTool("hermes_run", {
|
|
49
163
|
title: "Delegate a request to Hermes",
|
|
50
|
-
description: "
|
|
164
|
+
description: "Use Hermes-owned skills, connected services, browser workflows, messaging, schedules, or external automation through bridge policy. Do not use for ordinary local code edits.",
|
|
51
165
|
inputSchema: {
|
|
52
166
|
prompt: z.string().min(1),
|
|
53
167
|
mode: modeSchema.optional(),
|
|
@@ -60,7 +174,8 @@ export async function startMcpServer(configPath) {
|
|
|
60
174
|
maxTurns: z.number().int().positive().optional(),
|
|
61
175
|
timeoutSeconds: z.number().int().positive().optional(),
|
|
62
176
|
},
|
|
63
|
-
|
|
177
|
+
annotations: { openWorldHint: true },
|
|
178
|
+
}, (args) => guard(() => runtime.directExecutions.run(() => delegate(config, {
|
|
64
179
|
prompt: args.prompt,
|
|
65
180
|
mode: args.mode,
|
|
66
181
|
preset: args.preset,
|
|
@@ -71,25 +186,267 @@ export async function startMcpServer(configPath) {
|
|
|
71
186
|
model: args.model,
|
|
72
187
|
maxTurns: args.maxTurns,
|
|
73
188
|
timeoutSeconds: args.timeoutSeconds,
|
|
74
|
-
})));
|
|
189
|
+
}))));
|
|
75
190
|
server.registerTool("hermes_plan", {
|
|
76
191
|
title: "Ask Hermes for a plan",
|
|
77
|
-
description: "
|
|
78
|
-
inputSchema: {
|
|
79
|
-
|
|
192
|
+
description: "Ask Hermes to inspect its configured capabilities in plan mode. Hermes may access open-world tools, so review the response before taking or approving an external action.",
|
|
193
|
+
inputSchema: {
|
|
194
|
+
prompt: z.string().min(1),
|
|
195
|
+
preset: z.string().optional(),
|
|
196
|
+
contextFiles: z.array(z.string()).optional(),
|
|
197
|
+
},
|
|
198
|
+
annotations: { openWorldHint: true },
|
|
199
|
+
}, (args) => guard(() => runtime.directExecutions.run(() => delegate(config, {
|
|
80
200
|
prompt: args.prompt,
|
|
81
201
|
mode: "plan",
|
|
82
202
|
preset: args.preset,
|
|
83
203
|
contextFiles: args.contextFiles,
|
|
84
|
-
})));
|
|
204
|
+
}))));
|
|
205
|
+
server.registerTool("hermes_capabilities", {
|
|
206
|
+
title: "Discover configured Hermes capabilities",
|
|
207
|
+
description: "Inspect bridge status, configured presets, skills, toolsets, providers, models, and policy before deciding whether Hermes owns the requested capability.",
|
|
208
|
+
inputSchema: {},
|
|
209
|
+
annotations: { readOnlyHint: true },
|
|
210
|
+
}, () => guard(() => jsonResult(getBridgeCapabilities(config, transport))));
|
|
85
211
|
server.registerTool("hermes_presets", {
|
|
86
|
-
title: "List presets",
|
|
87
|
-
description: "List configured
|
|
88
|
-
|
|
212
|
+
title: "List Hermes delegation presets",
|
|
213
|
+
description: "List configured bridge presets and their declarative Hermes skills and toolsets.",
|
|
214
|
+
annotations: { readOnlyHint: true },
|
|
215
|
+
}, () => guard(() => jsonResult(config.presets)));
|
|
89
216
|
server.registerTool("hermes_status", {
|
|
90
217
|
title: "Check Hermes runtime status",
|
|
91
|
-
description: "Check whether the configured Hermes
|
|
92
|
-
|
|
93
|
-
|
|
218
|
+
description: "Check whether the configured Hermes CLI runtime is available without running a provider request.",
|
|
219
|
+
annotations: { readOnlyHint: true },
|
|
220
|
+
}, () => guard(() => jsonResult(checkHermesStatus(config))));
|
|
221
|
+
server.registerTool("hermes_submit", {
|
|
222
|
+
title: "Submit a cancellable Hermes job",
|
|
223
|
+
description: "Start a long Hermes plan, draft, or approval-preview job and return immediately. Direct execute requests are converted to request-approval; use hermes_prepare and hermes_approve for execution.",
|
|
224
|
+
inputSchema: {
|
|
225
|
+
prompt: z.string().min(1),
|
|
226
|
+
mode: modeSchema.optional(),
|
|
227
|
+
preset: z.string().optional(),
|
|
228
|
+
contextFiles: z.array(z.string()).optional(),
|
|
229
|
+
provider: z.string().optional(),
|
|
230
|
+
model: z.string().optional(),
|
|
231
|
+
maxTurns: z.number().int().positive().optional(),
|
|
232
|
+
timeoutSeconds: z.number().int().positive().optional(),
|
|
233
|
+
},
|
|
234
|
+
annotations: { openWorldHint: true },
|
|
235
|
+
}, (args) => guard(() => {
|
|
236
|
+
const built = effectiveRun(config, {
|
|
237
|
+
prompt: args.prompt,
|
|
238
|
+
mode: args.mode,
|
|
239
|
+
preset: args.preset,
|
|
240
|
+
contextFiles: args.contextFiles,
|
|
241
|
+
provider: args.provider,
|
|
242
|
+
model: args.model,
|
|
243
|
+
maxTurns: args.maxTurns,
|
|
244
|
+
timeoutSeconds: args.timeoutSeconds,
|
|
245
|
+
});
|
|
246
|
+
const run = {
|
|
247
|
+
...built,
|
|
248
|
+
mode: built.mode === "execute" ? "request-approval" : built.mode,
|
|
249
|
+
yolo: false,
|
|
250
|
+
};
|
|
251
|
+
const context = auditContext(run, transport, principalId);
|
|
252
|
+
return jsonResult(submitAuditedJob(runtime, run, context));
|
|
253
|
+
}));
|
|
254
|
+
server.registerTool("hermes_job_status", {
|
|
255
|
+
title: "Check a Hermes job",
|
|
256
|
+
description: "Read lifecycle metadata for an asynchronous Hermes job without returning its output.",
|
|
257
|
+
inputSchema: { jobId: idSchema },
|
|
258
|
+
annotations: { readOnlyHint: true },
|
|
259
|
+
}, ({ jobId }) => guard(() => {
|
|
260
|
+
ensureJobOwner(runtime, jobId, principalId);
|
|
261
|
+
const job = runtime.jobs.get(jobId);
|
|
262
|
+
if (!job)
|
|
263
|
+
throw new Error(`Unknown job: ${jobId}`);
|
|
264
|
+
const { output: _output, ...status } = job;
|
|
265
|
+
return jsonResult(status);
|
|
266
|
+
}));
|
|
267
|
+
server.registerTool("hermes_result", {
|
|
268
|
+
title: "Read a Hermes job result",
|
|
269
|
+
description: "Read the bounded stdout/stderr result of a completed asynchronous Hermes job.",
|
|
270
|
+
inputSchema: { jobId: idSchema },
|
|
271
|
+
annotations: { readOnlyHint: true },
|
|
272
|
+
}, ({ jobId }) => guard(() => {
|
|
273
|
+
ensureJobOwner(runtime, jobId, principalId);
|
|
274
|
+
const job = runtime.jobs.get(jobId);
|
|
275
|
+
if (!job)
|
|
276
|
+
throw new Error(`Unknown job: ${jobId}`);
|
|
277
|
+
return jsonResult(job);
|
|
278
|
+
}));
|
|
279
|
+
server.registerTool("hermes_cancel", {
|
|
280
|
+
title: "Cancel a Hermes job",
|
|
281
|
+
description: "Idempotently cancel a queued or running asynchronous Hermes job.",
|
|
282
|
+
inputSchema: { jobId: idSchema },
|
|
283
|
+
}, ({ jobId }) => guard(() => {
|
|
284
|
+
ensureJobOwner(runtime, jobId, principalId);
|
|
285
|
+
const job = runtime.jobs.cancel(jobId);
|
|
286
|
+
if (!job)
|
|
287
|
+
throw new Error(`Unknown job: ${jobId}`);
|
|
288
|
+
return jsonResult(job);
|
|
289
|
+
}));
|
|
290
|
+
server.registerTool("hermes_prepare", {
|
|
291
|
+
title: "Prepare an external action for approval",
|
|
292
|
+
description: "Create a local, non-executing preview and short-lived one-shot approval ID without invoking Hermes or its tools. The caller must show preview.action to the human before approval.",
|
|
293
|
+
inputSchema: {
|
|
294
|
+
prompt: z.string().min(1),
|
|
295
|
+
preset: z.string().optional(),
|
|
296
|
+
contextFiles: z.array(z.string()).optional(),
|
|
297
|
+
provider: z.string().optional(),
|
|
298
|
+
model: z.string().optional(),
|
|
299
|
+
maxTurns: z.number().int().positive().optional(),
|
|
300
|
+
timeoutSeconds: z.number().int().positive().optional(),
|
|
301
|
+
},
|
|
302
|
+
annotations: { openWorldHint: true },
|
|
303
|
+
}, (args) => guard(() => {
|
|
304
|
+
const built = effectiveRun(config, {
|
|
305
|
+
prompt: args.prompt,
|
|
306
|
+
mode: "execute",
|
|
307
|
+
preset: args.preset,
|
|
308
|
+
contextFiles: args.contextFiles,
|
|
309
|
+
provider: args.provider,
|
|
310
|
+
model: args.model,
|
|
311
|
+
maxTurns: args.maxTurns,
|
|
312
|
+
timeoutSeconds: args.timeoutSeconds,
|
|
313
|
+
});
|
|
314
|
+
const run = { ...built, mode: "request-approval", yolo: false };
|
|
315
|
+
const approval = runtime.approvals.prepare(run);
|
|
316
|
+
const context = auditContext(run, transport, principalId);
|
|
317
|
+
runtime.approvalAudit.set(approval.id, context);
|
|
318
|
+
try {
|
|
319
|
+
appendAuditEvent(runtime.auditFile, auditEvent("prepared", approval.id, context));
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
runtime.approvals.reject(approval.id);
|
|
323
|
+
runtime.approvalAudit.delete(approval.id);
|
|
324
|
+
throw error;
|
|
325
|
+
}
|
|
326
|
+
return jsonResult({
|
|
327
|
+
...approval,
|
|
328
|
+
preview: {
|
|
329
|
+
action: run.prompt,
|
|
330
|
+
presetName: run.presetName,
|
|
331
|
+
requestedMode: run.requestedMode,
|
|
332
|
+
effectiveMode: run.mode,
|
|
333
|
+
detectedRisks: run.detectedRisks,
|
|
334
|
+
contextFiles: run.contextDocuments.map((document) => document.path),
|
|
335
|
+
promptFingerprint: context.promptFingerprint,
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
}));
|
|
339
|
+
server.registerTool("hermes_approve", {
|
|
340
|
+
title: "Approve and submit a prepared Hermes action",
|
|
341
|
+
description: "Consume a prepared approval ID exactly once and submit the unchanged request for execution. This can cause external side effects.",
|
|
342
|
+
inputSchema: { approvalId: idSchema },
|
|
343
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
344
|
+
}, ({ approvalId }) => guard(() => {
|
|
345
|
+
const context = ensureApprovalOwner(runtime, approvalId, principalId);
|
|
346
|
+
const current = runtime.approvals.get(approvalId);
|
|
347
|
+
if (!current || current.status !== "awaiting_approval") {
|
|
348
|
+
throw new Error(`Approval is unavailable, expired, or already consumed: ${approvalId}`);
|
|
349
|
+
}
|
|
350
|
+
if (!runtime.jobs.canSubmit())
|
|
351
|
+
throw new Error("Hermes job queue is full; approval was not consumed");
|
|
352
|
+
appendAuditEvent(runtime.auditFile, auditEvent("approved", approvalId, context));
|
|
353
|
+
const consumed = runtime.approvals.approve(approvalId);
|
|
354
|
+
if (!consumed)
|
|
355
|
+
throw new Error(`Approval is unavailable, expired, or already consumed: ${approvalId}`);
|
|
356
|
+
const run = { ...consumed.run, mode: "execute", requestedMode: "execute" };
|
|
357
|
+
const jobContext = { ...context, effectiveMode: "execute" };
|
|
358
|
+
const job = submitAuditedJob(runtime, run, jobContext, consumed.approval.expiresAt);
|
|
359
|
+
runtime.approvalAudit.delete(approvalId);
|
|
360
|
+
return jsonResult({ approval: consumed.approval, job });
|
|
361
|
+
}));
|
|
362
|
+
server.registerTool("hermes_reject", {
|
|
363
|
+
title: "Reject a prepared Hermes action",
|
|
364
|
+
description: "Consume a prepared approval ID without executing the external action.",
|
|
365
|
+
inputSchema: { approvalId: idSchema },
|
|
366
|
+
}, ({ approvalId }) => guard(() => {
|
|
367
|
+
const context = ensureApprovalOwner(runtime, approvalId, principalId);
|
|
368
|
+
const current = runtime.approvals.get(approvalId);
|
|
369
|
+
if (!current || current.status !== "awaiting_approval") {
|
|
370
|
+
throw new Error(`Approval is unavailable, expired, or already consumed: ${approvalId}`);
|
|
371
|
+
}
|
|
372
|
+
appendAuditEvent(runtime.auditFile, auditEvent("rejected", approvalId, context));
|
|
373
|
+
const rejected = runtime.approvals.reject(approvalId);
|
|
374
|
+
if (!rejected)
|
|
375
|
+
throw new Error(`Unknown approval: ${approvalId}`);
|
|
376
|
+
runtime.approvalAudit.delete(approvalId);
|
|
377
|
+
return jsonResult(rejected);
|
|
378
|
+
}));
|
|
379
|
+
return server;
|
|
380
|
+
}
|
|
381
|
+
function ensureJobOwner(runtime, jobId, principalId) {
|
|
382
|
+
const owner = runtime.jobAudit.get(jobId);
|
|
383
|
+
if (!owner)
|
|
384
|
+
throw new Error(`Unknown job: ${jobId}`);
|
|
385
|
+
if (owner.principalId !== principalId)
|
|
386
|
+
throw new Error(`Job is not available to this principal: ${jobId}`);
|
|
387
|
+
}
|
|
388
|
+
function submitAuditedJob(runtime, run, context, startBefore) {
|
|
389
|
+
const job = runtime.jobs.submit(run, {
|
|
390
|
+
beforeStart: (queuedJob) => {
|
|
391
|
+
runtime.jobAudit.set(queuedJob.id, context);
|
|
392
|
+
appendAuditEvent(runtime.auditFile, auditEvent("submitted", queuedJob.id, context));
|
|
393
|
+
},
|
|
394
|
+
startBefore,
|
|
395
|
+
});
|
|
396
|
+
runtime.jobAudit.set(job.id, context);
|
|
397
|
+
return job;
|
|
398
|
+
}
|
|
399
|
+
function ensureApprovalOwner(runtime, approvalId, principalId) {
|
|
400
|
+
const owner = runtime.approvalAudit.get(approvalId);
|
|
401
|
+
if (!owner)
|
|
402
|
+
throw new Error(`Unknown approval: ${approvalId}`);
|
|
403
|
+
if (owner.principalId !== principalId)
|
|
404
|
+
throw new Error(`Approval is not available to this principal: ${approvalId}`);
|
|
405
|
+
return owner;
|
|
406
|
+
}
|
|
407
|
+
function pruneAuditContexts(contexts, exists) {
|
|
408
|
+
for (const id of contexts.keys()) {
|
|
409
|
+
if (!exists(id))
|
|
410
|
+
contexts.delete(id);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
export async function startMcpServer(configPath) {
|
|
414
|
+
const config = loadConfig(process.cwd(), configPath);
|
|
415
|
+
const runtime = createBridgeRuntime(config);
|
|
416
|
+
const server = createBridgeMcpServer(config, { runtime });
|
|
417
|
+
const transport = new StdioServerTransport();
|
|
418
|
+
let disposePromise;
|
|
419
|
+
const disposeRuntime = () => {
|
|
420
|
+
disposePromise ??= runtime.dispose();
|
|
421
|
+
return disposePromise;
|
|
422
|
+
};
|
|
423
|
+
const removeSignalHandlers = () => {
|
|
424
|
+
process.off("SIGINT", onSignal);
|
|
425
|
+
process.off("SIGTERM", onSignal);
|
|
426
|
+
};
|
|
427
|
+
const shutdown = async () => {
|
|
428
|
+
await disposeRuntime();
|
|
429
|
+
await server.close().catch(() => undefined);
|
|
430
|
+
removeSignalHandlers();
|
|
431
|
+
};
|
|
432
|
+
const onSignal = () => {
|
|
433
|
+
void shutdown().catch((error) => {
|
|
434
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
435
|
+
process.exitCode = 1;
|
|
436
|
+
});
|
|
437
|
+
};
|
|
438
|
+
transport.onclose = () => {
|
|
439
|
+
void disposeRuntime().finally(removeSignalHandlers);
|
|
440
|
+
};
|
|
441
|
+
process.once("SIGINT", onSignal);
|
|
442
|
+
process.once("SIGTERM", onSignal);
|
|
443
|
+
try {
|
|
444
|
+
await server.connect(transport);
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
removeSignalHandlers();
|
|
448
|
+
await disposeRuntime();
|
|
449
|
+
throw error;
|
|
450
|
+
}
|
|
94
451
|
}
|
|
95
452
|
//# sourceMappingURL=mcp-server.js.map
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -80,6 +80,8 @@ export interface AdapterResult {
|
|
|
80
80
|
/** The full constructed envelope. For large payloads this is what was written to the temp file, not the short `-q` pointer in `command`. */
|
|
81
81
|
prompt: string;
|
|
82
82
|
dryRun: boolean;
|
|
83
|
+
/** True when a bounded capture omitted additional child or dry-run output. */
|
|
84
|
+
outputTruncated?: boolean;
|
|
83
85
|
/** True when the child was killed because it exceeded the timeout. */
|
|
84
86
|
timedOut?: boolean;
|
|
85
87
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function positiveInteger(value: number | undefined, fallback: number, name: string): number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function positiveInteger(value, fallback, name) {
|
|
2
|
+
if (value === undefined)
|
|
3
|
+
return fallback;
|
|
4
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
5
|
+
throw new Error(`${name} must be a positive safe integer`);
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,KAAyB,EAAE,QAAgB,EAAE,IAAY;IACvF,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,kCAAkC,CAAC,CAAC;IAC3G,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -25,7 +25,12 @@ Hermes skills, tools, browser automation, MCPs, cron jobs, messaging, APIs
|
|
|
25
25
|
- `src/prompt.ts`: prompt envelope sent to Hermes.
|
|
26
26
|
- `src/context.ts`: context file loading with a per-file cap and an aggregate budget.
|
|
27
27
|
- `src/adapters/hermes-cli.ts`: Hermes CLI adapter (argv or temp-file prompt delivery, child-process timeout).
|
|
28
|
-
- `src/mcp-server.ts`:
|
|
28
|
+
- `src/mcp-server.ts`: MCP server factory, delegation tools, jobs, and approval orchestration.
|
|
29
|
+
- `src/http-server.ts`: authenticated, opt-in Streamable HTTP transport.
|
|
30
|
+
- `src/capabilities.ts`: configuration-backed capability inventory.
|
|
31
|
+
- `src/jobs.ts`: bounded process-local asynchronous jobs.
|
|
32
|
+
- `src/approvals.ts`: short-lived, one-shot approval records.
|
|
33
|
+
- `src/audit-log.ts`: privacy-preserving owner-only JSONL audit metadata.
|
|
29
34
|
- `src/status.ts`: runtime availability check.
|
|
30
35
|
- `src/version.ts`: single source of truth for the package version.
|
|
31
36
|
- `src/doctor.ts`: environment checks for `hermes-action doctor`.
|
|
@@ -40,9 +45,14 @@ The `install` / `uninstall` commands install an open-standard `SKILL.md` for Cla
|
|
|
40
45
|
- `src/install/marker-block.ts`: fail-safe marker block for the optional `CLAUDE.md` / `AGENTS.md` hint.
|
|
41
46
|
- `src/install/file-edit.ts`: shared read-edit-write helper used by the hint and the `.mcp.json` writer.
|
|
42
47
|
- `src/install/mcp-config.ts`: MCP snippets and the Claude Code `.mcp.json` merge/unmerge writer.
|
|
48
|
+
- `src/install/mcp-service.ts`: native Codex/Claude MCP registration, inspection, conflict handling, and removal.
|
|
43
49
|
- `src/install/install-service.ts`: per-agent install/uninstall with failure isolation.
|
|
44
50
|
|
|
45
|
-
|
|
51
|
+
The global default is a complete installation: managed skill plus MCP
|
|
52
|
+
registration through each agent's native CLI, using the bridge's absolute
|
|
53
|
+
launcher path. Defaults remain conservative: never modify `CLAUDE.md` /
|
|
54
|
+
`AGENTS.md` without `--project-hint`, never overwrite foreign skills or
|
|
55
|
+
customized MCP entries, and stay idempotent.
|
|
46
56
|
|
|
47
57
|
## Config precedence
|
|
48
58
|
|
|
@@ -68,14 +78,18 @@ Project config:
|
|
|
68
78
|
|
|
69
79
|
The bridge does not decide how Hermes completes the task. It only labels the requested behavior:
|
|
70
80
|
|
|
71
|
-
- `plan`:
|
|
81
|
+
- `plan`: prompt-level plan-only policy; callers must still treat configured Hermes tools as open-world.
|
|
72
82
|
- `draft`: produce an artifact, no external side effects.
|
|
73
83
|
- `execute`: execute allowed actions.
|
|
74
84
|
- `request-approval`: prepare the action and ask for approval.
|
|
75
85
|
|
|
76
86
|
## Policy
|
|
77
87
|
|
|
78
|
-
|
|
88
|
+
Direct CLI and `hermes_run` calls rely on the **host agent's approval prompt**.
|
|
89
|
+
The structured MCP path adds a second deterministic barrier:
|
|
90
|
+
`hermes_prepare` creates a local no-tool summary, stores an immutable short-lived request, and
|
|
91
|
+
`hermes_approve` consumes it exactly once. The bridge never treats its own model
|
|
92
|
+
output as human approval.
|
|
79
93
|
|
|
80
94
|
The bridge's own guard is a secondary, deterministic net: in `mode=execute` it changes the effective mode to `request-approval` unless the preset/policy is explicitly trusted (empty `require_approval_for`) or YOLO is enabled. This is independent of the prompt's language or wording.
|
|
81
95
|
|
|
@@ -104,13 +118,59 @@ Every child process is bounded by a timeout (per-mode defaults, overridable via
|
|
|
104
118
|
|
|
105
119
|
## MCP design
|
|
106
120
|
|
|
107
|
-
The MCP server exposes
|
|
121
|
+
The MCP server exposes orchestration primitives instead of mirroring every
|
|
122
|
+
Hermes tool.
|
|
108
123
|
|
|
109
124
|
Tools:
|
|
110
125
|
|
|
111
126
|
- `hermes_run`
|
|
112
127
|
- `hermes_plan`
|
|
128
|
+
- `hermes_capabilities`
|
|
113
129
|
- `hermes_presets`
|
|
114
130
|
- `hermes_status`
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
- `hermes_submit`
|
|
132
|
+
- `hermes_job_status`
|
|
133
|
+
- `hermes_result`
|
|
134
|
+
- `hermes_cancel`
|
|
135
|
+
- `hermes_prepare`
|
|
136
|
+
- `hermes_approve`
|
|
137
|
+
- `hermes_reject`
|
|
138
|
+
|
|
139
|
+
The server advertises routing instructions that distinguish Hermes-owned
|
|
140
|
+
connected services and automation from ordinary local coding work. Capability
|
|
141
|
+
discovery reports declarative presets and runtime status only; it does not
|
|
142
|
+
claim that a Hermes integration is live without a stable Hermes introspection
|
|
143
|
+
API.
|
|
144
|
+
|
|
145
|
+
Jobs are memory-only, concurrency-limited, cancellable, output-bounded, and
|
|
146
|
+
expire after 24 hours. Approval records expire after 15 minutes and are
|
|
147
|
+
one-shot. Audit JSONL stores only identifiers, modes, risks, prompt hashes, and
|
|
148
|
+
terminal metadata with `0600` permissions.
|
|
149
|
+
|
|
150
|
+
## HTTP transport
|
|
151
|
+
|
|
152
|
+
`hermes-action serve` exposes `/mcp` using Streamable HTTP. It binds loopback by
|
|
153
|
+
default. Direct non-loopback binding requires an explicit address in
|
|
154
|
+
`100.64.0.0/10`, `--allow-tailnet`, and a bearer token read from an environment
|
|
155
|
+
variable. The server validates Host, authenticates in constant time, restricts
|
|
156
|
+
direct peers to Tailscale CGNAT, limits request size and active sessions, and
|
|
157
|
+
never exposes an unauthenticated diagnostics endpoint.
|
|
158
|
+
|
|
159
|
+
Tailscale Serve in front of a loopback listener remains the preferred remote
|
|
160
|
+
deployment because TLS and tailnet identity stay outside the bridge. Requests
|
|
161
|
+
forwarded with a `*.ts.net` Host still require the bridge bearer token.
|
|
162
|
+
|
|
163
|
+
### Transitive Hono advisory
|
|
164
|
+
|
|
165
|
+
MCP SDK 1.29.0 currently depends on `@hono/node-server` 1.x, which npm flags
|
|
166
|
+
under [GHSA-frvp-7c67-39w9](https://github.com/advisories/GHSA-frvp-7c67-39w9).
|
|
167
|
+
That advisory applies only to the package's `serve-static` middleware on
|
|
168
|
+
Windows. The bridge never imports that middleware, serves no static files, and
|
|
169
|
+
rejects every HTTP path except `/mcp`, so the vulnerable code path is not
|
|
170
|
+
reachable here.
|
|
171
|
+
|
|
172
|
+
Re-evaluate this acceptance when the v1 SDK updates its Hono dependency, or
|
|
173
|
+
before adding static-file serving, a Hono middleware layer, or any HTTP route
|
|
174
|
+
that maps request paths to the filesystem. Do not force Hono 2 through an npm
|
|
175
|
+
override: the current SDK declares `^1.19.9`, and doing so produces an invalid
|
|
176
|
+
dependency tree for global installs.
|