agent-pool-mcp 1.2.0 → 1.3.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/README.md +68 -6
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/server.js +74 -2
- package/src/tool-definitions.js +20 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# agent-pool-mcp
|
|
2
2
|
|
|
3
|
-
**MCP server for multi-agent orchestration** — parallel task delegation and cross-model peer review via [Gemini CLI](https://github.com/google-gemini/gemini-cli).
|
|
3
|
+
**MCP server for multi-agent orchestration** — parallel task delegation, sequential pipelines, cron scheduling, and cross-model peer review via [Gemini CLI](https://github.com/google-gemini/gemini-cli).
|
|
4
4
|
|
|
5
5
|
> Developed by [RND-PRO](https://rnd-pro.com)
|
|
6
6
|
|
|
@@ -38,6 +38,60 @@ When the primary agent and Gemini workers are **different foundation models** (e
|
|
|
38
38
|
- **`get_task_result`** — Poll task status, retrieve results, and see live progress (last 200 tool/message events).
|
|
39
39
|
- **`cancel_task`** — Kill a running task and its entire process group immediately.
|
|
40
40
|
|
|
41
|
+
### 🔗 Pipelines — Sequential Task Chains
|
|
42
|
+
Define multi-step workflows where agents execute sequentially, with automatic handoff:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
┌─ frontend ─┐
|
|
46
|
+
research ─┤ ├── deploy
|
|
47
|
+
└─ backend ─┘
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- **`create_pipeline`** — Define a pipeline with named steps, triggers, and timeouts.
|
|
51
|
+
- **`run_pipeline`** — Start executing a pipeline. A detached daemon manages the lifecycle.
|
|
52
|
+
- **`list_pipelines`** — See all definitions, active runs, and recent completions.
|
|
53
|
+
- **`get_pipeline_status`** — Step-by-step status with emoji indicators.
|
|
54
|
+
- **`cancel_pipeline`** — Stop a running pipeline and kill active step processes.
|
|
55
|
+
|
|
56
|
+
**Agent Signals** (called BY agents running inside pipeline steps):
|
|
57
|
+
- **`signal_step_complete`** — Mark the current step as done. Accepts optional output and `run_id`.
|
|
58
|
+
- **`bounce_back`** — Return task to a previous step with feedback (e.g. "data incomplete"). Supports `maxBounces` limit.
|
|
59
|
+
|
|
60
|
+
**Triggers:**
|
|
61
|
+
|
|
62
|
+
| Trigger | Description |
|
|
63
|
+
|---------|-------------|
|
|
64
|
+
| `on_complete` | Start when a specific step succeeds |
|
|
65
|
+
| `on_complete_all` | Fan-in: start when ALL listed steps succeed |
|
|
66
|
+
| `on_file` | Start when a file appears and the producing process exits |
|
|
67
|
+
| Auto-fallback | Process death without signal → auto-complete/fail |
|
|
68
|
+
|
|
69
|
+
**Example — 3-step pipeline:**
|
|
70
|
+
```javascript
|
|
71
|
+
// Agent creates the pipeline
|
|
72
|
+
create_pipeline({
|
|
73
|
+
name: "article-workflow",
|
|
74
|
+
steps: [
|
|
75
|
+
{ name: "research", prompt: "Research the topic and write notes to research.md" },
|
|
76
|
+
{ name: "draft", prompt: "Read research.md and write article draft" },
|
|
77
|
+
{ name: "review", prompt: "Review the draft for accuracy and style" }
|
|
78
|
+
]
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// Agent starts execution — daemon handles the rest
|
|
82
|
+
run_pipeline({ pipeline_id: "article-workflow" })
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### ⏰ Cron Scheduler
|
|
86
|
+
Schedule agents to run automatically on a cron schedule:
|
|
87
|
+
|
|
88
|
+
- **`schedule_task`** — Schedule a Gemini CLI agent with cron expression (e.g. `0 9 * * MON-FRI`).
|
|
89
|
+
- **`list_schedules`** — See all schedules with next run times and daemon status.
|
|
90
|
+
- **`cancel_schedule`** — Remove a schedule. Daemon auto-exits when no schedules remain.
|
|
91
|
+
- **`get_scheduled_results`** — Retrieve results from past scheduled executions.
|
|
92
|
+
|
|
93
|
+
The scheduler runs as a **detached daemon** that survives IDE/CLI restarts. It uses atomic file locks to prevent duplicate execution when multiple clients are connected.
|
|
94
|
+
|
|
41
95
|
### 📋 3-Tier Skill System
|
|
42
96
|
Skills are Markdown files with YAML frontmatter that extend agent behavior. Agent-pool manages skills in three tiers:
|
|
43
97
|
1. **Project**: `.gemini/skills/` (local to repo, takes precedence).
|
|
@@ -210,11 +264,16 @@ src/
|
|
|
210
264
|
│ ├── consult.js ← Peer review via Gemini CLI
|
|
211
265
|
│ ├── results.js ← Task store + result formatting (TTL cleanup, ring buffer)
|
|
212
266
|
│ └── skills.js ← 3-tier skill management (project/global/built-in)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
267
|
+
├── runner/
|
|
268
|
+
│ ├── config.js ← Runner config loader (local/SSH)
|
|
269
|
+
│ ├── gemini-runner.js ← Process spawning (streaming JSON, depth tracking)
|
|
270
|
+
│ ├── process-manager.js ← PID tracking, system load awareness, group kill
|
|
271
|
+
│ └── ssh.js ← Shell escaping, remote PID tracking
|
|
272
|
+
└── scheduler/
|
|
273
|
+
├── cron.js ← Minimal cron expression parser (zero-dependency)
|
|
274
|
+
├── daemon.js ← Detached daemon: schedule ticks + pipeline lifecycle
|
|
275
|
+
├── pipeline.js ← Pipeline CRUD, run state, signals, bounce-back
|
|
276
|
+
└── scheduler.js ← Schedule management + daemon spawning
|
|
218
277
|
```
|
|
219
278
|
|
|
220
279
|
**Process management:**
|
|
@@ -222,7 +281,10 @@ src/
|
|
|
222
281
|
- **TTL Cleanup**: Completed task results are purged from memory after 10 minutes.
|
|
223
282
|
- **Live Events**: Progress polling uses a ring buffer to show the latest activity without overwhelming context.
|
|
224
283
|
- **Depth Tracking**: Nested orchestration support with optional `AGENT_POOL_MAX_DEPTH` limit.
|
|
284
|
+
- **Adaptive Polling**: Pipeline daemon uses 3s intervals when active, 30s when idle.
|
|
285
|
+
- **File-Based Communication**: Pipeline agents communicate through `.agent/runs/` JSON files — each Gemini process has its own MCP server instance but shares state via filesystem.
|
|
225
286
|
|
|
226
287
|
## License
|
|
227
288
|
|
|
228
289
|
MIT
|
|
290
|
+
|
package/index.js
CHANGED
|
@@ -33,6 +33,6 @@ async function startServer() {
|
|
|
33
33
|
const server = createServer();
|
|
34
34
|
const transport = new StdioServerTransport();
|
|
35
35
|
await server.connect(transport);
|
|
36
|
-
console.error('[agent-pool] MCP server v1.2.
|
|
36
|
+
console.error('[agent-pool] MCP server v1.2.1 started');
|
|
37
37
|
}
|
|
38
38
|
|
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
9
10
|
import {
|
|
10
11
|
ListToolsRequestSchema,
|
|
11
12
|
CallToolRequestSchema,
|
|
13
|
+
ListResourcesRequestSchema,
|
|
14
|
+
ReadResourceRequestSchema,
|
|
12
15
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
13
16
|
import { randomUUID } from 'node:crypto';
|
|
14
17
|
|
|
@@ -107,10 +110,34 @@ export function createServer() {
|
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
const server = new Server(
|
|
110
|
-
{ name: 'agent-pool', version: '1.2.
|
|
111
|
-
{ capabilities: { tools: {} } },
|
|
113
|
+
{ name: 'agent-pool', version: '1.2.1' },
|
|
114
|
+
{ capabilities: { tools: {}, resources: {} } },
|
|
112
115
|
);
|
|
113
116
|
|
|
117
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
118
|
+
resources: [{
|
|
119
|
+
uri: 'agent-pool://guide',
|
|
120
|
+
name: 'Usage Guide',
|
|
121
|
+
description: 'Comprehensive guide for agent-pool',
|
|
122
|
+
mimeType: 'text/markdown',
|
|
123
|
+
}],
|
|
124
|
+
}));
|
|
125
|
+
|
|
126
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
127
|
+
if (request.params.uri === 'agent-pool://guide') {
|
|
128
|
+
const guidePath = path.resolve(__dirname, '..', 'GUIDE.md');
|
|
129
|
+
const content = fs.readFileSync(guidePath, 'utf-8');
|
|
130
|
+
return {
|
|
131
|
+
contents: [{
|
|
132
|
+
uri: request.params.uri,
|
|
133
|
+
mimeType: 'text/markdown',
|
|
134
|
+
text: content,
|
|
135
|
+
}],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
throw new Error(`Resource not found: ${request.params.uri}`);
|
|
139
|
+
});
|
|
140
|
+
|
|
114
141
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
115
142
|
tools: TOOL_DEFINITIONS,
|
|
116
143
|
}));
|
|
@@ -155,6 +182,8 @@ export function createServer() {
|
|
|
155
182
|
response = handleCancelSchedule(args); break;
|
|
156
183
|
case 'get_scheduled_results':
|
|
157
184
|
response = handleGetScheduledResults(args); break;
|
|
185
|
+
case 'get_usage_guide':
|
|
186
|
+
response = handleGetUsageGuide(args); break;
|
|
158
187
|
case 'create_pipeline':
|
|
159
188
|
response = handleCreatePipeline(args); break;
|
|
160
189
|
case 'run_pipeline':
|
|
@@ -169,6 +198,8 @@ export function createServer() {
|
|
|
169
198
|
response = handleSignalStepComplete(args); break;
|
|
170
199
|
case 'bounce_back':
|
|
171
200
|
response = handleBounceBack(args); break;
|
|
201
|
+
case 'get_usage_guide':
|
|
202
|
+
response = handleGetUsageGuide(args); break;
|
|
172
203
|
default:
|
|
173
204
|
response = { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };
|
|
174
205
|
}
|
|
@@ -616,3 +647,44 @@ function handleBounceBack(args) {
|
|
|
616
647
|
}
|
|
617
648
|
}
|
|
618
649
|
|
|
650
|
+
/** @param {object} args */
|
|
651
|
+
function handleGetUsageGuide(args) {
|
|
652
|
+
const guidePath = path.resolve(__dirname, '..', 'GUIDE.md');
|
|
653
|
+
if (!fs.existsSync(guidePath)) {
|
|
654
|
+
return { content: [{ type: 'text', text: 'Guide not found.' }], isError: true };
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const fullContent = fs.readFileSync(guidePath, 'utf-8');
|
|
658
|
+
|
|
659
|
+
if (!args.topic) {
|
|
660
|
+
return { content: [{ type: 'text', text: fullContent }] };
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const topicLower = args.topic.toLowerCase();
|
|
664
|
+
const lines = fullContent.split('\n');
|
|
665
|
+
let inTopic = false;
|
|
666
|
+
let topicContent = [];
|
|
667
|
+
|
|
668
|
+
for (const line of lines) {
|
|
669
|
+
if (line.toLowerCase().startsWith(`## ${topicLower}`)) {
|
|
670
|
+
inTopic = true;
|
|
671
|
+
topicContent.push(line);
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (inTopic && line.startsWith('## ')) {
|
|
676
|
+
break; // End of section
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (inTopic) {
|
|
680
|
+
topicContent.push(line);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (topicContent.length === 0) {
|
|
685
|
+
return { content: [{ type: 'text', text: `Topic '${args.topic}' not found in the guide.\n\nAvailable topics: delegation, pipelines, scheduling, skills, peer-review, sessions.` }] };
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return { content: [{ type: 'text', text: topicContent.join('\n').trim() }] };
|
|
689
|
+
}
|
|
690
|
+
|
package/src/tool-definitions.js
CHANGED
|
@@ -6,6 +6,26 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
export const TOOL_DEFINITIONS = [
|
|
9
|
+
{
|
|
10
|
+
name: 'get_usage_guide',
|
|
11
|
+
description: [
|
|
12
|
+
'Get the comprehensive usage guide for agent-pool with examples and best practices.',
|
|
13
|
+
'Call this FIRST when planning how to use agent-pool tools for parallel work, pipelines, or scheduling.',
|
|
14
|
+
'Returns practical examples for each feature area.',
|
|
15
|
+
'',
|
|
16
|
+
'Available topics: delegation, pipelines, scheduling, skills, peer-review, sessions.',
|
|
17
|
+
'Omit topic to get the full guide.',
|
|
18
|
+
].join('\n'),
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
topic: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Optional topic filter: delegation, pipelines, scheduling, skills, peer-review, sessions',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
9
29
|
{
|
|
10
30
|
name: 'delegate_task',
|
|
11
31
|
description: [
|