@getmarrow/mcp 3.9.60 → 3.9.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -6
- package/dist/cli.js +94 -57
- package/dist/cli.js.map +1 -1
- package/dist/hook-context.d.ts +1 -1
- package/dist/hook-contract.d.ts +6 -6
- package/dist/hook-contract.js +1 -1
- package/dist/hook-pre-action.d.ts.map +1 -1
- package/dist/hook-pre-action.js +4 -2
- package/dist/hook-pre-action.js.map +1 -1
- package/dist/hook-session.d.ts +1 -1
- package/dist/hook.d.ts +1 -1
- package/dist/host-capability.d.ts +60 -0
- package/dist/host-capability.d.ts.map +1 -0
- package/dist/host-capability.js +118 -0
- package/dist/host-capability.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/lifecycle-spool.d.ts +9 -0
- package/dist/lifecycle-spool.d.ts.map +1 -1
- package/dist/lifecycle-spool.js +94 -20
- package/dist/lifecycle-spool.js.map +1 -1
- package/dist/request-reliability.d.ts +3 -1
- package/dist/request-reliability.d.ts.map +1 -1
- package/dist/request-reliability.js +41 -11
- package/dist/request-reliability.js.map +1 -1
- package/dist/runtime-contract.d.ts +1 -0
- package/dist/runtime-contract.d.ts.map +1 -1
- package/dist/runtime-contract.js +72 -11
- package/dist/runtime-contract.js.map +1 -1
- package/dist/spool-command.d.ts +17 -0
- package/dist/spool-command.d.ts.map +1 -0
- package/dist/spool-command.js +26 -0
- package/dist/spool-command.js.map +1 -0
- package/dist/status-cache.d.ts +21 -0
- package/dist/status-cache.d.ts.map +1 -0
- package/dist/status-cache.js +177 -0
- package/dist/status-cache.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -104,7 +104,27 @@ npx -y --package=@getmarrow/mcp@latest marrow-mcp ping
|
|
|
104
104
|
|
|
105
105
|
Detection and notification are automatic. After explicit installer activation, the local controller may restore only Marrow-managed hooks/configuration. Package upgrades, owner policy, credentials, and unrelated configuration remain explicit and subject to the operator's normal change policy.
|
|
106
106
|
|
|
107
|
-
## What's New in v3.9.
|
|
107
|
+
## What's New in v3.9.62
|
|
108
|
+
|
|
109
|
+
v3.9.62 integrates four model-neutral reliability and capability contracts:
|
|
110
|
+
|
|
111
|
+
- standalone `marrow_status` uses the bounded compact API contract and can return a fresh, owner-only last-known status projection without treating it as a live gate or authorization;
|
|
112
|
+
- ordinary runtime responses expose typed `runtime_authorization` backed by the authoritative gate receipt and omit `decision_id` unless the server actually created a decision;
|
|
113
|
+
- `spool-status` and `drain-spool` report the active credential namespace separately from isolated legacy debt, and a clear active namespace exits successfully without replaying, merging, editing, or deleting old-key files;
|
|
114
|
+
- initialize, prompt, setup, and tool responses qualify coverage by `host_capability`: MCP tools are on demand, while native hooks, an owned SDK process, a governed runner, or a custom event adapter cover only the scope proved by observed Marrow receipts.
|
|
115
|
+
|
|
116
|
+
The default surface remains six tools and the prompt remains named `marrow-always-on`. Host and model labels are display-only and never change auth, tenant, plan, policy, proof, schema, or API behavior.
|
|
117
|
+
|
|
118
|
+
## Previous: v3.9.61
|
|
119
|
+
|
|
120
|
+
v3.9.61 keeps an authoritative proof-pack rejection distinct from a control-path outage:
|
|
121
|
+
|
|
122
|
+
- backend `MARROW_PROOF_PACK_INCOMPLETE` responses are reported as `validation` / `proof_required`, not infrastructure failures;
|
|
123
|
+
- the exact missing proof fields and backend repair instruction remain visible to the agent;
|
|
124
|
+
- live proof validation does not return a stale outage brief or unavailable authorization state;
|
|
125
|
+
- proof enforcement remains fail-closed, and successful commit behavior is unchanged.
|
|
126
|
+
|
|
127
|
+
## Previous: v3.9.60
|
|
108
128
|
|
|
109
129
|
v3.9.60 restores the complete control-and-proof loop for ordinary MCP clients:
|
|
110
130
|
|
|
@@ -116,7 +136,7 @@ v3.9.60 restores the complete control-and-proof loop for ordinary MCP clients:
|
|
|
116
136
|
- a plan-gated handoff is reported as unavailable for the current plan, not as an API or authentication outage;
|
|
117
137
|
- the release canary runs with the customer's default client deadlines instead of silently overriding them.
|
|
118
138
|
|
|
119
|
-
MCP-only hosts
|
|
139
|
+
MCP-only hosts receive the same model-neutral control instructions and six-tool default surface, but MCP transport alone is on demand. A host or model label never changes that coverage contract. Marrow reports passive coverage only from observed lifecycle receipts, not from configuration detection.
|
|
120
140
|
|
|
121
141
|
## Previous: v3.9.59
|
|
122
142
|
|
|
@@ -129,7 +149,7 @@ v3.9.59 makes the six-tool control path reliable and honest across ordinary edge
|
|
|
129
149
|
- a first-session outage returns a clearly labeled local safety brief, and infrastructure failures are never mislabeled as policy denials;
|
|
130
150
|
- timeout errors return a concrete retry delay instead of an unresolved placeholder;
|
|
131
151
|
- Cloudflare edge denials are separated from key-scope or Marrow policy rejections;
|
|
132
|
-
- MCP initialization carries the
|
|
152
|
+
- MCP initialization carries the capability-qualified control/proof instructions even when a client does not request the optional prompt template;
|
|
133
153
|
- update, launch, setup, spool, and ping commands use the unambiguous `npx --package ... marrow-mcp` form;
|
|
134
154
|
- explicit spool drains tolerate slow edge delivery without extending passive hook latency.
|
|
135
155
|
|
|
@@ -251,6 +271,8 @@ With installed native hooks, protected tool calls follow this automatically. For
|
|
|
251
271
|
4. Perform the action only when its gate allows it. For a hard external choke point, run the command through `npx @getmarrow/install run`; it verifies the signed action permit immediately before execution.
|
|
252
272
|
5. Call `marrow_commit` with that `decision_id`, the outcome, gate receipt, and required proof.
|
|
253
273
|
|
|
274
|
+
`marrow_agent_runtime` returns `runtime_authorization` with the authoritative gate receipt. Ordinary runtime checks do not create a decision, so they omit `decision_id`; call `marrow_think` (or use `marrow_auto`) when a decision must be created and closed. An arbitration runtime that actually creates a decision returns that server-created `decision_id`. This contract is identical across MCP-compatible hosts and SDK-owned runtimes.
|
|
275
|
+
|
|
254
276
|
Example pre-action request:
|
|
255
277
|
|
|
256
278
|
```json
|
|
@@ -345,9 +367,21 @@ it does not run models, retain prompts, or infer a winner from labels.
|
|
|
345
367
|
|
|
346
368
|
## Passive Use
|
|
347
369
|
|
|
348
|
-
`npx -y --package=@getmarrow/mcp@latest marrow-mcp setup`
|
|
370
|
+
`npx -y --package=@getmarrow/mcp@latest marrow-mcp setup` configures supported prompt, pre-action, tool-result, and session-stop hooks. Configuration is not proof that the host invoked them. Marrow reports native passive coverage only after it observes the required prompt, pre-action, action-result, and session-end receipts.
|
|
371
|
+
|
|
372
|
+
### Capability and coverage contract
|
|
373
|
+
|
|
374
|
+
| Integration mode | Coverage Marrow can claim |
|
|
375
|
+
| --- | --- |
|
|
376
|
+
| MCP tools-only | On demand; covers only explicit MCP tool calls |
|
|
377
|
+
| Verified native hooks | Passive only for the lifecycle stages backed by observed hook receipts |
|
|
378
|
+
| `createPassiveRuntime().install()` | Only the owned Node process, and only while that runtime is installed and running |
|
|
379
|
+
| Governed runner | Only the command launched through the wrapper |
|
|
380
|
+
| Custom host | Requires a bounded event adapter; covers only the lifecycle events whose receipts Marrow observes |
|
|
381
|
+
|
|
382
|
+
This contract is model-neutral. A model name, host header, config file, installed hook entry, or successful MCP handshake does not certify passive coverage. Only observed Marrow receipts do. An unknown MCP host therefore gets the generic `mcp-client` identity and the same on-demand tools, schemas, and API semantics as a named host.
|
|
349
383
|
|
|
350
|
-
|
|
384
|
+
When invoked by a supported host, the configured hooks send compact classifications and lifecycle receipts. They do not need raw prompts, completions, command output, tool output, or credentials. A completed tool or session does not automatically become a successful business outcome; explicit success/failure closure is required.
|
|
351
385
|
|
|
352
386
|
Transient lifecycle receipts use a bounded owner-only spool and are retried with stable event IDs. Operators can inspect and drain it without exposing event content:
|
|
353
387
|
|
|
@@ -356,7 +390,7 @@ npx -y --package=@getmarrow/mcp@latest marrow-mcp spool-status
|
|
|
356
390
|
npx -y --package=@getmarrow/mcp@latest marrow-mcp drain-spool
|
|
357
391
|
```
|
|
358
392
|
|
|
359
|
-
The output contains only state,
|
|
393
|
+
The output contains only state, bounded pending/failed counts, oldest receipt timestamps, capacity, and an exact fix. A drain applies only to the active credential-and-agent namespace: isolated legacy namespace debt is reported separately and never changes a successful active-namespace drain into a failure. Legacy files are never replayed, merged, deleted, or attributed to the active identity. Restore the exact original identity to drain one, or preserve the selected file unchanged in a separate owner-only quarantine directory when that identity is unavailable. Terminal validation/authentication failures and exhausted retries in the active namespace remain explicit durable failures rather than cycling indefinitely.
|
|
360
394
|
|
|
361
395
|
Check the installed runtime:
|
|
362
396
|
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ const hook_session_1 = require("./hook-session");
|
|
|
17
17
|
const hook_pre_action_1 = require("./hook-pre-action");
|
|
18
18
|
const env_1 = require("./env");
|
|
19
19
|
const lifecycle_spool_1 = require("./lifecycle-spool");
|
|
20
|
+
const spool_command_1 = require("./spool-command");
|
|
20
21
|
const guidance_cache_1 = require("./guidance-cache");
|
|
21
22
|
const request_reliability_1 = require("./request-reliability");
|
|
22
23
|
const hook_contract_1 = require("./hook-contract");
|
|
@@ -24,6 +25,8 @@ const ping_state_1 = require("./ping-state");
|
|
|
24
25
|
const control_path_state_1 = require("./control-path-state");
|
|
25
26
|
const redact_1 = require("./redact");
|
|
26
27
|
const runtime_contract_1 = require("./runtime-contract");
|
|
28
|
+
const status_cache_1 = require("./status-cache");
|
|
29
|
+
const host_capability_1 = require("./host-capability");
|
|
27
30
|
// Parse CLI args
|
|
28
31
|
function parseArgs() {
|
|
29
32
|
const args = process.argv.slice(2);
|
|
@@ -127,17 +130,10 @@ async function runSpoolCommand(drain) {
|
|
|
127
130
|
const status = drain
|
|
128
131
|
? await (0, lifecycle_spool_1.drainLifecycleSpool)({ apiKey, baseUrl, agentId: resolved.agentId || undefined })
|
|
129
132
|
: (0, lifecycle_spool_1.lifecycleSpoolStatus)({ apiKey, agentId: resolved.agentId || undefined });
|
|
130
|
-
const
|
|
131
|
-
process.stdout.write(`${JSON.stringify(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
: status.state !== 'attention_required' && !namespaceAttention,
|
|
135
|
-
lifecycle_spool: status,
|
|
136
|
-
}, null, 2)}\n`);
|
|
137
|
-
if (status.state === 'attention_required' || namespaceAttention)
|
|
138
|
-
process.exitCode = 2;
|
|
139
|
-
else if (drain && status.state !== 'clear')
|
|
140
|
-
process.exitCode = 1;
|
|
133
|
+
const outcome = (0, spool_command_1.lifecycleSpoolCommandOutcome)(status, drain);
|
|
134
|
+
process.stdout.write(`${JSON.stringify(outcome.output, null, 2)}\n`);
|
|
135
|
+
if (outcome.exitCode !== 0)
|
|
136
|
+
process.exitCode = outcome.exitCode;
|
|
141
137
|
}
|
|
142
138
|
// ─── Setup command: inject Marrow instructions into CLAUDE.md ───
|
|
143
139
|
function runSetup() {
|
|
@@ -148,10 +144,10 @@ function runSetup() {
|
|
|
148
144
|
const marrowInstructions = `${MARROW_BLOCK_START}
|
|
149
145
|
## Marrow — Agent Control and Proof (auto-injected by @getmarrow/mcp setup)
|
|
150
146
|
|
|
151
|
-
|
|
147
|
+
Use Marrow according to the capability evidence returned by the MCP server:
|
|
152
148
|
|
|
153
|
-
1. **
|
|
154
|
-
2. **Before risky actions:** Respect the returned \`allow\`, \`warn\`, \`review_required\`, or \`block\` decision and its proof contract. Call \`marrow_agent_runtime\` explicitly when
|
|
149
|
+
1. **MCP baseline is on demand:** MCP transport exposes tools; it does not provide passive hooks. Call Marrow tools explicitly unless observed receipts verify another capability mode.
|
|
150
|
+
2. **Before risky actions:** Respect the returned \`allow\`, \`warn\`, \`review_required\`, or \`block\` decision and its proof contract. Call \`marrow_agent_runtime\` explicitly when verified passive coverage cannot cover the action.
|
|
155
151
|
3. **After meaningful work:** Record the real success or failure with \`marrow_commit\` or \`marrow_auto\`. A tool exit or session end is not proof that the business outcome succeeded.
|
|
156
152
|
4. **Unfinished work:** Leave pending outcomes visible. Do not invent success to clear a closure item.
|
|
157
153
|
5. **To explain an intervention:** Use \`marrow_decision_trace\`, then relay its \`intervention_receipt\` in one factual sentence when Marrow blocked, warned, or required review. Stay quiet for routine low-risk work.
|
|
@@ -160,6 +156,8 @@ You have Marrow MCP connected. Use it on EVERY session automatically:
|
|
|
160
156
|
|
|
161
157
|
Do not skip the gate or outcome. Marrow's value comes from controlling the action before execution and preserving evidence afterward.
|
|
162
158
|
|
|
159
|
+
Capability boundaries: verified native hooks cover only their observed lifecycle; \`createPassiveRuntime().install()\` covers only its owned Node process while installed; a governed runner covers only its wrapped command; and a custom host needs a bounded event adapter. A model name, host label, or installed configuration is not proof of coverage. Only observed Marrow receipts certify it.
|
|
160
|
+
|
|
163
161
|
For one-shot logging: \`marrow_auto({ action: "did X", outcome: "result Y", success: true })\` — one call, done.
|
|
164
162
|
${MARROW_BLOCK_END}`;
|
|
165
163
|
let dir = process.cwd();
|
|
@@ -203,37 +201,37 @@ ${MARROW_BLOCK_END}`;
|
|
|
203
201
|
}
|
|
204
202
|
const hookInstall = (0, hook_1.installPostToolUseHook)(process.cwd());
|
|
205
203
|
if (hookInstall.installed) {
|
|
206
|
-
process.stdout.write('
|
|
204
|
+
process.stdout.write('Configured PostToolUse hook. Coverage remains unverified until Marrow observes action-result receipts.\n');
|
|
207
205
|
}
|
|
208
206
|
else {
|
|
209
|
-
process.stdout.write('PostToolUse hook
|
|
207
|
+
process.stdout.write('PostToolUse hook configuration is present. Coverage remains unverified until Marrow observes action-result receipts.\n');
|
|
210
208
|
}
|
|
211
209
|
const contextHookInstall = (0, hook_context_1.installUserPromptSubmitHook)(process.cwd());
|
|
212
210
|
if (contextHookInstall.installed) {
|
|
213
|
-
process.stdout.write('
|
|
211
|
+
process.stdout.write('Configured UserPromptSubmit hook. Passive prompt coverage remains unverified until Marrow observes prompt receipts.\n');
|
|
214
212
|
}
|
|
215
213
|
else {
|
|
216
|
-
process.stdout.write('UserPromptSubmit hook
|
|
214
|
+
process.stdout.write('UserPromptSubmit hook configuration is present. Passive prompt coverage remains unverified until Marrow observes prompt receipts.\n');
|
|
217
215
|
}
|
|
218
216
|
const preActionHookInstall = (0, hook_pre_action_1.installPreActionHook)(process.cwd());
|
|
219
217
|
if (preActionHookInstall.installed) {
|
|
220
|
-
process.stdout.write('
|
|
218
|
+
process.stdout.write('Configured PreToolUse hook. Pre-action coverage remains unverified until Marrow observes pre-action receipts.\n');
|
|
221
219
|
}
|
|
222
220
|
else {
|
|
223
|
-
process.stdout.write('PreToolUse hook
|
|
221
|
+
process.stdout.write('PreToolUse hook configuration is present. Pre-action coverage remains unverified until Marrow observes pre-action receipts.\n');
|
|
224
222
|
}
|
|
225
223
|
const sessionHookInstall = (0, hook_session_1.installSessionEndHook)(process.cwd());
|
|
226
224
|
if (sessionHookInstall.installed) {
|
|
227
|
-
process.stdout.write('
|
|
225
|
+
process.stdout.write('Configured Stop hook. Session-end coverage remains unverified until Marrow observes session-end receipts.\n');
|
|
228
226
|
}
|
|
229
227
|
else {
|
|
230
|
-
process.stdout.write('Stop hook
|
|
228
|
+
process.stdout.write('Stop hook configuration is present. Session-end coverage remains unverified until Marrow observes session-end receipts.\n');
|
|
231
229
|
}
|
|
232
230
|
process.stdout.write(`Hook settings: ${hookInstall.settingsPath}\n`);
|
|
233
231
|
process.stdout.write('Set MARROW_AUTO_HOOK=false to disable passive hooks.\n');
|
|
234
232
|
process.stdout.write('Set MARROW_PASSIVE_BRIEF=false to disable automatic decision briefs, or MARROW_PASSIVE_BRIEF=always to brief every prompt.\n');
|
|
235
233
|
process.stdout.write('Set MARROW_HOOK_DEBUG=true for write-side hook diagnostics, or MARROW_CONTEXT_HOOK_DEBUG=true for prompt-context diagnostics.\n');
|
|
236
|
-
process.stdout.write('
|
|
234
|
+
process.stdout.write('Setup completed. MCP tools remain on demand; passive coverage is reported only after Marrow observes the required hook receipts.\n');
|
|
237
235
|
process.exit(0);
|
|
238
236
|
}
|
|
239
237
|
const cliArgs = parseArgs();
|
|
@@ -447,16 +445,21 @@ if (process.argv[2] !== 'keys') {
|
|
|
447
445
|
}
|
|
448
446
|
function toolFailure(toolName, failure) {
|
|
449
447
|
const result = (0, request_reliability_1.structuredRequestFailure)(failure);
|
|
450
|
-
const
|
|
448
|
+
const proofValidation = failure.code === 'proof_required';
|
|
449
|
+
const infrastructureFailure = !proofValidation && !['authentication_required', 'permission_denied'].includes(failure.code);
|
|
451
450
|
const supportsStale = ['marrow_agent_runtime', 'marrow_orient', 'marrow_ask', 'marrow_handoff_status', 'marrow_runtime_status', 'marrow_status'].includes(toolName || '');
|
|
452
451
|
const spool = (0, lifecycle_spool_1.lifecycleSpoolStatus)({ apiKey: API_KEY, agentId: FLEET_AGENT_ID });
|
|
453
|
-
result.failure_kind = infrastructureFailure ? 'infrastructure' : 'authorization';
|
|
452
|
+
result.failure_kind = proofValidation ? 'validation' : infrastructureFailure ? 'infrastructure' : 'authorization';
|
|
454
453
|
result.control_path = (0, control_path_state_1.controlPathStats)(toolName || 'marrow_control');
|
|
455
454
|
result.lifecycle_spool = {
|
|
456
455
|
...spool,
|
|
457
456
|
drain_command: 'npx -y --package=@getmarrow/mcp@latest marrow-mcp drain-spool',
|
|
458
457
|
};
|
|
459
458
|
result.host_capability = mcpHostCapability();
|
|
459
|
+
if (proofValidation) {
|
|
460
|
+
result.proof_required = true;
|
|
461
|
+
result.exact_next_action = failure.exactFix;
|
|
462
|
+
}
|
|
460
463
|
if (infrastructureFailure && supportsStale) {
|
|
461
464
|
let cached = null;
|
|
462
465
|
try {
|
|
@@ -484,22 +487,9 @@ if (process.argv[2] !== 'keys') {
|
|
|
484
487
|
return result;
|
|
485
488
|
}
|
|
486
489
|
function mcpHostCapability() {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
return {
|
|
491
|
-
transport: 'mcp_stdio',
|
|
492
|
-
host,
|
|
493
|
-
tools_available: true,
|
|
494
|
-
tool_invocation: 'on_demand',
|
|
495
|
-
passive_hooks: {
|
|
496
|
-
provided_by_mcp_transport: false,
|
|
497
|
-
external_host_hook_state: 'unverified',
|
|
498
|
-
observed_by_this_process: false,
|
|
499
|
-
},
|
|
500
|
-
always_on_state: 'host_dependent',
|
|
501
|
-
exact_next_action: 'Use the Marrow MCP tools on demand. Claim passive coverage only when the host separately configures trusted hooks and Marrow receives their lifecycle receipts.',
|
|
502
|
-
};
|
|
490
|
+
return (0, host_capability_1.resolveHostCapability)({
|
|
491
|
+
hostLabel: process.env.MARROW_CLIENT || process.env.MARROW_HARNESS || process.env.MARROW_AGENT_CLIENT,
|
|
492
|
+
});
|
|
503
493
|
}
|
|
504
494
|
function clientOperationalPayload(toolName, value) {
|
|
505
495
|
const payload = value && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -570,6 +560,23 @@ if (process.argv[2] !== 'keys') {
|
|
|
570
560
|
}
|
|
571
561
|
catch { /* owner-only cache is best effort */ }
|
|
572
562
|
}
|
|
563
|
+
function storeLastKnownStatus(status, source) {
|
|
564
|
+
try {
|
|
565
|
+
(0, status_cache_1.writeStatusCache)({
|
|
566
|
+
apiKey: API_KEY,
|
|
567
|
+
baseUrl: BASE_URL,
|
|
568
|
+
agentId: FLEET_AGENT_ID,
|
|
569
|
+
status,
|
|
570
|
+
source,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
catch { /* owner-only cache is best effort */ }
|
|
574
|
+
}
|
|
575
|
+
function refreshStatusInBackground() {
|
|
576
|
+
void (0, index_1.marrowStatus)(API_KEY, BASE_URL, SESSION_ID, FLEET_AGENT_ID)
|
|
577
|
+
.then((status) => storeLastKnownStatus(status, 'status'))
|
|
578
|
+
.catch(() => undefined);
|
|
579
|
+
}
|
|
573
580
|
// [FIX #6 & #7] Safe JSON response helper for memory API functions
|
|
574
581
|
async function safeMemoryResponse(res) {
|
|
575
582
|
if (!res.ok) {
|
|
@@ -815,7 +822,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
815
822
|
type: 'object',
|
|
816
823
|
description: 'Optional required proof pack for gated work: summary, checks, outcome, blockers, commits_prs_shas, rollback_target, handoff_result_file, deployment_and_smoke.',
|
|
817
824
|
},
|
|
818
|
-
gate_receipt_id: { type: 'string', description: '
|
|
825
|
+
gate_receipt_id: { type: 'string', description: 'Canonical receipt id from marrow_agent_runtime.runtime_authorization.id for risky work.' },
|
|
819
826
|
arbitration_receipt_id: { type: 'string', description: 'Required for arbitrated work: use marrow_arbitrate.arbitration.receipt_id from the same runtime response.' },
|
|
820
827
|
owner_approval_receipt_id: { type: 'string', description: 'Single-use owner approval receipt issued by authenticated dashboard review for review_required arbitration.' },
|
|
821
828
|
action: { type: 'string', description: 'Optional original action. If provided and gate_receipt_id is omitted, MCP can fetch a matching runtime gate receipt before commit.' },
|
|
@@ -1228,6 +1235,8 @@ if (process.argv[2] !== 'keys') {
|
|
|
1228
1235
|
name: 'marrow_agent_runtime',
|
|
1229
1236
|
description: 'One-call agent-native Marrow loop. Returns passive status, decision brief, risk gate, relevant lessons, ' +
|
|
1230
1237
|
'template suggestion, required proof pack, before-you-act instruction, and exact next action. ' +
|
|
1238
|
+
'Its runtime_authorization is the authoritative gate receipt; it returns decision_id only when runtime actually creates a decision. ' +
|
|
1239
|
+
'Use marrow_auto or marrow_think to create the decision_id required for outcome closure. ' +
|
|
1231
1240
|
'Use this before meaningful work when you want Marrow to guide the whole action in one call.',
|
|
1232
1241
|
inputSchema: {
|
|
1233
1242
|
type: 'object',
|
|
@@ -1682,13 +1691,15 @@ if (process.argv[2] !== 'keys') {
|
|
|
1682
1691
|
try {
|
|
1683
1692
|
if (method === 'initialize') {
|
|
1684
1693
|
initialized = true;
|
|
1694
|
+
const hostCapability = mcpHostCapability();
|
|
1685
1695
|
success(id, {
|
|
1686
1696
|
protocolVersion: '2024-11-05',
|
|
1687
1697
|
capabilities: { tools: {}, prompts: {} },
|
|
1688
1698
|
serverInfo: { name: 'marrow', version: hook_contract_1.MCP_ADAPTER_VERSION },
|
|
1689
1699
|
...(AUTO_ENROLL ? {
|
|
1690
|
-
instructions:
|
|
1700
|
+
instructions: `Use marrow_agent_runtime before consequential actions, obey fresh allow/warn/review_required/block results, use marrow_ask for relevant prior lessons, and close meaningful outcomes with marrow_commit. Infrastructure failures are not policy denials; continue only low-risk reversible work from the returned outage-safe brief, and require a fresh gate for high-risk work. ${(0, host_capability_1.hostCapabilityInstructions)(hostCapability)}`,
|
|
1691
1701
|
} : {}),
|
|
1702
|
+
_meta: { host_capability: hostCapability },
|
|
1692
1703
|
});
|
|
1693
1704
|
// Auto-enroll: emit enrollment notification on connection
|
|
1694
1705
|
if (AUTO_ENROLL) {
|
|
@@ -1700,9 +1711,10 @@ if (process.argv[2] !== 'keys') {
|
|
|
1700
1711
|
logger: 'marrow',
|
|
1701
1712
|
data: {
|
|
1702
1713
|
type: 'auto_enroll',
|
|
1703
|
-
message:
|
|
1714
|
+
message: `Marrow operating contract available. MCP tools are on demand. ${hostCapability.exact_next_action}`,
|
|
1704
1715
|
agentId: FLEET_AGENT_ID,
|
|
1705
1716
|
client_update: (0, request_reliability_1.localClientUpdate)(),
|
|
1717
|
+
host_capability: hostCapability,
|
|
1706
1718
|
},
|
|
1707
1719
|
},
|
|
1708
1720
|
});
|
|
@@ -1715,8 +1727,9 @@ if (process.argv[2] !== 'keys') {
|
|
|
1715
1727
|
prompts: [
|
|
1716
1728
|
{
|
|
1717
1729
|
name: 'marrow-always-on',
|
|
1718
|
-
description: '
|
|
1730
|
+
description: 'Marrow control and proof contract, qualified by verified host capability and observed lifecycle receipts.',
|
|
1719
1731
|
arguments: [],
|
|
1732
|
+
_meta: { host_capability: mcpHostCapability() },
|
|
1720
1733
|
},
|
|
1721
1734
|
],
|
|
1722
1735
|
});
|
|
@@ -1732,8 +1745,10 @@ if (process.argv[2] !== 'keys') {
|
|
|
1732
1745
|
error(id, -32602, 'Unknown prompt');
|
|
1733
1746
|
return;
|
|
1734
1747
|
}
|
|
1748
|
+
const hostCapability = mcpHostCapability();
|
|
1735
1749
|
success(id, {
|
|
1736
|
-
description: '
|
|
1750
|
+
description: 'Marrow control and proof contract — coverage is capability-qualified and receipt-verified',
|
|
1751
|
+
_meta: { host_capability: hostCapability },
|
|
1737
1752
|
messages: [
|
|
1738
1753
|
{
|
|
1739
1754
|
role: 'user',
|
|
@@ -1741,14 +1756,16 @@ if (process.argv[2] !== 'keys') {
|
|
|
1741
1756
|
type: 'text',
|
|
1742
1757
|
text: `You have Marrow — the agent control and proof layer around this workflow.
|
|
1743
1758
|
|
|
1744
|
-
##
|
|
1759
|
+
## Capability-qualified operating contract
|
|
1760
|
+
|
|
1761
|
+
${(0, host_capability_1.hostCapabilityInstructions)(hostCapability)}
|
|
1745
1762
|
|
|
1746
|
-
|
|
1747
|
-
- UserPromptSubmit
|
|
1748
|
-
- PostToolUse
|
|
1749
|
-
- Stop
|
|
1763
|
+
When verified by observed receipts, native hooks can cover these bounded lifecycle stages:
|
|
1764
|
+
- UserPromptSubmit can request relevant policy, warnings, lessons, and a decision brief before risky work.
|
|
1765
|
+
- PostToolUse can record compact tool success or failure receipts.
|
|
1766
|
+
- Stop can keep unfinished outcomes visible instead of silently treating session exit as success.
|
|
1750
1767
|
|
|
1751
|
-
Hooks never make a blocked action safe. Before a consequential action, respect the returned allow, warn, review_required, or block decision and its required proof. Call marrow_agent_runtime explicitly when
|
|
1768
|
+
Hooks never make a blocked action safe. Before a consequential action, respect the returned allow, warn, review_required, or block decision and its required proof. Call marrow_agent_runtime explicitly when verified passive coverage cannot cover the action.
|
|
1752
1769
|
|
|
1753
1770
|
When runtime/status returns a client_update notice, tell the operator and use its exact update and verification commands only when local change policy permits. Never silently change packages or configuration.
|
|
1754
1771
|
|
|
@@ -1797,7 +1814,7 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1797
1814
|
`2. Use marrow_agent_runtime when a risky action needs an explicit gate.\n` +
|
|
1798
1815
|
`3. Close meaningful work with marrow_commit; a tool exit alone is not outcome proof.\n` +
|
|
1799
1816
|
`4. Use marrow_decision_trace to explain the prior failure, lesson, gate, proof, workflow, and outcome path.\n\n` +
|
|
1800
|
-
|
|
1817
|
+
`${(0, host_capability_1.hostCapabilityInstructions)(mcpHostCapability())}\n\nLeave unknown outcomes pending instead of inventing success.\n`;
|
|
1801
1818
|
const orientText = JSON.stringify(result, null, 2);
|
|
1802
1819
|
success(id, {
|
|
1803
1820
|
content: [{ type: 'text', text: enrollmentText + orientText }],
|
|
@@ -1964,7 +1981,12 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1964
1981
|
}, SESSION_ID, FLEET_AGENT_ID, signal), { highRisk: true, toolName: 'marrow_auto.runtime' });
|
|
1965
1982
|
storeRuntimeGuidance(runtimeGate);
|
|
1966
1983
|
}
|
|
1967
|
-
const
|
|
1984
|
+
const canonicalRuntimeReceiptId = (0, runtime_contract_1.runtimeAuthorizationReceiptId)(runtimeGate);
|
|
1985
|
+
const suppliedRuntimeReceiptId = typeof args.gate_receipt_id === 'string'
|
|
1986
|
+
? args.gate_receipt_id
|
|
1987
|
+
: canonicalRuntimeReceiptId;
|
|
1988
|
+
const proofCanClose = !highRisk
|
|
1989
|
+
|| (0, runtime_contract_1.highRiskRuntimeCanClose)(runtimeGate, suppliedProof, suppliedRuntimeReceiptId);
|
|
1968
1990
|
const acceptedSuccess = proofCanClose ? outcomeSuccess : undefined;
|
|
1969
1991
|
const delivery = () => (0, index_1.marrowAuto)(API_KEY, BASE_URL, {
|
|
1970
1992
|
action,
|
|
@@ -1972,9 +1994,10 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1972
1994
|
success: acceptedSuccess,
|
|
1973
1995
|
type,
|
|
1974
1996
|
proof: suppliedProof,
|
|
1975
|
-
gate_receipt_id:
|
|
1976
|
-
|
|
1977
|
-
|
|
1997
|
+
gate_receipt_id: suppliedRuntimeReceiptId || undefined,
|
|
1998
|
+
// Low-risk one-shot capture does not need a policy gate. Consequential
|
|
1999
|
+
// work already obtained and validated canonical runtime authorization.
|
|
2000
|
+
auto_gate: highRisk,
|
|
1978
2001
|
}, SESSION_ID, FLEET_AGENT_ID, 8_000);
|
|
1979
2002
|
let delivered = null;
|
|
1980
2003
|
let deliveryFailure = null;
|
|
@@ -2055,7 +2078,20 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2055
2078
|
return;
|
|
2056
2079
|
}
|
|
2057
2080
|
if (toolName === 'marrow_status') {
|
|
2081
|
+
let cached = null;
|
|
2082
|
+
try {
|
|
2083
|
+
cached = (0, status_cache_1.readStatusCache)({ apiKey: API_KEY, baseUrl: BASE_URL, agentId: FLEET_AGENT_ID });
|
|
2084
|
+
}
|
|
2085
|
+
catch { /* owner-only cache is best effort */ }
|
|
2086
|
+
if (cached) {
|
|
2087
|
+
const startedAt = Date.now();
|
|
2088
|
+
refreshStatusInBackground();
|
|
2089
|
+
(0, control_path_state_1.recordControlPathSample)('marrow_status', Date.now() - startedAt, true);
|
|
2090
|
+
toolSuccess(id, clientOperationalPayload('marrow_status', (0, status_cache_1.cachedStatusPayload)(cached)));
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2058
2093
|
const result = await withControlDeadline((signal) => (0, index_1.marrowStatus)(API_KEY, BASE_URL, SESSION_ID, FLEET_AGENT_ID, signal), { cacheAware: false, toolName: 'marrow_status' });
|
|
2094
|
+
storeLastKnownStatus(result, 'status');
|
|
2059
2095
|
toolSuccess(id, clientOperationalPayload('marrow_status', result));
|
|
2060
2096
|
return;
|
|
2061
2097
|
}
|
|
@@ -2252,6 +2288,7 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2252
2288
|
};
|
|
2253
2289
|
const result = await withControlDeadline((signal) => (0, index_1.marrowAgentRuntime)(API_KEY, BASE_URL, runtimeInput, SESSION_ID, FLEET_AGENT_ID, signal), { highRisk: isHighRiskAction(runtimeInput.action, runtimeInput.type), toolName: 'marrow_agent_runtime' });
|
|
2254
2290
|
storeRuntimeGuidance(result);
|
|
2291
|
+
storeLastKnownStatus(result.status, 'runtime');
|
|
2255
2292
|
toolSuccess(id, clientOperationalPayload('marrow_agent_runtime', result));
|
|
2256
2293
|
return;
|
|
2257
2294
|
}
|