@awcp/mcp 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +305 -0
- package/dist/auto-daemon.d.ts +63 -0
- package/dist/auto-daemon.d.ts.map +1 -0
- package/dist/auto-daemon.js +152 -0
- package/dist/auto-daemon.js.map +1 -0
- package/dist/bin/awcp-mcp.d.ts +3 -18
- package/dist/bin/awcp-mcp.d.ts.map +1 -1
- package/dist/bin/awcp-mcp.js +221 -46
- package/dist/bin/awcp-mcp.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/peer-discovery.d.ts +27 -0
- package/dist/peer-discovery.d.ts.map +1 -0
- package/dist/peer-discovery.js +117 -0
- package/dist/peer-discovery.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -2
- package/dist/server.js.map +1 -0
- package/dist/tools/delegate-cancel.d.ts +2 -5
- package/dist/tools/delegate-cancel.d.ts.map +1 -1
- package/dist/tools/delegate-cancel.js +8 -26
- package/dist/tools/delegate-cancel.js.map +1 -0
- package/dist/tools/delegate-cancel.txt +16 -0
- package/dist/tools/delegate-output.d.ts +1 -1
- package/dist/tools/delegate-output.d.ts.map +1 -1
- package/dist/tools/delegate-output.js +8 -25
- package/dist/tools/delegate-output.js.map +1 -0
- package/dist/tools/delegate-output.txt +22 -0
- package/dist/tools/delegate.d.ts +6 -1
- package/dist/tools/delegate.d.ts.map +1 -1
- package/dist/tools/delegate.js +35 -26
- package/dist/tools/delegate.js.map +1 -0
- package/dist/tools/delegate.txt +46 -0
- package/package.json +7 -4
package/README.md
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# @awcp/mcp
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server that provides workspace delegation tools for AI agents.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package enables AI agents (like Claude) to delegate workspaces to remote Executor agents via the AWCP protocol. It automatically manages a Delegator Daemon and provides three MCP tools:
|
|
8
|
+
|
|
9
|
+
- **`delegate`** — Delegate a workspace to a remote Executor
|
|
10
|
+
- **`delegate_output`** — Get delegation status/results
|
|
11
|
+
- **`delegate_cancel`** — Cancel active delegations
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @awcp/mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or use directly with npx:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @awcp/mcp --peers http://executor:4001
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Claude Desktop Configuration
|
|
28
|
+
|
|
29
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcpServers": {
|
|
34
|
+
"awcp": {
|
|
35
|
+
"command": "npx",
|
|
36
|
+
"args": ["@awcp/mcp", "--peers", "http://localhost:10200"]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Restart Claude Desktop, then you can ask:
|
|
43
|
+
|
|
44
|
+
> "Use the delegate tool to ask another agent to add tests to ./src"
|
|
45
|
+
|
|
46
|
+
### Multiple Executors
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"awcp": {
|
|
52
|
+
"command": "npx",
|
|
53
|
+
"args": [
|
|
54
|
+
"@awcp/mcp",
|
|
55
|
+
"--peers", "http://coding-agent:10200,http://review-agent:10201"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## CLI Options
|
|
63
|
+
|
|
64
|
+
### Daemon Options
|
|
65
|
+
|
|
66
|
+
| Option | Default | Description |
|
|
67
|
+
|--------|---------|-------------|
|
|
68
|
+
| `--daemon-url URL` | (auto-start) | Use existing Delegator Daemon instead of auto-starting |
|
|
69
|
+
| `--port PORT` | `3100` | Port for auto-started daemon |
|
|
70
|
+
|
|
71
|
+
### Peer Discovery
|
|
72
|
+
|
|
73
|
+
| Option | Default | Description |
|
|
74
|
+
|--------|---------|-------------|
|
|
75
|
+
| `--peers URL,...` | (none) | Comma-separated list of Executor base URLs |
|
|
76
|
+
|
|
77
|
+
The `--peers` flag fetches A2A Agent Cards at startup, providing the LLM with context about available executors and their capabilities.
|
|
78
|
+
|
|
79
|
+
### Export Options
|
|
80
|
+
|
|
81
|
+
| Option | Default | Description |
|
|
82
|
+
|--------|---------|-------------|
|
|
83
|
+
| `--exports-dir DIR` | `~/.awcp/exports` | Directory for workspace exports |
|
|
84
|
+
| `--export-strategy TYPE` | `symlink` | Export strategy: `symlink`, `bind`, or `worktree` |
|
|
85
|
+
|
|
86
|
+
### Transport Options
|
|
87
|
+
|
|
88
|
+
| Option | Default | Description |
|
|
89
|
+
|--------|---------|-------------|
|
|
90
|
+
| `--transport TYPE` | `archive` | Transport type: `archive` or `sshfs` |
|
|
91
|
+
|
|
92
|
+
**Archive transport** (default) — Best for remote executors over network:
|
|
93
|
+
| Option | Default | Description |
|
|
94
|
+
|--------|---------|-------------|
|
|
95
|
+
| `--temp-dir DIR` | `~/.awcp/temp` | Temp directory for archives |
|
|
96
|
+
|
|
97
|
+
**SSHFS transport** — Best for local executors with low latency:
|
|
98
|
+
| Option | Default | Description |
|
|
99
|
+
|--------|---------|-------------|
|
|
100
|
+
| `--ssh-ca-key PATH` | (required) | CA private key path |
|
|
101
|
+
| `--ssh-host HOST` | `localhost` | SSH server host |
|
|
102
|
+
| `--ssh-port PORT` | `22` | SSH server port |
|
|
103
|
+
| `--ssh-user USER` | (current user) | SSH username |
|
|
104
|
+
| `--ssh-key-dir DIR` | `~/.awcp/keys` | SSH key directory |
|
|
105
|
+
|
|
106
|
+
### Admission Control
|
|
107
|
+
|
|
108
|
+
| Option | Default | Description |
|
|
109
|
+
|--------|---------|-------------|
|
|
110
|
+
| `--max-total-bytes N` | `100MB` | Max workspace size |
|
|
111
|
+
| `--max-file-count N` | `10000` | Max number of files |
|
|
112
|
+
| `--max-single-file-bytes N` | `50MB` | Max single file size |
|
|
113
|
+
|
|
114
|
+
### Delegation Defaults
|
|
115
|
+
|
|
116
|
+
| Option | Default | Description |
|
|
117
|
+
|--------|---------|-------------|
|
|
118
|
+
| `--default-ttl SECONDS` | `3600` | Default lease duration |
|
|
119
|
+
| `--default-access-mode MODE` | `rw` | Default access: `ro` or `rw` |
|
|
120
|
+
|
|
121
|
+
## MCP Tools
|
|
122
|
+
|
|
123
|
+
### `delegate`
|
|
124
|
+
|
|
125
|
+
Delegate a workspace to a remote Executor for collaborative task execution.
|
|
126
|
+
|
|
127
|
+
**Parameters:**
|
|
128
|
+
|
|
129
|
+
| Parameter | Type | Required | Description |
|
|
130
|
+
|-----------|------|----------|-------------|
|
|
131
|
+
| `description` | string | ✓ | Short task description (for logs) |
|
|
132
|
+
| `prompt` | string | ✓ | Full task instructions |
|
|
133
|
+
| `workspace_dir` | string | ✓ | Local directory path to delegate |
|
|
134
|
+
| `peer_url` | string | ✓ | Executor's AWCP endpoint URL |
|
|
135
|
+
| `ttl_seconds` | number | | Lease duration (default: 3600) |
|
|
136
|
+
| `access_mode` | `ro` \| `rw` | | Access mode (default: rw) |
|
|
137
|
+
| `background` | boolean | | If true, returns immediately |
|
|
138
|
+
|
|
139
|
+
**Example:**
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
delegate(
|
|
143
|
+
description: "Add unit tests",
|
|
144
|
+
prompt: "Add comprehensive unit tests for UserService class...",
|
|
145
|
+
workspace_dir: "/Users/me/project",
|
|
146
|
+
peer_url: "http://localhost:10200/awcp",
|
|
147
|
+
background: true
|
|
148
|
+
)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `delegate_output`
|
|
152
|
+
|
|
153
|
+
Get delegation status or wait for completion.
|
|
154
|
+
|
|
155
|
+
**Parameters:**
|
|
156
|
+
|
|
157
|
+
| Parameter | Type | Required | Description |
|
|
158
|
+
|-----------|------|----------|-------------|
|
|
159
|
+
| `delegation_id` | string | ✓ | Delegation ID |
|
|
160
|
+
| `block` | boolean | | Wait for completion if still running |
|
|
161
|
+
| `timeout` | number | | Max seconds to wait (default: 60) |
|
|
162
|
+
|
|
163
|
+
**Example:**
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
delegate_output(
|
|
167
|
+
delegation_id: "del_abc123",
|
|
168
|
+
block: true,
|
|
169
|
+
timeout: 120
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `delegate_cancel`
|
|
174
|
+
|
|
175
|
+
Cancel active delegations.
|
|
176
|
+
|
|
177
|
+
**Parameters:**
|
|
178
|
+
|
|
179
|
+
| Parameter | Type | Required | Description |
|
|
180
|
+
|-----------|------|----------|-------------|
|
|
181
|
+
| `delegation_id` | string | | Specific delegation to cancel |
|
|
182
|
+
| `all` | boolean | | Cancel all active delegations |
|
|
183
|
+
|
|
184
|
+
**Example:**
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
delegate_cancel(delegation_id: "del_abc123")
|
|
188
|
+
# or
|
|
189
|
+
delegate_cancel(all: true)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Programmatic Usage
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { createAwcpMcpServer } from '@awcp/mcp';
|
|
196
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
197
|
+
|
|
198
|
+
const server = createAwcpMcpServer({
|
|
199
|
+
daemonUrl: 'http://localhost:3100',
|
|
200
|
+
peers: {
|
|
201
|
+
peers: [
|
|
202
|
+
{ url: 'http://localhost:10200', awcpUrl: 'http://localhost:10200/awcp', card: agentCard }
|
|
203
|
+
],
|
|
204
|
+
summary: '...'
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const transport = new StdioServerTransport();
|
|
209
|
+
await server.connect(transport);
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Configuration Examples
|
|
213
|
+
|
|
214
|
+
### Basic Local Development
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
awcp-mcp --peers http://localhost:10200
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Production with Custom Limits
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
awcp-mcp \
|
|
224
|
+
--peers http://agent1.example.com:10200,http://agent2.example.com:10200 \
|
|
225
|
+
--max-total-bytes 500000000 \
|
|
226
|
+
--max-file-count 50000 \
|
|
227
|
+
--default-ttl 7200
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### SSHFS Transport (Low Latency)
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
awcp-mcp \
|
|
234
|
+
--peers http://localhost:10200 \
|
|
235
|
+
--transport sshfs \
|
|
236
|
+
--ssh-ca-key ~/.awcp/ca
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Claude Desktop with Full Options
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"mcpServers": {
|
|
244
|
+
"awcp": {
|
|
245
|
+
"command": "npx",
|
|
246
|
+
"args": [
|
|
247
|
+
"@awcp/mcp",
|
|
248
|
+
"--peers", "http://localhost:10200",
|
|
249
|
+
"--port", "3100",
|
|
250
|
+
"--exports-dir", "/tmp/awcp/exports",
|
|
251
|
+
"--temp-dir", "/tmp/awcp/temp",
|
|
252
|
+
"--max-total-bytes", "200000000",
|
|
253
|
+
"--default-ttl", "7200"
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## How It Works
|
|
261
|
+
|
|
262
|
+
1. **Startup**: MCP server starts and auto-launches Delegator Daemon
|
|
263
|
+
2. **Peer Discovery**: Fetches Agent Cards from `--peers` URLs
|
|
264
|
+
3. **Tool Registration**: Registers delegation tools with peer context
|
|
265
|
+
4. **Delegation Flow**:
|
|
266
|
+
- LLM calls `delegate` tool
|
|
267
|
+
- Daemon exports workspace and sends INVITE to Executor
|
|
268
|
+
- Executor mounts/extracts workspace and executes task
|
|
269
|
+
- Results are returned via SSE events
|
|
270
|
+
- Workspace changes are synced back (Archive transport)
|
|
271
|
+
|
|
272
|
+
## Troubleshooting
|
|
273
|
+
|
|
274
|
+
### "Daemon not responding"
|
|
275
|
+
|
|
276
|
+
Check if port 3100 is available or specify a different port:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
awcp-mcp --port 3200
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### "Agent Card not found"
|
|
283
|
+
|
|
284
|
+
Ensure the Executor is running and accessible:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
curl http://localhost:10200/.well-known/agent-card.json
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### "Workspace too large"
|
|
291
|
+
|
|
292
|
+
Increase limits or exclude large directories:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
awcp-mcp --max-total-bytes 500000000
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Note: `node_modules/` and `.git/` are automatically excluded.
|
|
299
|
+
|
|
300
|
+
## Related
|
|
301
|
+
|
|
302
|
+
- [@awcp/sdk](../sdk) — Delegator and Executor implementations
|
|
303
|
+
- [@awcp/core](../core) — Protocol types and errors
|
|
304
|
+
- [@awcp/transport-archive](../transport-archive) — Archive transport
|
|
305
|
+
- [@awcp/transport-sshfs](../transport-sshfs) — SSHFS transport
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-start Delegator Daemon
|
|
3
|
+
*
|
|
4
|
+
* Automatically starts the Delegator Daemon if not running.
|
|
5
|
+
* Used by MCP server to provide zero-config experience.
|
|
6
|
+
*/
|
|
7
|
+
import type { AccessMode } from '@awcp/sdk';
|
|
8
|
+
import { type DaemonInstance } from '@awcp/sdk/delegator/daemon';
|
|
9
|
+
/**
|
|
10
|
+
* Options for auto-starting the daemon
|
|
11
|
+
*/
|
|
12
|
+
export interface AutoDaemonOptions {
|
|
13
|
+
/** Port for the daemon (default: 3100) */
|
|
14
|
+
port?: number;
|
|
15
|
+
/** Timeout in ms to wait for daemon to start (default: 10000) */
|
|
16
|
+
startTimeout?: number;
|
|
17
|
+
/** Directory for workspace exports (default: ~/.awcp/exports) */
|
|
18
|
+
exportsDir?: string;
|
|
19
|
+
/** Export strategy: symlink, bind, worktree (default: symlink) */
|
|
20
|
+
exportStrategy?: 'symlink' | 'bind' | 'worktree';
|
|
21
|
+
/** Transport type (default: archive) */
|
|
22
|
+
transport?: 'archive' | 'sshfs';
|
|
23
|
+
/** Maximum total bytes for workspace (default: 100MB) */
|
|
24
|
+
maxTotalBytes?: number;
|
|
25
|
+
/** Maximum file count (default: 10000) */
|
|
26
|
+
maxFileCount?: number;
|
|
27
|
+
/** Maximum single file size in bytes (default: 50MB) */
|
|
28
|
+
maxSingleFileBytes?: number;
|
|
29
|
+
/** Default TTL in seconds (default: 3600) */
|
|
30
|
+
defaultTtl?: number;
|
|
31
|
+
/** Default access mode: ro or rw (default: rw) */
|
|
32
|
+
defaultAccessMode?: AccessMode;
|
|
33
|
+
/** Directory for temp files (default: ~/.awcp/temp) */
|
|
34
|
+
tempDir?: string;
|
|
35
|
+
/** Path to CA private key (required for SSHFS) */
|
|
36
|
+
sshCaKey?: string;
|
|
37
|
+
/** SSH server host (default: localhost) */
|
|
38
|
+
sshHost?: string;
|
|
39
|
+
/** SSH server port (default: 22) */
|
|
40
|
+
sshPort?: number;
|
|
41
|
+
/** SSH username (default: current user) */
|
|
42
|
+
sshUser?: string;
|
|
43
|
+
/** Directory for SSH keys (default: ~/.awcp/keys) */
|
|
44
|
+
sshKeyDir?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Start daemon in-process
|
|
48
|
+
*
|
|
49
|
+
* This starts the daemon in the same process as the MCP server.
|
|
50
|
+
* Simpler but means the daemon dies when MCP server dies.
|
|
51
|
+
*/
|
|
52
|
+
export declare function startInProcessDaemon(options?: AutoDaemonOptions): Promise<DaemonInstance>;
|
|
53
|
+
/**
|
|
54
|
+
* Ensure daemon is running, starting it if necessary
|
|
55
|
+
*
|
|
56
|
+
* Returns the daemon URL. If daemon is already running, just returns the URL.
|
|
57
|
+
* If not running, starts it in-process and returns the URL.
|
|
58
|
+
*/
|
|
59
|
+
export declare function ensureDaemonRunning(options?: AutoDaemonOptions): Promise<{
|
|
60
|
+
url: string;
|
|
61
|
+
daemon?: DaemonInstance;
|
|
62
|
+
}>;
|
|
63
|
+
//# sourceMappingURL=auto-daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-daemon.d.ts","sourceRoot":"","sources":["../src/auto-daemon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAmB,UAAU,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGvF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAEhC,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,cAAc,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;IAGjD,wCAAwC;IACxC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAGhC,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAG5B,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAG/B,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsGD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAazB;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,CA6BnD"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-start Delegator Daemon
|
|
3
|
+
*
|
|
4
|
+
* Automatically starts the Delegator Daemon if not running.
|
|
5
|
+
* Used by MCP server to provide zero-config experience.
|
|
6
|
+
*/
|
|
7
|
+
import { mkdir } from 'node:fs/promises';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
import { startDelegatorDaemon } from '@awcp/sdk/delegator/daemon';
|
|
11
|
+
import { ArchiveTransport } from '@awcp/transport-archive';
|
|
12
|
+
/**
|
|
13
|
+
* Default AWCP directory
|
|
14
|
+
*/
|
|
15
|
+
function getAwcpDir() {
|
|
16
|
+
return process.env.AWCP_HOME || join(homedir(), '.awcp');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if daemon is running by hitting health endpoint
|
|
20
|
+
*/
|
|
21
|
+
async function isDaemonRunning(url) {
|
|
22
|
+
try {
|
|
23
|
+
const res = await fetch(`${url}/health`, { signal: AbortSignal.timeout(2000) });
|
|
24
|
+
return res.ok;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Wait for daemon to become healthy
|
|
32
|
+
*/
|
|
33
|
+
async function waitForDaemon(url, timeoutMs) {
|
|
34
|
+
const start = Date.now();
|
|
35
|
+
while (Date.now() - start < timeoutMs) {
|
|
36
|
+
if (await isDaemonRunning(url)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create default delegator config
|
|
45
|
+
*/
|
|
46
|
+
async function createDefaultConfig(options) {
|
|
47
|
+
const awcpDir = getAwcpDir();
|
|
48
|
+
const exportsDir = options.exportsDir || join(awcpDir, 'exports');
|
|
49
|
+
const tempDir = options.tempDir || join(awcpDir, 'temp');
|
|
50
|
+
// Create transport based on type
|
|
51
|
+
let transport;
|
|
52
|
+
if (options.transport === 'sshfs') {
|
|
53
|
+
// Dynamically import SSHFS transport to avoid requiring it when not used
|
|
54
|
+
const { SshfsTransport } = await import('@awcp/transport-sshfs');
|
|
55
|
+
if (!options.sshCaKey) {
|
|
56
|
+
throw new Error('SSHFS transport requires --ssh-ca-key option');
|
|
57
|
+
}
|
|
58
|
+
transport = new SshfsTransport({
|
|
59
|
+
delegator: {
|
|
60
|
+
caKeyPath: options.sshCaKey,
|
|
61
|
+
keyDir: options.sshKeyDir || join(awcpDir, 'keys'),
|
|
62
|
+
host: options.sshHost || 'localhost',
|
|
63
|
+
port: options.sshPort || 22,
|
|
64
|
+
user: options.sshUser || process.env.USER,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Default to Archive transport (no SSHFS setup required)
|
|
70
|
+
transport = new ArchiveTransport({
|
|
71
|
+
delegator: {
|
|
72
|
+
tempDir,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
export: {
|
|
78
|
+
baseDir: exportsDir,
|
|
79
|
+
strategy: options.exportStrategy || 'symlink',
|
|
80
|
+
},
|
|
81
|
+
transport,
|
|
82
|
+
admission: {
|
|
83
|
+
maxTotalBytes: options.maxTotalBytes,
|
|
84
|
+
maxFileCount: options.maxFileCount,
|
|
85
|
+
maxSingleFileBytes: options.maxSingleFileBytes,
|
|
86
|
+
},
|
|
87
|
+
defaults: {
|
|
88
|
+
ttlSeconds: options.defaultTtl,
|
|
89
|
+
accessMode: options.defaultAccessMode,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Ensure AWCP directories exist
|
|
95
|
+
*/
|
|
96
|
+
async function ensureDirectories(options) {
|
|
97
|
+
const awcpDir = getAwcpDir();
|
|
98
|
+
const exportsDir = options.exportsDir || join(awcpDir, 'exports');
|
|
99
|
+
const tempDir = options.tempDir || join(awcpDir, 'temp');
|
|
100
|
+
await mkdir(awcpDir, { recursive: true });
|
|
101
|
+
await mkdir(exportsDir, { recursive: true });
|
|
102
|
+
await mkdir(tempDir, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Start daemon in-process
|
|
106
|
+
*
|
|
107
|
+
* This starts the daemon in the same process as the MCP server.
|
|
108
|
+
* Simpler but means the daemon dies when MCP server dies.
|
|
109
|
+
*/
|
|
110
|
+
export async function startInProcessDaemon(options = {}) {
|
|
111
|
+
const port = options.port ?? 3100;
|
|
112
|
+
await ensureDirectories(options);
|
|
113
|
+
const config = await createDefaultConfig(options);
|
|
114
|
+
const daemon = await startDelegatorDaemon({
|
|
115
|
+
port,
|
|
116
|
+
delegator: config,
|
|
117
|
+
});
|
|
118
|
+
return daemon;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Ensure daemon is running, starting it if necessary
|
|
122
|
+
*
|
|
123
|
+
* Returns the daemon URL. If daemon is already running, just returns the URL.
|
|
124
|
+
* If not running, starts it in-process and returns the URL.
|
|
125
|
+
*/
|
|
126
|
+
export async function ensureDaemonRunning(options = {}) {
|
|
127
|
+
const port = options.port ?? 3100;
|
|
128
|
+
const url = `http://localhost:${port}`;
|
|
129
|
+
const startTimeout = options.startTimeout ?? 10000;
|
|
130
|
+
// Check if already running
|
|
131
|
+
if (await isDaemonRunning(url)) {
|
|
132
|
+
console.error(`[AWCP] Daemon already running at ${url}`);
|
|
133
|
+
return { url };
|
|
134
|
+
}
|
|
135
|
+
// Start daemon in-process
|
|
136
|
+
console.error(`[AWCP] Starting Delegator Daemon on port ${port}...`);
|
|
137
|
+
try {
|
|
138
|
+
const daemon = await startInProcessDaemon(options);
|
|
139
|
+
// Wait for it to be ready
|
|
140
|
+
if (await waitForDaemon(url, startTimeout)) {
|
|
141
|
+
console.error(`[AWCP] Daemon started successfully at ${url}`);
|
|
142
|
+
return { url, daemon };
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw new Error('Daemon started but health check failed');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
throw new Error(`Failed to start Delegator Daemon: ${error instanceof Error ? error.message : String(error)}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=auto-daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-daemon.js","sourceRoot":"","sources":["../src/auto-daemon.ts"],"names":[],"mappings":"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"}
|
package/dist/bin/awcp-mcp.d.ts
CHANGED
|
@@ -3,27 +3,12 @@
|
|
|
3
3
|
* AWCP MCP Server CLI
|
|
4
4
|
*
|
|
5
5
|
* Starts an MCP server that provides AWCP delegation tools.
|
|
6
|
-
*
|
|
6
|
+
* Automatically starts the Delegator Daemon if not already running.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
|
9
|
-
* awcp-mcp [
|
|
9
|
+
* awcp-mcp [options]
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
* --daemon-url URL of Delegator Daemon (default: http://localhost:3100)
|
|
13
|
-
* --help Show this help message
|
|
14
|
-
*
|
|
15
|
-
* Example:
|
|
16
|
-
* awcp-mcp --daemon-url http://localhost:3100
|
|
17
|
-
*
|
|
18
|
-
* Claude Desktop config (claude_desktop_config.json):
|
|
19
|
-
* {
|
|
20
|
-
* "mcpServers": {
|
|
21
|
-
* "awcp": {
|
|
22
|
-
* "command": "npx",
|
|
23
|
-
* "args": ["awcp-mcp", "--daemon-url", "http://localhost:3100"]
|
|
24
|
-
* }
|
|
25
|
-
* }
|
|
26
|
-
* }
|
|
11
|
+
* See --help for all options.
|
|
27
12
|
*/
|
|
28
13
|
export {};
|
|
29
14
|
//# sourceMappingURL=awcp-mcp.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awcp-mcp.d.ts","sourceRoot":"","sources":["../../src/bin/awcp-mcp.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"awcp-mcp.d.ts","sourceRoot":"","sources":["../../src/bin/awcp-mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
|