@tethral/acr-mcp
v2.11.2
Published
MCP server for ACR (Agent Composition Records). An interaction profile registry for AI agents — build a profile, and query it through behavioral lenses (friction, coverage, stable corridors, failure registry, trend, revealed-preference, compensation signa
Maintainers
Readme
@tethral/acr-mcp
MCP server for the ACR (Agent Composition Records) network. Log agent interactions, build an interaction profile, and query it through behavioral lenses.
60-second quickstart
No signup. No API key. No credit card. Two pieces: a host-side observer (captures every tool call automatically) and an MCP (lets the agent query its own profile).
Step 1 — install the observer (Claude Code)
The observer is what actually fills your profile. It runs as a Claude Code PreToolUse/PostToolUse hook, sees every tool call your agent makes, and emits a receipt without the LLM having to remember anything.
npm install -g @tethral/acr-hookThen add to ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [{ "matcher": ".*", "hooks": [["npx", "@tethral/acr-hook", "pre"]] }],
"PostToolUse": [{ "matcher": ".*", "hooks": [["npx", "@tethral/acr-hook", "post"]] }]
}
}The hook reads agent_id and api_url from ~/.claude/.acr-state.json, which the MCP (step 2) writes on first registration. No per-user config needed.
Not on Claude Code? Skip to step 2 — the MCP still works, but the
log_interactiontool will be your only capture path, and LLMs are unreliable about calling it. Host-side observers for Cursor / Continue / other hosts are on the roadmap.
Step 2 — install the MCP (any host)
The MCP is the query layer. It registers your agent, exposes the lenses (get_friction_report, get_coverage, get_stable_corridors, get_failure_registry, get_trend), and lets the agent enrich its own receipts with chain structure, decision tokens, and substitution links the hook can't see.
Claude Code — one command, available in every directory:
claude mcp add acr -s user -- npx -y @tethral/acr-mcp@latest(Drop -s user for project-scope, or use -s local to keep it private to you in this repo.)
Cursor, Continue, Claude Desktop, any other MCP client — add to your config (.mcp.json for project-scope, or the client's user-scope MCP file):
{
"mcpServers": {
"acr": {
"command": "npx",
"args": ["-y", "@tethral/acr-mcp@latest"]
}
}
}Or run directly:
npx -y @tethral/acr-mcp # stdio transport
npx -y @tethral/acr-mcp-http # HTTP transportOn first use your agent auto-registers and gets a human-readable name (e.g. anthropic-amber-fox). The hook starts emitting receipts on the next tool call, and get_friction_report fills in once you've accumulated some signal. Call get_my_agent any time to see your agent ID, API key, and dashboard link.
Want an API key for authenticated writes? You already have one — get_my_agent returns it. But the ingest path accepts unauthenticated writes too, so low-barrier onboarding just works.
First Session
The minimum useful sequence on day one — backed by tests/integration/first-session.test.ts so the steps below stay in sync with the actual tool surface:
- Discover —
get_my_agentreturns your agent id, API key, and dashboard link. No registration call needed. - Capture — the hook captures every tool call automatically. If you haven't installed the hook, call
log_interactionmanually after external calls — but expect lens views to be sparse, because LLMs forget. - Enrich — for multi-step workflows or substitution-graph signals, call
log_interactionwithchain_id,preceded_by,substitution_of,result_used, ordecision_tokens. These signals only come from the agent; the hook can't infer them. - Orient —
orient_mereads your state and routes you to the next useful tool. State-aware: brand new (cohort baselines), some data (fill in gaps), steady (drill into friction). - Read a lens —
get_friction_reportfor where time goes,get_coveragefor which signals you're missing,get_stable_corridorsfor paths you can rely on. - Network awareness —
check_environmentshows pipeline health, aggregation freshness, and any anomaly signals affecting components in your composition.
What It Does
ACR is an interaction profile registry — not a security product, not a skill store.
- Agent registers — composition is recorded (what skills, MCPs, tools it has)
- Agent logs interactions — every external tool call, API request, or MCP interaction
- Signals compile into an interaction profile — timing, chain position, retries, anomaly flags
- Lenses interpret the profile — friction, coverage, stable corridors, failure registry, trend
- Anomaly signal notifications — if ACR observes anomaly signals affecting a component in your composition, you get a notification
Lenses at a glance
Free tier: summary, top 3 targets, trend, coverage, stable corridors. Paid tier adds: baselines, retry overhead, directional analysis, population drift.
| Lens | Ask it when… | Key output | Act on it by… |
|---|---|---|---|
| get_friction_report | Where is my time going? | Top targets by wait share, retry waste, chain overhead | Caching slow targets, reducing retries on high-failure ones, replacing consistently failed vendors |
| get_failure_registry | What's breaking and how? | Status codes, error categories per target | Checking error codes to distinguish transient failures from config errors |
| get_stable_corridors | What can I rely on? | Zero-failure, low-variance targets | Routing critical-path work through the zero-failure targets |
| get_trend | Getting better or worse? | Failure rate and latency delta vs last period | Investigating rising failure rates before they compound; checking notifications if a target degraded |
| get_coverage | Am I logging enough? | Which receipt fields are missing and what they unlock | Adding the missing fields to your log_interaction calls to unlock the gaps |
| summarize_my_agent | Quick status check? | Profile + friction + coverage in one call | Getting a one-call status check at the start or end of a session |
Example output
Friction Report for anthropic-amber-fox (week)
Agent ID: agt_01abc123def456
Period: 2026-04-10T00:00:00Z to 2026-04-17T00:00:00Z
Tier: free
── Summary ──
Interactions: 312
Total wait: 84.3s
Friction: 11.8% of active time
Failures: 9 (2.9% rate)
Shadow tax: 22.9% of wait (failed 18.5s · retries 19.8s · chain queue 4.0s)
── By Category ──
tool_call: 287 calls, 77.4s total, avg 270ms | median 240ms | p95 1820ms
delegation: 25 calls, 6.9s total, avg 276ms | median 210ms | p95 980ms
── Top Targets ──
api:openai.com (api)
198 calls | 68.2% of wait time (57.5s)
median 290ms | p95 1850ms
faster than 41% of agents on this target
faster than 78% of anthropic peers (cohort: 14)
mcp:filesystem (mcp_server)
89 calls | 18.4% of wait time (15.5s)
median 174ms | p95 620ms
── Chain Analysis ──
Distinct chains: 14
Avg chain length: 3.2 calls
Total chain overhead: 4.1s
── Directional Analysis ──
None recorded this week.
── Retry Overhead ──
None recorded this week.
── Population Drift ──
None recorded this week.Tools (30)
Your agent
| Tool | Purpose |
|------|---------|
| orient_me | State-aware entry point. Classifies your agent (new / some-data / steady) and routes to the next useful tool. |
| get_my_agent | Your agent ID, API key, dashboard link, health snapshot, and menu of available lenses. |
| register_agent | Explicit registration with composition. Auto-registration is the default on first call. |
| update_composition | Update your composition without re-registering. Preserves agent identity. |
| configure_deep_composition | Privacy control: enable/disable sub-component capture for this session. |
Interaction logging
| Tool | Purpose |
|------|---------|
| log_interaction | Record an interaction. Call after every external tool call, API request, or MCP interaction. Every lens depends on this. |
| get_interaction_log | Paginated interaction history with network context. |
Behavioral lenses
| Tool | Purpose |
|------|---------|
| get_friction_report | Where time and tokens are lost: top targets, chain overhead, retry waste. Paid: population baselines (vs_baseline, baseline_median_ms, volatility), retry overhead, directional analysis (directional_pairs), population drift, population comparison. |
| get_profile | Full interaction profile: identity, counts, composition summary, composition delta. |
| summarize_my_agent | One-read overview across profile, friction, and coverage lenses. |
| get_coverage | Signal completeness: which fields you populate on receipts, which you don't. |
| get_stable_corridors | Reliably fast interaction paths: zero failures, low variance, high sample count. |
| get_failure_registry | Per-target failure breakdown: status codes, error codes, categories. |
| get_trend | Latency and failure rate changes: current vs previous period, raw deltas. |
| get_revealed_preference | Declared-but-uncalled bindings vs called-but-undeclared targets: where real behavior diverges from composition metadata. |
| get_compensation_signatures | Repeated multi-hop patterns an agent falls back on: chain-shape stability, frequency, and fleet-wide comparison when available. |
| whats_new | Time-scoped digest: yesterday's friction, today's activity, week trend, unread signals — in one call. |
| get_composition_diff | Compare your declared composition against what your interactions actually exercise. |
Anomaly signal notifications
| Tool | Purpose |
|------|---------|
| check_environment | Pipeline health, aggregation freshness, and active anomaly signals. Call on startup. |
| get_notifications | Unread anomaly signal notifications about components in your composition. |
| acknowledge_signal | Acknowledge an anomaly signal notification after reviewing with your operator. Expires in 30 days. |
| dismiss_pattern | Suppress a noticed pattern from future renderings. |
Watches
| Tool | Purpose |
|------|---------|
| set_watch | Create or update a watch on a friction/trend metric; fires a notification on threshold crossing. |
| list_watches | List your active watches and their current evaluation state. |
Network observation
| Tool | Purpose |
|------|---------|
| get_network_status | Network-wide dashboard: agent/system totals, signal rates, skill anomalies, escalations. |
| get_skill_tracker | Adoption and anomaly signals for skills observed by the network. |
Lookups
| Tool | Purpose |
|------|---------|
| check_entity | Ask the network what it knows about a specific skill, agent, or system. |
| search_skills | Query the network's knowledge of a skill by name. |
| get_skill_versions | Version history for a skill hash. |
Tier
| Tool | Purpose |
|------|---------|
| get_tier_features | Free vs paid feature comparison. Lens output also includes contextual upsells when your data suggests a paid feature would help (suppress with ACR_NO_UPSELL=1). |
Dashboard
View your agent's profile and friction analysis at dashboard.acr.nfkey.ai. Requires your agent ID and API key (shown by get_my_agent).
The public leaderboard shows anonymous aggregate data — most used MCP servers, reliability rankings, skill adoption — no auth required.
Configuration
All boolean env vars accept 1/true/yes/on (truthy) or 0/false/no/off (falsy), case-insensitive. Anything else falls back to the default.
Endpoints
| Env Var | Default | Description |
|---------|---------|-------------|
| ACR_API_URL | https://acr.nfkey.ai | ACR API endpoint |
| ACR_RESOLVER_URL | Same as ACR_API_URL | Skill resolver endpoint |
| ACR_DASHBOARD_URL | https://dashboard.acr.nfkey.ai | Dashboard URL shown in get_my_agent |
Behavior toggles
| Env Var | Default | Description |
|---------|---------|-------------|
| ACR_DEEP_COMPOSITION | true | Capture sub-components of skills/MCPs. Disable to send only top-level composition. |
| ACR_DISABLE_FETCH_OBSERVE | false | Disable the transport-boundary fetch observer (no passive receipt emission). |
| ACR_DISABLE_ENV_PROBE | false | Disable environmental latency probes at startup. |
| ACR_DISABLE_VERSION_CHECK | false | Skip the background npm version check. |
| ACR_NO_UPSELL | false | Suppress contextual paid-tier upsell lines in lens output. |
| ACR_ENV_PROBE_TARGETS | built-in list | Comma-separated override for the probe's target hosts. |
HTTP transport (only used by acr-mcp-http)
| Env Var | Default | Description |
|---------|---------|-------------|
| ACR_MCP_HTTP_PORT | 3001 | HTTP listen port. |
| ACR_MCP_AUTH_TOKEN | unset | If set, clients must present Authorization: Bearer <token>. |
| ACR_MCP_STATELESS | false | Run without per-session state (each request is independent). |
Environment detection overrides
These override the auto-detected environment tags stored with the agent registration. Set them when the defaults misclassify your deployment.
| Env Var | Default | Description |
|---------|---------|-------------|
| ACR_DEVICE_CLASS | auto | One of sbc / mobile / desktop / server / unknown. |
| ACR_PLATFORM | process.platform | Override the detected OS platform. |
| ACR_ARCH | process.arch | Override the detected CPU architecture. |
| ACR_IS_SERVER | unset | Set to 1 to force the server device class without memory/platform checks. |
Registering your composition
update_composition accepts three fields. Here's where to get the values:
skill_hashes: SHA-256 of the SKILL.md file content. Shell:sha256sum path/to/SKILL.md | cut -d' ' -f1. Node:crypto.createHash('sha256').update(fs.readFileSync('SKILL.md')).digest('hex').mcp_components: Use the MCP server name as you have it in your settings (e.g."github","filesystem"). These are the keys undermcpServersin your config.api_components: The target system IDs you log to (e.g."api:openai.com"). These should match what you pass astarget_system_idinlog_interaction.
These values are used by ACR to match your composition against the network's anomaly signal observations. If a skill or MCP you use has elevated signals, you'll receive a targeted notification.
Troubleshooting
Friction report is empty
Call get_coverage to check which signals you're populating. If total_interactions is 0, you haven't called log_interaction yet — every lens depends on logged receipts. Try a broader scope: get_friction_report with scope: "week" or scope: "yesterday".
Dashboard shows no data
The dashboard updates as receipts arrive. If you've logged interactions but see nothing, confirm your agent ID matches: call get_my_agent and check the dashboard link it returns. Data is scoped per agent — other agents' data isn't visible on your profile.
Targeted notifications aren't arriving
Call orient_me — it surfaces composition state. If your composition is empty (0 skills, 0 MCPs, 0 tools), anomaly notifications are network-wide only. Call update_composition with your current stack to enable targeted alerts.
Data Collection
ACR collects interaction metadata only: target system names, timing, status, and provider class. No request/response content, API keys, prompts, or PII is collected. We intentionally don't track the agent's owner. Full terms.
License
MIT
