@getmarrow/mcp 3.9.32 → 3.9.34

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 CHANGED
@@ -11,9 +11,15 @@
11
11
 
12
12
  Marrow gives your agent a memory that compounds.
13
13
 
14
- With `@getmarrow/mcp`, any MCP-compatible client can log intent before acting, inspect live loop state during work, and commit outcomes back to the hive when the work is done. That means your agent stops operating like an amnesiac and starts carrying forward real decision history.
14
+ With `@getmarrow/mcp`, any MCP-compatible client can log intent before acting, inspect live loop state during work, and commit outcomes back to Marrow when the work is done. That means your agent stops operating like an amnesiac and starts carrying forward real decision history.
15
15
 
16
- **Your agent stops repeating the same mistakes. It learns from prior sessions — and from the wider Marrow hive — through a clean MCP tool surface.**
16
+ **Your agent stops repeating the same mistakes. It learns from prior sessions — and from authorized fleet memory plus sanitized shared signals — through a clean MCP tool surface.**
17
+
18
+ ## Trust and Data Boundaries
19
+
20
+ Marrow is tenant-aware by design. Private account, fleet, memory, workflow, and proof-pack data stays scoped to the authenticated account and authorized agent-bound keys. Shared/hive learning uses visibility-controlled, sanitized aggregate signals; it is not raw cross-customer decision sharing.
21
+
22
+ For business pilots, review the live trust notes before production rollout: https://getmarrow.ai/docs#trust-boundaries
17
23
 
18
24
  ---
19
25
 
@@ -26,6 +32,7 @@ npx @getmarrow/install --yes
26
32
  ```
27
33
 
28
34
  The installer detects your MCP client, agent instructions, Node project, and runtime surfaces, then wires the safest passive setup automatically.
35
+ It now also includes a governed runner: `npx @getmarrow/install run --agent <agent-id> -- <command>`, which gives MCP and non-MCP agents the same pre-action Marrow risk gate and automatic outcome closure for existing shell, deploy, publish, merge, and migration commands.
29
36
  MCP clients can also call `marrow_first_value` to show the first five-minute proof payload directly inside the agent.
30
37
 
31
38
  Use this MCP package directly when you want manual MCP server/hook setup for Claude Code, Claude Desktop, Cursor, or another MCP-compatible client. Use `@getmarrow/sdk` when you are building a custom Node/TypeScript integration in code.
@@ -37,6 +44,7 @@ Marrow auto-logs at three layers — transparent to your agent, invisible to you
37
44
  | Layer | How | Agent effort |
38
45
  |-------|-----|-------------|
39
46
  | Server-side | Every authenticated API call auto-logged as a decision | Zero |
47
+ | Governed runner | `npx @getmarrow/install run --agent <id> -- <command>` — pre-action gate + outcome proof around existing commands | Minimal |
40
48
  | SDK | `marrow.think()` / `marrow.commit()` — explicit control | Minimal |
41
49
  | MCP hooks | `npx @getmarrow/mcp setup` — PostToolUse + UserPromptSubmit hooks | Zero |
42
50
 
@@ -76,14 +84,35 @@ Accounts with <7 days of activity AND <20 decisions get an onboarding payload sh
76
84
 
77
85
  ---
78
86
 
79
- ## What's New in v3.9.32
87
+ ## What's New in v3.9.33
80
88
 
81
- v3.9.32 is a docs-sync release for Marrow's enterprise readiness contract. Runtime behavior is unchanged from v3.9.31.
89
+ v3.9.33 adds MCP tools for adaptive governance recommendations and explicit policy profiles, while keeping the enterprise readiness contract documented for business pilots.
82
90
 
83
- - MCP agents can call the Marrow API endpoint `GET /v1/agent/enterprise-readiness?agents=20` when an owner asks whether Marrow is ready for a fleet rollout.
91
+ - `marrow_mode_recommend` returns an explainable `passive`, `pilot`, or `enforce` recommendation for the current project/workflow.
92
+ - `marrow_policy_profiles` lists saved account policy profiles, including the default business starter profile.
93
+ - `marrow_create_policy_profile` creates or updates explicit rules such as local=passive, staging=pilot, production deploys=enforce.
94
+ - `marrow_assign_project_policy_profile` binds an active profile to a project key so future resolves use it automatically.
95
+ - `marrow_policy_resolve` resolves the current workflow mode from saved policy profiles, falling back to recommendation.
96
+ - Marrow does not silently auto-switch modes. The agent/user must accept or override the recommendation.
97
+ - MCP agents can call `GET /v1/agent/enterprise-readiness?agents=20` when an owner asks whether Marrow is ready for a fleet rollout.
84
98
  - The response is owner-safe and covers tenant isolation, data boundaries, fail behavior, policy controls, scale proof, and a 30-day pilot package.
85
- - Marrow is explicit about readiness: controlled business pilots are supported when production gates pass; regulated enterprise use still requires formal SOC 2/legal/SLA completion.
86
- - The source-of-truth docs now include the enterprise trust and scale readiness page at [getmarrow.ai/docs](https://getmarrow.ai/docs/).
99
+ - The source-of-truth docs include the enterprise trust and scale readiness page at [getmarrow.ai/docs](https://getmarrow.ai/docs/).
100
+
101
+ ```json
102
+ {
103
+ "project": {
104
+ "name": "agent-api",
105
+ "type": "node",
106
+ "frameworks": ["edge-service"],
107
+ "signals": ["package_json", "platform_config", "github_actions"]
108
+ },
109
+ "workflow": {
110
+ "action": "deploy production service",
111
+ "type": "deploy",
112
+ "environment": "production"
113
+ }
114
+ }
115
+ ```
87
116
 
88
117
  ## What's New in v3.9.31
89
118
 
@@ -114,9 +143,9 @@ Previous agent-native runtime behavior remains current:
114
143
 
115
144
  ```json
