pilotswarm 0.0.1 → 0.4.1
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 +37 -1
- package/mcp/README.md +484 -0
- package/mcp/dist/bin/pilotswarm-mcp.d.ts +3 -0
- package/mcp/dist/bin/pilotswarm-mcp.d.ts.map +1 -0
- package/mcp/dist/bin/pilotswarm-mcp.js +367 -0
- package/mcp/dist/bin/pilotswarm-mcp.js.map +1 -0
- package/mcp/dist/src/auth.d.ts +7 -0
- package/mcp/dist/src/auth.d.ts.map +1 -0
- package/mcp/dist/src/auth.js +99 -0
- package/mcp/dist/src/auth.js.map +1 -0
- package/mcp/dist/src/context.d.ts +48 -0
- package/mcp/dist/src/context.d.ts.map +1 -0
- package/mcp/dist/src/context.js +83 -0
- package/mcp/dist/src/context.js.map +1 -0
- package/mcp/dist/src/index.d.ts +4 -0
- package/mcp/dist/src/index.d.ts.map +1 -0
- package/mcp/dist/src/index.js +3 -0
- package/mcp/dist/src/index.js.map +1 -0
- package/mcp/dist/src/prompts/skills.d.ts +4 -0
- package/mcp/dist/src/prompts/skills.d.ts.map +1 -0
- package/mcp/dist/src/prompts/skills.js +11 -0
- package/mcp/dist/src/prompts/skills.js.map +1 -0
- package/mcp/dist/src/resources/agents.d.ts +4 -0
- package/mcp/dist/src/resources/agents.d.ts.map +1 -0
- package/mcp/dist/src/resources/agents.js +64 -0
- package/mcp/dist/src/resources/agents.js.map +1 -0
- package/mcp/dist/src/resources/facts.d.ts +4 -0
- package/mcp/dist/src/resources/facts.d.ts.map +1 -0
- package/mcp/dist/src/resources/facts.js +125 -0
- package/mcp/dist/src/resources/facts.js.map +1 -0
- package/mcp/dist/src/resources/models.d.ts +4 -0
- package/mcp/dist/src/resources/models.d.ts.map +1 -0
- package/mcp/dist/src/resources/models.js +43 -0
- package/mcp/dist/src/resources/models.js.map +1 -0
- package/mcp/dist/src/resources/sessions.d.ts +4 -0
- package/mcp/dist/src/resources/sessions.d.ts.map +1 -0
- package/mcp/dist/src/resources/sessions.js +190 -0
- package/mcp/dist/src/resources/sessions.js.map +1 -0
- package/mcp/dist/src/resources/subscriptions.d.ts +9 -0
- package/mcp/dist/src/resources/subscriptions.d.ts.map +1 -0
- package/mcp/dist/src/resources/subscriptions.js +157 -0
- package/mcp/dist/src/resources/subscriptions.js.map +1 -0
- package/mcp/dist/src/server.d.ts +4 -0
- package/mcp/dist/src/server.d.ts.map +1 -0
- package/mcp/dist/src/server.js +59 -0
- package/mcp/dist/src/server.js.map +1 -0
- package/mcp/dist/src/tools/agents.d.ts +4 -0
- package/mcp/dist/src/tools/agents.d.ts.map +1 -0
- package/mcp/dist/src/tools/agents.js +317 -0
- package/mcp/dist/src/tools/agents.js.map +1 -0
- package/mcp/dist/src/tools/facts.d.ts +4 -0
- package/mcp/dist/src/tools/facts.d.ts.map +1 -0
- package/mcp/dist/src/tools/facts.js +151 -0
- package/mcp/dist/src/tools/facts.js.map +1 -0
- package/mcp/dist/src/tools/models.d.ts +4 -0
- package/mcp/dist/src/tools/models.d.ts.map +1 -0
- package/mcp/dist/src/tools/models.js +256 -0
- package/mcp/dist/src/tools/models.js.map +1 -0
- package/mcp/dist/src/tools/sessions.d.ts +4 -0
- package/mcp/dist/src/tools/sessions.d.ts.map +1 -0
- package/mcp/dist/src/tools/sessions.js +606 -0
- package/mcp/dist/src/tools/sessions.js.map +1 -0
- package/mcp/dist/src/util/command.d.ts +52 -0
- package/mcp/dist/src/util/command.d.ts.map +1 -0
- package/mcp/dist/src/util/command.js +78 -0
- package/mcp/dist/src/util/command.js.map +1 -0
- package/package.json +82 -6
- package/tui/README.md +35 -0
- package/tui/bin/tui.js +30 -0
- package/tui/plugins/.mcp.json +7 -0
- package/tui/plugins/plugin.json +13 -0
- package/tui/plugins/session-policy.json +8 -0
- package/tui/src/app.js +850 -0
- package/tui/src/auth/cli.js +111 -0
- package/tui/src/auth/entra-auth.js +218 -0
- package/tui/src/bootstrap-env.js +176 -0
- package/tui/src/embedded-workers.js +79 -0
- package/tui/src/http-transport-host.js +106 -0
- package/tui/src/index.js +340 -0
- package/tui/src/node-sdk-transport.js +1794 -0
- package/tui/src/platform.js +984 -0
- package/tui/src/plugin-config.js +273 -0
- package/tui/src/portal.js +7 -0
- package/tui/src/version.js +7 -0
- package/tui/tui-splash-mobile.txt +7 -0
- package/tui/tui-splash.txt +11 -0
- package/ui/core/README.md +6 -0
- package/ui/core/src/commands.js +93 -0
- package/ui/core/src/context-usage.js +212 -0
- package/ui/core/src/controller.js +6201 -0
- package/ui/core/src/formatting.js +1036 -0
- package/ui/core/src/history.js +950 -0
- package/ui/core/src/index.js +13 -0
- package/ui/core/src/layout.js +332 -0
- package/ui/core/src/reducer.js +1952 -0
- package/ui/core/src/selectors.js +5419 -0
- package/ui/core/src/session-errors.js +14 -0
- package/ui/core/src/session-tree.js +151 -0
- package/ui/core/src/state.js +251 -0
- package/ui/core/src/store.js +23 -0
- package/ui/core/src/system-titles.js +24 -0
- package/ui/core/src/themes/catppuccin-mocha.js +56 -0
- package/ui/core/src/themes/cobalt2.js +56 -0
- package/ui/core/src/themes/dark-high-contrast.js +56 -0
- package/ui/core/src/themes/daylight.js +62 -0
- package/ui/core/src/themes/dracula.js +56 -0
- package/ui/core/src/themes/github-dark.js +56 -0
- package/ui/core/src/themes/github-light.js +59 -0
- package/ui/core/src/themes/gruvbox-dark.js +56 -0
- package/ui/core/src/themes/hacker-x-matrix.js +56 -0
- package/ui/core/src/themes/hacker-x-orion-prime.js +56 -0
- package/ui/core/src/themes/helpers.js +79 -0
- package/ui/core/src/themes/high-contrast-mono.js +59 -0
- package/ui/core/src/themes/index.js +52 -0
- package/ui/core/src/themes/light-high-contrast.js +62 -0
- package/ui/core/src/themes/noctis-obscuro.js +56 -0
- package/ui/core/src/themes/noctis.js +56 -0
- package/ui/core/src/themes/paper-ink.js +62 -0
- package/ui/core/src/themes/solarized-ops.js +59 -0
- package/ui/core/src/themes/terminal-green.js +59 -0
- package/ui/core/src/themes/tokyo-night.js +56 -0
- package/ui/react/README.md +5 -0
- package/ui/react/src/chat-status.js +39 -0
- package/ui/react/src/components.js +1989 -0
- package/ui/react/src/index.js +4 -0
- package/ui/react/src/platform.js +15 -0
- package/ui/react/src/use-controller-state.js +38 -0
- package/ui/react/src/web-app.js +4457 -0
- package/web/README.md +198 -0
- package/web/api/router.js +196 -0
- package/web/api/ws.js +152 -0
- package/web/auth/authz/engine.js +204 -0
- package/web/auth/config.js +115 -0
- package/web/auth/index.js +175 -0
- package/web/auth/normalize/entra.js +22 -0
- package/web/auth/providers/entra.js +76 -0
- package/web/auth/providers/none.js +24 -0
- package/web/auth.js +10 -0
- package/web/bin/serve.js +53 -0
- package/web/config.js +20 -0
- package/web/dist/app.js +469 -0
- package/web/dist/assets/index-DmGOcKR-.css +1 -0
- package/web/dist/assets/index-xJ8IzIZY.js +24 -0
- package/web/dist/assets/msal-CytV9RFv.js +7 -0
- package/web/dist/assets/pilotswarm-D9pEmenA.js +90 -0
- package/web/dist/assets/react-CEPDSRB6.js +1 -0
- package/web/dist/index.html +16 -0
- package/web/runtime.js +455 -0
- package/web/server.js +276 -0
- package/index.js +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
1
|
# pilotswarm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The PilotSwarm application package — one install gives you every user-facing
|
|
4
|
+
surface of a [PilotSwarm](https://github.com/affandar/pilotswarm) deployment:
|
|
5
|
+
|
|
6
|
+
| Bin | What it is |
|
|
7
|
+
|---|---|
|
|
8
|
+
| `pilotswarm` | Terminal UI. `pilotswarm remote --api-url <portal-url>` attaches to any deployment (auto Entra sign-in); `pilotswarm local` runs an embedded dev stack. `pilotswarm-cli` is an alias. |
|
|
9
|
+
| `pilotswarm-web` | The portal server: hosts the browser UI **and** the deployment's Web API (`/api/v1` + `/api/v1/ws`) — the single integration surface every client rides. |
|
|
10
|
+
| `pilotswarm-mcp` | MCP server exposing PilotSwarm sessions/facts/models to Claude Desktop, Cursor, or any MCP client. `--api-url <portal-url>` is the supported mode. |
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g pilotswarm
|
|
14
|
+
|
|
15
|
+
# attach the TUI to a deployment — the URL is the only credential you need
|
|
16
|
+
pilotswarm remote --api-url https://portal.example.com
|
|
17
|
+
|
|
18
|
+
# host a portal (needs worker-side env: DATABASE_URL etc.)
|
|
19
|
+
pilotswarm-web --plugin ./plugin
|
|
20
|
+
|
|
21
|
+
# expose a deployment to an MCP client
|
|
22
|
+
pilotswarm-mcp --api-url https://portal.example.com
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Library surfaces (used by the shipped UIs; importable for custom hosts):
|
|
26
|
+
|
|
27
|
+
- `pilotswarm/ui-core` — framework-free UI controller/state/selectors
|
|
28
|
+
- `pilotswarm/ui-react` — the shared React composition (Ink + DOM)
|
|
29
|
+
- `pilotswarm/host` — node-host layer (SDK transport, plugin/config resolution)
|
|
30
|
+
- `pilotswarm/web` — the portal server entry (`startServer`)
|
|
31
|
+
|
|
32
|
+
Building an app or service instead of a UI? You want
|
|
33
|
+
[`pilotswarm-sdk`](https://www.npmjs.com/package/pilotswarm-sdk) — including
|
|
34
|
+
its zero-dependency wire client at `pilotswarm-sdk/api`.
|
|
35
|
+
|
|
36
|
+
Docs: [Quick Start](https://github.com/affandar/pilotswarm/blob/main/docs/quickstart/docker.md) ·
|
|
37
|
+
[User Guide](https://github.com/affandar/pilotswarm/blob/main/docs/user-guide/README.md) ·
|
|
38
|
+
[Web API Reference](https://github.com/affandar/pilotswarm/blob/main/docs/api/reference.md) ·
|
|
39
|
+
[Architecture / Layering](https://github.com/affandar/pilotswarm/blob/main/docs/architecture/layering.md)
|
package/mcp/README.md
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# PilotSwarm MCP Server
|
|
2
|
+
|
|
3
|
+
Exposes PilotSwarm sessions, agents, facts, and models to any MCP-compatible client via the [Model Context Protocol](https://modelcontextprotocol.io/). Connect Claude Desktop, Copilot CLI, Cursor, VS Code, ChatGPT, or any MCP client to a running PilotSwarm instance.
|
|
4
|
+
|
|
5
|
+
> **Web API mode is the default.** `--api-url https://portal.example.com` talks to a deployment through the portal's [Web API](../../docs/api/reference.md) — the only credential this process holds is the deployment URL (plus a bearer token on Entra deployments: run `pilotswarm auth login --api-url <url>` once and the server reads the cached token, or set `PILOTSWARM_API_TOKEN` for service principals / CI). **Direct mode** (`--store "$DATABASE_URL"`) connects straight to the database and is internal-only — for tests and trusted placement alongside workers; see [Direct mode](#direct-mode-internal). The debug `dump_session` tool is direct-mode only. See [Layering](../../docs/architecture/layering.md) for the full picture.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### Stdio Transport (recommended for local IDEs)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx -y -p pilotswarm pilotswarm-mcp --api-url https://portal.example.com
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### HTTP Transport (recommended for remote/shared access)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
PILOTSWARM_MCP_KEY=your-secret-key npx -y -p pilotswarm pilotswarm-mcp \
|
|
19
|
+
--transport http --port 3100 \
|
|
20
|
+
--api-url https://portal.example.com
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> The package is published as `pilotswarm`; the executable bin is `pilotswarm-mcp`. Use `npx -p pilotswarm pilotswarm-mcp` (or install globally) so npm resolves the right package.
|
|
24
|
+
|
|
25
|
+
> **Prerequisite:** A running PilotSwarm deployment — all you need is its URL. On an Entra deployment, authenticate once with `pilotswarm auth login --api-url <url>` (or set `PILOTSWARM_API_TOKEN`).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Connecting MCP Clients
|
|
30
|
+
|
|
31
|
+
Each client below shows both **Stdio** (local, recommended) and **HTTP** (remote/shared) configurations.
|
|
32
|
+
|
|
33
|
+
> **HTTP prerequisite:** Start the HTTP server first:
|
|
34
|
+
> ```bash
|
|
35
|
+
> PILOTSWARM_MCP_KEY=your-secret-key npx -y -p pilotswarm pilotswarm-mcp \
|
|
36
|
+
> --transport http --port 3100 \
|
|
37
|
+
> --api-url https://portal.example.com
|
|
38
|
+
> ```
|
|
39
|
+
|
|
40
|
+
### GitHub Copilot CLI
|
|
41
|
+
|
|
42
|
+
Add to your `.mcp.json` (project root or `~/.copilot/`):
|
|
43
|
+
|
|
44
|
+
**Stdio (local):**
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"pilotswarm": {
|
|
50
|
+
"type": "stdio",
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": [
|
|
53
|
+
"-y",
|
|
54
|
+
"-p", "pilotswarm",
|
|
55
|
+
"pilotswarm-mcp",
|
|
56
|
+
"--api-url", "https://portal.example.com"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**HTTP (remote):**
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"pilotswarm": {
|
|
69
|
+
"type": "http",
|
|
70
|
+
"url": "http://your-host:3100/mcp",
|
|
71
|
+
"headers": {
|
|
72
|
+
"Authorization": "Bearer ${PILOTSWARM_MCP_KEY}"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Claude Desktop
|
|
80
|
+
|
|
81
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
82
|
+
|
|
83
|
+
**Stdio (local):**
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"pilotswarm": {
|
|
89
|
+
"command": "npx",
|
|
90
|
+
"args": [
|
|
91
|
+
"-y",
|
|
92
|
+
"-p", "pilotswarm",
|
|
93
|
+
"pilotswarm-mcp",
|
|
94
|
+
"--api-url", "https://portal.example.com"
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**HTTP (remote):**
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"pilotswarm": {
|
|
107
|
+
"url": "http://your-host:3100/mcp",
|
|
108
|
+
"headers": {
|
|
109
|
+
"Authorization": "Bearer ${PILOTSWARM_MCP_KEY}"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Claude Code (CLI)
|
|
117
|
+
|
|
118
|
+
Add a `.mcp.json` in your project root:
|
|
119
|
+
|
|
120
|
+
**Stdio (local):**
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"pilotswarm": {
|
|
126
|
+
"type": "stdio",
|
|
127
|
+
"command": "npx",
|
|
128
|
+
"args": [
|
|
129
|
+
"-y",
|
|
130
|
+
"-p", "pilotswarm",
|
|
131
|
+
"pilotswarm-mcp",
|
|
132
|
+
"--api-url", "https://portal.example.com"
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**HTTP (remote):**
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"mcpServers": {
|
|
144
|
+
"pilotswarm": {
|
|
145
|
+
"type": "http",
|
|
146
|
+
"url": "http://your-host:3100/mcp",
|
|
147
|
+
"headers": {
|
|
148
|
+
"Authorization": "Bearer ${PILOTSWARM_MCP_KEY}"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Cursor
|
|
156
|
+
|
|
157
|
+
Open **Settings → MCP** and add a server, or edit `~/.cursor/mcp.json`:
|
|
158
|
+
|
|
159
|
+
**Stdio (local):**
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"mcpServers": {
|
|
164
|
+
"pilotswarm": {
|
|
165
|
+
"command": "npx",
|
|
166
|
+
"args": [
|
|
167
|
+
"-y",
|
|
168
|
+
"-p", "pilotswarm",
|
|
169
|
+
"pilotswarm-mcp",
|
|
170
|
+
"--api-url", "https://portal.example.com"
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**HTTP (remote):**
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"mcpServers": {
|
|
182
|
+
"pilotswarm": {
|
|
183
|
+
"url": "http://your-host:3100/mcp",
|
|
184
|
+
"headers": {
|
|
185
|
+
"Authorization": "Bearer ${PILOTSWARM_MCP_KEY}"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### VS Code (Copilot)
|
|
193
|
+
|
|
194
|
+
Add `.vscode/mcp.json` to your workspace:
|
|
195
|
+
|
|
196
|
+
**Stdio (local):**
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"servers": {
|
|
201
|
+
"pilotswarm": {
|
|
202
|
+
"type": "stdio",
|
|
203
|
+
"command": "npx",
|
|
204
|
+
"args": [
|
|
205
|
+
"-y",
|
|
206
|
+
"-p", "pilotswarm",
|
|
207
|
+
"pilotswarm-mcp",
|
|
208
|
+
"--api-url", "https://portal.example.com"
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**HTTP (remote):**
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"servers": {
|
|
220
|
+
"pilotswarm": {
|
|
221
|
+
"type": "http",
|
|
222
|
+
"url": "http://your-host:3100/mcp",
|
|
223
|
+
"headers": {
|
|
224
|
+
"Authorization": "Bearer ${PILOTSWARM_MCP_KEY}"
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### ChatGPT (via HTTP)
|
|
232
|
+
|
|
233
|
+
ChatGPT supports MCP via HTTP transport only.
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
URL: http://your-host:3100/mcp
|
|
237
|
+
Auth: Bearer token via PILOTSWARM_MCP_KEY
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Generic HTTP Client
|
|
241
|
+
|
|
242
|
+
Test with curl:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Initialize a session
|
|
246
|
+
curl -X POST http://127.0.0.1:3100/mcp \
|
|
247
|
+
-H "Authorization: Bearer $PILOTSWARM_MCP_KEY" \
|
|
248
|
+
-H "Content-Type: application/json" \
|
|
249
|
+
-d '{
|
|
250
|
+
"jsonrpc": "2.0",
|
|
251
|
+
"id": 1,
|
|
252
|
+
"method": "initialize",
|
|
253
|
+
"params": {
|
|
254
|
+
"protocolVersion": "2025-03-26",
|
|
255
|
+
"capabilities": {},
|
|
256
|
+
"clientInfo": { "name": "curl", "version": "1.0.0" }
|
|
257
|
+
}
|
|
258
|
+
}'
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
The response includes an `mcp-session-id` header — pass it in subsequent requests:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# List tools
|
|
265
|
+
curl -X POST http://127.0.0.1:3100/mcp \
|
|
266
|
+
-H "Authorization: Bearer $PILOTSWARM_MCP_KEY" \
|
|
267
|
+
-H "Content-Type: application/json" \
|
|
268
|
+
-H "mcp-session-id: <session-id-from-above>" \
|
|
269
|
+
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Programmatic (Node.js SDK)
|
|
273
|
+
|
|
274
|
+
Connect using the official MCP SDK:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
278
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
279
|
+
|
|
280
|
+
const transport = new StreamableHTTPClientTransport(
|
|
281
|
+
new URL("http://127.0.0.1:3100/mcp"),
|
|
282
|
+
{
|
|
283
|
+
requestInit: {
|
|
284
|
+
headers: { "Authorization": "Bearer your-key" },
|
|
285
|
+
},
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const client = new Client({ name: "my-app", version: "1.0.0" });
|
|
290
|
+
await client.connect(transport);
|
|
291
|
+
|
|
292
|
+
// List available tools
|
|
293
|
+
const { tools } = await client.listTools();
|
|
294
|
+
console.log(tools.map((t) => t.name));
|
|
295
|
+
|
|
296
|
+
// Create a session
|
|
297
|
+
const result = await client.callTool({
|
|
298
|
+
name: "create_session",
|
|
299
|
+
arguments: { title: "My Session" },
|
|
300
|
+
});
|
|
301
|
+
console.log(result);
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Direct mode (internal)
|
|
307
|
+
|
|
308
|
+
For tests and trusted co-located placement (same network boundary as the
|
|
309
|
+
workers and database), the server can bypass the Web API and connect straight
|
|
310
|
+
to the datastore:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
npx -y -p pilotswarm pilotswarm-mcp --store "$DATABASE_URL" --model-providers .model_providers.json
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
This is not a supported integration surface — it holds database credentials,
|
|
317
|
+
skips the deployment's authorization seam, and is kept for internal use. One
|
|
318
|
+
debug capability lives only here: the `pilotswarm://sessions/{id}/dump`
|
|
319
|
+
resource (`dump_session`), which reads session state files off disk.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## CLI Options
|
|
324
|
+
|
|
325
|
+
| Flag | Default | Env var | Description |
|
|
326
|
+
|------|---------|---------|-------------|
|
|
327
|
+
| `--api-url` | — | `PILOTSWARM_API_URL` | Deployment URL (Web API mode — the default way to run). Mutually exclusive with `--store`. |
|
|
328
|
+
| `--transport` | `stdio` | — | Transport mode: `stdio` or `http` |
|
|
329
|
+
| `--port` | `3100` | — | HTTP server port (only used with `--transport http`) |
|
|
330
|
+
| `--host` | `127.0.0.1` | `PILOTSWARM_MCP_HOST` | Host/interface to bind the HTTP server to |
|
|
331
|
+
| `--allowed-hosts` | bound host + `127.0.0.1`/`localhost`/`[::1]` on `--port` | `PILOTSWARM_MCP_ALLOWED_HOSTS` | Comma-separated `host:port` allowlist for the `Host` header (DNS-rebinding defense). Required when fronting the server with a reverse proxy or public hostname. |
|
|
332
|
+
| `--max-sessions` | `256` | `PILOTSWARM_MCP_MAX_SESSIONS` | Maximum concurrent MCP sessions; new sessions beyond the cap are rejected with `503` |
|
|
333
|
+
| `--session-idle-timeout-ms` | `300000` (5 min) | `PILOTSWARM_MCP_SESSION_IDLE_MS` | Close sessions whose last request was more than this many ms ago (sweeper runs every ~30s). Set to `0` to disable. Required to prevent slot-leaks from one-shot HTTP clients that disconnect without `DELETE /mcp`. |
|
|
334
|
+
| `--store` | — | `DATABASE_URL` | PostgreSQL connection string ([direct mode](#direct-mode-internal), internal) |
|
|
335
|
+
| `--model-providers` | — | — | Path to model providers JSON config (direct mode; web mode lists models through the API) |
|
|
336
|
+
| `--plugin` | — | — | Plugin directory (repeatable for multiple dirs) |
|
|
337
|
+
| `--log-level` | `error` | — | Log verbosity for lifecycle messages: `debug`, `info`, `warn`, `error`, or `silent` |
|
|
338
|
+
|
|
339
|
+
### HTTP-only env vars
|
|
340
|
+
|
|
341
|
+
| Env var | Required | Description |
|
|
342
|
+
|---------|----------|-------------|
|
|
343
|
+
| `PILOTSWARM_MCP_KEY` | Yes (HTTP transport) | Bearer token clients must present in `Authorization: Bearer <key>`. Server refuses to start without it. |
|
|
344
|
+
| `PILOTSWARM_MCP_HOST` | No | Same as `--host` |
|
|
345
|
+
| `PILOTSWARM_MCP_ALLOWED_HOSTS` | No | Same as `--allowed-hosts` |
|
|
346
|
+
| `PILOTSWARM_MCP_MAX_SESSIONS` | No | Same as `--max-sessions` |
|
|
347
|
+
| `PILOTSWARM_MCP_SESSION_IDLE_MS` | No | Same as `--session-idle-timeout-ms` |
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Available Tools (20)
|
|
352
|
+
|
|
353
|
+
### Session Management
|
|
354
|
+
|
|
355
|
+
| Tool | Description |
|
|
356
|
+
|------|-------------|
|
|
357
|
+
| `create_session` | Create a new PilotSwarm session, optionally bound to a named agent |
|
|
358
|
+
| `send_message` | Send a fire-and-forget message to a session |
|
|
359
|
+
| `send_and_wait` | Send a message and wait for the response (default timeout: 120 s) |
|
|
360
|
+
| `send_answer` | Answer a pending `input_required` question in a session |
|
|
361
|
+
| `abort_session` | Cancel a running session with an optional reason |
|
|
362
|
+
| `rename_session` | Rename a session title |
|
|
363
|
+
| `delete_session` | Soft-delete a session |
|
|
364
|
+
| `list_sessions` | Discovery — list all sessions with status, model, agent info, and parent/child relationships |
|
|
365
|
+
| `get_session_detail` | Discovery — get detailed info for a session including status, context usage, cron state, and pending questions |
|
|
366
|
+
| `get_session_events` | Discovery — read the CMS event stream for a session, with `after_seq` pagination and long-poll support |
|
|
367
|
+
|
|
368
|
+
### External MCP boundary
|
|
369
|
+
|
|
370
|
+
The PilotSwarm MCP server is an **external surface**: it accepts tool calls from clients outside the agent's reasoning loop (Claude Desktop, custom MCP clients, ops tooling). It mutates only **top-level sessions**.
|
|
371
|
+
|
|
372
|
+
**Sub-agent lifecycle is not part of the external surface.** Creating, messaging, and cancelling a sub-agent are operations whose semantics depend on the parent session's reasoning context — only the parent has the context to decide why, when, and with what task to spawn or message a child. Those operations are exposed only to the in-loop LLM via the orchestration's `spawn_agent` tool and related command handlers.
|
|
373
|
+
|
|
374
|
+
External MCP clients can **inspect** the sub-agent tree freely:
|
|
375
|
+
|
|
376
|
+
- `list_agents` — list direct children, filter by parent/status
|
|
377
|
+
- `list_registered_agents` — read the catalog of agent definitions
|
|
378
|
+
- `get_agent_tree` — recursive subtree from a root session
|
|
379
|
+
- `get_session_tree_stats` — aggregated metrics across a subtree
|
|
380
|
+
- `get_session_detail`, `get_session_events` — work on any session id, including child sessions
|
|
381
|
+
- `pilotswarm://agents/{agentId}` resources — read-only details for *system* sub-agents (sweeper, resourcemgr, etc.); not a generic per-child resource
|
|
382
|
+
|
|
383
|
+
External clients **cannot** spawn, message, or cancel a sub-agent. Calling a removed tool name returns the standard MCP "unknown tool" error.
|
|
384
|
+
|
|
385
|
+
Top-level session control (`create_session`, `send_message`, `delete_session`, etc.) is unaffected by this boundary — those tools remain on the external surface.
|
|
386
|
+
|
|
387
|
+
### Agent Management
|
|
388
|
+
|
|
389
|
+
| Tool | Description |
|
|
390
|
+
|------|-------------|
|
|
391
|
+
| `list_agents` | Discovery — list all sub-agents (child sessions) with name, status, model, parent, and task; filter by parent or status |
|
|
392
|
+
| `list_registered_agents` | Discovery — read PilotSwarm's catalog of registered agent definitions visible to this MCP server (name, title, description, system flag, parent constraint). Pure read; no creation affordance. |
|
|
393
|
+
| `get_agent_tree` | Discovery — recursive sub-agent subtree rooted at a session id, bounded by `max_depth` (default 5). |
|
|
394
|
+
| `get_session_tree_stats` | Discovery — aggregated metrics for a session and all its descendants: token totals, session count, dehydration / hydration counts, per-model breakdown, cache hit ratio. |
|
|
395
|
+
|
|
396
|
+
### Knowledge (Facts)
|
|
397
|
+
|
|
398
|
+
| Tool | Description |
|
|
399
|
+
|------|-------------|
|
|
400
|
+
| `store_fact` | Store a key-value fact (shared or session-scoped) |
|
|
401
|
+
| `read_facts` | Query facts by key pattern, tags, or session scope (caller-trusted — see [Security model](#security-model)) |
|
|
402
|
+
| `delete_fact` | Delete a fact by key |
|
|
403
|
+
|
|
404
|
+
### Model & Commands
|
|
405
|
+
|
|
406
|
+
| Tool | Description |
|
|
407
|
+
|------|-------------|
|
|
408
|
+
| `list_models` | Discovery — list all available LLM models, optionally grouped by provider (web mode reads them through the API; direct mode reads `--model-providers`) |
|
|
409
|
+
| `switch_model` | Change the model for a session (web mode uses the API's model-switch operation — the same path as the portal UI) |
|
|
410
|
+
| `send_command` | Send an arbitrary orchestration command to a session ([direct mode](#direct-mode-internal) only — raw command plumbing is not exposed over the Web API) |
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Available Resources (15)
|
|
415
|
+
|
|
416
|
+
| URI | Description |
|
|
417
|
+
|-----|-------------|
|
|
418
|
+
| `pilotswarm://sessions` | List all sessions with status |
|
|
419
|
+
| `pilotswarm://sessions/{id}` | Detailed info for a specific session |
|
|
420
|
+
| `pilotswarm://sessions/{id}/messages` | Chat history for a session |
|
|
421
|
+
| `pilotswarm://sessions/{id}/events` | CMS event stream for a session |
|
|
422
|
+
| `pilotswarm://sessions/{id}/dump` | Full session dump (config, state, messages, events) |
|
|
423
|
+
| `pilotswarm://agents/{agentId}` | System-agent detail (one resource per running system agent, enumerated dynamically) |
|
|
424
|
+
| `pilotswarm://agents/{agentId}/events` | Event stream for a system agent (enumerated dynamically) |
|
|
425
|
+
| `pilotswarm://facts` | Query the knowledge/facts store |
|
|
426
|
+
| `pilotswarm://facts/skills` | Index of skill facts |
|
|
427
|
+
| `pilotswarm://facts/skills/{key}` | Detail for a specific skill fact |
|
|
428
|
+
| `pilotswarm://facts/asks` | Index of ask (open-question) facts |
|
|
429
|
+
| `pilotswarm://facts/asks/{key}` | Detail for a specific ask fact |
|
|
430
|
+
| `pilotswarm://facts/intake` | Intake (raw) facts feed |
|
|
431
|
+
| `pilotswarm://facts/intake/{keyPattern}` | Intake facts filtered by key pattern |
|
|
432
|
+
| `pilotswarm://models` | Available LLM models grouped by provider |
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Authentication
|
|
437
|
+
|
|
438
|
+
Two independent boundaries: inbound (MCP clients → this server) and outbound (this server → the deployment).
|
|
439
|
+
|
|
440
|
+
**Inbound (MCP transport):**
|
|
441
|
+
|
|
442
|
+
- **Stdio** — No auth needed. Process-level isolation provides security (the MCP client spawns the server as a child process).
|
|
443
|
+
- **HTTP** — Requires the `PILOTSWARM_MCP_KEY` environment variable. All requests must include an `Authorization: Bearer <key>` header. The server refuses to start if the key is not set.
|
|
444
|
+
|
|
445
|
+
**Outbound (Web API mode):**
|
|
446
|
+
|
|
447
|
+
- **No-auth deployment** — nothing to configure.
|
|
448
|
+
- **Entra deployment** — the server resolves a token from `PILOTSWARM_API_TOKEN` (service principal / CI) or the cache written by `pilotswarm auth login --api-url <url>`. The deployment's own authorization (role → admin gates, facts read scoping) applies to every call this server makes.
|
|
449
|
+
|
|
450
|
+
CORS is enabled for all origins, with `mcp-session-id` and `mcp-protocol-version` exposed as response headers.
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## Security model
|
|
455
|
+
|
|
456
|
+
The MCP server treats every connected client as trusted with the full scope of the underlying PilotSwarm deployment. Concretely:
|
|
457
|
+
|
|
458
|
+
- **Authentication is at the transport, not at the tool.** Stdio mode relies on OS-level process isolation; HTTP mode relies on a single shared bearer key (`PILOTSWARM_MCP_KEY`). There is no per-client identity that the server could map to a particular PilotSwarm session.
|
|
459
|
+
- **Tools that take a `session_id` accept it as caller input.** This is true of `read_facts`, `store_fact`, `delete_fact`, and the session-management tools. The server does **not** verify that the calling MCP client "owns" the session it names, because it has no notion of client ownership in the first place. A client that can call the tool can scope its call to any session ID it knows or guesses.
|
|
460
|
+
- **Implication for `read_facts`.** Any client authorized to talk to this MCP endpoint can read facts scoped to any session — including facts another caller wrote with `session_id` set to a different session. The `reader_session_id` and `granted_session_ids` parameters are likewise caller-supplied and exist to drive the SDK's fact-access checks; they are not themselves authenticated.
|
|
461
|
+
- **What the server does enforce.** DNS-rebinding defense via the `Host` header allowlist (`--allowed-hosts`), constant-time bearer comparison, a per-process session cap (`--max-sessions`), and standard CORS headers. These protect the endpoint perimeter; they do not subdivide privilege between clients past the perimeter.
|
|
462
|
+
|
|
463
|
+
If your deployment needs a stricter per-client privilege boundary (e.g. each MCP client may only read facts for sessions it owns), the right place to add it is the transport / auth layer — for example, by issuing per-client bearer keys, mapping each key to an allowed session-ID set, and enforcing that mapping in middleware before the tool dispatch. The current tool layer intentionally does not pretend to enforce a boundary it cannot see.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## Architecture
|
|
468
|
+
|
|
469
|
+
The MCP server uses the official [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) and [Hono](https://hono.dev/) for the HTTP layer.
|
|
470
|
+
|
|
471
|
+
**Stdio mode** — a single `McpServer` instance connects to one stdio transport.
|
|
472
|
+
|
|
473
|
+
**HTTP mode** — each HTTP client session gets its own `McpServer` + `WebStandardStreamableHTTPServerTransport` pair. This is required by the MCP SDK (each `server.connect(transport)` call is one-shot). Client sessions are tracked by the `mcp-session-id` header and cleaned up on disconnect.
|
|
474
|
+
|
|
475
|
+
**Shared context** — all server instances share a single `PilotSwarmClient`, `PilotSwarmManagementClient`, and `FactStore`. Tools and resources dispatch to these shared services regardless of which MCP session they belong to. In Web API mode those are the `{ apiUrl }` clients plus a `WebFactStore`; in direct mode they connect straight to the datastore (`PgFactStore` + `ModelProviderRegistry`).
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
MCP Client (Claude, Cursor, etc.)
|
|
479
|
+
│
|
|
480
|
+
├── stdio ──→ McpServer ──→ Shared Context ──┬─ web: /api/v1 ──→ deployment
|
|
481
|
+
│ │
|
|
482
|
+
└── HTTP ───→ Hono /mcp ──→ Per-session └─ direct: PilotSwarm DB (internal)
|
|
483
|
+
McpServer ──→ Shared Context
|
|
484
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pilotswarm-mcp.d.ts","sourceRoot":"","sources":["../../bin/pilotswarm-mcp.ts"],"names":[],"mappings":""}
|