agent-orchestrator-mcp 1.0.0__tar.gz
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.
- agent_orchestrator_mcp-1.0.0/.github/workflows/mcp-smithery-publish.yml +26 -0
- agent_orchestrator_mcp-1.0.0/.gitignore +10 -0
- agent_orchestrator_mcp-1.0.0/.mcp.json +223 -0
- agent_orchestrator_mcp-1.0.0/LICENSE +21 -0
- agent_orchestrator_mcp-1.0.0/PKG-INFO +36 -0
- agent_orchestrator_mcp-1.0.0/README.md +64 -0
- agent_orchestrator_mcp-1.0.0/package.json +18 -0
- agent_orchestrator_mcp-1.0.0/pyproject.toml +24 -0
- agent_orchestrator_mcp-1.0.0/server.py +486 -0
- agent_orchestrator_mcp-1.0.0/smithery.yaml +132 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish to Smithery
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
name: Publish MCP Server to Smithery
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout repository
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Setup Node.js
|
|
18
|
+
uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: '20'
|
|
21
|
+
|
|
22
|
+
- name: Publish to Smithery
|
|
23
|
+
env:
|
|
24
|
+
SMITHERY_API_KEY: ${{ secrets.SMITHERY_API_KEY }}
|
|
25
|
+
run: |
|
|
26
|
+
npx @smithery/cli mcp publish "https://github.com/${{ github.repository }}" -n nicholastempleman/${{ github.event.repository.name }}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-orchestrator-mcp",
|
|
3
|
+
"description": "> **By [MEOK AI Labs](https://meok.ai)** \u2014 Multi-agent task management: create agents, delegate tasks with trust-based routing, coordinate file",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"tools": [
|
|
6
|
+
{
|
|
7
|
+
"name": "create_agent",
|
|
8
|
+
"description": "Create a new agent with a name, role, department, and capabilities.",
|
|
9
|
+
"parameters": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": {
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"role": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"department": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"capabilities": {
|
|
22
|
+
"type": "array"
|
|
23
|
+
},
|
|
24
|
+
"instructions": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"required": [
|
|
29
|
+
"name",
|
|
30
|
+
"role"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "list_agents",
|
|
36
|
+
"description": "List all registered agents with their trust levels, task counts, and status.",
|
|
37
|
+
"parameters": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"department": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"required": []
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "delegate_task",
|
|
49
|
+
"description": "Delegate a task to a specific agent or auto-route to the best match",
|
|
50
|
+
"parameters": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"task": {
|
|
54
|
+
"type": "string"
|
|
55
|
+
},
|
|
56
|
+
"agent_id": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
},
|
|
59
|
+
"capability": {
|
|
60
|
+
"type": "string"
|
|
61
|
+
},
|
|
62
|
+
"department": {
|
|
63
|
+
"type": "string"
|
|
64
|
+
},
|
|
65
|
+
"priority": {
|
|
66
|
+
"type": "string"
|
|
67
|
+
},
|
|
68
|
+
"care_score": {
|
|
69
|
+
"type": "number"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"required": [
|
|
73
|
+
"task"
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "complete_task",
|
|
79
|
+
"description": "Mark a task as completed (or failed). Updates the agent's trust level",
|
|
80
|
+
"parameters": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"properties": {
|
|
83
|
+
"task_id": {
|
|
84
|
+
"type": "string"
|
|
85
|
+
},
|
|
86
|
+
"agent_id": {
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
"result_summary": {
|
|
90
|
+
"type": "string"
|
|
91
|
+
},
|
|
92
|
+
"care_score": {
|
|
93
|
+
"type": "number"
|
|
94
|
+
},
|
|
95
|
+
"success": {
|
|
96
|
+
"type": "boolean"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"required": [
|
|
100
|
+
"task_id",
|
|
101
|
+
"agent_id",
|
|
102
|
+
"result_summary"
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"name": "acquire_files",
|
|
108
|
+
"description": "Acquire file locks for coordinated multi-agent work. Prevents conflicts",
|
|
109
|
+
"parameters": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"properties": {
|
|
112
|
+
"agent_id": {
|
|
113
|
+
"type": "string"
|
|
114
|
+
},
|
|
115
|
+
"files": {
|
|
116
|
+
"type": "array"
|
|
117
|
+
},
|
|
118
|
+
"task_id": {
|
|
119
|
+
"type": "string"
|
|
120
|
+
},
|
|
121
|
+
"exclusive": {
|
|
122
|
+
"type": "boolean"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"required": [
|
|
126
|
+
"agent_id",
|
|
127
|
+
"files",
|
|
128
|
+
"task_id"
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name": "release_files",
|
|
134
|
+
"description": "Release file locks held by an agent after task completion.",
|
|
135
|
+
"parameters": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"properties": {
|
|
138
|
+
"agent_id": {
|
|
139
|
+
"type": "string"
|
|
140
|
+
},
|
|
141
|
+
"files": {
|
|
142
|
+
"type": "array"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"required": [
|
|
146
|
+
"agent_id",
|
|
147
|
+
"files"
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "start_sprint",
|
|
153
|
+
"description": "Start a focused sprint with named goals and a time limit. Sprints help",
|
|
154
|
+
"parameters": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": {
|
|
157
|
+
"name": {
|
|
158
|
+
"type": "string"
|
|
159
|
+
},
|
|
160
|
+
"goals": {
|
|
161
|
+
"type": "array"
|
|
162
|
+
},
|
|
163
|
+
"duration_minutes": {
|
|
164
|
+
"type": "integer"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"required": [
|
|
168
|
+
"name",
|
|
169
|
+
"goals"
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"name": "complete_sprint",
|
|
175
|
+
"description": "Complete a sprint and record which goals were achieved. Returns the",
|
|
176
|
+
"parameters": {
|
|
177
|
+
"type": "object",
|
|
178
|
+
"properties": {
|
|
179
|
+
"sprint_id": {
|
|
180
|
+
"type": "string"
|
|
181
|
+
},
|
|
182
|
+
"completed_goals": {
|
|
183
|
+
"type": "array"
|
|
184
|
+
},
|
|
185
|
+
"summary": {
|
|
186
|
+
"type": "string"
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"required": [
|
|
190
|
+
"sprint_id"
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "get_dashboard",
|
|
196
|
+
"description": "Get the full orchestration dashboard: agent count, trust averages,",
|
|
197
|
+
"parameters": {
|
|
198
|
+
"type": "object",
|
|
199
|
+
"properties": {},
|
|
200
|
+
"required": []
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "get_task_queue",
|
|
205
|
+
"description": "Get the task queue, optionally filtered by status (assigned/completed/failed)",
|
|
206
|
+
"parameters": {
|
|
207
|
+
"type": "object",
|
|
208
|
+
"properties": {
|
|
209
|
+
"status": {
|
|
210
|
+
"type": "string"
|
|
211
|
+
},
|
|
212
|
+
"agent_id": {
|
|
213
|
+
"type": "string"
|
|
214
|
+
},
|
|
215
|
+
"limit": {
|
|
216
|
+
"type": "integer"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"required": []
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MEOK AI Labs (meok.ai)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-orchestrator-mcp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: MEOK AI Labs — agent-orchestrator-mcp
|
|
5
|
+
Project-URL: Homepage, https://meok.ai
|
|
6
|
+
Project-URL: Repository, https://github.com/CSOAI-ORG/agent-orchestrator-mcp
|
|
7
|
+
Author-email: MEOK AI Labs <nicholas@meok.ai>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 MEOK AI Labs (meok.ai)
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Keywords: agent,ai,mcp,meok,orchestrator
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Operating System :: OS Independent
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
35
|
+
Requires-Python: >=3.10
|
|
36
|
+
Requires-Dist: mcp>=1.0.0
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Agent Orchestrator MCP Server
|
|
2
|
+
|
|
3
|
+
> **By [MEOK AI Labs](https://meok.ai)** — Sovereign AI tools for everyone.
|
|
4
|
+
|
|
5
|
+
Multi-agent task management system for AI applications. Create agents with roles and capabilities, delegate tasks with trust-based routing, coordinate file access, run focused sprints, and monitor performance through a unified dashboard.
|
|
6
|
+
|
|
7
|
+
[](https://mcpize.com/mcp/agent-orchestrator)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://meok.ai)
|
|
10
|
+
|
|
11
|
+
## Tools
|
|
12
|
+
|
|
13
|
+
| Tool | Description |
|
|
14
|
+
|------|-------------|
|
|
15
|
+
| `create_agent` | Create a new agent with name, role, and capabilities |
|
|
16
|
+
| `list_agents` | List all registered agents with trust levels and status |
|
|
17
|
+
| `delegate_task` | Delegate a task to an agent or auto-route to best match |
|
|
18
|
+
| `complete_task` | Mark a task as completed or failed |
|
|
19
|
+
| `acquire_files` | Acquire file locks for coordinated multi-agent work |
|
|
20
|
+
| `release_files` | Release file locks held by an agent |
|
|
21
|
+
| `start_sprint` | Start a focused sprint with goals and a time limit |
|
|
22
|
+
| `complete_sprint` | Complete a sprint and record achieved goals |
|
|
23
|
+
| `get_dashboard` | Get the full orchestration dashboard |
|
|
24
|
+
| `get_task_queue` | Get the task queue filtered by status |
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install mcp
|
|
30
|
+
git clone https://github.com/CSOAI-ORG/agent-orchestrator-mcp.git
|
|
31
|
+
cd agent-orchestrator-mcp
|
|
32
|
+
python server.py
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Claude Desktop Config
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"agent-orchestrator": {
|
|
41
|
+
"command": "python",
|
|
42
|
+
"args": ["server.py"],
|
|
43
|
+
"cwd": "/path/to/agent-orchestrator-mcp"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Pricing
|
|
50
|
+
|
|
51
|
+
| Plan | Price | Requests |
|
|
52
|
+
|------|-------|----------|
|
|
53
|
+
| Free | $0/mo | 100 calls/day, 10 agents max |
|
|
54
|
+
| Pro | $9/mo | Unlimited agents + webhook notifications |
|
|
55
|
+
| Enterprise | Contact us | Custom + LLM-powered routing |
|
|
56
|
+
|
|
57
|
+
[Get on MCPize](https://mcpize.com/mcp/agent-orchestrator)
|
|
58
|
+
|
|
59
|
+
## Part of MEOK AI Labs
|
|
60
|
+
|
|
61
|
+
This is one of 255+ MCP servers by MEOK AI Labs. Browse all at [meok.ai](https://meok.ai) or [GitHub](https://github.com/CSOAI-ORG).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
**MEOK AI Labs** | [meok.ai](https://meok.ai) | nicholas@meok.ai | United Kingdom
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-orchestrator-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MEOK AI Labs — agent orchestrator MCP Server",
|
|
5
|
+
"main": "server.py",
|
|
6
|
+
"mcp": {
|
|
7
|
+
"name": "agent orchestrator",
|
|
8
|
+
"vendor": "MEOK AI Labs",
|
|
9
|
+
"homepage": "https://meok.ai",
|
|
10
|
+
"repository": "https://github.com/CSOAI-ORG/agent-orchestrator-mcp",
|
|
11
|
+
"runtime": "python",
|
|
12
|
+
"tags": ["mcp", "mcp-server", "meok-ai-labs", "ai-tools"]
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["mcp", "mcp-server", "meok-ai-labs"],
|
|
15
|
+
"author": "MEOK AI Labs <nicholas@meok.ai>",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {"type": "git", "url": "https://github.com/CSOAI-ORG/agent-orchestrator-mcp"}
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
[project]
|
|
5
|
+
name = "agent-orchestrator-mcp"
|
|
6
|
+
version = "1.0.0"
|
|
7
|
+
description = "MEOK AI Labs — agent-orchestrator-mcp"
|
|
8
|
+
license = {file = "LICENSE"}
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
authors = [{name = "MEOK AI Labs", email = "nicholas@meok.ai"}]
|
|
11
|
+
dependencies = ["mcp>=1.0.0"]
|
|
12
|
+
keywords = ["mcp", "ai", "meok", "agent", "orchestrator"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Topic :: Software Development :: Libraries",
|
|
18
|
+
]
|
|
19
|
+
[project.urls]
|
|
20
|
+
Homepage = "https://meok.ai"
|
|
21
|
+
Repository = "https://github.com/CSOAI-ORG/agent-orchestrator-mcp"
|
|
22
|
+
[tool.hatch.build.targets.wheel]
|
|
23
|
+
packages = ["."]
|
|
24
|
+
only-include = ["server.py"]
|
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Agent Orchestrator MCP Server
|
|
4
|
+
===============================
|
|
5
|
+
Multi-agent task management system. Create agents with roles and capabilities,
|
|
6
|
+
delegate tasks with trust-based routing, coordinate multi-agent file access,
|
|
7
|
+
run sprint workflows, and monitor agent performance. Based on the Sovereign
|
|
8
|
+
Temple 47-agent coordination framework.
|
|
9
|
+
|
|
10
|
+
Install: pip install mcp
|
|
11
|
+
Run: python server.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import sys, os
|
|
16
|
+
sys.path.insert(0, os.path.expanduser('~/clawd/meok-labs-engine/shared'))
|
|
17
|
+
from auth_middleware import check_access
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import uuid
|
|
21
|
+
import time
|
|
22
|
+
from datetime import datetime, timedelta
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Optional
|
|
25
|
+
from collections import defaultdict
|
|
26
|
+
from mcp.server.fastmcp import FastMCP
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Rate limiting
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
FREE_DAILY_LIMIT = 100
|
|
32
|
+
FREE_MAX_AGENTS = 10
|
|
33
|
+
_usage: dict[str, list[datetime]] = defaultdict(list)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _check_rate_limit(caller: str = "anonymous") -> Optional[str]:
|
|
37
|
+
now = datetime.now()
|
|
38
|
+
cutoff = now - timedelta(days=1)
|
|
39
|
+
_usage[caller] = [t for t in _usage[caller] if t > cutoff]
|
|
40
|
+
if len(_usage[caller]) >= FREE_DAILY_LIMIT:
|
|
41
|
+
return f"Free tier limit reached ({FREE_DAILY_LIMIT}/day). Upgrade to Pro: https://mcpize.com/agent-orchestrator-mcp/pro"
|
|
42
|
+
_usage[caller].append(now)
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
# Persistent Storage
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
DATA_DIR = Path.home() / ".mcp-agents"
|
|
50
|
+
DATA_DIR.mkdir(exist_ok=True)
|
|
51
|
+
AGENTS_FILE = DATA_DIR / "agents.json"
|
|
52
|
+
TASKS_FILE = DATA_DIR / "tasks.json"
|
|
53
|
+
SPRINTS_FILE = DATA_DIR / "sprints.json"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _load_json(path: Path) -> dict:
|
|
57
|
+
if path.exists():
|
|
58
|
+
try:
|
|
59
|
+
return json.loads(path.read_text())
|
|
60
|
+
except json.JSONDecodeError:
|
|
61
|
+
return {}
|
|
62
|
+
return {}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _save_json(path: Path, data: dict):
|
|
66
|
+
path.write_text(json.dumps(data, indent=2, default=str))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
# Agent Registry
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
class AgentStore:
|
|
73
|
+
def __init__(self):
|
|
74
|
+
self.agents = _load_json(AGENTS_FILE)
|
|
75
|
+
self.tasks = _load_json(TASKS_FILE)
|
|
76
|
+
self.sprints = _load_json(SPRINTS_FILE)
|
|
77
|
+
self._file_locks: dict[str, dict] = {} # file -> {"agent": str, "task": str, "exclusive": bool}
|
|
78
|
+
|
|
79
|
+
def save(self):
|
|
80
|
+
_save_json(AGENTS_FILE, self.agents)
|
|
81
|
+
_save_json(TASKS_FILE, self.tasks)
|
|
82
|
+
_save_json(SPRINTS_FILE, self.sprints)
|
|
83
|
+
|
|
84
|
+
def create_agent(self, name: str, role: str, department: str = "general",
|
|
85
|
+
capabilities: list[str] | None = None,
|
|
86
|
+
instructions: str = "") -> dict:
|
|
87
|
+
aid = name.lower().replace(" ", "_")
|
|
88
|
+
if aid in self.agents and len(self.agents) >= FREE_MAX_AGENTS:
|
|
89
|
+
pass # Allow update
|
|
90
|
+
elif len(self.agents) >= FREE_MAX_AGENTS and aid not in self.agents:
|
|
91
|
+
return {"error": f"Free tier limit: max {FREE_MAX_AGENTS} agents. Upgrade for unlimited."}
|
|
92
|
+
|
|
93
|
+
now = datetime.now().isoformat()
|
|
94
|
+
self.agents[aid] = {
|
|
95
|
+
"name": name,
|
|
96
|
+
"role": role,
|
|
97
|
+
"department": department,
|
|
98
|
+
"capabilities": capabilities or [],
|
|
99
|
+
"instructions": instructions,
|
|
100
|
+
"trust_level": 0.5,
|
|
101
|
+
"tasks_completed": self.agents.get(aid, {}).get("tasks_completed", 0),
|
|
102
|
+
"tasks_failed": self.agents.get(aid, {}).get("tasks_failed", 0),
|
|
103
|
+
"created_at": self.agents.get(aid, {}).get("created_at", now),
|
|
104
|
+
"updated_at": now,
|
|
105
|
+
"status": "active",
|
|
106
|
+
}
|
|
107
|
+
self.save()
|
|
108
|
+
return {"status": "created", "agent_id": aid, "name": name, "role": role}
|
|
109
|
+
|
|
110
|
+
def get_agent(self, aid: str) -> Optional[dict]:
|
|
111
|
+
return self.agents.get(aid)
|
|
112
|
+
|
|
113
|
+
def list_agents(self, department: str | None = None) -> list[dict]:
|
|
114
|
+
agents = []
|
|
115
|
+
for aid, agent in self.agents.items():
|
|
116
|
+
if department and agent.get("department") != department:
|
|
117
|
+
continue
|
|
118
|
+
agents.append({"id": aid, **agent})
|
|
119
|
+
return agents
|
|
120
|
+
|
|
121
|
+
def find_best_agent(self, capability: str | None = None,
|
|
122
|
+
department: str | None = None) -> Optional[str]:
|
|
123
|
+
"""Find the best agent for a task based on capability match and trust level."""
|
|
124
|
+
candidates = []
|
|
125
|
+
for aid, agent in self.agents.items():
|
|
126
|
+
if agent.get("status") != "active":
|
|
127
|
+
continue
|
|
128
|
+
if department and agent.get("department") != department:
|
|
129
|
+
continue
|
|
130
|
+
if capability and capability not in agent.get("capabilities", []):
|
|
131
|
+
continue
|
|
132
|
+
candidates.append((aid, agent.get("trust_level", 0.5)))
|
|
133
|
+
|
|
134
|
+
if not candidates:
|
|
135
|
+
return None
|
|
136
|
+
# Sort by trust level descending
|
|
137
|
+
candidates.sort(key=lambda x: x[1], reverse=True)
|
|
138
|
+
return candidates[0][0]
|
|
139
|
+
|
|
140
|
+
def delegate_task(self, task_desc: str, agent_id: str | None = None,
|
|
141
|
+
capability: str | None = None,
|
|
142
|
+
department: str | None = None,
|
|
143
|
+
priority: str = "normal",
|
|
144
|
+
care_score: float = 0.5) -> dict:
|
|
145
|
+
"""Delegate a task to a specific agent or auto-route to best match."""
|
|
146
|
+
if not agent_id:
|
|
147
|
+
agent_id = self.find_best_agent(capability, department)
|
|
148
|
+
if not agent_id or agent_id not in self.agents:
|
|
149
|
+
return {"error": f"Agent '{agent_id}' not found. Create an agent first."}
|
|
150
|
+
|
|
151
|
+
tid = str(uuid.uuid4())[:8]
|
|
152
|
+
now = datetime.now().isoformat()
|
|
153
|
+
task = {
|
|
154
|
+
"id": tid,
|
|
155
|
+
"description": task_desc,
|
|
156
|
+
"agent_id": agent_id,
|
|
157
|
+
"agent_name": self.agents[agent_id]["name"],
|
|
158
|
+
"status": "assigned",
|
|
159
|
+
"priority": priority,
|
|
160
|
+
"care_score": care_score,
|
|
161
|
+
"created_at": now,
|
|
162
|
+
"updated_at": now,
|
|
163
|
+
"result": None,
|
|
164
|
+
}
|
|
165
|
+
self.tasks[tid] = task
|
|
166
|
+
self.save()
|
|
167
|
+
return {"status": "delegated", "task_id": tid, "agent_id": agent_id,
|
|
168
|
+
"agent_name": self.agents[agent_id]["name"], "task": task_desc}
|
|
169
|
+
|
|
170
|
+
def complete_task(self, task_id: str, agent_id: str,
|
|
171
|
+
result_summary: str, care_score: float = 0.5,
|
|
172
|
+
success: bool = True) -> dict:
|
|
173
|
+
"""Mark a task as completed and update agent trust."""
|
|
174
|
+
if task_id not in self.tasks:
|
|
175
|
+
return {"error": f"Task {task_id} not found"}
|
|
176
|
+
|
|
177
|
+
task = self.tasks[task_id]
|
|
178
|
+
task["status"] = "completed" if success else "failed"
|
|
179
|
+
task["result"] = result_summary
|
|
180
|
+
task["care_score"] = care_score
|
|
181
|
+
task["updated_at"] = datetime.now().isoformat()
|
|
182
|
+
|
|
183
|
+
# Update agent trust based on outcome
|
|
184
|
+
if agent_id in self.agents:
|
|
185
|
+
agent = self.agents[agent_id]
|
|
186
|
+
if success:
|
|
187
|
+
agent["tasks_completed"] = agent.get("tasks_completed", 0) + 1
|
|
188
|
+
# Trust increases with successful completions
|
|
189
|
+
trust_delta = 0.02 * care_score
|
|
190
|
+
agent["trust_level"] = min(1.0, agent.get("trust_level", 0.5) + trust_delta)
|
|
191
|
+
else:
|
|
192
|
+
agent["tasks_failed"] = agent.get("tasks_failed", 0) + 1
|
|
193
|
+
trust_delta = -0.05
|
|
194
|
+
agent["trust_level"] = max(0.0, agent.get("trust_level", 0.5) + trust_delta)
|
|
195
|
+
|
|
196
|
+
self.save()
|
|
197
|
+
return {"status": task["status"], "task_id": task_id, "agent_id": agent_id,
|
|
198
|
+
"result": result_summary}
|
|
199
|
+
|
|
200
|
+
def acquire_files(self, agent_id: str, files: list[str], task_id: str,
|
|
201
|
+
exclusive: bool = False) -> dict:
|
|
202
|
+
"""Acquire file locks for coordinated multi-agent work."""
|
|
203
|
+
conflicts = []
|
|
204
|
+
for f in files:
|
|
205
|
+
if f in self._file_locks:
|
|
206
|
+
lock = self._file_locks[f]
|
|
207
|
+
if lock["exclusive"] or exclusive:
|
|
208
|
+
conflicts.append({"file": f, "locked_by": lock["agent"]})
|
|
209
|
+
|
|
210
|
+
if conflicts:
|
|
211
|
+
return {"status": "conflict", "conflicts": conflicts}
|
|
212
|
+
|
|
213
|
+
for f in files:
|
|
214
|
+
self._file_locks[f] = {
|
|
215
|
+
"agent": agent_id,
|
|
216
|
+
"task": task_id,
|
|
217
|
+
"exclusive": exclusive,
|
|
218
|
+
"acquired_at": datetime.now().isoformat(),
|
|
219
|
+
}
|
|
220
|
+
return {"status": "acquired", "files": files, "agent_id": agent_id}
|
|
221
|
+
|
|
222
|
+
def release_files(self, agent_id: str, files: list[str]) -> dict:
|
|
223
|
+
"""Release file locks."""
|
|
224
|
+
released = []
|
|
225
|
+
for f in files:
|
|
226
|
+
if f in self._file_locks and self._file_locks[f]["agent"] == agent_id:
|
|
227
|
+
del self._file_locks[f]
|
|
228
|
+
released.append(f)
|
|
229
|
+
return {"status": "released", "files": released}
|
|
230
|
+
|
|
231
|
+
def start_sprint(self, name: str, goals: list[str], duration_minutes: int = 60) -> dict:
|
|
232
|
+
"""Start a focused sprint with goals and time limit."""
|
|
233
|
+
sid = str(uuid.uuid4())[:8]
|
|
234
|
+
now = datetime.now()
|
|
235
|
+
sprint = {
|
|
236
|
+
"id": sid,
|
|
237
|
+
"name": name,
|
|
238
|
+
"goals": goals,
|
|
239
|
+
"status": "active",
|
|
240
|
+
"started_at": now.isoformat(),
|
|
241
|
+
"ends_at": (now + timedelta(minutes=duration_minutes)).isoformat(),
|
|
242
|
+
"duration_minutes": duration_minutes,
|
|
243
|
+
"completed_goals": [],
|
|
244
|
+
"tasks": [],
|
|
245
|
+
}
|
|
246
|
+
self.sprints[sid] = sprint
|
|
247
|
+
self.save()
|
|
248
|
+
return {"status": "started", "sprint_id": sid, "name": name,
|
|
249
|
+
"ends_at": sprint["ends_at"], "goals": goals}
|
|
250
|
+
|
|
251
|
+
def complete_sprint(self, sprint_id: str, completed_goals: list[str] | None = None,
|
|
252
|
+
summary: str = "") -> dict:
|
|
253
|
+
"""Complete a sprint and record results."""
|
|
254
|
+
if sprint_id not in self.sprints:
|
|
255
|
+
return {"error": f"Sprint {sprint_id} not found"}
|
|
256
|
+
|
|
257
|
+
sprint = self.sprints[sprint_id]
|
|
258
|
+
sprint["status"] = "completed"
|
|
259
|
+
sprint["completed_at"] = datetime.now().isoformat()
|
|
260
|
+
sprint["completed_goals"] = completed_goals or []
|
|
261
|
+
sprint["summary"] = summary
|
|
262
|
+
|
|
263
|
+
total = len(sprint["goals"])
|
|
264
|
+
done = len(sprint["completed_goals"])
|
|
265
|
+
sprint["completion_rate"] = round(done / max(total, 1) * 100, 1)
|
|
266
|
+
|
|
267
|
+
self.save()
|
|
268
|
+
return {
|
|
269
|
+
"status": "completed",
|
|
270
|
+
"sprint_id": sprint_id,
|
|
271
|
+
"completion_rate": sprint["completion_rate"],
|
|
272
|
+
"completed": done,
|
|
273
|
+
"total": total,
|
|
274
|
+
"summary": summary,
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
def get_dashboard(self) -> dict:
|
|
278
|
+
"""Get full orchestration dashboard."""
|
|
279
|
+
total_agents = len(self.agents)
|
|
280
|
+
active_agents = sum(1 for a in self.agents.values() if a.get("status") == "active")
|
|
281
|
+
|
|
282
|
+
total_tasks = len(self.tasks)
|
|
283
|
+
by_status = defaultdict(int)
|
|
284
|
+
for t in self.tasks.values():
|
|
285
|
+
by_status[t.get("status", "unknown")] += 1
|
|
286
|
+
|
|
287
|
+
avg_trust = 0
|
|
288
|
+
if self.agents:
|
|
289
|
+
avg_trust = sum(a.get("trust_level", 0.5) for a in self.agents.values()) / len(self.agents)
|
|
290
|
+
|
|
291
|
+
active_sprints = [s for s in self.sprints.values() if s.get("status") == "active"]
|
|
292
|
+
file_locks = len(self._file_locks)
|
|
293
|
+
|
|
294
|
+
# Department breakdown
|
|
295
|
+
departments = defaultdict(int)
|
|
296
|
+
for a in self.agents.values():
|
|
297
|
+
departments[a.get("department", "general")] += 1
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
"agents": {"total": total_agents, "active": active_agents, "avg_trust": round(avg_trust, 3)},
|
|
301
|
+
"tasks": {"total": total_tasks, "by_status": dict(by_status)},
|
|
302
|
+
"sprints": {"active": len(active_sprints), "total": len(self.sprints)},
|
|
303
|
+
"file_locks": file_locks,
|
|
304
|
+
"departments": dict(departments),
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
# Global store
|
|
309
|
+
store = AgentStore()
|
|
310
|
+
|
|
311
|
+
# ---------------------------------------------------------------------------
|
|
312
|
+
# MCP Server
|
|
313
|
+
# ---------------------------------------------------------------------------
|
|
314
|
+
mcp = FastMCP(
|
|
315
|
+
"Agent Orchestrator MCP",
|
|
316
|
+
instructions="Multi-agent task management: create agents, delegate tasks with trust-based routing, coordinate file access, run sprints, and monitor performance.")
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
@mcp.tool()
|
|
320
|
+
def create_agent(name: str, role: str, department: str = "general",
|
|
321
|
+
capabilities: list[str] | None = None,
|
|
322
|
+
instructions: str = "", api_key: str = "") -> dict:
|
|
323
|
+
"""Create a new agent with a name, role, department, and capabilities.
|
|
324
|
+
Agents accumulate trust through successful task completion.
|
|
325
|
+
Free tier: max 10 agents."""
|
|
326
|
+
allowed, msg, tier = check_access(api_key)
|
|
327
|
+
if not allowed:
|
|
328
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
329
|
+
|
|
330
|
+
err = _check_rate_limit()
|
|
331
|
+
if err:
|
|
332
|
+
return {"error": err}
|
|
333
|
+
return store.create_agent(name, role, department, capabilities, instructions)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
@mcp.tool()
|
|
337
|
+
def list_agents(department: str | None = None, api_key: str = "") -> dict:
|
|
338
|
+
"""List all registered agents with their trust levels, task counts, and status.
|
|
339
|
+
Optionally filter by department."""
|
|
340
|
+
allowed, msg, tier = check_access(api_key)
|
|
341
|
+
if not allowed:
|
|
342
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
343
|
+
|
|
344
|
+
err = _check_rate_limit()
|
|
345
|
+
if err:
|
|
346
|
+
return {"error": err}
|
|
347
|
+
agents = store.list_agents(department)
|
|
348
|
+
return {"agents": agents, "count": len(agents)}
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@mcp.tool()
|
|
352
|
+
def delegate_task(task: str, agent_id: str | None = None,
|
|
353
|
+
capability: str | None = None,
|
|
354
|
+
department: str | None = None,
|
|
355
|
+
priority: str = "normal",
|
|
356
|
+
care_score: float = 0.5, api_key: str = "") -> dict:
|
|
357
|
+
"""Delegate a task to a specific agent or auto-route to the best match
|
|
358
|
+
based on capability, department, and trust level. Priority: low/normal/high/urgent.
|
|
359
|
+
Care score (0-1) influences trust updates on completion."""
|
|
360
|
+
allowed, msg, tier = check_access(api_key)
|
|
361
|
+
if not allowed:
|
|
362
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
363
|
+
|
|
364
|
+
err = _check_rate_limit()
|
|
365
|
+
if err:
|
|
366
|
+
return {"error": err}
|
|
367
|
+
return store.delegate_task(task, agent_id, capability, department, priority, care_score)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@mcp.tool()
|
|
371
|
+
def complete_task(task_id: str, agent_id: str, result_summary: str,
|
|
372
|
+
care_score: float = 0.5, success: bool = True, api_key: str = "") -> dict:
|
|
373
|
+
"""Mark a task as completed (or failed). Updates the agent's trust level
|
|
374
|
+
based on success/failure and care score. Successful tasks increase trust,
|
|
375
|
+
failed tasks decrease it."""
|
|
376
|
+
allowed, msg, tier = check_access(api_key)
|
|
377
|
+
if not allowed:
|
|
378
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
379
|
+
|
|
380
|
+
err = _check_rate_limit()
|
|
381
|
+
if err:
|
|
382
|
+
return {"error": err}
|
|
383
|
+
return store.complete_task(task_id, agent_id, result_summary, care_score, success)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
@mcp.tool()
|
|
387
|
+
def acquire_files(agent_id: str, files: list[str], task_id: str,
|
|
388
|
+
exclusive: bool = False, api_key: str = "") -> dict:
|
|
389
|
+
"""Acquire file locks for coordinated multi-agent work. Prevents conflicts
|
|
390
|
+
when multiple agents need to modify the same files. Set exclusive=true for
|
|
391
|
+
write locks, false for read locks."""
|
|
392
|
+
allowed, msg, tier = check_access(api_key)
|
|
393
|
+
if not allowed:
|
|
394
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
395
|
+
|
|
396
|
+
err = _check_rate_limit()
|
|
397
|
+
if err:
|
|
398
|
+
return {"error": err}
|
|
399
|
+
return store.acquire_files(agent_id, files, task_id, exclusive)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@mcp.tool()
|
|
403
|
+
def release_files(agent_id: str, files: list[str], api_key: str = "") -> dict:
|
|
404
|
+
"""Release file locks held by an agent after task completion."""
|
|
405
|
+
allowed, msg, tier = check_access(api_key)
|
|
406
|
+
if not allowed:
|
|
407
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
408
|
+
|
|
409
|
+
err = _check_rate_limit()
|
|
410
|
+
if err:
|
|
411
|
+
return {"error": err}
|
|
412
|
+
return store.release_files(agent_id, files)
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
@mcp.tool()
|
|
416
|
+
def start_sprint(name: str, goals: list[str], duration_minutes: int = 60, api_key: str = "") -> dict:
|
|
417
|
+
"""Start a focused sprint with named goals and a time limit. Sprints help
|
|
418
|
+
agents coordinate on a set of objectives within a deadline."""
|
|
419
|
+
allowed, msg, tier = check_access(api_key)
|
|
420
|
+
if not allowed:
|
|
421
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
422
|
+
|
|
423
|
+
err = _check_rate_limit()
|
|
424
|
+
if err:
|
|
425
|
+
return {"error": err}
|
|
426
|
+
return store.start_sprint(name, goals, duration_minutes)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
@mcp.tool()
|
|
430
|
+
def complete_sprint(sprint_id: str, completed_goals: list[str] | None = None,
|
|
431
|
+
summary: str = "", api_key: str = "") -> dict:
|
|
432
|
+
"""Complete a sprint and record which goals were achieved. Returns the
|
|
433
|
+
completion rate percentage."""
|
|
434
|
+
allowed, msg, tier = check_access(api_key)
|
|
435
|
+
if not allowed:
|
|
436
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
437
|
+
|
|
438
|
+
err = _check_rate_limit()
|
|
439
|
+
if err:
|
|
440
|
+
return {"error": err}
|
|
441
|
+
return store.complete_sprint(sprint_id, completed_goals, summary)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
@mcp.tool()
|
|
445
|
+
def get_dashboard(api_key: str = "") -> dict:
|
|
446
|
+
"""Get the full orchestration dashboard: agent count, trust averages,
|
|
447
|
+
task breakdown by status, active sprints, file locks, and department distribution."""
|
|
448
|
+
allowed, msg, tier = check_access(api_key)
|
|
449
|
+
if not allowed:
|
|
450
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
451
|
+
|
|
452
|
+
err = _check_rate_limit()
|
|
453
|
+
if err:
|
|
454
|
+
return {"error": err}
|
|
455
|
+
return store.get_dashboard()
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
@mcp.tool()
|
|
459
|
+
def get_task_queue(status: str | None = None, agent_id: str | None = None,
|
|
460
|
+
limit: int = 20, api_key: str = "") -> dict:
|
|
461
|
+
"""Get the task queue, optionally filtered by status (assigned/completed/failed)
|
|
462
|
+
or agent. Returns tasks sorted by most recent."""
|
|
463
|
+
allowed, msg, tier = check_access(api_key)
|
|
464
|
+
if not allowed:
|
|
465
|
+
return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
|
|
466
|
+
|
|
467
|
+
err = _check_rate_limit()
|
|
468
|
+
if err:
|
|
469
|
+
return {"error": err}
|
|
470
|
+
|
|
471
|
+
tasks = []
|
|
472
|
+
for tid, task in sorted(store.tasks.items(),
|
|
473
|
+
key=lambda x: x[1].get("updated_at", ""), reverse=True):
|
|
474
|
+
if status and task.get("status") != status:
|
|
475
|
+
continue
|
|
476
|
+
if agent_id and task.get("agent_id") != agent_id:
|
|
477
|
+
continue
|
|
478
|
+
tasks.append(task)
|
|
479
|
+
if len(tasks) >= limit:
|
|
480
|
+
break
|
|
481
|
+
|
|
482
|
+
return {"tasks": tasks, "count": len(tasks)}
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
if __name__ == "__main__":
|
|
486
|
+
mcp.run()
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
name: agent-orchestrator-mcp
|
|
2
|
+
description: 'Multi-agent task management: create agents, delegate tasks with trust-based
|
|
3
|
+
routing, coordinate file'
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
tools:
|
|
6
|
+
- name: create_agent
|
|
7
|
+
description: Create a new agent with a name, role, department, and capabilities.
|
|
8
|
+
parameters:
|
|
9
|
+
- name: name
|
|
10
|
+
type: string
|
|
11
|
+
required: true
|
|
12
|
+
- name: role
|
|
13
|
+
type: string
|
|
14
|
+
required: true
|
|
15
|
+
- name: department
|
|
16
|
+
type: string
|
|
17
|
+
required: false
|
|
18
|
+
- name: capabilities
|
|
19
|
+
type: array
|
|
20
|
+
required: false
|
|
21
|
+
- name: instructions
|
|
22
|
+
type: string
|
|
23
|
+
required: false
|
|
24
|
+
- name: list_agents
|
|
25
|
+
description: List all registered agents with their trust levels, task counts, and
|
|
26
|
+
status.
|
|
27
|
+
parameters:
|
|
28
|
+
- name: department
|
|
29
|
+
type: string
|
|
30
|
+
required: false
|
|
31
|
+
- name: delegate_task
|
|
32
|
+
description: Delegate a task to a specific agent or auto-route to the best match
|
|
33
|
+
parameters:
|
|
34
|
+
- name: task
|
|
35
|
+
type: string
|
|
36
|
+
required: true
|
|
37
|
+
- name: agent_id
|
|
38
|
+
type: string
|
|
39
|
+
required: false
|
|
40
|
+
- name: capability
|
|
41
|
+
type: string
|
|
42
|
+
required: false
|
|
43
|
+
- name: department
|
|
44
|
+
type: string
|
|
45
|
+
required: false
|
|
46
|
+
- name: priority
|
|
47
|
+
type: string
|
|
48
|
+
required: false
|
|
49
|
+
- name: care_score
|
|
50
|
+
type: number
|
|
51
|
+
required: false
|
|
52
|
+
- name: complete_task
|
|
53
|
+
description: Mark a task as completed (or failed). Updates the agent's trust level
|
|
54
|
+
parameters:
|
|
55
|
+
- name: task_id
|
|
56
|
+
type: string
|
|
57
|
+
required: true
|
|
58
|
+
- name: agent_id
|
|
59
|
+
type: string
|
|
60
|
+
required: true
|
|
61
|
+
- name: result_summary
|
|
62
|
+
type: string
|
|
63
|
+
required: true
|
|
64
|
+
- name: care_score
|
|
65
|
+
type: number
|
|
66
|
+
required: false
|
|
67
|
+
- name: success
|
|
68
|
+
type: boolean
|
|
69
|
+
required: false
|
|
70
|
+
- name: acquire_files
|
|
71
|
+
description: Acquire file locks for coordinated multi-agent work. Prevents conflicts
|
|
72
|
+
parameters:
|
|
73
|
+
- name: agent_id
|
|
74
|
+
type: string
|
|
75
|
+
required: true
|
|
76
|
+
- name: files
|
|
77
|
+
type: array
|
|
78
|
+
required: true
|
|
79
|
+
- name: task_id
|
|
80
|
+
type: string
|
|
81
|
+
required: true
|
|
82
|
+
- name: exclusive
|
|
83
|
+
type: boolean
|
|
84
|
+
required: false
|
|
85
|
+
- name: release_files
|
|
86
|
+
description: Release file locks held by an agent after task completion.
|
|
87
|
+
parameters:
|
|
88
|
+
- name: agent_id
|
|
89
|
+
type: string
|
|
90
|
+
required: true
|
|
91
|
+
- name: files
|
|
92
|
+
type: array
|
|
93
|
+
required: true
|
|
94
|
+
- name: start_sprint
|
|
95
|
+
description: Start a focused sprint with named goals and a time limit. Sprints help
|
|
96
|
+
parameters:
|
|
97
|
+
- name: name
|
|
98
|
+
type: string
|
|
99
|
+
required: true
|
|
100
|
+
- name: goals
|
|
101
|
+
type: array
|
|
102
|
+
required: true
|
|
103
|
+
- name: duration_minutes
|
|
104
|
+
type: integer
|
|
105
|
+
required: false
|
|
106
|
+
- name: complete_sprint
|
|
107
|
+
description: Complete a sprint and record which goals were achieved. Returns the
|
|
108
|
+
parameters:
|
|
109
|
+
- name: sprint_id
|
|
110
|
+
type: string
|
|
111
|
+
required: true
|
|
112
|
+
- name: completed_goals
|
|
113
|
+
type: array
|
|
114
|
+
required: false
|
|
115
|
+
- name: summary
|
|
116
|
+
type: string
|
|
117
|
+
required: false
|
|
118
|
+
- name: get_dashboard
|
|
119
|
+
description: 'Get the full orchestration dashboard: agent count, trust averages,'
|
|
120
|
+
parameters: []
|
|
121
|
+
- name: get_task_queue
|
|
122
|
+
description: Get the task queue, optionally filtered by status (assigned/completed/failed)
|
|
123
|
+
parameters:
|
|
124
|
+
- name: status
|
|
125
|
+
type: string
|
|
126
|
+
required: false
|
|
127
|
+
- name: agent_id
|
|
128
|
+
type: string
|
|
129
|
+
required: false
|
|
130
|
+
- name: limit
|
|
131
|
+
type: integer
|
|
132
|
+
required: false
|