116
145
  {
117
- "action": "deploy Cloudflare Worker to production",
146
+ "action": "deploy edge service to production",
118
147
  "type": "deploy",
119
- "surfaces": ["github", "cloudflare", "production"]
148
+ "surfaces": ["github", "deployment-platform", "production"]
120
149
  }
121
150
  ```
122
151
 
@@ -124,6 +153,31 @@ Full feature history, examples, and API reference live at [getmarrow.ai/docs](ht
124
153
 
125
154
  ---
126
155
 
156
+ ### Gated Commit Proof
157
+
158
+ For risky actions, call `marrow_agent_runtime` before acting and pass the receipt plus proof into `marrow_commit`:
159
+
160
+ ```json
161
+ {
162
+ "decision_id": "...",
163
+ "success": true,
164
+ "outcome": "Deploy succeeded and production smoke passed",
165
+ "gate_receipt_id": "runtime.gate_receipt.id",
166
+ "proof": {
167
+ "summary": "Production deploy completed",
168
+ "checks": ["tests passed", "smoke passed"],
169
+ "outcome": "success",
170
+ "blockers": "none",
171
+ "commits_prs_shas": "abc123",
172
+ "rollback_target": "previous release version",
173
+ "handoff_result_file": "/tmp/marrow-handoffs/release/result.md",
174
+ "deployment_and_smoke": "production smoke passed"
175
+ }
176
+ }
177
+ ```
178
+
179
+ If you provide `action` and omit `gate_receipt_id`, `marrow_commit` can fetch a matching runtime gate receipt automatically.
180
+
127
181
  ## Human-Directed Attribution Status
128
182
 
129
183
  The Marrow API supports privacy-preserving provenance fields on direct `POST /v1/decisions` calls: `source_kind`, `human_directed`, `source_confidence`, `instruction_ref`, `instruction_hash`, and `source_meta`. These fields classify instruction source class without identifying the human or storing raw prompts/PII.
@@ -184,7 +238,7 @@ Use it before deploys, publishes, merges, DB migrations, key rotation, destructi
184
238
 
185
239
  ```json
186
240
  {
187
- "action": "rotate Cloudflare deploy token and verify production",
241
+ "action": "rotate deployment token and verify production",
188
242
  "riskTolerance": "medium",
189
243
  "requiresApproval": true
190
244
  }
@@ -204,7 +258,7 @@ Marrow now tells the agent exactly what it contributed to each decision, so the
204
258
 
205
259
  Three new fields:
206
260
 
207
- - `marrow_think` returns `marrow_contributed` describing what intelligence Marrow surfaced for this decision (warnings consulted, hive patterns, similar decisions, workflow templates, loop detection, collective insight).
261
+ - `marrow_think` returns `marrow_contributed` describing what intelligence Marrow surfaced for this decision (warnings consulted, shared patterns, similar decisions, workflow templates, loop detection, collective insight).
208
262
  - `marrow_commit` returns `marrow_contributed` describing concrete signals on the commit itself (pattern reused, warning avoided, workflow step).
209
263
  - `marrow_session_end` returns `session_summary` aggregating Marrow's contribution across the session, plus a one-line `narrative` for the agent to surface as it wraps up.
210
264
 
