@getmarrow/mcp 3.9.76 → 3.9.77
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 +19 -3
- package/dist/cli.js +178 -10
- package/dist/cli.js.map +1 -1
- package/dist/hook-contract.d.ts +2 -2
- package/dist/hook-contract.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -87,6 +87,18 @@ For most new installations, start with the universal installer instead:
|
|
|
87
87
|
npx @getmarrow/install activate
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
## Tool Profiles
|
|
91
|
+
|
|
92
|
+
Ordinary setup does not require `MARROW_TOOL_PROFILE`. When the variable is unset, Marrow uses the `primary` profile and exposes exactly the 17 tools in [Primary MCP Tools](#primary-mcp-tools).
|
|
93
|
+
|
|
94
|
+
- `MARROW_TOOL_PROFILE=primary` explicitly selects the same 17-tool primary surface.
|
|
95
|
+
- `MARROW_TOOL_PROFILE=core` preserves the seven-tool runtime, think, commit, ask, status, auto, and handoff-status surface.
|
|
96
|
+
- `MARROW_TOOL_PROFILE=full` exposes the complete advanced and legacy catalog for integrations that require it.
|
|
97
|
+
|
|
98
|
+
An invalid value returns a bounded configuration error with the exact allowed values; it never falls back to `full`. Restart the MCP process after changing the profile.
|
|
99
|
+
|
|
100
|
+
Local visibility does not grant paid access. Every tool call continues through Marrow's backend authentication, tenant, key-permission, plan, proof, and policy enforcement. MCP status responses include `mcp_tool_profile` with the configured and effective profile, visible tool names/count, and a backend primary-tool entitlement projection when fresh authenticated evidence is provided. Missing or cached entitlement evidence is labeled unavailable and cannot authorize a call.
|
|
101
|
+
|
|
90
102
|
## Keeping MCP Current
|
|
91
103
|
|
|
92
104
|
Marrow's hosted API, website, and dashboard update automatically; local MCP hooks, configuration, and pinned package commands do not silently rewrite themselves. Keeping them current delivers new client-side features, compatibility improvements, and any published security fixes. During authenticated status/runtime activity, Marrow returns a `client_update` notice when the package is behind or unknown, and passive context shows the agent the exact update and verification commands.
|
|
@@ -104,7 +116,11 @@ npx -y --package=@getmarrow/mcp@latest marrow-mcp ping
|
|
|
104
116
|
|
|
105
117
|
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
118
|
|
|
107
|
-
## What's New in v3.9.
|
|
119
|
+
## What's New in v3.9.77
|
|
120
|
+
|
|
121
|
+
v3.9.77 makes `primary` the ordinary MCP profile when `MARROW_TOOL_PROFILE` is unset. The default surface now matches the 17 documented Primary MCP Tools, while explicit `core` preserves the seven-tool control loop and explicit `full` preserves the complete catalog. Invalid values fail with an exact bounded repair instead of broadening visibility. Status responses report the effective profile, visible names/count, and fresh backend-projected entitlement states when provided; local visibility and cached evidence never authorize access. The exact-version 11-tool control-path canary remains pinned to `full`.
|
|
122
|
+
|
|
123
|
+
## Previous: v3.9.76
|
|
108
124
|
|
|
109
125
|
v3.9.76 fixes owner-approved `marrow_auto` closeout by binding an arbitrated operation to the exact server-created arbitration decision, rejecting decision mismatches before commit, and returning an honest terminal action for non-arbitrated `review_required` gates. Chat and proof text cannot substitute for a dashboard-issued approval receipt, and only a backend `committed: true` response closes the operation.
|
|
110
126
|
|
|
@@ -197,7 +213,7 @@ v3.9.62 integrates four model-neutral reliability and capability contracts:
|
|
|
197
213
|
- `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;
|
|
198
214
|
- initialize, prompt, setup, and tool responses qualify coverage by `host_capability`: MCP tools are on demand, while client-self-reported hook activity remains visible but never certifies coverage or control.
|
|
199
215
|
|
|
200
|
-
|
|
216
|
+
In v3.9.62, the default surface was seven tools (runtime, think, commit, ask, status, auto, handoff status) and the prompt remained named `marrow-always-on`. Host and model labels are display-only and never change auth, tenant, plan, policy, proof, schema, or API behavior. Grok hook activity is client-self-reported and does not certify observed coverage; the governed wrapper remains an explicit bounded fallback.
|
|
201
217
|
|
|
202
218
|
## Previous: v3.9.61
|
|
203
219
|
|
|
@@ -251,7 +267,7 @@ The compact agent control path introduced in v3.9.57 remains the default:
|
|
|
251
267
|
- `marrow_status`, `marrow_ask`, and `marrow_agent_runtime` use authenticated routes with bounded retries and typed failures;
|
|
252
268
|
- transient read failures return an owner-only last-known brief when available, while cached guidance can never authorize high-risk work;
|
|
253
269
|
- normal tool errors return structured `ok`, `error_code`, `exact_fix`, `stale_brief`, and `client_update` data instead of raw MCP `fetch failed` errors;
|
|
254
|
-
- the default agent surface
|
|
270
|
+
- the v3.9.58 default agent surface was seven tools: runtime, think, commit, ask, status, auto, and handoff status; `MARROW_TOOL_PROFILE=full` selected legacy or advanced integrations;
|
|
255
271
|
- risky `marrow_auto` calls obtain a fresh runtime gate automatically and cannot self-close as successful without required proof;
|
|
256
272
|
- `marrow_run` requires an explicit outcome and never invents proof or a successful result;
|
|
257
273
|
- the package includes an exact-version control-path canary covering every route reported in the production incident.
|
package/dist/cli.js
CHANGED
|
@@ -544,6 +544,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
544
544
|
drain_command: 'npx -y --package=@getmarrow/mcp@latest marrow-mcp drain-spool',
|
|
545
545
|
legacy_namespaces: spool.other_namespaces?.count || 0,
|
|
546
546
|
},
|
|
547
|
+
mcp_tool_profile: mcpToolProfileStatus(payload),
|
|
547
548
|
};
|
|
548
549
|
}
|
|
549
550
|
// [FIX #9] Runtime validation helper for required string params
|
|
@@ -1718,15 +1719,168 @@ if (process.argv[2] !== 'keys') {
|
|
|
1718
1719
|
'marrow_auto',
|
|
1719
1720
|
'marrow_handoff_status',
|
|
1720
1721
|
]);
|
|
1722
|
+
const PRIMARY_TOOL_NAMES = new Set([
|
|
1723
|
+
'marrow_agent_runtime',
|
|
1724
|
+
'marrow_arbitrate',
|
|
1725
|
+
'marrow_coordinate',
|
|
1726
|
+
'marrow_replay_compare',
|
|
1727
|
+
'marrow_decision_brief',
|
|
1728
|
+
'marrow_think',
|
|
1729
|
+
'marrow_commit',
|
|
1730
|
+
'marrow_workflow_gate',
|
|
1731
|
+
'marrow_completion_contracts',
|
|
1732
|
+
'marrow_evaluate_completion_contract',
|
|
1733
|
+
'marrow_agent_status',
|
|
1734
|
+
'marrow_value_report',
|
|
1735
|
+
'marrow_buyer_proof',
|
|
1736
|
+
'marrow_governance_timeline',
|
|
1737
|
+
'marrow_decision_trace',
|
|
1738
|
+
'marrow_fleet_lessons',
|
|
1739
|
+
'marrow_model_usage',
|
|
1740
|
+
]);
|
|
1741
|
+
function activeToolProfile() {
|
|
1742
|
+
const configured = process.env.MARROW_TOOL_PROFILE;
|
|
1743
|
+
if (configured === undefined || configured === 'primary')
|
|
1744
|
+
return 'primary';
|
|
1745
|
+
if (configured === 'core' || configured === 'full')
|
|
1746
|
+
return configured;
|
|
1747
|
+
throw new Error('Invalid MARROW_TOOL_PROFILE value. Set MARROW_TOOL_PROFILE=primary, core, or full, '
|
|
1748
|
+
+ 'or unset it for primary; then restart MCP.');
|
|
1749
|
+
}
|
|
1750
|
+
function toolsForProfile(profile) {
|
|
1751
|
+
if (profile === 'full')
|
|
1752
|
+
return TOOLS;
|
|
1753
|
+
const visibleNames = profile === 'primary' ? PRIMARY_TOOL_NAMES : CORE_TOOL_NAMES;
|
|
1754
|
+
return TOOLS.filter((tool) => visibleNames.has(tool.name));
|
|
1755
|
+
}
|
|
1721
1756
|
function advertisedTools() {
|
|
1722
|
-
return
|
|
1723
|
-
? TOOLS
|
|
1724
|
-
: TOOLS.filter((tool) => CORE_TOOL_NAMES.has(tool.name));
|
|
1757
|
+
return toolsForProfile(activeToolProfile());
|
|
1725
1758
|
}
|
|
1726
1759
|
function toolAllowedByActiveProfile(toolName) {
|
|
1727
|
-
return
|
|
1728
|
-
|
|
1729
|
-
|
|
1760
|
+
return Boolean(toolName && toolsForProfile(activeToolProfile()).some((tool) => tool.name === toolName));
|
|
1761
|
+
}
|
|
1762
|
+
function recordValue(value) {
|
|
1763
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
1764
|
+
? value
|
|
1765
|
+
: null;
|
|
1766
|
+
}
|
|
1767
|
+
function nonNegativeInteger(value) {
|
|
1768
|
+
return Number.isInteger(value) && Number(value) >= 0;
|
|
1769
|
+
}
|
|
1770
|
+
function validatedPrimaryToolAvailability(value) {
|
|
1771
|
+
const projection = recordValue(value);
|
|
1772
|
+
const evidence = recordValue(projection?.entitlement_evidence);
|
|
1773
|
+
const counts = recordValue(projection?.counts);
|
|
1774
|
+
const tools = projection?.tools;
|
|
1775
|
+
const expectedNames = [...PRIMARY_TOOL_NAMES];
|
|
1776
|
+
if (!projection
|
|
1777
|
+
|| projection.profile !== 'primary'
|
|
1778
|
+
|| (projection.current_plan !== null && typeof projection.current_plan !== 'string')
|
|
1779
|
+
|| typeof projection.owner_management_url !== 'string'
|
|
1780
|
+
|| !evidence
|
|
1781
|
+
|| (evidence.state !== 'available' && evidence.state !== 'unavailable')
|
|
1782
|
+
|| typeof evidence.source !== 'string'
|
|
1783
|
+
|| typeof evidence.authoritative !== 'boolean'
|
|
1784
|
+
|| evidence.authorizing !== false
|
|
1785
|
+
|| !counts
|
|
1786
|
+
|| !nonNegativeInteger(counts.total)
|
|
1787
|
+
|| !nonNegativeInteger(counts.entitled)
|
|
1788
|
+
|| !nonNegativeInteger(counts.upgrade_required)
|
|
1789
|
+
|| !nonNegativeInteger(counts.unavailable)
|
|
1790
|
+
|| counts.total !== expectedNames.length
|
|
1791
|
+
|| counts.entitled + counts.upgrade_required + counts.unavailable !== counts.total
|
|
1792
|
+
|| !Array.isArray(tools)
|
|
1793
|
+
|| tools.length !== expectedNames.length) {
|
|
1794
|
+
return null;
|
|
1795
|
+
}
|
|
1796
|
+
if ((evidence.state === 'available' && evidence.authoritative !== true)
|
|
1797
|
+
|| (evidence.state === 'unavailable' && evidence.authoritative !== false)) {
|
|
1798
|
+
return null;
|
|
1799
|
+
}
|
|
1800
|
+
const derivedCounts = { entitled: 0, upgrade_required: 0, unavailable: 0 };
|
|
1801
|
+
for (let index = 0; index < tools.length; index++) {
|
|
1802
|
+
const tool = recordValue(tools[index]);
|
|
1803
|
+
const state = tool?.state;
|
|
1804
|
+
if (!tool
|
|
1805
|
+
|| tool.name !== expectedNames[index]
|
|
1806
|
+
|| (state !== 'entitled' && state !== 'upgrade_required' && state !== 'unavailable')
|
|
1807
|
+
|| typeof tool.always_available !== 'boolean'
|
|
1808
|
+
|| (tool.plan_feature !== null && typeof tool.plan_feature !== 'string')
|
|
1809
|
+
|| (tool.minimum_plan !== null && typeof tool.minimum_plan !== 'string')
|
|
1810
|
+
|| typeof tool.owner_management_url !== 'string') {
|
|
1811
|
+
return null;
|
|
1812
|
+
}
|
|
1813
|
+
derivedCounts[state]++;
|
|
1814
|
+
}
|
|
1815
|
+
if (derivedCounts.entitled !== counts.entitled
|
|
1816
|
+
|| derivedCounts.upgrade_required !== counts.upgrade_required
|
|
1817
|
+
|| derivedCounts.unavailable !== counts.unavailable) {
|
|
1818
|
+
return null;
|
|
1819
|
+
}
|
|
1820
|
+
return {
|
|
1821
|
+
projection,
|
|
1822
|
+
evidenceState: evidence.state,
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
function backendPrimaryToolAvailability(value) {
|
|
1826
|
+
const payload = recordValue(value);
|
|
1827
|
+
if (!payload)
|
|
1828
|
+
return null;
|
|
1829
|
+
const data = recordValue(payload.data);
|
|
1830
|
+
const status = recordValue(payload.status);
|
|
1831
|
+
const entitlements = recordValue(payload.entitlements);
|
|
1832
|
+
const entitlementProjection = recordValue(payload.entitlement_projection);
|
|
1833
|
+
const statusEntitlements = recordValue(status?.entitlements);
|
|
1834
|
+
const statusProjection = recordValue(status?.entitlement_projection);
|
|
1835
|
+
const candidates = [
|
|
1836
|
+
payload.primary_tool_availability,
|
|
1837
|
+
data?.primary_tool_availability,
|
|
1838
|
+
status?.primary_tool_availability,
|
|
1839
|
+
entitlements?.primary_tool_availability,
|
|
1840
|
+
entitlementProjection?.primary_tool_availability,
|
|
1841
|
+
statusEntitlements?.primary_tool_availability,
|
|
1842
|
+
statusProjection?.primary_tool_availability,
|
|
1843
|
+
];
|
|
1844
|
+
for (const candidate of candidates) {
|
|
1845
|
+
const validated = validatedPrimaryToolAvailability(candidate);
|
|
1846
|
+
if (validated)
|
|
1847
|
+
return validated;
|
|
1848
|
+
}
|
|
1849
|
+
return null;
|
|
1850
|
+
}
|
|
1851
|
+
function mcpToolProfileStatus(value) {
|
|
1852
|
+
const profile = activeToolProfile();
|
|
1853
|
+
const visibleToolNames = toolsForProfile(profile).map((tool) => tool.name);
|
|
1854
|
+
const payload = recordValue(value);
|
|
1855
|
+
const cachedOrStale = payload?.cached === true
|
|
1856
|
+
|| payload?.stale === true
|
|
1857
|
+
|| payload?.status_freshness === 'stale';
|
|
1858
|
+
const backendProjection = cachedOrStale ? null : backendPrimaryToolAvailability(payload);
|
|
1859
|
+
const backendProjectionAvailable = backendProjection?.evidenceState === 'available';
|
|
1860
|
+
return {
|
|
1861
|
+
configured_profile: process.env.MARROW_TOOL_PROFILE ?? 'unset',
|
|
1862
|
+
effective_profile: profile,
|
|
1863
|
+
visible_tool_count: visibleToolNames.length,
|
|
1864
|
+
visible_tool_names: visibleToolNames,
|
|
1865
|
+
local_visibility_grants_entitlement: false,
|
|
1866
|
+
backend_entitlement_projection: {
|
|
1867
|
+
evidence_state: backendProjectionAvailable ? 'available' : 'unavailable',
|
|
1868
|
+
source: cachedOrStale
|
|
1869
|
+
? 'cached_or_stale_status'
|
|
1870
|
+
: backendProjection
|
|
1871
|
+
? 'authenticated_backend'
|
|
1872
|
+
: 'backend_projection_not_provided',
|
|
1873
|
+
authorizes_calls: false,
|
|
1874
|
+
primary_tool_availability: backendProjectionAvailable ? backendProjection.projection : null,
|
|
1875
|
+
},
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
function withMcpToolProfileStatus(value) {
|
|
1879
|
+
const payload = recordValue(value) || { data: value };
|
|
1880
|
+
return {
|
|
1881
|
+
...payload,
|
|
1882
|
+
mcp_tool_profile: mcpToolProfileStatus(payload),
|
|
1883
|
+
};
|
|
1730
1884
|
}
|
|
1731
1885
|
// Request handler
|
|
1732
1886
|
async function handleRequest(req) {
|
|
@@ -1847,7 +2001,10 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1847
2001
|
const toolName = params?.name;
|
|
1848
2002
|
const args = (params?.arguments || {});
|
|
1849
2003
|
if (!toolAllowedByActiveProfile(toolName)) {
|
|
1850
|
-
|
|
2004
|
+
const repair = toolName && PRIMARY_TOOL_NAMES.has(toolName)
|
|
2005
|
+
? 'Unset MARROW_TOOL_PROFILE or set MARROW_TOOL_PROFILE=primary, then restart MCP.'
|
|
2006
|
+
: 'Set MARROW_TOOL_PROFILE=full, then restart MCP for the complete advanced/legacy catalog.';
|
|
2007
|
+
error(id, -32601, `Tool is not available in the active Marrow tool profile. ${repair}`);
|
|
1851
2008
|
return;
|
|
1852
2009
|
}
|
|
1853
2010
|
if (toolName === 'marrow_orient') {
|
|
@@ -2304,13 +2461,24 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2304
2461
|
return;
|
|
2305
2462
|
}
|
|
2306
2463
|
if (toolName === 'marrow_agent_status') {
|
|
2307
|
-
const result = await (
|
|
2308
|
-
|
|
2464
|
+
const result = await withControlDeadline(async (signal) => {
|
|
2465
|
+
const [analyticsStatus, context] = await Promise.all([
|
|
2466
|
+
(0, index_1.marrowAgentStatus)(API_KEY, BASE_URL, args.period || '7d', args.agentId || FLEET_AGENT_ID, SESSION_ID, FLEET_AGENT_ID, signal),
|
|
2467
|
+
(0, index_1.marrowAgentContext)(API_KEY, BASE_URL, SESSION_ID, FLEET_AGENT_ID, signal)
|
|
2468
|
+
.catch(() => null),
|
|
2469
|
+
]);
|
|
2470
|
+
const contextProjection = recordValue(context)?.primary_tool_availability;
|
|
2471
|
+
return {
|
|
2472
|
+
...analyticsStatus,
|
|
2473
|
+
...(contextProjection === undefined ? {} : { primary_tool_availability: contextProjection }),
|
|
2474
|
+
};
|
|
2475
|
+
}, { cacheAware: false, toolName: 'marrow_agent_status' });
|
|
2476
|
+
success(id, { content: [{ type: 'text', text: JSON.stringify(withMcpToolProfileStatus({ ...result, local_control: (0, control_state_1.localControlEvidence)(Boolean(API_KEY)) }), null, 2) }] });
|
|
2309
2477
|
return;
|
|
2310
2478
|
}
|
|
2311
2479
|
if (toolName === 'marrow_runtime_status') {
|
|
2312
2480
|
const result = await withControlDeadline((signal) => (0, index_1.marrowRuntimeStatus)(API_KEY, BASE_URL, args.fast !== false, SESSION_ID, FLEET_AGENT_ID, signal), { cacheAware: false, toolName: 'marrow_runtime_status' });
|
|
2313
|
-
success(id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
|
|
2481
|
+
success(id, { content: [{ type: 'text', text: JSON.stringify(withMcpToolProfileStatus(result), null, 2) }] });
|
|
2314
2482
|
return;
|
|
2315
2483
|
}
|
|
2316
2484
|
if (toolName === 'marrow_value_report') {
|