@tethral/acr-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tethral, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @tethral/acr-mcp
2
+
3
+ MCP server for the [ACR](https://acr.nfkey.ai) (Agent Composition Records) network. Check skills before installing, log interactions, and get friction reports showing what's costing your agent the most.
4
+
5
+ ## Quick Start
6
+
7
+ ```json
8
+ {
9
+ "mcpServers": {
10
+ "acr": {
11
+ "command": "npx",
12
+ "args": ["@tethral/acr-mcp"]
13
+ }
14
+ }
15
+ }
16
+ ```
17
+
18
+ That's it. The server auto-registers your agent on first use.
19
+
20
+ ## Tools
21
+
22
+ | Tool | Description | Required Params |
23
+ |------|-------------|----------------|
24
+ | `log_interaction` | Log an external interaction | `target_system_id`, `category`, `status` |
25
+ | `check_entity` | Check if a skill/agent/system is known | `entity_type`, `entity_id` |
26
+ | `get_friction_report` | See what's costing you the most | (none — uses auto-assigned ID) |
27
+ | `check_environment` | Get network threat overview | (none) |
28
+ | `register_agent` | Custom registration (optional) | `public_key`, `provider_class` |
29
+
30
+ ## Configuration
31
+
32
+ | Env Var | Default | Description |
33
+ |---------|---------|-------------|
34
+ | `ACR_API_URL` | `https://acr.nfkey.ai` | Ingestion API URL |
35
+ | `ACR_RESOLVER_URL` | Same as API URL | Resolver API URL |
36
+
37
+ ## Data Collection
38
+
39
+ ACR collects interaction metadata only: target system names, timing, status, and provider class. No request/response content, API keys, prompts, or PII is collected. [Full terms](https://acr.nfkey.ai/terms).
40
+
41
+ ## License
42
+
43
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { registerAgentTool } from './tools/register-agent.js';
5
+ import { logInteractionTool } from './tools/log-interaction.js';
6
+ import { checkEntityTool } from './tools/check-entity.js';
7
+ import { checkEnvironmentTool } from './tools/check-environment.js';
8
+ import { getFrictionReportTool } from './tools/get-friction-report.js';
9
+ const ACR_API_URL = process.env.ACR_API_URL ?? 'https://acr.nfkey.ai';
10
+ const ACR_RESOLVER_URL = process.env.ACR_RESOLVER_URL ?? ACR_API_URL;
11
+ const server = new McpServer({
12
+ name: 'acr-agent-registry',
13
+ version: '0.1.0',
14
+ });
15
+ registerAgentTool(server, ACR_API_URL);
16
+ logInteractionTool(server, ACR_API_URL);
17
+ checkEntityTool(server, ACR_API_URL, ACR_RESOLVER_URL);
18
+ checkEnvironmentTool(server, ACR_API_URL, ACR_RESOLVER_URL);
19
+ getFrictionReportTool(server, ACR_API_URL);
20
+ async function main() {
21
+ const transport = new StdioServerTransport();
22
+ await server.connect(transport);
23
+ }
24
+ main().catch((err) => {
25
+ console.error('ACR MCP server failed to start:', err);
26
+ process.exit(1);
27
+ });
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,sBAAsB,CAAC;AACtE,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW,CAAC;AAErE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACvC,kBAAkB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACxC,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;AACvD,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAC5D,qBAAqB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function getAgentId(): string | null;
2
+ export declare function setAgentId(id: string): void;
3
+ /**
4
+ * Ensure the agent is registered. Called before any tool that needs an agent_id.
5
+ * If not registered, auto-registers with a pseudo_ ID.
6
+ * Returns the agent_id.
7
+ */
8
+ export declare function ensureRegistered(): Promise<string>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * MCP server session state.
3
+ * Handles auto-registration so agents don't need to manually call register_agent.
4
+ */
5
+ import { randomBytes } from 'node:crypto';
6
+ let agentId = null;
7
+ let registering = false;
8
+ const ACR_API_URL = process.env.ACR_API_URL ?? 'https://acr.nfkey.ai';
9
+ export function getAgentId() {
10
+ return agentId;
11
+ }
12
+ export function setAgentId(id) {
13
+ agentId = id;
14
+ }
15
+ /**
16
+ * Ensure the agent is registered. Called before any tool that needs an agent_id.
17
+ * If not registered, auto-registers with a pseudo_ ID.
18
+ * Returns the agent_id.
19
+ */
20
+ export async function ensureRegistered() {
21
+ if (agentId)
22
+ return agentId;
23
+ if (registering) {
24
+ // Another call is already registering — wait briefly
25
+ await new Promise((r) => setTimeout(r, 1000));
26
+ if (agentId)
27
+ return agentId;
28
+ }
29
+ registering = true;
30
+ try {
31
+ const pseudoKey = `pseudo_${randomBytes(16).toString('hex')}`;
32
+ const res = await fetch(`${ACR_API_URL}/api/v1/register`, {
33
+ method: 'POST',
34
+ headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify({
36
+ public_key: pseudoKey,
37
+ provider_class: 'unknown',
38
+ }),
39
+ });
40
+ if (res.ok) {
41
+ const data = await res.json();
42
+ agentId = data.agent_id;
43
+ return agentId;
44
+ }
45
+ // Registration failed — use pseudo ID locally
46
+ agentId = `pseudo_${randomBytes(6).toString('hex')}`;
47
+ return agentId;
48
+ }
49
+ finally {
50
+ registering = false;
51
+ }
52
+ }
53
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,IAAI,OAAO,GAAkB,IAAI,CAAC;AAClC,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,sBAAsB,CAAC;AAEtE,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,GAAG,EAAE,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,WAAW,EAAE,CAAC;QAChB,qDAAqD;QACrD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9C,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC9B,CAAC;IAED,WAAW,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,UAAU,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAE9D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,kBAAkB,EAAE;YACxD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EAAE,SAAS;gBACrB,cAAc,EAAE,SAAS;aAC1B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA0B,CAAC;YACtD,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YACxB,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,8CAA8C;QAC9C,OAAO,GAAG,UAAU,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO,OAAO,CAAC;IACjB,CAAC;YAAS,CAAC;QACT,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function checkEntityTool(server: McpServer, apiUrl: string, resolverUrl: string): void;
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
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
+ }, async ({ entity_type, entity_id }) => {
7
+ try {
8
+ let url;
9
+ switch (entity_type) {
10
+ case 'skill':
11
+ url = `${resolverUrl}/v1/skill/${entity_id}`;
12
+ break;
13
+ case 'agent':
14
+ url = `${resolverUrl}/v1/agent/${entity_id}`;
15
+ break;
16
+ case 'system':
17
+ url = `${resolverUrl}/v1/system/${encodeURIComponent(entity_id)}/health`;
18
+ break;
19
+ }
20
+ const res = await fetch(url);
21
+ const data = await res.json();
22
+ if (entity_type === 'skill') {
23
+ if (!data.found) {
24
+ return {
25
+ content: [{
26
+ type: 'text',
27
+ text: `Unknown skill. This hash has not been seen in the ACR network. Exercise caution with unfamiliar skills.`,
28
+ }],
29
+ };
30
+ }
31
+ const level = (data.threat_level ?? 'none').toUpperCase();
32
+ let text = `Skill found.\n\nThreat Level: ${level}`;
33
+ if (data.skill_name)
34
+ text += `\nName: ${data.skill_name}`;
35
+ if (data.agent_count != null)
36
+ text += `\nAgents using: ${data.agent_count}`;
37
+ if (data.interaction_count != null)
38
+ text += `\nInteractions: ${data.interaction_count}`;
39
+ if (data.anomaly_rate != null)
40
+ text += `\nAnomaly rate: ${(data.anomaly_rate * 100).toFixed(1)}%`;
41
+ if (data.threat_level === 'high' || data.threat_level === 'critical') {
42
+ text += `\n\nWARNING: This skill has been flagged. Do not install without explicit user confirmation.`;
43
+ }
44
+ else if (data.threat_level === 'medium') {
45
+ text += `\n\nCaution: Elevated anomaly signals. Proceed only if the user confirms.`;
46
+ }
47
+ return { content: [{ type: 'text', text }] };
48
+ }
49
+ if (entity_type === 'agent') {
50
+ if (!data.found) {
51
+ return { content: [{ type: 'text', text: `Agent ${entity_id} not found in the network.` }] };
52
+ }
53
+ return {
54
+ content: [{
55
+ type: 'text',
56
+ text: `Agent found.\n\nStatus: ${data.status}\nProvider: ${data.provider_class}\nRegistered: ${data.registered}\nLast active: ${data.last_active}`,
57
+ }],
58
+ };
59
+ }
60
+ // system
61
+ if (!data.found) {
62
+ return { content: [{ type: 'text', text: `System ${entity_id} not found.` }] };
63
+ }
64
+ return {
65
+ content: [{
66
+ type: 'text',
67
+ 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)}%`,
68
+ }],
69
+ };
70
+ }
71
+ catch (err) {
72
+ const msg = err instanceof Error ? err.message : 'Unknown error';
73
+ return { content: [{ type: 'text', text: `Lookup error: ${msg}` }] };
74
+ }
75
+ });
76
+ }
77
+ //# sourceMappingURL=check-entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-entity.js","sourceRoot":"","sources":["../../../src/tools/check-entity.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 checkEnvironmentTool(server: McpServer, apiUrl: string, resolverUrl: string): void;
@@ -0,0 +1,28 @@
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.', {}, async () => {
3
+ try {
4
+ const [threatsRes, healthRes] = await Promise.all([
5
+ fetch(`${resolverUrl}/v1/threats/active`),
6
+ fetch(`${apiUrl}/api/v1/health`),
7
+ ]);
8
+ const threats = await threatsRes.json();
9
+ const health = await healthRes.json();
10
+ let text = `ACR Network Status: ${health.status ?? 'unknown'}\n`;
11
+ if (Array.isArray(threats) && threats.length > 0) {
12
+ text += `\nActive Threats: ${threats.length}\n`;
13
+ 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`;
15
+ }
16
+ }
17
+ else {
18
+ text += '\nNo active threats detected.';
19
+ }
20
+ return { content: [{ type: 'text', text }] };
21
+ }
22
+ catch (err) {
23
+ const msg = err instanceof Error ? err.message : 'Unknown error';
24
+ return { content: [{ type: 'text', text: `Environment check error: ${msg}` }] };
25
+ }
26
+ });
27
+ }
28
+ //# sourceMappingURL=check-environment.js.map
@@ -0,0 +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,sHAAsH,EACtH,EAAE,EACF,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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function getFrictionReportTool(server: McpServer, apiUrl: string): void;
@@ -0,0 +1,49 @@
1
+ import { z } from 'zod';
2
+ import { ensureRegistered, getAgentId } from '../state.js';
3
+ export function getFrictionReportTool(server, apiUrl) {
4
+ 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. This is a read-only query of your own data.", {
5
+ agent_id: z.string().optional().describe('Your ACR agent ID (auto-assigned if omitted)'),
6
+ scope: z.enum(['session', 'day', 'week']).optional().default('day').describe('Time window for the report'),
7
+ }, async ({ agent_id, scope }) => {
8
+ const id = agent_id || getAgentId() || await ensureRegistered();
9
+ try {
10
+ const res = await fetch(`${apiUrl}/api/v1/agent/${id}/friction?scope=${scope}`);
11
+ const data = await res.json();
12
+ if (data.error) {
13
+ return { content: [{ type: 'text', text: `Error: ${data.error.message}` }] };
14
+ }
15
+ const s = data.summary;
16
+ if (s.total_interactions === 0) {
17
+ return {
18
+ content: [{
19
+ type: 'text',
20
+ text: `No interactions recorded for scope "${scope}". Start logging interactions to see friction data.`,
21
+ }],
22
+ };
23
+ }
24
+ let text = `Friction Report (${scope})\n`;
25
+ text += `Period: ${data.period_start} to ${data.period_end}\n\n`;
26
+ text += `Total interactions: ${s.total_interactions}\n`;
27
+ text += `Total wait time: ${(s.total_wait_time_ms / 1000).toFixed(1)}s\n`;
28
+ text += `Friction: ${s.friction_percentage.toFixed(2)}% of active time spent waiting\n`;
29
+ text += `Failures: ${s.total_failures} (${(s.failure_rate * 100).toFixed(1)}% failure rate)\n`;
30
+ if (data.top_targets && data.top_targets.length > 0) {
31
+ text += `\nTop Bottlenecks:\n`;
32
+ for (const t of data.top_targets) {
33
+ const pct = (t.proportion_of_total * 100).toFixed(1);
34
+ text += `\n ${t.target_system_id}\n`;
35
+ text += ` ${pct}% of wait time | ${t.interaction_count} calls | median ${t.median_duration_ms}ms\n`;
36
+ if (t.failure_count > 0) {
37
+ text += ` ${t.failure_count} failures\n`;
38
+ }
39
+ }
40
+ }
41
+ return { content: [{ type: 'text', text }] };
42
+ }
43
+ catch (err) {
44
+ const msg = err instanceof Error ? err.message : 'Unknown error';
45
+ return { content: [{ type: 'text', text: `Friction report error: ${msg}` }] };
46
+ }
47
+ });
48
+ }
49
+ //# sourceMappingURL=get-friction-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-friction-report.js","sourceRoot":"","sources":["../../../src/tools/get-friction-report.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 logInteractionTool(server: McpServer, apiUrl: string): void;
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ import { ensureRegistered, getAgentId } from '../state.js';
3
+ function inferSystemType(systemId) {
4
+ const prefix = systemId.split(':')[0];
5
+ const map = {
6
+ mcp: 'mcp_server', api: 'api', agent: 'agent',
7
+ skill: 'skill', platform: 'platform',
8
+ };
9
+ return map[prefix ?? ''] ?? 'unknown';
10
+ }
11
+ const DATA_NOTICE = ' ACR collects interaction metadata (target names, timing, status) for threat detection and friction analysis. No request/response content is collected. Terms: https://acr.nfkey.ai/terms';
12
+ export function logInteractionTool(server, apiUrl) {
13
+ server.tool('log_interaction', 'Log an interaction receipt to the ACR network. Call after interacting with any external tool, API, or service.' + DATA_NOTICE, {
14
+ target_system_id: z.string().describe('Target in type:name format (e.g., mcp:github, api:stripe.com)'),
15
+ category: z.enum([
16
+ 'tool_call', 'delegation', 'data_exchange', 'skill_install',
17
+ 'commerce', 'research', 'code', 'communication',
18
+ ]).describe('Interaction category'),
19
+ status: z.enum(['success', 'failure', 'timeout', 'partial']).describe('Outcome'),
20
+ duration_ms: z.number().nonnegative().optional().default(0).describe('Duration in ms (0 if unknown)'),
21
+ agent_id: z.string().optional().describe('Your ACR agent ID (auto-assigned if omitted)'),
22
+ anomaly_flagged: z.boolean().optional().default(false).describe('Set true if something seemed wrong'),
23
+ anomaly_detail: z.string().max(500).optional().describe('What seemed wrong. DO NOT include credentials or API keys.'),
24
+ }, async (params) => {
25
+ try {
26
+ const id = params.agent_id || getAgentId() || await ensureRegistered();
27
+ const res = await fetch(`${apiUrl}/api/v1/receipts`, {
28
+ method: 'POST',
29
+ headers: { 'Content-Type': 'application/json' },
30
+ body: JSON.stringify({
31
+ emitter: {
32
+ agent_id: id,
33
+ provider_class: 'unknown',
34
+ },
35
+ target: {
36
+ system_id: params.target_system_id,
37
+ system_type: inferSystemType(params.target_system_id),
38
+ },
39
+ interaction: {
40
+ category: params.category,
41
+ status: params.status,
42
+ duration_ms: params.duration_ms,
43
+ request_timestamp_ms: Date.now() - (params.duration_ms ?? 0),
44
+ },
45
+ anomaly: {
46
+ flagged: params.anomaly_flagged,
47
+ detail: params.anomaly_detail,
48
+ },
49
+ }),
50
+ });
51
+ const data = await res.json();
52
+ if (!res.ok) {
53
+ return { content: [{ type: 'text', text: `Failed to log: ${JSON.stringify(data)}` }] };
54
+ }
55
+ return {
56
+ content: [{
57
+ type: 'text',
58
+ text: `Logged ${data.accepted} receipt(s). IDs: ${data.receipt_ids.join(', ')}`,
59
+ }],
60
+ };
61
+ }
62
+ catch (err) {
63
+ const msg = err instanceof Error ? err.message : 'Unknown error';
64
+ return { content: [{ type: 'text', text: `Logging error: ${msg}` }] };
65
+ }
66
+ });
67
+ }
68
+ //# sourceMappingURL=log-interaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-interaction.js","sourceRoot":"","sources":["../../../src/tools/log-interaction.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 registerAgentTool(server: McpServer, apiUrl: string): void;
@@ -0,0 +1,51 @@
1
+ import { z } from 'zod';
2
+ import { setAgentId } from '../state.js';
3
+ const DATA_NOTICE = ' ACR collects interaction metadata (target names, timing, status) for threat detection and friction analysis. No request/response content is collected. Terms: https://acr.nfkey.ai/terms';
4
+ export function registerAgentTool(server, apiUrl) {
5
+ server.tool('register_agent', 'Register an agent with the ACR network. Optional — agents are auto-registered on first tool call.' + DATA_NOTICE, {
6
+ public_key: z.string().min(32).describe('Agent public key or unique identifier (min 32 chars)'),
7
+ provider_class: z.enum([
8
+ 'anthropic', 'openai', 'google', 'openclaw', 'langchain',
9
+ 'crewai', 'autogen', 'custom', 'unknown',
10
+ ]).describe('Agent provider/framework'),
11
+ skills: z.array(z.string()).optional().describe('List of installed skill names'),
12
+ skill_hashes: z.array(z.string()).optional().describe('SHA-256 hashes of installed SKILL.md files'),
13
+ operational_domain: z.string().max(200).optional().describe('What domain this agent operates in'),
14
+ }, async ({ public_key, provider_class, skills, skill_hashes, operational_domain }) => {
15
+ try {
16
+ const res = await fetch(`${apiUrl}/api/v1/register`, {
17
+ method: 'POST',
18
+ headers: { 'Content-Type': 'application/json' },
19
+ body: JSON.stringify({
20
+ public_key,
21
+ provider_class,
22
+ composition: (skills || skill_hashes) ? { skills, skill_hashes } : undefined,
23
+ operational_domain,
24
+ }),
25
+ });
26
+ const data = await res.json();
27
+ if (!res.ok) {
28
+ return { content: [{ type: 'text', text: `Registration failed: ${JSON.stringify(data)}` }] };
29
+ }
30
+ // Store agent_id for auto-use in other tools
31
+ setAgentId(data.agent_id);
32
+ const briefing = data.environment_briefing;
33
+ let text = `Registered successfully.\n\nAgent ID: ${data.agent_id}\nComposition Hash: ${data.composition_hash}\n`;
34
+ if (briefing.connected_systems.length > 0) {
35
+ text += `\nConnected Systems: ${briefing.connected_systems.length}`;
36
+ }
37
+ if (briefing.active_threats.length > 0) {
38
+ text += `\n\nActive Threats: ${briefing.active_threats.length}`;
39
+ for (const t of briefing.active_threats) {
40
+ text += `\n- [${t.threat_level.toUpperCase()}] ${t.description}`;
41
+ }
42
+ }
43
+ return { content: [{ type: 'text', text }] };
44
+ }
45
+ catch (err) {
46
+ const msg = err instanceof Error ? err.message : 'Unknown error';
47
+ return { content: [{ type: 'text', text: `Registration error: ${msg}` }] };
48
+ }
49
+ });
50
+ }
51
+ //# sourceMappingURL=register-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-agent.js","sourceRoot":"","sources":["../../../src/tools/register-agent.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@tethral/acr-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for the ACR (Agent Composition Records) network. Check skills, log interactions, get friction reports.",
5
+ "type": "module",
6
+ "main": "dist/src/index.js",
7
+ "types": "dist/src/index.d.ts",
8
+ "bin": {
9
+ "acr-mcp": "dist/src/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsx watch src/index.ts",
14
+ "typecheck": "tsc --noEmit",
15
+ "prepublishOnly": "pnpm build"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.29.0",
19
+ "zod": "^3.23.0"
20
+ },
21
+ "devDependencies": {
22
+ "tsx": "^4.11.0"
23
+ },
24
+ "keywords": ["mcp", "agent", "acr", "composition", "registry", "tethral", "skill", "threat", "friction"],
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/theAnthropol/AgentRegistry",
29
+ "directory": "packages/mcp-server"
30
+ },
31
+ "homepage": "https://acr.nfkey.ai",
32
+ "engines": { "node": ">=20.0.0" },
33
+ "files": ["dist", "README.md", "LICENSE"],
34
+ "publishConfig": {
35
+ "access": "public",
36
+ "provenance": true
37
+ }
38
+ }