package/dist/cli.js CHANGED
@@ -296,7 +296,7 @@ if (process.argv[2] !== 'keys') {
296
296
  decision_id: lastDecisionId,
297
297
  success: false,
298
298
  outcome: 'Session ended without explicit commit',
299
- }, SESSION_ID);
299
+ }, SESSION_ID, FLEET_AGENT_ID);
300
300
  }
301
301
  catch (err) {
302
302
  const msg = err instanceof Error ? err.message : String(err);
@@ -572,6 +572,15 @@ if (process.argv[2] !== 'keys') {
572
572
  success: { type: 'boolean', description: 'Did the action succeed?' },
573
573
  outcome: { type: 'string', description: 'What happened — be specific, this trains the hive' },
574
574
  caused_by: { type: 'string', description: 'Optional: what caused this action' },
575
+ proof: {
576
+ type: 'object',
577
+ description: 'Optional required proof pack for gated work: summary, checks, outcome, blockers, commits_prs_shas, rollback_target, handoff_result_file, deployment_and_smoke.',
578
+ },
579
+ gate_receipt_id: { type: 'string', description: 'Receipt id from marrow_agent_runtime.gate_receipt.id for risky work.' },
580
+ 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.' },
581
+ type: { type: 'string', description: 'Optional original action type for auto gate lookup, e.g. deploy, publish, merge, handoff, implementation.' },
582
+ surfaces: { type: 'array', items: { type: 'string' }, description: 'Optional surfaces for auto gate receipt, e.g. github, cloudflare, npm, production.' },
583
+ auto_gate: { type: 'boolean', description: 'If true/default and action is provided, call marrow_agent_runtime to obtain gate_receipt_id before commit.' },
575
584
  },
576
585
  required: ['decision_id', 'success', 'outcome'],
577
586
  },
@@ -959,6 +968,66 @@ if (process.argv[2] !== 'keys') {
959
968
  required: ['action'],
960
969
  },
961
970
  },
