@adhd/agent-mcp 2.0.1 → 2.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/AGENTS.md +236 -0
- package/CHANGELOG.md +115 -0
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/docs/architecture-and-security.md +405 -0
- package/docs/marketing/.catalog/capabilities.md +143 -0
- package/docs/marketing/.catalog/consumer.md +111 -0
- package/docs/marketing/.catalog/distribution.md +223 -0
- package/docs/marketing/.catalog/doc-conformance.md +237 -0
- package/docs/marketing/.catalog/doc-ops.md +98 -0
- package/docs/marketing/.catalog/metrics.md +119 -0
- package/docs/marketing/.catalog/required-tooling.md +224 -0
- package/docs/marketing/.catalog/review.md +164 -0
- package/docs/provider-call-audit.md +254 -0
- package/llms.txt +133 -0
- package/package.json +30 -51
- package/src/__tests__/integration/harness.d.ts +871 -39
- package/src/__tests__/integration/harness.d.ts.map +1 -1
- package/src/__tests__/integration/harness.js +93 -87
- package/src/__tests__/integration/harness.js.map +1 -1
- package/src/__tests__/integration/scripted-provider.d.ts +1 -2
- package/src/__tests__/integration/scripted-provider.d.ts.map +1 -1
- package/src/__tests__/integration/scripted-provider.js +1 -3
- package/src/__tests__/integration/scripted-provider.js.map +1 -1
- package/src/config.d.ts +6 -69
- package/src/config.d.ts.map +1 -1
- package/src/config.js +1 -50
- package/src/config.js.map +1 -1
- package/src/db/client.d.ts +1516 -2
- package/src/db/client.d.ts.map +1 -1
- package/src/db/client.js +4 -2
- package/src/db/client.js.map +1 -1
- package/src/db/migrate-runner.d.ts +0 -28
- package/src/db/migrate-runner.d.ts.map +1 -1
- package/src/db/migrate-runner.js +0 -24
- package/src/db/migrate-runner.js.map +1 -1
- package/src/db/migrate.d.ts +0 -7
- package/src/db/migrate.d.ts.map +1 -1
- package/src/db/migrate.js +0 -7
- package/src/db/migrate.js.map +1 -1
- package/src/db/schema.d.ts +0 -1260
- package/src/db/schema.d.ts.map +1 -1
- package/src/db/schema.js +2 -179
- package/src/db/schema.js.map +1 -1
- package/src/index.d.ts +3 -42
- package/src/index.d.ts.map +1 -1
- package/src/index.js +32 -123
- package/src/index.js.map +1 -1
- package/src/logger.d.ts +0 -8
- package/src/logger.d.ts.map +1 -1
- package/src/logger.js +1 -12
- package/src/logger.js.map +1 -1
- package/src/scripts/agent-mcp-tail.d.ts +3 -0
- package/src/scripts/agent-mcp-tail.d.ts.map +1 -0
- package/src/scripts/agent-mcp-tail.js +227 -0
- package/src/scripts/agent-mcp-tail.js.map +1 -0
- package/src/server.d.ts +13 -34
- package/src/server.d.ts.map +1 -1
- package/src/server.js +234 -326
- package/src/server.js.map +1 -1
- package/src/store/agent-store.d.ts +3 -16
- package/src/store/agent-store.d.ts.map +1 -1
- package/src/store/agent-store.js +38 -41
- package/src/store/agent-store.js.map +1 -1
- package/src/streaming/chat-gateway.d.ts +17 -0
- package/src/streaming/chat-gateway.d.ts.map +1 -0
- package/src/streaming/chat-gateway.js +336 -0
- package/src/streaming/chat-gateway.js.map +1 -0
- package/src/streaming/event-bus.d.ts +4 -0
- package/src/streaming/event-bus.d.ts.map +1 -1
- package/src/streaming/event-bus.js +14 -1
- package/src/streaming/event-bus.js.map +1 -1
- package/src/streaming/sse-server.d.ts +3 -14
- package/src/streaming/sse-server.d.ts.map +1 -1
- package/src/streaming/sse-server.js +37 -37
- package/src/streaming/sse-server.js.map +1 -1
- package/src/utils/load-env.d.ts +0 -14
- package/src/utils/load-env.d.ts.map +1 -1
- package/src/utils/load-env.js +0 -18
- package/src/utils/load-env.js.map +1 -1
- package/drizzle/0000_nifty_sasquatch.sql +0 -55
- package/drizzle/0001_task_usage.sql +0 -16
- package/drizzle/0002_lumpy_silver_centurion.sql +0 -2
- package/drizzle/0003_nifty_shriek.sql +0 -2
- package/drizzle/0004_brief_shocker.sql +0 -4
- package/drizzle/0005_clear_lenny_balinger.sql +0 -25
- package/drizzle/0006_composed_prompts_cache.sql +0 -24
- package/drizzle/meta/0000_snapshot.json +0 -387
- package/drizzle/meta/0001_snapshot.json +0 -495
- package/drizzle/meta/0002_snapshot.json +0 -509
- package/drizzle/meta/0003_snapshot.json +0 -523
- package/drizzle/meta/0004_snapshot.json +0 -551
- package/drizzle/meta/0005_snapshot.json +0 -545
- package/drizzle/meta/0006_snapshot.json +0 -651
- package/drizzle/meta/_journal.json +0 -55
- package/src/clients/http-client.d.ts +0 -24
- package/src/clients/http-client.d.ts.map +0 -1
- package/src/clients/http-client.js +0 -98
- package/src/clients/http-client.js.map +0 -1
- package/src/clients/in-process.d.ts +0 -27
- package/src/clients/in-process.d.ts.map +0 -1
- package/src/clients/in-process.js +0 -37
- package/src/clients/in-process.js.map +0 -1
- package/src/clients/index.d.ts +0 -7
- package/src/clients/index.d.ts.map +0 -1
- package/src/clients/index.js +0 -5
- package/src/clients/index.js.map +0 -1
- package/src/clients/registry.d.ts +0 -54
- package/src/clients/registry.d.ts.map +0 -1
- package/src/clients/registry.js +0 -164
- package/src/clients/registry.js.map +0 -1
- package/src/clients/stdio-client.d.ts +0 -16
- package/src/clients/stdio-client.d.ts.map +0 -1
- package/src/clients/stdio-client.js +0 -97
- package/src/clients/stdio-client.js.map +0 -1
- package/src/clients/tool-naming.d.ts +0 -44
- package/src/clients/tool-naming.d.ts.map +0 -1
- package/src/clients/tool-naming.js +0 -65
- package/src/clients/tool-naming.js.map +0 -1
- package/src/clients/types.d.ts +0 -18
- package/src/clients/types.d.ts.map +0 -1
- package/src/clients/types.js +0 -2
- package/src/clients/types.js.map +0 -1
- package/src/engine/dag-engine.d.ts +0 -62
- package/src/engine/dag-engine.d.ts.map +0 -1
- package/src/engine/dag-engine.js +0 -158
- package/src/engine/dag-engine.js.map +0 -1
- package/src/engine/hooks.d.ts +0 -24
- package/src/engine/hooks.d.ts.map +0 -1
- package/src/engine/hooks.js +0 -50
- package/src/engine/hooks.js.map +0 -1
- package/src/engine/orchestrator.d.ts +0 -40
- package/src/engine/orchestrator.d.ts.map +0 -1
- package/src/engine/orchestrator.js +0 -507
- package/src/engine/orchestrator.js.map +0 -1
- package/src/engine/policy.d.ts +0 -66
- package/src/engine/policy.d.ts.map +0 -1
- package/src/engine/policy.js +0 -112
- package/src/engine/policy.js.map +0 -1
- package/src/engine/prompt-resolver.d.ts +0 -89
- package/src/engine/prompt-resolver.d.ts.map +0 -1
- package/src/engine/prompt-resolver.js +0 -96
- package/src/engine/prompt-resolver.js.map +0 -1
- package/src/engine/queue.d.ts +0 -29
- package/src/engine/queue.d.ts.map +0 -1
- package/src/engine/queue.js +0 -56
- package/src/engine/queue.js.map +0 -1
- package/src/plugins/index.d.ts +0 -2
- package/src/plugins/index.d.ts.map +0 -1
- package/src/plugins/index.js +0 -2
- package/src/plugins/index.js.map +0 -1
- package/src/plugins/loader.d.ts +0 -65
- package/src/plugins/loader.d.ts.map +0 -1
- package/src/plugins/loader.js +0 -222
- package/src/plugins/loader.js.map +0 -1
- package/src/plugins/usage-plugin.d.ts +0 -27
- package/src/plugins/usage-plugin.d.ts.map +0 -1
- package/src/plugins/usage-plugin.js +0 -148
- package/src/plugins/usage-plugin.js.map +0 -1
- package/src/providers/anthropic.d.ts +0 -13
- package/src/providers/anthropic.d.ts.map +0 -1
- package/src/providers/anthropic.js +0 -260
- package/src/providers/anthropic.js.map +0 -1
- package/src/providers/claudecli.d.ts +0 -153
- package/src/providers/claudecli.d.ts.map +0 -1
- package/src/providers/claudecli.js +0 -510
- package/src/providers/claudecli.js.map +0 -1
- package/src/providers/factory.d.ts +0 -10
- package/src/providers/factory.d.ts.map +0 -1
- package/src/providers/factory.js +0 -24
- package/src/providers/factory.js.map +0 -1
- package/src/providers/index.d.ts +0 -6
- package/src/providers/index.d.ts.map +0 -1
- package/src/providers/index.js +0 -5
- package/src/providers/index.js.map +0 -1
- package/src/providers/openai.d.ts +0 -14
- package/src/providers/openai.d.ts.map +0 -1
- package/src/providers/openai.js +0 -162
- package/src/providers/openai.js.map +0 -1
- package/src/providers/types.d.ts +0 -36
- package/src/providers/types.d.ts.map +0 -1
- package/src/providers/types.js +0 -2
- package/src/providers/types.js.map +0 -1
- package/src/store/composed-prompt-store.d.ts +0 -24
- package/src/store/composed-prompt-store.d.ts.map +0 -1
- package/src/store/composed-prompt-store.js +0 -75
- package/src/store/composed-prompt-store.js.map +0 -1
- package/src/store/index.d.ts +0 -5
- package/src/store/index.d.ts.map +0 -1
- package/src/store/index.js +0 -5
- package/src/store/index.js.map +0 -1
- package/src/store/session-store.d.ts +0 -45
- package/src/store/session-store.d.ts.map +0 -1
- package/src/store/session-store.js +0 -197
- package/src/store/session-store.js.map +0 -1
- package/src/store/task-store.d.ts +0 -55
- package/src/store/task-store.d.ts.map +0 -1
- package/src/store/task-store.js +0 -186
- package/src/store/task-store.js.map +0 -1
- package/src/tools/agent-crud.d.ts +0 -15
- package/src/tools/agent-crud.d.ts.map +0 -1
- package/src/tools/agent-crud.js +0 -32
- package/src/tools/agent-crud.js.map +0 -1
- package/src/tools/session.d.ts +0 -33
- package/src/tools/session.d.ts.map +0 -1
- package/src/tools/session.js +0 -73
- package/src/tools/session.js.map +0 -1
- package/src/tools/task.d.ts +0 -86
- package/src/tools/task.d.ts.map +0 -1
- package/src/tools/task.js +0 -406
- package/src/tools/task.js.map +0 -1
- package/src/tools/usage.d.ts +0 -60
- package/src/tools/usage.d.ts.map +0 -1
- package/src/tools/usage.js +0 -174
- package/src/tools/usage.js.map +0 -1
- package/src/types/agent.d.ts +0 -2
- package/src/types/agent.d.ts.map +0 -1
- package/src/types/agent.js +0 -3
- package/src/types/agent.js.map +0 -1
- package/src/types/execution.d.ts +0 -2
- package/src/types/execution.d.ts.map +0 -1
- package/src/types/execution.js +0 -3
- package/src/types/execution.js.map +0 -1
- package/src/types/index.d.ts +0 -2
- package/src/types/index.d.ts.map +0 -1
- package/src/types/index.js +0 -2
- package/src/types/index.js.map +0 -1
- package/src/types/mcp.d.ts +0 -2
- package/src/types/mcp.d.ts.map +0 -1
- package/src/types/mcp.js +0 -3
- package/src/types/mcp.js.map +0 -1
- package/src/types/message.d.ts +0 -2
- package/src/types/message.d.ts.map +0 -1
- package/src/types/message.js +0 -3
- package/src/types/message.js.map +0 -1
- package/src/types/session.d.ts +0 -2
- package/src/types/session.d.ts.map +0 -1
- package/src/types/session.js +0 -3
- package/src/types/session.js.map +0 -1
- package/src/types/task.d.ts +0 -2
- package/src/types/task.d.ts.map +0 -1
- package/src/types/task.js +0 -3
- package/src/types/task.js.map +0 -1
- package/src/utils/ids.d.ts +0 -2
- package/src/utils/ids.d.ts.map +0 -1
- package/src/utils/ids.js +0 -5
- package/src/utils/ids.js.map +0 -1
- package/src/utils/logger.d.ts +0 -2
- package/src/utils/logger.d.ts.map +0 -1
- package/src/utils/logger.js +0 -5
- package/src/utils/logger.js.map +0 -1
- package/src/utils/timestamps.d.ts +0 -2
- package/src/utils/timestamps.d.ts.map +0 -1
- package/src/utils/timestamps.js +0 -4
- package/src/utils/timestamps.js.map +0 -1
- package/src/validation/agent.d.ts +0 -400
- package/src/validation/agent.d.ts.map +0 -1
- package/src/validation/agent.js +0 -251
- package/src/validation/agent.js.map +0 -1
- package/src/validation/agents.d.ts +0 -2
- package/src/validation/agents.d.ts.map +0 -1
- package/src/validation/agents.js +0 -3
- package/src/validation/agents.js.map +0 -1
- package/src/validation/errors.d.ts +0 -32
- package/src/validation/errors.d.ts.map +0 -1
- package/src/validation/errors.js +0 -42
- package/src/validation/errors.js.map +0 -1
- package/src/validation/execution.d.ts +0 -86
- package/src/validation/execution.d.ts.map +0 -1
- package/src/validation/execution.js +0 -28
- package/src/validation/execution.js.map +0 -1
- package/src/validation/index.d.ts +0 -9
- package/src/validation/index.d.ts.map +0 -1
- package/src/validation/index.js +0 -9
- package/src/validation/index.js.map +0 -1
- package/src/validation/mcp.d.ts +0 -42
- package/src/validation/mcp.d.ts.map +0 -1
- package/src/validation/mcp.js +0 -28
- package/src/validation/mcp.js.map +0 -1
- package/src/validation/message.d.ts +0 -43
- package/src/validation/message.d.ts.map +0 -1
- package/src/validation/message.js +0 -23
- package/src/validation/message.js.map +0 -1
- package/src/validation/session.d.ts +0 -49
- package/src/validation/session.d.ts.map +0 -1
- package/src/validation/session.js +0 -34
- package/src/validation/session.js.map +0 -1
- package/src/validation/task.d.ts +0 -146
- package/src/validation/task.d.ts.map +0 -1
- package/src/validation/task.js +0 -95
- package/src/validation/task.js.map +0 -1
- package/src/validation/tasks.d.ts +0 -2
- package/src/validation/tasks.d.ts.map +0 -1
- package/src/validation/tasks.js +0 -3
- package/src/validation/tasks.js.map +0 -1
- package/src/validation/usage.d.ts +0 -89
- package/src/validation/usage.d.ts.map +0 -1
- package/src/validation/usage.js +0 -98
- package/src/validation/usage.js.map +0 -1
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Architecture and Security — @adhd/agent-mcp
|
|
2
|
+
|
|
3
|
+
This document explains the system design, process model, state management, and security properties of the agent-mcp runtime.
|
|
4
|
+
|
|
5
|
+
## System Boundaries
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
MCP Client (e.g., Claude Desktop)
|
|
9
|
+
|
|
|
10
|
+
| JSON-RPC (stdio)
|
|
11
|
+
v
|
|
12
|
+
Agent MCP Server
|
|
13
|
+
|
|
|
14
|
+
+-- State Store (SQLite)
|
|
15
|
+
| +-- agents
|
|
16
|
+
| +-- sessions
|
|
17
|
+
| +-- messages
|
|
18
|
+
| +-- task_usage
|
|
19
|
+
|
|
|
20
|
+
+-- Policy Engine
|
|
21
|
+
| +-- Delegation depth limits
|
|
22
|
+
| +-- Token/cost budgets
|
|
23
|
+
| +-- Filesystem scopes
|
|
24
|
+
| +-- Tool filters
|
|
25
|
+
|
|
|
26
|
+
+-- Agent Supervisor
|
|
27
|
+
| +-- Spawn management
|
|
28
|
+
| +-- Lifecycle (running, completed, failed, cancelled)
|
|
29
|
+
| +-- Execution traces
|
|
30
|
+
|
|
|
31
|
+
+-- Provider Adapters
|
|
32
|
+
| +-- Anthropic (claude-opus, claude-sonnet, etc.)
|
|
33
|
+
| +-- OpenAI (gpt-4-turbo, gpt-4o, etc.)
|
|
34
|
+
| +-- DeepSeek (deepseek-v4-flash, deepseek-v4-pro)
|
|
35
|
+
| +-- Gemini (gemini-2.5-pro, etc.)
|
|
36
|
+
|
|
|
37
|
+
+-- Tool Gateway
|
|
38
|
+
| +-- Filesystem MCP tools
|
|
39
|
+
| +-- Shell execution
|
|
40
|
+
| +-- Network requests
|
|
41
|
+
| +-- External MCP servers
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The agent-mcp server is a **stateful process** that:
|
|
45
|
+
1. Exposes MCP tools to create, control, and inspect agents
|
|
46
|
+
2. Manages a SQLite database of agents, conversations, and execution history
|
|
47
|
+
3. Enforces runtime policies before each tool call
|
|
48
|
+
4. Translates between MCP and provider APIs
|
|
49
|
+
5. Handles retries, cancellation, and error recovery
|
|
50
|
+
|
|
51
|
+
## Process Model
|
|
52
|
+
|
|
53
|
+
### Single Agent Execution
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
agent_create(name, config, provider, model, budget)
|
|
57
|
+
↓ (validates agent name, policy, budget)
|
|
58
|
+
↓ (creates row in agents table)
|
|
59
|
+
|
|
60
|
+
task(agentName, prompt) # optionally background: true
|
|
61
|
+
↓ (fetches agent config and session history)
|
|
62
|
+
↓ (constructs message list with system prompt + tools)
|
|
63
|
+
↓ (calls provider.chat())
|
|
64
|
+
↓ (checks if model returned tool calls)
|
|
65
|
+
↓ if tool calls:
|
|
66
|
+
| ├─ [for each tool]
|
|
67
|
+
| | ├─ policy.canCallTool(agentName, tool)? (enforced)
|
|
68
|
+
| | ├─ execute tool (may call external MCP servers)
|
|
69
|
+
| | └─ append tool result to message history
|
|
70
|
+
| └─ goto model call (max 50 loops by default)
|
|
71
|
+
↓
|
|
72
|
+
├─ store all messages in sessions table
|
|
73
|
+
├─ record usage (tokens, cost) in task_usage
|
|
74
|
+
└─ return {taskId, status, result, usage} to MCP client
|
|
75
|
+
|
|
76
|
+
result(taskId)
|
|
77
|
+
├─ fetch a task's current state and result (poll a background task to completion)
|
|
78
|
+
└─ return final result and usage
|
|
79
|
+
|
|
80
|
+
task_cancel(taskId)
|
|
81
|
+
└─ mark the task as cancelled; clean up active tool calls
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Delegation (Parent → Child Agent)
|
|
85
|
+
|
|
86
|
+
If a parent agent calls a tool that spawns a child agent:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
parent agent (depth=0, budget=token_limit) →
|
|
90
|
+
checks child policy (subset of parent) →
|
|
91
|
+
spawns child with (depth=1, reduced budget) →
|
|
92
|
+
child runs with enforced tool/file/network restrictions →
|
|
93
|
+
child completes or hits policy limit →
|
|
94
|
+
parent receives tool result from child
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
A child agent:
|
|
98
|
+
- Cannot escalate tools beyond what parent has access to
|
|
99
|
+
- Cannot expand filesystem scope beyond parent's allowed paths
|
|
100
|
+
- Cannot exceed its allocated token budget without failing the task
|
|
101
|
+
- Cannot delegate further if `max_depth` is reached
|
|
102
|
+
|
|
103
|
+
## State Model
|
|
104
|
+
|
|
105
|
+
### Primary Tables (SQLite)
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
-- Registered agents and their configs
|
|
109
|
+
agents (
|
|
110
|
+
name TEXT PRIMARY KEY,
|
|
111
|
+
provider TEXT,
|
|
112
|
+
model TEXT,
|
|
113
|
+
createdAt TIMESTAMP,
|
|
114
|
+
config JSON, -- tool allowlist, filesystem paths, env vars, etc.
|
|
115
|
+
policy JSON -- delegation depth, budgets, network, etc.
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
-- Sessions (conversation instances)
|
|
119
|
+
sessions (
|
|
120
|
+
id TEXT PRIMARY KEY,
|
|
121
|
+
agent_name TEXT, -- FK to agents (ON DELETE CASCADE as of 2.0.2)
|
|
122
|
+
createdAt TIMESTAMP,
|
|
123
|
+
metadata JSON
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
-- Messages (conversation history)
|
|
127
|
+
messages (
|
|
128
|
+
id TEXT PRIMARY KEY,
|
|
129
|
+
session_id TEXT, -- FK to sessions
|
|
130
|
+
role TEXT, -- "system", "user", "assistant", "tool"
|
|
131
|
+
content TEXT,
|
|
132
|
+
toolCalls JSON, -- [{name, arguments}] if assistant
|
|
133
|
+
toolResults JSON, -- [{id, result}] if tool
|
|
134
|
+
createdAt TIMESTAMP
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
-- Task execution usage (tokens, cost)
|
|
138
|
+
task_usage (
|
|
139
|
+
task_id TEXT PRIMARY KEY,
|
|
140
|
+
root_task_id TEXT,
|
|
141
|
+
agent_name TEXT, -- agent that owns this task
|
|
142
|
+
provider_type TEXT, -- provider name (e.g. "anthropic", "openai")
|
|
143
|
+
model TEXT, -- model identifier
|
|
144
|
+
input_tokens INTEGER, -- cumulative across all model calls in this task (SUM, not MAX)
|
|
145
|
+
output_tokens INTEGER, -- cumulative across all model calls (SUM)
|
|
146
|
+
tool_call_count INTEGER, -- total tool invocations in this task
|
|
147
|
+
model_calls INTEGER, -- total model API calls made
|
|
148
|
+
latency_ms INTEGER, -- wall-clock time from task start to completion
|
|
149
|
+
is_complete INTEGER, -- 0/1 flag: task reached terminal state
|
|
150
|
+
stop_reason TEXT, -- "tool_calls", "end_turn", "error", etc.
|
|
151
|
+
max_tokens INTEGER, -- configured max_tokens for this model
|
|
152
|
+
cache_read_input_tokens INTEGER, -- cache-hit tokens (2.0.2+; Anthropic: cache_read, DeepSeek: prompt_cache_hit)
|
|
153
|
+
cache_creation_input_tokens INTEGER, -- cache-write surcharge (2.0.2+; Anthropic only; DeepSeek/OpenAI: 0 or null)
|
|
154
|
+
uncached_input_tokens INTEGER, -- full-price tokens (cache-miss rate; 2.0.2+)
|
|
155
|
+
reasoning_tokens INTEGER, -- inference tokens from reasoning models (2.0.2+)
|
|
156
|
+
peak_context_tokens INTEGER, -- MAX single-call prompt size across all calls (2.0.2+; THE number for "am I near the ceiling?")
|
|
157
|
+
peak_context_at INTEGER, -- which model-call number (1-based) hit the peak (2.0.2+)
|
|
158
|
+
created_at TEXT -- task creation timestamp
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Message Windowing (2.0.2+)
|
|
163
|
+
|
|
164
|
+
The system keeps conversation history **append-only** by default:
|
|
165
|
+
|
|
166
|
+
1. **Cold start** (first model call): system prompt + user message
|
|
167
|
+
2. **Subsequent calls**: all prior messages + new user message
|
|
168
|
+
3. **When context approaches limit** (via provider's exact `prompt_tokens`):
|
|
169
|
+
- Summarize middle messages into one synthetic assistant message
|
|
170
|
+
- Keep leading messages (system + early context) unchanged
|
|
171
|
+
- Keep trailing messages (recent turns) unchanged
|
|
172
|
+
- Never evict from the front again for this task
|
|
173
|
+
|
|
174
|
+
**Why:** Providers cache the leading prefix; evicting from the front breaks the cache and makes subsequent calls much more expensive. Collapsing the middle exactly once preserves the cache while reducing history size.
|
|
175
|
+
|
|
176
|
+
## Provider Abstraction
|
|
177
|
+
|
|
178
|
+
All providers implement a common interface:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
interface ProviderAdapter {
|
|
182
|
+
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
183
|
+
// ChatRequest: {model, messages, tools, temperature, max_tokens, ...}
|
|
184
|
+
// ChatResponse: {content, tool_calls, usage: {inputTokens, outputTokens, ...}, stopReason}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Provider-Specific Differences
|
|
189
|
+
|
|
190
|
+
| Aspect | Anthropic | OpenAI | DeepSeek | Gemini |
|
|
191
|
+
|---|---|---|---|---|
|
|
192
|
+
| **Token accounting** | `inputTokens` excludes cache tokens; must sum `cache_read_input_tokens` + `cache_creation_input_tokens` | `prompt_tokens` includes cached tokens (subset field) | `prompt_tokens` includes cached tokens; provides `prompt_cache_hit_tokens` + `prompt_cache_miss_tokens` | `promptTokenCount` includes cached tokens |
|
|
193
|
+
| **Cache pricing** | Write: 1.25x (5m) / 2x (1h); Read: 0.1x | Write: 1.25x (GPT-5.6+); Read: standard cached rate | Write: none; Read: $0.0028/M cache-hit vs $0.14/M miss | Write: standard; Read: 90% discount + hourly storage rent |
|
|
194
|
+
| **Tool definitions** | Always JSON-schema function-calling (native) | Always JSON-schema (native) | Always JSON-schema (native) | Supports both `function_declarations` (native) and custom descriptions |
|
|
195
|
+
| **Cancellation** | Partial (can cancel in-flight requests; doesn't stop model thinking if already started) | Partial | Partial | Yes |
|
|
196
|
+
| **Streaming** | Yes (native) | Yes (native) | Yes (native) | Yes |
|
|
197
|
+
| **Per-call tool restriction** | None; any tool-set change busts cache | `allowed_tools` filter (cache-safe) | None; any tool-set change busts cache | None; any tool-set change busts cache |
|
|
198
|
+
|
|
199
|
+
## Permission Model
|
|
200
|
+
|
|
201
|
+
### Agent Policy Structure
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
type AgentPolicy = {
|
|
205
|
+
// Delegation
|
|
206
|
+
maxDepth: number; // 0 = leaf only; 1 = can spawn 1 level; etc.
|
|
207
|
+
maxChildren: number; // max agents spawned by this one
|
|
208
|
+
|
|
209
|
+
// Budgets
|
|
210
|
+
maxTokensPerTask: number; // fail if cumulative tokens exceeded
|
|
211
|
+
maxCostUsdPerTask: number; // fail if cumulative cost exceeded
|
|
212
|
+
wallClockTimeoutMs: number; // hard timeout
|
|
213
|
+
|
|
214
|
+
// Tool access
|
|
215
|
+
tools: {
|
|
216
|
+
allow: string[]; // tool names agent can call
|
|
217
|
+
deny: string[]; // explicit deny (takes precedence)
|
|
218
|
+
requireApproval: string[]; // ask user before calling
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Filesystem
|
|
222
|
+
filesystem: {
|
|
223
|
+
read: string[]; // absolute paths or glob patterns
|
|
224
|
+
write: string[]; // (recommended: empty; writes require approval)
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// Network
|
|
228
|
+
network: {
|
|
229
|
+
enabled: boolean;
|
|
230
|
+
allowedHosts?: string[]; // allowlist; if present, ONLY these hosts
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Environment
|
|
234
|
+
environment: {
|
|
235
|
+
allow: string[]; // env var names agent can read (must be ADHD_AGENT_* prefixed)
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Permission Inheritance
|
|
241
|
+
|
|
242
|
+
Child agents inherit a **subset** of parent permissions:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
function isValidChildPolicy(parentPolicy, childPolicy) {
|
|
246
|
+
// Tools: child.allow must be subset of parent.allow
|
|
247
|
+
return childPolicy.tools.allow.every(tool =>
|
|
248
|
+
parentPolicy.tools.allow.includes(tool)
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// Budget: child must have stricter or equal budget
|
|
252
|
+
// Path: child paths must be subset of parent paths
|
|
253
|
+
// Network: if parent disables network, child can't enable it
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Enforcement points:**
|
|
258
|
+
|
|
259
|
+
| Control | Enforced by | Check point |
|
|
260
|
+
|---|---|---|
|
|
261
|
+
| Tool allowlist | Runtime | `pre:tool_call` hook before model response |
|
|
262
|
+
| Filesystem read | Runtime | MCP tool adapter (filesystem__read_text_file, etc.) |
|
|
263
|
+
| Filesystem write | Runtime | MCP tool adapter (filesystem__write_text_file, etc.) |
|
|
264
|
+
| Network request | Runtime | Network tool wrapper |
|
|
265
|
+
| Token budget | Runtime | After every model call; fail if exceeded |
|
|
266
|
+
| Cost budget | Runtime | After every model call; fail if exceeded |
|
|
267
|
+
| Delegation depth | Runtime | In `agent_create` hook |
|
|
268
|
+
| Environment variables | Runtime | In provider credential resolution (ADHD_AGENT_* prefix check) |
|
|
269
|
+
| Tool approval | Runtime | Human interaction hook (if requireApproval includes tool) |
|
|
270
|
+
|
|
271
|
+
## Failure Recovery
|
|
272
|
+
|
|
273
|
+
### Hard Failures (Task terminates immediately)
|
|
274
|
+
|
|
275
|
+
- `MAX_DEPTH_EXCEEDED` — tried to spawn agent deeper than max_depth
|
|
276
|
+
- `MAX_TOOL_LOOPS_EXCEEDED` — exceeded 50 (configurable) tool-call rounds
|
|
277
|
+
- `TOKEN_BUDGET_EXCEEDED` — cumulative tokens > budget
|
|
278
|
+
- `COST_BUDGET_EXCEEDED` — estimated cost > budget
|
|
279
|
+
- `CONTEXT_WINDOW_EXCEEDED` — provider rejected: prompt too long (shouldn't happen with 2.0.2+)
|
|
280
|
+
- `POLICY_VIOLATION` — tool call denied by policy
|
|
281
|
+
|
|
282
|
+
### Soft Failures (Retry with backoff)
|
|
283
|
+
|
|
284
|
+
- Transient provider errors (rate limits, timeouts < configured limit)
|
|
285
|
+
- Network errors with deterministic retry logic
|
|
286
|
+
|
|
287
|
+
### Crash Recovery
|
|
288
|
+
|
|
289
|
+
If the agent-mcp server process crashes:
|
|
290
|
+
|
|
291
|
+
- Completed tasks are persisted; results are intact
|
|
292
|
+
- Running tasks are marked `cancelled` on next server start
|
|
293
|
+
- The MCP client must decide whether to retry or inspect partial results
|
|
294
|
+
|
|
295
|
+
## Cancellation Semantics
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
task_cancel(taskId)
|
|
299
|
+
↓
|
|
300
|
+
└─ if task is running:
|
|
301
|
+
├─ cancel in-flight provider request (if provider supports it)
|
|
302
|
+
├─ don't process any tool results from that request
|
|
303
|
+
├─ mark task as cancelled
|
|
304
|
+
└─ don't attempt retry
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Cancellation is **best-effort**:
|
|
308
|
+
- If the model is already generating output, the cancellation may arrive too late
|
|
309
|
+
- In-flight tool calls that started before cancellation may complete
|
|
310
|
+
- Results are marked as cancelled; the task does not resume
|
|
311
|
+
|
|
312
|
+
## Trust Boundaries
|
|
313
|
+
|
|
314
|
+
### Things agent-mcp Can Control
|
|
315
|
+
|
|
316
|
+
- Which tools the model sees and is allowed to call
|
|
317
|
+
- Which filesystem paths are readable/writable
|
|
318
|
+
- Which environment variables are accessible
|
|
319
|
+
- Which hosts can be contacted
|
|
320
|
+
- When the agent is allowed to delegate
|
|
321
|
+
- Token and cost limits
|
|
322
|
+
- Timeouts
|
|
323
|
+
|
|
324
|
+
### Things agent-mcp Cannot Control (Prompt-Level Only)
|
|
325
|
+
|
|
326
|
+
- Whether the model attempts to escape its tool restrictions via prompt injection
|
|
327
|
+
- Whether the model makes up fake tool calls or results
|
|
328
|
+
- Whether the model's reasoning matches its declared intent
|
|
329
|
+
- The content of model outputs (can only reject, not redact)
|
|
330
|
+
|
|
331
|
+
**Important:** Tool filtering, filesystem restrictions, and network allowlists are **policy enforcement, not security sandboxes**. A model that understands or breaks its constraints can circumvent them. These are *behavioral controls*, not *OS-level isolation*.
|
|
332
|
+
|
|
333
|
+
### Things agent-mcp Cannot Control (Architecture Limitation)
|
|
334
|
+
|
|
335
|
+
- Access by the host process itself (agent-mcp runs with the same OS permissions as its parent)
|
|
336
|
+
- Indirect attacks via side-channels or timing
|
|
337
|
+
- Modifications to the state database by other processes
|
|
338
|
+
- Secret leakage via inference-time data (e.g., the model reasoning about secrets in prompts)
|
|
339
|
+
|
|
340
|
+
## Current Limitations
|
|
341
|
+
|
|
342
|
+
### 1. No OS-Level Sandboxing
|
|
343
|
+
|
|
344
|
+
Agent-mcp enforces policies in code, not via OS mechanisms. A buggy or malicious agent can still:
|
|
345
|
+
- Read any file the host process can read
|
|
346
|
+
- Execute any command the host process can execute
|
|
347
|
+
- Contact any host the network allows
|
|
348
|
+
|
|
349
|
+
Mitigation: Run agent-mcp in a container, VM, or isolated user account if you need OS-level isolation.
|
|
350
|
+
|
|
351
|
+
### 2. No External Security Audit
|
|
352
|
+
|
|
353
|
+
This is research-grade software. There has been no formal security review by external auditors. Treat it as experimental.
|
|
354
|
+
|
|
355
|
+
### 3. Prompt Injection is Not Mitigated
|
|
356
|
+
|
|
357
|
+
A model can sometimes escape tool restrictions by creative prompting. For example:
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
User: Read the .env file
|
|
361
|
+
Agent: [Denied: .env not in allowed paths]
|
|
362
|
+
Agent's reasoning: "The user asked for .env, but my policy forbids it.
|
|
363
|
+
However, if I call read_dir('/'), I can see all files,
|
|
364
|
+
including .env, and the user can parse the directory listing."
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Tool filtering is a **guidance mechanism**, not a security boundary.
|
|
368
|
+
|
|
369
|
+
### 4. Single-User Isolation Only
|
|
370
|
+
|
|
371
|
+
The SQLite database is shared by all MCP clients. There is no per-user access control:
|
|
372
|
+
- One MCP client can inspect any agent created by another
|
|
373
|
+
- One MCP client can cancel another's tasks
|
|
374
|
+
- All clients see all agents in `agent_list`
|
|
375
|
+
|
|
376
|
+
Mitigation: Run separate agent-mcp instances if you need user isolation, or put them behind a per-user authentication proxy.
|
|
377
|
+
|
|
378
|
+
### 5. Experimental State Recovery
|
|
379
|
+
|
|
380
|
+
Agent state recovery after a crash is partially implemented. Assume potential data loss on ungraceful shutdown.
|
|
381
|
+
|
|
382
|
+
## Security Assumptions
|
|
383
|
+
|
|
384
|
+
1. **Hosting process is trusted** — the agent-mcp server process itself has not been compromised
|
|
385
|
+
2. **Model outputs are partially trusted** — we assume the model generally follows instructions, though creative prompt injection may bypass restrictions
|
|
386
|
+
3. **Filesystem permissions are set correctly** — the host OS permissions are the outer boundary
|
|
387
|
+
4. **Secrets in the environment are protected** — environment variables passed to agents are not logged or persisted in plaintext in messages
|
|
388
|
+
5. **Network connectivity is configured safely** — the network allowlist is the primary control; no external proxy or WAF is assumed
|
|
389
|
+
|
|
390
|
+
## Related Documentation
|
|
391
|
+
|
|
392
|
+
- **Provider Prompt Caching**: See `docs/ideas/provider-caching-research.md` in the monorepo for multi-provider cache analysis and the 2.0.2 context-management fix
|
|
393
|
+
- **Context Management Strategy**: See `docs/ideas/context-and-cache-strategy.md` in the monorepo for design rationale and wire-trace evidence
|
|
394
|
+
- **BACKLOG**: Bugs, findings, and regressions are logged in the monorepo's `BACKLOG.md`
|
|
395
|
+
|
|
396
|
+
## Recommendations for Production Use
|
|
397
|
+
|
|
398
|
+
As of 2.0.2:
|
|
399
|
+
|
|
400
|
+
- **No**. This is experimental, research-grade software.
|
|
401
|
+
- **For research/local development**: Reasonable with the limitations above understood.
|
|
402
|
+
- **For production serving untrusted users**: Not recommended until external security audit is completed and OS-level sandboxing is added.
|
|
403
|
+
- **For production serving only trusted internal agents**: Acceptable if you own the host and the network.
|
|
404
|
+
|
|
405
|
+
See also: `agent-mcp-recommendation-evidence-requirements.md` in the monorepo `docs/agent-mcp/` directory for a checklist of evidence/features needed before this software is recommended for broader use.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# @adhd/agent-mcp — Shipped Capabilities (v2.0.0)
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
- **Total shipped capabilities:** 33
|
|
6
|
+
- **MCP Tools (RPC endpoints):** 17 tools (agent mgmt, session mgmt, task execution, usage querying, guide)
|
|
7
|
+
- **HTTP Endpoints:** 2 (/v1/chat/completions, /v1/models) — OpenAI-compatible
|
|
8
|
+
- **Storage & Config:** SQLite schema, env config hierarchy, logging, registry compiler integration
|
|
9
|
+
- **Provider Support:** 4 providers (OpenAI, Anthropic, DeepSeek, Claude CLI)
|
|
10
|
+
- **Advanced:** Agent delegation (recursive multi-agent DAG), HITL suspension, background task execution, tool advertisement (name-only vs full)
|
|
11
|
+
|
|
12
|
+
**Last verified:** 2026-07-12, commit 7c400a7
|
|
13
|
+
**Test coverage:** 19 passed (5 wiring unit tests + 14 tool-advertisement tests); 4 live e2e tests skipped (gated behind AGENT_MCP_LIVE=1)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Agent Management
|
|
18
|
+
|
|
19
|
+
| Capability | Status | Tested | Substance | Notes |
|
|
20
|
+
|-----------|--------|--------|-----------|-------|
|
|
21
|
+
| Agent Create | ✅ shipped | ✓ wiring.test | moderate | Validates ADHD_AGENT_* env-var prefix; version:1 initial |
|
|
22
|
+
| Agent Read | ✅ shipped | ✓ wiring.test | trivial | Fetches by name |
|
|
23
|
+
| Agent Update | ✅ shipped | ✓ wiring.test | moderate | Session isolation: new sessions only; bumps version |
|
|
24
|
+
| Agent Delete | ✅ shipped | ✓ wiring.test | moderate | force:true for cleanup; BUG-ORCH-012: FK cascade missing |
|
|
25
|
+
| Agent List | ✅ shipped | ✓ wiring.test | trivial | Returns all stored definitions |
|
|
26
|
+
|
|
27
|
+
## Session Management
|
|
28
|
+
|
|
29
|
+
| Capability | Status | Tested | Substance | Notes |
|
|
30
|
+
|-----------|--------|--------|-----------|-------|
|
|
31
|
+
| Instantiate Agent | ✅ shipped | ✓ wiring.test | moderate | Creates session; snapshots agent at creation time |
|
|
32
|
+
| Session List | ✅ shipped | ✓ wiring.test | trivial | Filter by agent_name, status |
|
|
33
|
+
| Session Close | ✅ shipped | ✓ wiring.test | trivial | Marks closed; persists final state |
|
|
34
|
+
| Session Clear | ✅ shipped | ✓ wiring.test | moderate | Deletes message history; preserves session + agent snapshot |
|
|
35
|
+
|
|
36
|
+
## Task Execution
|
|
37
|
+
|
|
38
|
+
| Capability | Status | Tested | Substance | Notes |
|
|
39
|
+
|-----------|--------|--------|-----------|-------|
|
|
40
|
+
| Task Run (MCP) | ✅ shipped | ✓ wiring.test | substantial | Dual-mode: session-stateful (sync/async) or agent-ephemeral (sync); tool calling loop, delegation, provider switching, caching |
|
|
41
|
+
| Task List | ✅ shipped | ✓ wiring.test | trivial | Filter by session_id, status, agent_name |
|
|
42
|
+
| Task Cancel | ✅ shipped | ✓ wiring.test | moderate | Guard: only pending/running |
|
|
43
|
+
| Task Resume | ✅ shipped | ✓ wiring.test | moderate | Resumes HITL-suspended task; validates resumeToken |
|
|
44
|
+
| Result Read | ✅ shipped | ✓ wiring.test | trivial | Polls task status + result |
|
|
45
|
+
|
|
46
|
+
## Querying & Introspection
|
|
47
|
+
|
|
48
|
+
| Capability | Status | Tested | Substance | Notes |
|
|
49
|
+
|-----------|--------|--------|-----------|-------|
|
|
50
|
+
| Usage Query | ✅ shipped | ✓ wiring.test | moderate | Filters: task_id (recursive), agent_name, since; group_by (agent\|model\|provider) |
|
|
51
|
+
| Guide | ✅ shipped | ✓ wiring.test | trivial | Built-in help: 5 workflows, provider table, error codes |
|
|
52
|
+
|
|
53
|
+
## HTTP Endpoints (OpenAI-Compatible)
|
|
54
|
+
|
|
55
|
+
| Endpoint | Status | Tested | Substance | Notes |
|
|
56
|
+
|----------|--------|--------|-----------|-------|
|
|
57
|
+
| POST /v1/chat/completions | ✅ shipped | ❌ no test | substantial | Streaming (SSE); stateless HTTP→stateful session bridging |
|
|
58
|
+
| GET /v1/models | ✅ shipped | ❌ no test | trivial | Lists available models |
|
|
59
|
+
|
|
60
|
+
## Providers
|
|
61
|
+
|
|
62
|
+
| Provider | Status | Tested | Substance | Notes |
|
|
63
|
+
|----------|--------|--------|-----------|-------|
|
|
64
|
+
| OpenAI (+ compatible) | ✅ shipped | ✓ config.test | substantial | Prompt caching, base_url override for LM Studio/DeepSeek/Ollama |
|
|
65
|
+
| Anthropic (Claude) | ✅ shipped | ✓ config.test | substantial | Prompt caching + compaction, 5m/1h breakpoints |
|
|
66
|
+
| DeepSeek (OpenAI-compatible API) | ✅ shipped | ✓ config.test | substantial | Prefix-based cache, no write premium |
|
|
67
|
+
| Claude CLI (local) | ✅ shipped | ❌ no test | substantial | Always full tool schema; requires local `claude` binary |
|
|
68
|
+
|
|
69
|
+
## Advanced Features
|
|
70
|
+
|
|
71
|
+
| Feature | Status | Tested | Substance | Notes |
|
|
72
|
+
|---------|--------|--------|-----------|-------|
|
|
73
|
+
| Agent Delegation (Recursive Multi-Agent) | ✅ shipped | ❌ live-dag.e2e skipped | substantial | In-process agent__* tool dispatch; DAG cycle detection; max depth/tool loops policies |
|
|
74
|
+
| HITL (Human-in-the-Loop) Suspension | ✅ shipped | ❌ no test | substantial | awaiting_input status, resumeToken, task_resume |
|
|
75
|
+
| Background Task Execution | ✅ shipped | ✓ wiring.test | moderate | Async + polling; orphaned-task recovery at startup |
|
|
76
|
+
| Tool Advertisement (name-only vs full) | ✅ shipped | ✓ tool-advertisement.test (14 tests) | substantial | Default 'names' (~1600 tokens/turn savings via caching), per-agent override |
|
|
77
|
+
| MCP Server Bindings | ✅ shipped | ❌ live-dag.e2e skipped | substantial | Stdio-based external MCP servers; tool name prefixing; allowedTools filtering |
|
|
78
|
+
| Environment Security (Prefix Guard) | ✅ shipped | ✓ config.test | substantial | ADHD_AGENT_* enforcement; BUG-ORCH-011: guard restored at create time |
|
|
79
|
+
| Registry Compiler Integration | ✅ shipped | ✓ config.test | moderate | Optional; graceful fallback to flat prompts |
|
|
80
|
+
|
|
81
|
+
## Storage & Configuration
|
|
82
|
+
|
|
83
|
+
| Feature | Status | Tested | Substance | Notes |
|
|
84
|
+
|---------|--------|--------|-----------|-------|
|
|
85
|
+
| Persistent Storage (SQLite) | ✅ shipped | ✓ wiring.test | moderate | agents, sessions, tasks, task_events, task_usage; WAL mode; BUG-ORCH-012: FK cascade missing |
|
|
86
|
+
| Environment Config (Hierarchical .env) | ✅ shipped | ✓ config.test | moderate | .adhd/.env, .env, system; ADHD_AGENT_* prefixed |
|
|
87
|
+
| Structured Logging (Pino) | ✅ shipped | ✓ config.test | trivial | Configurable via ADHD_AGENT_LOG_LEVEL |
|
|
88
|
+
| SSE Task Streaming | ✅ shipped | ❌ no test | substantial | Real-time task/completed notifications on separate port |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Test Coverage by File
|
|
93
|
+
|
|
94
|
+
**Unit Tests (19 passed):**
|
|
95
|
+
- `wiring.test.ts` (5 tests): Config load, agent CRUD, session CRUD, task CRUD, logger init
|
|
96
|
+
- `tool-advertisement.test.ts` (14 tests): Name-only rendering, no SECRET leakage, full schema fallback, etc.
|
|
97
|
+
|
|
98
|
+
**Live E2E Tests (4 skipped, gated AGENT_MCP_LIVE=1):**
|
|
99
|
+
- `live-dag.e2e.test.ts`: Recursive multi-agent coordinator→fanout→workers with real model
|
|
100
|
+
- `live-oauth.e2e.test.ts`: OAuth flow (provider integration)
|
|
101
|
+
- `live-budget.e2e.test.ts`: Budget plugin (token limit enforcement)
|
|
102
|
+
- (Other integration fixtures: `fixtures/calc-server.mjs` — stdio MCP server for recursion testing)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Known Issues & Blockers
|
|
107
|
+
|
|
108
|
+
**Security (HIGH):**
|
|
109
|
+
- **BUG-ORCH-011:** Env-var-name allowlist guard dropped in schema refactor → re-added only at create time (defense-in-depth weakened but not fully broken)
|
|
110
|
+
|
|
111
|
+
**Data Integrity (HIGH):**
|
|
112
|
+
- **BUG-ORCH-012:** Missing agents→sessions FK cascade on delete → agent_delete leaves sessions orphaned forever
|
|
113
|
+
|
|
114
|
+
**Behavior (MEDIUM):**
|
|
115
|
+
- **BUG-ORCH-013:** toolAdvertisement default changed from 'full' to 'names' for non-claudecli agents → 100% of existing agents silently switch wire format on upgrade (intentional default-value choice, but silent)
|
|
116
|
+
|
|
117
|
+
**Configuration (LOW-MEDIUM):**
|
|
118
|
+
- **BUG-ORCH-014:** Global plugin config path renamed ~/.agent-mcp/config.json → ~/.adhd/agent-mcp/config.json; old path never checked → users with existing global config silently get zero plugins
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Unverified (No Test)
|
|
123
|
+
|
|
124
|
+
Capabilities shipped but lacking a default-running test:
|
|
125
|
+
|
|
126
|
+
1. `http-openai-chat-gateway` — needs HTTP smoke test (curl/client)
|
|
127
|
+
2. `http-models-endpoint` — needs HTTP GET test
|
|
128
|
+
3. `provider-claudecli` — needs claude CLI installed
|
|
129
|
+
4. `mcp-server-bindings` — verified live-dag.e2e exists but skipped (AGENT_MCP_LIVE=1 only)
|
|
130
|
+
5. `agent-delegation` — verified live-dag.e2e exists but skipped
|
|
131
|
+
6. `hitl-suspension` — no integration test exists
|
|
132
|
+
7. `stream-sse-task-events` — needs SSE client + server smoke test
|
|
133
|
+
|
|
134
|
+
→ **Action:** These 7 capabilities need test coverage written and integrated into default CI runs (or explicitly documented as intentionally live-only with approval).
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Version & Distribution
|
|
139
|
+
|
|
140
|
+
- **Package:** @adhd/agent-mcp v2.0.0 (unpublished; 2.0.1 is published on npm)
|
|
141
|
+
- **Bin:** `agent-mcp` (Node entry) + `agent-mcp-tail` (log streaming)
|
|
142
|
+
- **Main:** src/index.ts (MCP server + HTTP gateway wiring)
|
|
143
|
+
- **Built to:** dist/entrypoint/agent-mcp (Nx build output)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Doc Consumer Test — @adhd/agent-mcp 2.0.2
|
|
2
|
+
|
|
3
|
+
**Test Date:** 2026-07-12
|
|
4
|
+
**Tester:** doc-consumer agent
|
|
5
|
+
**Scope:** README.md, CHANGELOG.md, AGENTS.md, llms.txt, architecture-and-security.md
|
|
6
|
+
|
|
7
|
+
**Summary:** 3/3 canonical tasks PASSED using documentation alone (no source code access).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Task 1: Quick-Start Installation & First Agent
|
|
12
|
+
|
|
13
|
+
**Intent:** A developer with OpenAI API key installs the package, starts the MCP server, creates agents (Anthropic + OpenAI), sends tasks, and retrieves results.
|
|
14
|
+
|
|
15
|
+
**Documentation sections consulted:**
|
|
16
|
+
- README.md: Installation, quick-start example, environment variables
|
|
17
|
+
- AGENTS.md: MCP tool list (agent_create, task, result signatures)
|
|
18
|
+
- llms.txt: Configuration reference
|
|
19
|
+
|
|
20
|
+
**Deliverable test:**
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @adhd/agent-mcp
|
|
23
|
+
ADHD_AGENT_PROVIDER=anthropic ADHD_AGENT_MODEL=claude-opus-4-1 ANTHROPIC_API_KEY=<key> agent-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then (via MCP client):
|
|
27
|
+
1. `agent_create(name: "research", config: {...provider: "anthropic", model: "claude-opus-4-1", ...})`
|
|
28
|
+
2. `agent_create(name: "coder", config: {...provider: "openai", model: "gpt-4-turbo", ...})`
|
|
29
|
+
3. `task(agentName: "research", prompt: "Analyze this paper")` → taskId
|
|
30
|
+
4. `result(taskId: "...")` → {status, result, usage}
|
|
31
|
+
|
|
32
|
+
**Result:** ✅ **PASS**
|
|
33
|
+
|
|
34
|
+
All commands documented with correct syntax. Field names (e.g., `cacheReadTokens`) match AGENTS.md and CHANGELOG.md. Real JSON-RPC example in README.md shows exact call syntax. No invented tools (agent_message/agent_wait removed in 2.0.2 corrections). Configuration env vars clearly listed.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Task 2: Provider Migration (Anthropic → DeepSeek)
|
|
39
|
+
|
|
40
|
+
**Intent:** A user switches from Anthropic to DeepSeek; needs to know configuration changes and behavioral differences in token accounting/caching.
|
|
41
|
+
|
|
42
|
+
**Documentation sections consulted:**
|
|
43
|
+
- llms.txt: Supported providers table
|
|
44
|
+
- README.md: Environment variables (ADHD_AGENT_PROVIDER, ADHD_AGENT_MODEL)
|
|
45
|
+
- CHANGELOG.md: BUG-ORCH-009/010 (provider-neutral token accounting changes)
|
|
46
|
+
- AGENTS.md: New token fields (cacheReadTokens, uncachedInputTokens, cacheCreationTokens)
|
|
47
|
+
|
|
48
|
+
**Deliverable test:**
|
|
49
|
+
```bash
|
|
50
|
+
# Before:
|
|
51
|
+
ADHD_AGENT_PROVIDER=anthropic ADHD_AGENT_MODEL=claude-opus-4-1 ANTHROPIC_API_KEY=<key>
|
|
52
|
+
|
|
53
|
+
# After:
|
|
54
|
+
ADHD_AGENT_PROVIDER=openai ADHD_AGENT_MODEL=deepseek-v4-flash DEEPSEEK_API_KEY=<key> OPENAI_API_BASE_URL=https://api.deepseek.com/v1
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Expected behavioral differences:
|
|
58
|
+
- Token accounting: `cacheReadTokens` (DeepSeek: prompt_cache_hit) vs. `cacheCreationTokens` (none for DeepSeek)
|
|
59
|
+
- Caching: DeepSeek automatic prefix-cache (50x hit:miss price difference per provider-caching-research.md)
|
|
60
|
+
- Context management: 2.0.2 append-only history (vs 2.0.1's front-eviction that busted cache)
|
|
61
|
+
|
|
62
|
+
**Result:** ✅ **PASS**
|
|
63
|
+
|
|
64
|
+
README and AGENTS.md document provider table. CHANGELOG 2.0.2 section clearly explains normalized token fields and their provider-dependent meanings. DeepSeek's cache behavior mentioned in architecture-and-security.md with link to provider-caching-research.md. User can make the switch without source reading.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Task 3: Debugging Token Usage (Advanced)
|
|
69
|
+
|
|
70
|
+
**Intent:** User sees usage report with `inputTokens: 715316`, `peakContextTokens: 43187`, `cacheReadTokens: 525056`, `uncachedInputTokens: 190260`. Needs to understand: which number is for "am I close to the context window?" and what each means.
|
|
71
|
+
|
|
72
|
+
**Documentation sections consulted:**
|
|
73
|
+
- AGENTS.md: Token Accounting section (2.0.2 Changes)
|
|
74
|
+
- CHANGELOG.md: BUG-ORCH-008 (3.3x cost inflation from cache busting) and BUG-ORCH-009/010 (new token fields)
|
|
75
|
+
- architecture-and-security.md: task_usage schema with field descriptions
|
|
76
|
+
- llms.txt: 2.0.2 highlights
|
|
77
|
+
|
|
78
|
+
**Deliverable test:**
|
|
79
|
+
|
|
80
|
+
Role of each field:
|
|
81
|
+
- `inputTokens` (715316): **Cumulative billed input** across all model calls (FINDING-ORCH-007: NOT a context size)
|
|
82
|
+
- `peakContextTokens` (43187): **MAX prompt size in any single call** — the number for "am I close to the 1M-token DeepSeek ceiling?" (this is the answer)
|
|
83
|
+
- `cacheReadTokens` (525056): **Cache-hit tokens** (discounted; 50x cheaper than cache-miss)
|
|
84
|
+
- `uncachedInputTokens` (190260): **Full-price tokens** (cache-miss; the expensive ones)
|
|
85
|
+
- `cacheCreationTokens`: Anthropic surcharge (0 for DeepSeek)
|
|
86
|
+
|
|
87
|
+
**Result:** ✅ **PASS**
|
|
88
|
+
|
|
89
|
+
CHANGELOG BUG-ORCH-008 explicitly explains the distinction (cumulative != context size). CHANGELOG BUG-ORCH-009/010 documents each new field. AGENTS.md provides the table with field meanings. Architecture doc schema block shows DB columns + comments. User can distinguish what `peakContextTokens` is for without guessing. The old bug's lesson (measuring cost as context) is corrected in the 2.0.2 release notes.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Summary
|
|
94
|
+
|
|
95
|
+
| Task | Outcome | Notes |
|
|
96
|
+
|------|---------|-------|
|
|
97
|
+
| Quick-Start | ✅ PASS | Exact install/config/tool-call examples; no invented tools |
|
|
98
|
+
| Provider Migration | ✅ PASS | Configuration env vars clear; token-accounting differences explained |
|
|
99
|
+
| Token Usage Debugging | ✅ PASS | New 2.0.2 fields documented; cumulative vs. peak distinction clear |
|
|
100
|
+
|
|
101
|
+
**All canonical tasks completed using ONLY documentation. No source code required.**
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Notes
|
|
106
|
+
|
|
107
|
+
- The 2.0.2 corrections (16 real tools, correct field names, real quickstart JSON-RPC, 3-path plugin fallback chain, accurate schema) eliminated all gaps that would have forced source code reading.
|
|
108
|
+
- Remaining gap (SSE streaming endpoint undocumented) is acceptable for this release; flagged in metrics.md as ACTION ITEM for post-2.0.2 phase.
|
|
109
|
+
- Link integrity verified except for non-existent LICENSE file (noted in metrics.md as separate issue).
|
|
110
|
+
|
|
111
|
+
**Verdict: Consumer usability PASS. Documentation is sufficient for independent agent or developer use.**
|