@tethral/acr-mcp 0.9.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +38 -32
  2. package/dist/src/env-detect.d.ts +15 -0
  3. package/dist/src/env-detect.js +22 -0
  4. package/dist/src/env-detect.js.map +1 -1
  5. package/dist/src/middleware/correlation-window.d.ts +68 -0
  6. package/dist/src/middleware/correlation-window.js +113 -0
  7. package/dist/src/middleware/correlation-window.js.map +1 -0
  8. package/dist/src/server.d.ts +3 -0
  9. package/dist/src/server.js +32 -9
  10. package/dist/src/server.js.map +1 -1
  11. package/dist/src/session-state.d.ts +3 -0
  12. package/dist/src/session-state.js +11 -0
  13. package/dist/src/session-state.js.map +1 -1
  14. package/dist/src/tools/acknowledge-threat.js +11 -6
  15. package/dist/src/tools/acknowledge-threat.js.map +1 -1
  16. package/dist/src/tools/check-entity.js +57 -58
  17. package/dist/src/tools/check-entity.js.map +1 -1
  18. package/dist/src/tools/check-environment.js +8 -4
  19. package/dist/src/tools/check-environment.js.map +1 -1
  20. package/dist/src/tools/disable-deep-composition.d.ts +20 -0
  21. package/dist/src/tools/disable-deep-composition.js +45 -0
  22. package/dist/src/tools/disable-deep-composition.js.map +1 -0
  23. package/dist/src/tools/get-coverage.d.ts +2 -0
  24. package/dist/src/tools/get-coverage.js +67 -0
  25. package/dist/src/tools/get-coverage.js.map +1 -0
  26. package/dist/src/tools/get-failure-registry.d.ts +2 -0
  27. package/dist/src/tools/get-failure-registry.js +75 -0
  28. package/dist/src/tools/get-failure-registry.js.map +1 -0
  29. package/dist/src/tools/get-friction-report.js +66 -15
  30. package/dist/src/tools/get-friction-report.js.map +1 -1
  31. package/dist/src/tools/get-interaction-log.js +22 -25
  32. package/dist/src/tools/get-interaction-log.js.map +1 -1
  33. package/dist/src/tools/get-my-agent.js +5 -1
  34. package/dist/src/tools/get-my-agent.js.map +1 -1
  35. package/dist/src/tools/get-network-status.js +11 -8
  36. package/dist/src/tools/get-network-status.js.map +1 -1
  37. package/dist/src/tools/get-notifications.js +9 -10
  38. package/dist/src/tools/get-notifications.js.map +1 -1
  39. package/dist/src/tools/get-profile.d.ts +2 -0
  40. package/dist/src/tools/get-profile.js +89 -0
  41. package/dist/src/tools/get-profile.js.map +1 -0
  42. package/dist/src/tools/get-skill-tracker.js +16 -14
  43. package/dist/src/tools/get-skill-tracker.js.map +1 -1
  44. package/dist/src/tools/get-skill-versions.js +14 -11
  45. package/dist/src/tools/get-skill-versions.js.map +1 -1
  46. package/dist/src/tools/get-stable-corridors.d.ts +2 -0
  47. package/dist/src/tools/get-stable-corridors.js +65 -0
  48. package/dist/src/tools/get-stable-corridors.js.map +1 -0
  49. package/dist/src/tools/get-trend.d.ts +2 -0
  50. package/dist/src/tools/get-trend.js +75 -0
  51. package/dist/src/tools/get-trend.js.map +1 -0
  52. package/dist/src/tools/log-interaction.d.ts +2 -1
  53. package/dist/src/tools/log-interaction.js +116 -25
  54. package/dist/src/tools/log-interaction.js.map +1 -1
  55. package/dist/src/tools/register-agent.js +67 -15
  56. package/dist/src/tools/register-agent.js.map +1 -1
  57. package/dist/src/tools/search-skills.js +33 -19
  58. package/dist/src/tools/search-skills.js.map +1 -1
  59. package/dist/src/tools/summarize-my-agent.d.ts +2 -0
  60. package/dist/src/tools/summarize-my-agent.js +100 -0
  61. package/dist/src/tools/summarize-my-agent.js.map +1 -0
  62. package/dist/src/tools/update-composition.js +67 -13
  63. package/dist/src/tools/update-composition.js.map +1 -1
  64. package/package.json +4 -4
@@ -1,9 +1,14 @@
1
1
  import { z } from 'zod';