971
+ {
972
+ name: 'marrow_mode_recommend',
973
+ description: 'Recommend passive, pilot, or enforce mode from project/workflow signals. Marrow never auto-switches here; the agent/user must accept or override.',
974
+ inputSchema: {
975
+ type: 'object',
976
+ properties: {
977
+ project: { type: 'object', description: 'Project signals: name, type, frameworks, signals, package_scripts, config_files.' },
978
+ workflow: { type: 'object', description: 'Workflow context: action, type, branch, environment.' },
979
+ agent: { type: 'object', description: 'Agent context: id and role.' },
980
+ selected_mode: { type: 'string', enum: ['passive', 'pilot', 'enforce'], description: 'Optional final user-selected mode to log.' },
981
+ selection_source: { type: 'string', enum: ['accepted', 'overridden', 'ignored', 'system'], description: 'How the final mode was selected.' },
982
+ },
983
+ required: [],
984
+ },
985
+ },
986
+ {
987
+ name: 'marrow_policy_profiles',
988
+ description: 'List saved Marrow governance policy profiles for this account. Returns default-business when none are saved.',
989
+ inputSchema: { type: 'object', properties: {}, required: [] },
990
+ },
991
+ {
992
+ name: 'marrow_create_policy_profile',
993
+ description: 'Create or update an explicit governance policy profile. Mutating call; requires a key with full scope.',
994
+ inputSchema: {
995
+ type: 'object',
996
+ properties: {
997
+ name: { type: 'string', description: 'Profile name, e.g. default-business or production-agents.' },
998
+ description: { type: 'string', description: 'Optional profile description.' },
999
+ rules: { type: 'array', items: { type: 'object' }, description: 'Rules with match fields and mode passive/pilot/enforce.' },
1000
+ },
1001
+ required: ['name'],
1002
+ },
1003
+ },
1004
+ {
1005
+ name: 'marrow_assign_project_policy_profile',
1006
+ description: 'Assign an active governance policy profile to a project key. Mutating call; requires a key with full scope.',
1007
+ inputSchema: {
1008
+ type: 'object',
1009
+ properties: {
1010
+ project_key: { type: 'string', description: 'Stable project key, e.g. marrow-api or clinic-api.' },
1011
+ profile_id: { type: 'string', description: 'Active policy profile id.' },
1012
+ },
1013
+ required: ['project_key', 'profile_id'],
1014
+ },
1015
+ },
1016
+ {
1017
+ name: 'marrow_policy_resolve',
1018
+ description: 'Resolve the explicit mode for a project/workflow from saved policy profiles, falling back to recommendation. Does not auto-apply.',
1019
+ inputSchema: {
1020
+ type: 'object',
1021
+ properties: {
1022
+ profile_id: { type: 'string', description: 'Optional policy profile id.' },
1023
+ profile_name: { type: 'string', description: 'Optional policy profile name.' },
1024
+ project: { type: 'object', description: 'Project signals: name, type, frameworks, signals, package_scripts, config_files.' },
1025
+ workflow: { type: 'object', description: 'Workflow context: action, type, branch, environment.' },
1026
+ agent: { type: 'object', description: 'Agent context: id and role.' },
1027
+ },
1028
+ required: [],
1029
+ },
1030
+ },
962
1031
  {
963
1032
  name: 'marrow_workflow_gate',
964
1033
  description: 'Pre-action risk gate for deploys, publishes, merges, DB migrations, key rotation, destructive commands, and production work. ' +
@@ -1263,13 +1332,13 @@ This is not optional overhead — it's how you stop repeating the same failures.
1263
1332
  let result;
1264
1333
  const wantAutoWarn = args.autoWarn ?? true;
1265
1334
  try {
1266
- result = await (0, index_1.marrowOrient)(API_KEY, BASE_URL, { taskType: args.taskType, autoWarn: wantAutoWarn }, SESSION_ID);
1335
+ result = await (0, index_1.marrowOrient)(API_KEY, BASE_URL, { taskType: args.taskType, autoWarn: wantAutoWarn }, SESSION_ID, FLEET_AGENT_ID);
1267
1336
  }
1268
1337
  catch (e) {
1269
1338
  // autoWarn endpoint may not be deployed yet — fall back to legacy orient
1270
1339
  if (wantAutoWarn) {
1271
1340
  process.stderr.write(`[marrow] autoWarn orient not available, falling back to legacy\n`);
1272
- result = await (0, index_1.marrowOrient)(API_KEY, BASE_URL, { taskType: args.taskType, autoWarn: false }, SESSION_ID);
1341
+ result = await (0, index_1.marrowOrient)(API_KEY, BASE_URL, { taskType: args.taskType, autoWarn: false }, SESSION_ID, FLEET_AGENT_ID);
1273
1342
  }
1274
1343
  else {
1275
1344
  throw e;
@@ -1354,7 +1423,13 @@ This is not optional overhead — it's how you stop repeating the same failures.
1354
1423
  success: args.success,
1355
1424
  outcome,
1356
1425
  caused_by: args.caused_by,
1357
- }, SESSION_ID);
1426
+ proof: args.proof,
1427
+ gate_receipt_id: args.gate_receipt_id,
1428
+ action: args.action,
1429
+ type: args.type,
1430
+ surfaces: args.surfaces,
1431
+ auto_gate: args.auto_gate,
1432
+ }, SESSION_ID, FLEET_AGENT_ID);
1358
1433
  const commitResult = { ...result, narrative: result.narrative ?? null };
1359
1434
  lastCommitted = true;
1360
1435
  lastDecisionId = null;
@@ -1386,7 +1461,19 @@ This is not optional overhead — it's how you stop repeating the same failures.
1386
1461
  decision_id: thinkResult.decision_id,
1387
1462
  success: args.success ?? true,
1388
1463
  outcome,
1389
- }, SESSION_ID);
1464
+ proof: {
1465
+ summary: description,
1466
+ checks: ['marrow_run completed'],
1467
+ outcome,
1468
+ blockers: (args.success ?? true) ? 'none' : 'see outcome',
1469
+ commits_prs_shas: 'not applicable',
1470
+ rollback_target: 'not applicable',
1471
+ handoff_result_file: 'not applicable',
1472
+ deployment_and_smoke: 'not applicable',
1473
+ },
1474
+ action: description,
1475
+ type: args.type || 'general',
1476
+ }, SESSION_ID, FLEET_AGENT_ID);
1390
1477
  }
1391
1478
  catch (err) {
1392
1479
  const msg = err instanceof Error ? err.message : String(err);
@@ -1435,7 +1522,23 @@ This is not optional overhead — it's how you stop repeating the same failures.
1435
1522
  }
1436
1523
  else {
1437
1524
  const thinkResult = await (0, index_1.marrowThink)(API_KEY, BASE_URL, { action, type }, SESSION_ID, FLEET_AGENT_ID);
1438
- await (0, index_1.marrowCommit)(API_KEY, BASE_URL, { decision_id: thinkResult.decision_id, success: outcomeSuccess, outcome }, SESSION_ID);
1525
+ await (0, index_1.marrowCommit)(API_KEY, BASE_URL, {
1526
+ decision_id: thinkResult.decision_id,
1527
+ success: outcomeSuccess,
1528
+ outcome,
1529
+ proof: {
1530
+ summary: action,
1531
+ checks: ['marrow_auto completed'],
1532
+ outcome,
1533
+ blockers: outcomeSuccess ? 'none' : 'see outcome',
1534
+ commits_prs_shas: 'not applicable',
1535
+ rollback_target: 'not applicable',
1536
+ handoff_result_file: 'not applicable',
1537
+ deployment_and_smoke: 'not applicable',
1538
+ },
1539
+ action,
1540
+ type,
1541
+ }, SESSION_ID, FLEET_AGENT_ID);
1439
1542
  }
1440
1543
  }
1441
1544
  catch (err) {
@@ -1652,6 +1755,62 @@ This is not optional overhead — it's how you stop repeating the same failures.
1652
1755
  success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
1653
1756
  return;
1654
1757
  }
1758
+ if (toolName === 'marrow_mode_recommend') {
1759
+ const result = await (0, index_1.marrowRecommendGovernanceMode)(API_KEY, BASE_URL, {
1760
+ project: args.project && typeof args.project === 'object' && !Array.isArray(args.project)
1761
+ ? (0, redact_1.redactSensitiveValue)(args.project)
1762
+ : undefined,
1763
+ workflow: args.workflow && typeof args.workflow === 'object' && !Array.isArray(args.workflow)
1764
+ ? (0, redact_1.redactSensitiveValue)(args.workflow)
1765
+ : undefined,
1766
+ agent: args.agent && typeof args.agent === 'object' && !Array.isArray(args.agent)
1767
+ ? (0, redact_1.redactSensitiveValue)(args.agent)
1768
+ : { id: FLEET_AGENT_ID || AGENT_ID },
1769
+ selected_mode: args.selected_mode,
1770
+ selection_source: args.selection_source,
1771
+ }, SESSION_ID, FLEET_AGENT_ID);
1772
+ success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
1773
+ return;
1774
+ }
1775
+ if (toolName === 'marrow_policy_profiles') {
1776
+ const result = await (0, index_1.marrowListPolicyProfiles)(API_KEY, BASE_URL, SESSION_ID, FLEET_AGENT_ID);
1777
+ success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
1778
+ return;
1779
+ }
1780
+ if (toolName === 'marrow_create_policy_profile') {
1781
+ const result = await (0, index_1.marrowCreatePolicyProfile)(API_KEY, BASE_URL, {
1782
+ name: args.name,
1783
+ description: args.description,
1784
+ rules: Array.isArray(args.rules) ? args.rules : undefined,
1785
+ }, SESSION_ID, FLEET_AGENT_ID);
1786
+ success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
1787
+ return;
1788
+ }
1789
+ if (toolName === 'marrow_assign_project_policy_profile') {
1790
+ const result = await (0, index_1.marrowAssignProjectPolicyProfile)(API_KEY, BASE_URL, {
1791
+ project_key: args.project_key,
1792
+ profile_id: args.profile_id,
1793
+ }, SESSION_ID, FLEET_AGENT_ID);
1794
+ success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
1795
+ return;
1796
+ }
1797
+ if (toolName === 'marrow_policy_resolve') {
1798
+ const result = await (0, index_1.marrowResolvePolicy)(API_KEY, BASE_URL, {
1799
+ profile_id: args.profile_id,
1800
+ profile_name: args.profile_name,
1801
+ project: args.project && typeof args.project === 'object' && !Array.isArray(args.project)
1802
+ ? (0, redact_1.redactSensitiveValue)(args.project)
1803
+ : undefined,
1804
+ workflow: args.workflow && typeof args.workflow === 'object' && !Array.isArray(args.workflow)
1805
+ ? (0, redact_1.redactSensitiveValue)(args.workflow)
1806
+ : undefined,
1807
+ agent: args.agent && typeof args.agent === 'object' && !Array.isArray(args.agent)
1808
+ ? (0, redact_1.redactSensitiveValue)(args.agent)
1809
+ : { id: FLEET_AGENT_ID || AGENT_ID },
1810
+ }, SESSION_ID, FLEET_AGENT_ID);
1811
+ success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
1812
+ return;
1813
+ }
1655
1814
  if (toolName === 'marrow_workflow_gate') {
1656
1815
  const result = await (0, index_1.marrowWorkflowGate)(API_KEY, BASE_URL, {
1657
1816
  action: (0, redact_1.redactSensitiveText)(args.action),