2
2
  export function checkEntityTool(server, apiUrl, resolverUrl) {
3
- server.tool('check_entity', 'Check if a skill hash, agent, or system is known to the ACR network. Use before installing skills to verify safety. This is a read-only lookup — no data is sent to ACR.', {
4
- entity_type: z.enum(['skill', 'agent', 'system']).describe('Type of entity to look up'),
5
- entity_id: z.string().describe('The entity identifier: skill SHA-256 hash, agent_id, or system_id'),
6
- }, { readOnlyHint: true, destructiveHint: false }, async ({ entity_type, entity_id }) => {
3
+ server.registerTool('check_entity', {
4
+ description: 'Ask the ACR network what it knows about a specific skill hash, agent, or system. Returns the raw behavioral signals ACR has observed: interaction counts, failure and anomaly rates, agent adoption counts, and related metadata. This is NOT a security check — ACR does not evaluate, score, or test. It only records what has been observed and surfaces the raw counts. Read-only lookup; no data is sent to ACR.',
5
+ inputSchema: {
6
+ entity_type: z.enum(['skill', 'agent', 'system']).describe('Type of entity to look up'),
7
+ entity_id: z.string().describe('The entity identifier: skill SHA-256 hash, agent_id, or system_id'),
8
+ },
9
+ annotations: { readOnlyHint: true, destructiveHint: false },
10
+ _meta: { priorityHint: 0.6 },
11
+ }, async ({ entity_type, entity_id }) => {
7
12
  try {
8
13
  let url;
9
14
  switch (entity_type) {
@@ -41,76 +46,57 @@ export function checkEntityTool(server, apiUrl, resolverUrl) {
41
46
  return {
42
47
  content: [{
43
48
  type: 'text',
44
- text: `Unknown skill. This hash has not been seen in the ACR network. Exercise caution with unfamiliar skills.${similarText}`,
49
+ text: `Unknown skill. This hash has not been observed by the ACR network.${similarText}`,
45
50
  }],
46
51
  };
47
52
  }
48
- // ── BLOCKED SKILL: Content scan detected threats ──
49
- if (data.blocked) {
50
- let text = `BLOCKED SKILL DO NOT INSTALL\n`;
51
- text += `════════════════════════════════════════\n`;
52
- if (data.skill_name)
53
- text += `Name: ${data.skill_name}\n`;
54
- text += `Threat Level: ${(data.threat_level ?? 'unknown').toUpperCase()}\n`;
55
- text += `Security Score: ${data.scan_score ?? 0}/100\n`;
56
- if (data.blocked_reason)
57
- text += `\nReason: ${data.blocked_reason}\n`;
58
- if (data.threat_patterns && data.threat_patterns.length > 0) {
59
- text += `\nDetected Threat Patterns:\n`;
60
- for (const p of data.threat_patterns) {
61
- text += ` - ${p}\n`;
62
- }
63
- }
64
- text += `\nThis skill has been flagged by ACR's content security scanner `;
65
- text += `and is BLOCKED from installation. The skill content is not `;
66
- text += `available for download, copy, or viewing.\n`;
67
- text += `\nIf you currently have this skill installed, you should `;
68
- text += `consider uninstalling it and notifying your user.\n`;
69
- text += `\nTo request a review or dispute this block, `;
70
- text += `contact security@tethral.com with hash: ${entity_id}`;
71
- return { content: [{ type: 'text', text }] };
72
- }
73
- // ── Normal skill response ──
74
- const level = (data.threat_level ?? 'none').toUpperCase();
75
- let text = `Skill found.\n\nThreat Level: ${level}`;
53
+ // Skill signals raw observed data from the network. No
54
+ // synthetic threat level label, no "FLAGGED BY ACR" verdict.
55
+ // The MCP reports what the network has seen; the operator
56
+ // decides what to do with it.
57
+ let text = `Skill found: ${data.skill_hash?.slice(0, 16) ?? entity_id.slice(0, 16)}...\n`;
76
58
  if (data.skill_name)
77
- text += `\nName: ${data.skill_name}`;
59
+ text += `Name: ${data.skill_name}\n`;
78
60
  if (data.description)
79
- text += `\nDescription: ${data.description}`;
61
+ text += `Description: ${data.description}\n`;
80
62
  if (data.version)
81
- text += `\nVersion: ${data.version}`;
63
+ text += `Version: ${data.version}\n`;
82
64
  if (data.author)
83
- text += `\nAuthor: ${data.author}`;
65
+ text += `Author: ${data.author}\n`;
84
66
  if (data.category)
85
- text += `\nCategory: ${data.category}`;
67
+ text += `Category: ${data.category}\n`;
86
68
  if (data.tags && data.tags.length > 0)
87
- text += `\nTags: ${data.tags.join(', ')}`;
69
+ text += `Tags: ${data.tags.join(', ')}\n`;
70
+ text += `\n── Network signals ──\n`;
88
71
  if (data.agent_count != null)
89
- text += `\nAgents using: ${data.agent_count}`;
72
+ text += ` Agents observed using this skill: ${data.agent_count}\n`;
90
73
  if (data.interaction_count != null)
91
- text += `\nInteractions: ${data.interaction_count}`;
74
+ text += ` Total interactions observed: ${data.interaction_count}\n`;
75
+ if (data.anomaly_signal_count != null)
76
+ text += ` Anomaly signals reported: ${data.anomaly_signal_count}\n`;
92
77
  if (data.anomaly_rate != null)
93
- text += `\nAnomaly rate: ${(data.anomaly_rate * 100).toFixed(1)}%`;
94
- if (data.scan_score != null)
95
- text += `\nSecurity Score: ${data.scan_score}/100`;
96
- if (data.threat_patterns && data.threat_patterns.length > 0) {
97
- text += `\nSecurity Findings: ${data.threat_patterns.join(', ')}`;
78
+ text += ` Anomaly rate: ${(data.anomaly_rate * 100).toFixed(1)}%\n`;
79
+ // Signal categories observed — these are descriptive tags of
80
+ // what kinds of anomaly patterns the network has seen, not
81
+ // severity labels.
82
+ if (data.threat_patterns && Array.isArray(data.threat_patterns) && data.threat_patterns.length > 0) {
83
+ text += ` Anomaly pattern categories: ${data.threat_patterns.join(', ')}\n`;
98
84
  }
99
- // Version freshness check
85
+ // Scan signals — if the content scanner observed something,
86
+ // the scanner's raw findings (which patterns it matched) are
87
+ // reported here. No pass/fail verdict.
88
+ if (data.scan_score != null)
89
+ text += ` Content scanner score (external): ${data.scan_score}\n`;
90
+ // Version freshness — raw comparison, no advice.
100
91
  if (data.is_current_version === false) {
101
- text += `\n\nOUTDATED: You are ${data.versions_behind ?? '?'} version(s) behind.`;
92
+ text += `\n── Version ──\n`;
93
+ text += ` This version is ${data.versions_behind ?? '?'} behind the latest observed version.`;
102
94
  if (data.current_hash)
103
- text += ` Current hash: ${data.current_hash.slice(0, 16)}...`;
104
- text += '\nConsider updating to the latest version.';
95
+ text += ` Latest hash: ${data.current_hash.slice(0, 16)}...`;
96
+ text += '\n';
105
97
  }
106
98
  else if (data.is_current_version === true) {
107
- text += '\n\nThis is the latest version.';
108
- }
109
- if (data.threat_level === 'high' || data.threat_level === 'critical') {
110
- text += `\n\nWARNING: This skill has been flagged. Do not install without explicit user confirmation.`;
111
- }
112
- else if (data.threat_level === 'medium') {
113
- text += `\n\nCaution: Elevated anomaly signals. Proceed only if the user confirms.`;
99
+ text += `\n── Version ──\n This is the latest version observed by the network.\n`;
114
100
  }
115
101
  return { content: [{ type: 'text', text }] };
116
102
  }
@@ -129,10 +115,23 @@ export function checkEntityTool(server, apiUrl, resolverUrl) {
129
115
  if (!data.found) {
130
116
  return { content: [{ type: 'text', text: `System ${entity_id} not found.` }] };
131
117
  }
118
+ // Raw network signals for the target system. No synthetic
119
+ // health_status label — client reads the rates and decides.
120
+ let sysText = `System found: ${entity_id}\n`;
121
+ sysText += `Type: ${data.system_type}\n\n`;
122
+ sysText += `── Network signals ──\n`;
123
+ sysText += ` Total interactions observed: ${data.total_interactions ?? 0}\n`;
124
+ sysText += ` Distinct agents using this system: ${data.distinct_agents ?? 0}\n`;
125
+ sysText += ` Failure rate: ${((data.failure_rate ?? 0) * 100).toFixed(1)}%\n`;
126
+ sysText += ` Anomaly rate: ${((data.anomaly_rate ?? 0) * 100).toFixed(1)}%\n`;
127
+ if (data.median_duration_ms != null)
128
+ sysText += ` Median duration: ${data.median_duration_ms}ms\n`;
129
+ if (data.p95_duration_ms != null)
130
+ sysText += ` p95 duration: ${data.p95_duration_ms}ms\n`;
132
131
  return {
133
132
  content: [{
134
133
  type: 'text',
135
- text: `System found.\n\nHealth: ${data.health_status}\nType: ${data.system_type}\nTotal interactions: ${data.total_interactions}\nDistinct agents: ${data.distinct_agents}\nAnomaly rate: ${((data.anomaly_rate ?? 0) * 100).toFixed(1)}%`,
134
+ text: sysText,
136
135
  }],
137
136
  };
138
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"check-entity.js","sourceRoot":"","sources":["../../../src/tools/check-entity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check-entity.js","sourceRoot":"","sources":["../../../src/tools/check-entity.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,9 @@
1
1
  export function checkEnvironmentTool(server, apiUrl, resolverUrl) {
2
- server.tool('check_environment', 'Check the current ACR network environment: active threats and system health. Call on startup or when assessing risk. Remember to call log_interaction after every external tool call so ACR can detect threats and track friction.', {}, { readOnlyHint: true, destructiveHint: false }, async () => {
2
+ server.registerTool('check_environment', {
3
+ description: 'Check the current ACR network environment: active anomaly signals and network-level observation data. Call on startup to see the state of the broader network. Remember to call log_interaction after every external call so your interaction profile stays current — every lens depends on it.',
4
+ annotations: { readOnlyHint: true, destructiveHint: false },
5
+ _meta: { priorityHint: 0.8 },
6
+ }, async () => {
3
7
  try {
4
8
  const [threatsRes, healthRes] = await Promise.all([
5
9
  fetch(`${resolverUrl}/v1/threats/active`),
@@ -9,13 +13,13 @@ export function checkEnvironmentTool(server, apiUrl, resolverUrl) {
9
13
  const health = await healthRes.json();
10
14
  let text = `ACR Network Status: ${health.status ?? 'unknown'}\n`;
11
15
  if (Array.isArray(threats) && threats.length > 0) {
12
- text += `\nActive Threats: ${threats.length}\n`;
16
+ text += `\nSkills with elevated anomaly signals: ${threats.length}\n`;
13
17
  for (const t of threats) {
14
- text += `- [${t.threat_level.toUpperCase()}] ${t.skill_name || t.skill_hash.substring(0, 16) + '...'} (${t.anomaly_signal_count} signals)\n`;
18
+ text += `- ${t.skill_name || t.skill_hash.substring(0, 16) + '...'} ${t.anomaly_signal_count} signals, ${t.agent_count ?? 0} reporters\n`;
15
19
  }
16
20
  }
17
21
  else {
18
- text += '\nNo active threats detected.';
22
+ text += '\nNo elevated anomaly signals observed.';
19
23
  }
20
24
  return { content: [{ type: 'text', text }] };
21
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"check-environment.js","sourceRoot":"","sources":["../../../src/tools/check-environment.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAc,EAAE,WAAmB;IACzF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,oOAAoO,EACpO,EAAE,EACF,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChD,KAAK,CAAC,GAAG,WAAW,oBAAoB,CAAC;gBACzC,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC;aACjC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;YAEtC,IAAI,IAAI,GAAG,uBAAuB,MAAM,CAAC,MAAM,IAAI,SAAS,IAAI,CAAC;YAEjE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjD,IAAI,IAAI,qBAAqB,OAAO,CAAC,MAAM,IAAI,CAAC;gBAChD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,IAAI,MAAM,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,oBAAoB,aAAa,CAAC;gBAC/I,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,+BAA+B,CAAC;YAC1C,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACjE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,4BAA4B,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC;QAC3F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"check-environment.js","sourceRoot":"","sources":["../../../src/tools/check-environment.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAc,EAAE,WAAmB;IACzF,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,WAAW,EAAE,iSAAiS;QAC9S,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE;QAC3D,KAAK,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE;KAC7B,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChD,KAAK,CAAC,GAAG,WAAW,oBAAoB,CAAC;gBACzC,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC;aACjC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;YAEtC,IAAI,IAAI,GAAG,uBAAuB,MAAM,CAAC,MAAM,IAAI,SAAS,IAAI,CAAC;YAEjE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjD,IAAI,IAAI,2CAA2C,OAAO,CAAC,MAAM,IAAI,CAAC;gBACtE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,IAAI,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,oBAAoB,aAAa,CAAC,CAAC,WAAW,IAAI,CAAC,cAAc,CAAC;gBAC9I,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,yCAAyC,CAAC;YACpD,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACjE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,4BAA4B,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC;QAC3F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { SessionState } from '../session-state.js';
3
+ /**
4
+ * Operator privacy control for deep composition capture.
5
+ *
6
+ * By default, when the agent reports composition (via register_agent or
7
+ * update_composition), rich component records include sub_components —
8
+ * ACR gets the internals of each attached skill or MCP so it can
9
+ * distinguish internal friction from external friction correctly.
10
+ *
11
+ * Operators who don't want ACR to see the internals can disable deep
12
+ * composition capture. When off, the MCP still sends top-level component
13
+ * data (skill name, MCP name, hash) but strips sub_components before
14
+ * sending. ACR's internal-vs-external classification becomes coarser as
15
+ * a result — that's the tradeoff.
16
+ *
17
+ * Also settable via the ACR_DEEP_COMPOSITION=false environment variable
18
+ * at MCP startup.
19
+ */
20
+ export declare function disableDeepCompositionTool(server: McpServer, getSession: () => SessionState): void;
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Operator privacy control for deep composition capture.
4
+ *
5
+ * By default, when the agent reports composition (via register_agent or
6
+ * update_composition), rich component records include sub_components —
7
+ * ACR gets the internals of each attached skill or MCP so it can
8
+ * distinguish internal friction from external friction correctly.
9
+ *
10
+ * Operators who don't want ACR to see the internals can disable deep
11
+ * composition capture. When off, the MCP still sends top-level component
12
+ * data (skill name, MCP name, hash) but strips sub_components before
13
+ * sending. ACR's internal-vs-external classification becomes coarser as
14
+ * a result — that's the tradeoff.
15
+ *
16
+ * Also settable via the ACR_DEEP_COMPOSITION=false environment variable
17
+ * at MCP startup.
18
+ */
19
+ export function disableDeepCompositionTool(server, getSession) {
20
+ server.registerTool('configure_deep_composition', {
21
+ description: 'Operator privacy control. Enable or disable deep composition capture for this session. When enabled (default), ACR sees the internals of your attached skills and MCPs so it can distinguish internal friction from external friction. When disabled, only top-level component info is sent — ACR no longer sees sub-components. Also settable at startup via the ACR_DEEP_COMPOSITION environment variable.',
22
+ inputSchema: {
23
+ enabled: z.boolean().describe('Set to true to enable deep capture, false to disable.'),
24
+ },
25
+ annotations: { readOnlyHint: false, destructiveHint: false },
26
+ _meta: { priorityHint: 0.3 },
27
+ }, async ({ enabled }) => {
28
+ const session = getSession();
29
+ const previous = session.deepComposition;
30
+ session.setDeepComposition(enabled);
31
+ const statusText = enabled
32
+ ? 'Deep composition capture is now ENABLED. ACR will include sub-components of skills and MCPs in future composition reports. This lets the network distinguish internal interactions (your agent engaging its own parts) from external interactions (those parts reaching outside).'
33
+ : 'Deep composition capture is now DISABLED. Future composition reports will include only top-level components (skill names, MCP names, hashes) without sub_components. ACR will not see the internals of your attached parts. Internal-vs-external classification becomes coarser as a result.';
34
+ const changeText = previous === enabled
35
+ ? ' (no change — was already this way)'
36
+ : '';
37
+ return {
38
+ content: [{
39
+ type: 'text',
40
+ text: `${statusText}${changeText}`,
41
+ }],
42
+ };
43
+ });
44
+ }
45
+ //# sourceMappingURL=disable-deep-composition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disable-deep-composition.js","sourceRoot":"","sources":["../../../src/tools/disable-deep-composition.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAiB,EACjB,UAA8B;IAE9B,MAAM,CAAC,YAAY,CACjB,4BAA4B,EAC5B;QACE,WAAW,EACT,8YAA8Y;QAChZ,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;SACvF;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE;QAC5D,KAAK,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE;KAC7B,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACpB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;QACzC,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAEpC,MAAM,UAAU,GAAG,OAAO;YACxB,CAAC,CAAC,mRAAmR;YACrR,CAAC,CAAC,8RAA8R,CAAC;QAEnS,MAAM,UAAU,GAAG,QAAQ,KAAK,OAAO;YACrC,CAAC,CAAC,qCAAqC;YACvC,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,GAAG,UAAU,GAAG,UAAU,EAAE;iBACnC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function getCoverageTool(server: McpServer, apiUrl: string): void;
@@ -0,0 +1,67 @@
1
+ import { z } from 'zod';
2
+ import { ensureRegistered, getAgentId, getAgentName, getApiUrl } from '../state.js';
3
+ async function resolveId(nameOrId) {
4
+ if (nameOrId.startsWith('acr_') || nameOrId.startsWith('pseudo_'))
5
+ return nameOrId;
6
+ const res = await fetch(`${getApiUrl()}/api/v1/agent/${encodeURIComponent(nameOrId)}`);
7
+ if (!res.ok)
8
+ throw new Error(`Agent "${nameOrId}" not found`);
9
+ return (await res.json()).agent_id;
10
+ }
11
+ export function getCoverageTool(server, apiUrl) {
12
+ server.registerTool('get_coverage', {
13
+ description: 'Signal coverage: which fields you populate on your receipts and which you don\'t. Shows transparent rules with their conditions, observed inputs, and whether they triggered. Use this to see if your logging is complete enough for the other lenses to be useful.',
14
+ inputSchema: {
15
+ agent_id: z.string().optional().describe('Your ACR agent ID (auto-assigned if omitted)'),
16
+ agent_name: z.string().optional().describe('Your agent name (alternative to agent_id)'),
17
+ },
18
+ annotations: { readOnlyHint: true, destructiveHint: false },
19
+ _meta: { priorityHint: 0.5 },
20
+ }, async ({ agent_id, agent_name }) => {
21
+ let id;
22
+ try {
23
+ id = agent_name ? await resolveId(agent_name) : (agent_id || getAgentId() || await ensureRegistered());
24
+ }
25
+ catch (err) {
26
+ return { content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : 'Unknown'}` }] };
27
+ }
28
+ try {
29
+ const res = await fetch(`${apiUrl}/api/v1/agent/${id}/coverage`);
30
+ if (!res.ok) {
31
+ const errText = await res.text().catch(() => `HTTP ${res.status}`);
32
+ return { content: [{ type: 'text', text: `Coverage error: ${errText}` }] };
33
+ }
34
+ const data = await res.json();
35
+ const displayName = agent_name || getAgentName() || id;
36
+ const signals = data.signals;
37
+ const rules = data.rules;
38
+ let text = `Coverage Report for ${displayName}\n${'='.repeat(30)}\n`;
39
+ text += `\n-- Signal Counts --\n`;
40
+ for (const [key, value] of Object.entries(signals)) {
41
+ text += ` ${key}: ${value}\n`;
42
+ }
43
+ if (rules && rules.length > 0) {
44
+ const triggered = rules.filter((r) => r.triggered);
45
+ const ok = rules.filter((r) => !r.triggered);
46
+ if (triggered.length > 0) {
47
+ text += `\n-- Coverage Gaps (${triggered.length}) --\n`;
48
+ for (const r of triggered) {
49
+ text += ` ${r.signal}: ${r.rule}\n`;
50
+ text += ` observed: ${JSON.stringify(r.observed)}\n`;
51
+ }
52
+ }
53
+ if (ok.length > 0) {
54
+ text += `\n-- Covered (${ok.length}) --\n`;
55
+ for (const r of ok) {
56
+ text += ` ${r.signal}: ${r.rule} — OK\n`;
57
+ }
58
+ }
59
+ }
60
+ return { content: [{ type: 'text', text }] };
61
+ }
62
+ catch (err) {
63
+ return { content: [{ type: 'text', text: `Coverage error: ${err instanceof Error ? err.message : 'Unknown'}` }] };
64
+ }
65
+ });
66
+ }
67
+ //# sourceMappingURL=get-coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-coverage.js","sourceRoot":"","sources":["../../../src/tools/get-coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function getFailureRegistryTool(server: McpServer, apiUrl: string): void;
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod';
2
+ import { ensureRegistered, getAgentId, getAgentName, getApiUrl } from '../state.js';
3
+ async function resolveId(nameOrId) {
4
+ if (nameOrId.startsWith('acr_') || nameOrId.startsWith('pseudo_'))
5
+ return nameOrId;
6
+ const res = await fetch(`${getApiUrl()}/api/v1/agent/${encodeURIComponent(nameOrId)}`);
7
+ if (!res.ok)
8
+ throw new Error(`Agent "${nameOrId}" not found`);
9
+ return (await res.json()).agent_id;
10
+ }
11
+ export function getFailureRegistryTool(server, apiUrl) {
12
+ server.registerTool('get_failure_registry', {
13
+ description: 'Failure registry: per-target breakdown of failures — status codes, error codes, categories, and median duration when failed. Shows where your interactions are failing and how.',
14
+ inputSchema: {
15
+ agent_id: z.string().optional().describe('Your ACR agent ID (auto-assigned if omitted)'),
16
+ agent_name: z.string().optional().describe('Your agent name (alternative to agent_id)'),
17
+ scope: z.enum(['day', 'week', 'month']).optional().default('week').describe('Time window'),
18
+ },
19
+ annotations: { readOnlyHint: true, destructiveHint: false },
20
+ _meta: { priorityHint: 0.6 },
21
+ }, async ({ agent_id, agent_name, scope }) => {
22
+ let id;
23
+ try {
24
+ id = agent_name ? await resolveId(agent_name) : (agent_id || getAgentId() || await ensureRegistered());
25
+ }
26
+ catch (err) {
27
+ return { content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : 'Unknown'}` }] };
28
+ }
29
+ try {
30
+ const res = await fetch(`${apiUrl}/api/v1/agent/${id}/failure-registry?scope=${scope}`);
31
+ if (!res.ok) {
32
+ const errText = await res.text().catch(() => `HTTP ${res.status}`);
33
+ return { content: [{ type: 'text', text: `Failure registry error: ${errText}` }] };
34
+ }
35
+ const data = await res.json();
36
+ const displayName = data.name || agent_name || getAgentName() || id;
37
+ const failures = data.failures ?? [];
38
+ let text = `Failure Registry for ${displayName} (${scope})\n${'='.repeat(30)}\n`;
39
+ text += `Period: ${data.period_start} to ${data.period_end}\n`;
40
+ text += `Total interactions: ${data.total_interactions}\n`;
41
+ text += `Total failures: ${data.total_failures}\n`;
42
+ text += `Failure rate: ${(data.failure_rate * 100).toFixed(1)}%\n`;
43
+ text += `Distinct failing targets: ${data.distinct_failing_targets}\n`;
44
+ if (failures.length === 0) {
45
+ text += `\nNo failures recorded in this period.\n`;
46
+ }
47
+ else {
48
+ for (const f of failures) {
49
+ text += `\n ${f.target_system_id} (${f.target_system_type})\n`;
50
+ text += ` total failures: ${f.total_count}\n`;
51
+ const statuses = f.statuses;
52
+ if (statuses && Object.keys(statuses).length > 0) {
53
+ text += ` statuses: ${Object.entries(statuses).map(([k, v]) => `${k}=${v}`).join(', ')}\n`;
54
+ }
55
+ const errors = f.error_codes;
56
+ if (errors && Object.keys(errors).length > 0) {
57
+ text += ` error codes: ${Object.entries(errors).map(([k, v]) => `${k}=${v}`).join(', ')}\n`;
58
+ }
59
+ const cats = f.categories;
60
+ if (cats && Object.keys(cats).length > 0) {
61
+ text += ` categories: ${Object.entries(cats).map(([k, v]) => `${k}=${v}`).join(', ')}\n`;
62
+ }
63
+ if (f.median_duration_when_failed_ms != null) {
64
+ text += ` median duration when failed: ${f.median_duration_when_failed_ms}ms\n`;
65
+ }
66
+ }
67
+ }
68
+ return { content: [{ type: 'text', text }] };
69
+ }
70
+ catch (err) {
71
+ return { content: [{ type: 'text', text: `Failure registry error: ${err instanceof Error ? err.message : 'Unknown'}` }] };
72
+ }
73
+ });
74
+ }
75
+ //# sourceMappingURL=get-failure-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-failure-registry.js","sourceRoot":"","sources":["../../../src/tools/get-failure-registry.ts"],"names":[],"mappings":"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"}
@@ -16,11 +16,16 @@ async function resolveAgentId(nameOrId) {
16
16
  return data.agent_id;
17
17
  }
18
18
  export function getFrictionReportTool(server, apiUrl) {
19
- server.tool('get_friction_report', "Get a friction analysis report showing what's costing this agent the most time and money. Shows which external systems are the biggest bottlenecks. Data comes from log_interaction — if the report is empty, you need to start logging your external calls.", {
20
- agent_id: z.string().optional().describe('Your ACR agent ID (auto-assigned if omitted)'),
21
- agent_name: z.string().optional().describe('Your agent name (alternative to agent_id). Use this if you know your name but not your ID.'),
22
- scope: z.enum(['session', 'day', 'week']).optional().default('day').describe('Time window for the report'),
23
- }, { readOnlyHint: true, destructiveHint: false }, async ({ agent_id, agent_name, scope }) => {
19
+ server.registerTool('get_friction_report', {
20
+ description: "Query the friction lens of your interaction profile — one of several lenses available (more on the roadmap). The friction lens surfaces where time and tokens are being lost: bottleneck targets, chain overhead, retry waste, directional friction between targets, and how you compare to the population baseline. Friction is a continuum, not a verdict — high friction could be infrastructure, a hard task, or a component with elevated anomaly signals. Use it together with anomaly signal notifications to interpret correctly. Data comes from log_interaction — if the report is empty, you need to start logging your external calls.",
21
+ inputSchema: {
22
+ agent_id: z.string().optional().describe('Your ACR agent ID (auto-assigned if omitted)'),
23
+ agent_name: z.string().optional().describe('Your agent name (alternative to agent_id). Use this if you know your name but not your ID.'),
24
+ scope: z.enum(['session', 'day', 'week']).optional().default('day').describe('Time window for the report'),
25
+ },
26
+ annotations: { readOnlyHint: true, destructiveHint: false },
27
+ _meta: { priorityHint: 0.7 },
28
+ }, async ({ agent_id, agent_name, scope }) => {
24
29
  let id;
25
30
  try {
26
31
  if (agent_name) {
@@ -93,11 +98,9 @@ export function getFrictionReportTool(server, apiUrl) {
93
98
  .join(', ');
94
99
  text += ` statuses: ${statuses}\n`;
95
100
  }
96
- // Baseline comparison (paid tier)
101
+ // Baseline comparison (paid tier) — raw numbers only.
97
102
  if (t.vs_baseline != null) {
98
- const dir = t.vs_baseline > 1 ? 'slower' : t.vs_baseline < 1 ? 'faster' : 'same as';
99
- const pctDiff = Math.abs(Math.round((t.vs_baseline - 1) * 100));
100
- text += ` vs population: ${pctDiff}% ${dir} baseline`;
103
+ text += ` ratio to population baseline: ${t.vs_baseline.toFixed(2)}`;
101
104
  if (t.baseline_median_ms != null)
102
105
  text += ` (baseline median ${t.baseline_median_ms}ms, p95 ${t.baseline_p95_ms}ms)`;
103
106
  if (t.volatility != null)
@@ -117,12 +120,16 @@ export function getFrictionReportTool(server, apiUrl) {
117
120
  if (t.failure_count > 0 && !t.recent_anomalies?.length) {
118
121
  text += ` ${t.failure_count} failures\n`;
119
122
  }
120
- // Network health context
121
- if (t.network_health_status) {
122
- text += ` network: ${t.network_health_status.toUpperCase()}`;
123
- text += ` — failure ${((t.network_failure_rate ?? 0) * 100).toFixed(1)}%`;
124
- text += `, anomaly ${((t.network_anomaly_rate ?? 0) * 100).toFixed(1)}%`;
125
- text += ` across ${t.network_agent_count ?? 0} agents\n`;
123
+ // Network context — raw rates across the population. No
124
+ // synthetic health_status label (the inherited column is
125
+ // ignored here; see inherited-drift note in
126
+ // proposals/open-items-plan.md).
127
+ if (t.network_failure_rate != null ||
128
+ t.network_anomaly_rate != null ||
129
+ t.network_agent_count != null) {
130
+ text += ` population: ${t.network_agent_count ?? 0} agents`;
131
+ text += `, failure rate ${((t.network_failure_rate ?? 0) * 100).toFixed(1)}%`;
132
+ text += `, anomaly rate ${((t.network_anomaly_rate ?? 0) * 100).toFixed(1)}%\n`;
126
133
  }
127
134
  }
128
135
  }
@@ -140,6 +147,50 @@ export function getFrictionReportTool(server, apiUrl) {
140
147
  text += ` ${s.source}: ${s.interaction_count} interactions\n`;
141
148
  }
142
149
  }
150
+ // Chain Analysis
151
+ if (data.chain_analysis) {
152
+ const ca = data.chain_analysis;
153
+ text += '\n── Chain Analysis ──\n';
154
+ text += ` Distinct chains: ${ca.chain_count}\n`;
155
+ text += ` Avg chain length: ${ca.avg_chain_length} calls\n`;
156
+ text += ` Total chain overhead: ${(ca.total_chain_overhead_ms / 1000).toFixed(1)}s\n`;
157
+ if (ca.top_patterns && ca.top_patterns.length > 0) {
158
+ text += ' Top patterns:\n';
159
+ for (const p of ca.top_patterns) {
160
+ text += ` ${p.pattern.join(' -> ')} (${p.frequency}x, ${p.avg_overhead_ms}ms avg overhead)\n`;
161
+ }
162
+ }
163
+ }
164
+ // Directional Analysis (pro) — raw amplification factor, no
165
+ // SLOWS/SPEEDS/~ label. Client reads the factor.
166
+ if (data.directional_pairs && data.directional_pairs.length > 0) {
167
+ text += '\n── Directional Analysis ──\n';
168
+ for (const dp of data.directional_pairs) {
169
+ text += ` ${dp.source_target} -> ${dp.destination_target}: amplification ${dp.amplification_factor.toFixed(2)}x`;
170
+ text += ` (${dp.avg_duration_when_preceded}ms after vs ${dp.avg_duration_standalone}ms standalone)`;
171
+ text += ` [${dp.sample_count} samples]\n`;
172
+ }
173
+ }
174
+ // Retry Overhead (pro)
175
+ if (data.retry_overhead) {
176
+ const ro = data.retry_overhead;
177
+ text += '\n── Retry Overhead ──\n';
178
+ text += ` Total retries: ${ro.total_retries}\n`;
179
+ text += ` Wasted time: ${(ro.total_wasted_ms / 1000).toFixed(1)}s\n`;
180
+ for (const t of ro.top_retry_targets) {
181
+ text += ` ${t.target_system_id}: ${t.retry_count} retries, ${t.wasted_ms}ms wasted\n`;
182
+ }
183
+ }
184
+ // Population Drift (pro) — raw drift percentage, no
185
+ // DEGRADING/IMPROVING/stable label.
186
+ if (data.population_drift && data.population_drift.targets.length > 0) {
187
+ text += '\n── Population Drift ──\n';
188
+ for (const t of data.population_drift.targets) {
189
+ const sign = t.drift_percentage > 0 ? '+' : '';
190
+ text += ` ${t.target_system_id}: ${sign}${t.drift_percentage}% vs baseline`;
191
+ text += ` (current ${t.current_median_ms}ms, baseline ${t.baseline_median_ms}ms)\n`;
192
+ }
193
+ }
143
194
  // Population comparison (paid tier)
144
195
  if (data.population_comparison) {
145
196
  text += `\n── Population ──\n`;