vantage-peers-mcp 2.12.1 → 2.13.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 +218 -3
- package/dist/server.js +0 -0
- package/dist/src/paging.d.ts +21 -0
- package/dist/src/paging.js +26 -0
- package/dist/src/tools/exportOkfBundle.d.ts +5 -2
- package/dist/src/tools/exportOkfBundle.js +10 -3
- package/dist/src/tools/importOkfBundle.d.ts +45 -0
- package/dist/src/tools/importOkfBundle.js +81 -0
- package/dist/src/tools/validateOkfBundle.d.ts +43 -0
- package/dist/src/tools/validateOkfBundle.js +80 -0
- package/dist/src/tools.d.ts +94 -0
- package/dist/src/tools.js +776 -240
- package/package.json +1 -1
- package/dist/src/crypto.d.ts +0 -23
- package/dist/src/crypto.js +0 -39
- package/dist/src/scope-filter.d.ts +0 -65
- package/dist/src/scope-filter.js +0 -84
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ Day 92 VP MCP quality overhaul (mission `k57a36y8w5t085bqr23dsmvb2d882506`, PR #
|
|
|
25
25
|
- **C1 — 87 Zod `outputSchema` exports** following the per-family envelope standard (`create_*` → `{id,...}`, `list_*` → `{items,cursor}`, `delete_*` → `{id,deleted:true}`, etc.) based on the `whoamiOutputSchema` precedent (commit `5231811`).
|
|
26
26
|
- **C2 — Unicode NFC normalization + case-insensitive orchestrator-ID matching** applied at all write paths and filter comparisons; closes the NFD/NFC silent mismatch class discovered in the Hélios/helios production regression.
|
|
27
27
|
- **C3 — 97 tool descriptions standardized** (1-line summary + WHEN clause + concrete EXAMPLE, 80–500 chars) + 10 canonical aliases aligned to the `verb_noun_snake` whitelist.
|
|
28
|
+
- **PR-J (Day 113) — canonical 114-tool snapshot quality gate** (`mcp-server/src/__tests__/tools-descriptions-canonical.test.ts`): inventory floor ≥100, length floor ≥60 chars, placeholder ban, category contracts (every `list_*` mentions `limit` + `cap`/`default 20`/`default 100`; every recall-class tool carries the PR-H VP-Sources doctrine verbatim). 15 `list_*` descriptions amended in T-GREEN `41944dc` to add the paging qualifier `Default limit N. cap M.` aligned with PR-A/B/C/E precedent.
|
|
28
29
|
- **C4 — `claude-peers` legacy references removed** from source and docs + grep-gate CI check to prevent reintroduction.
|
|
29
30
|
- **A3 — `whoami` LECTURE tool** (PR #661, commit `5231811`) — returns `suggested_orchestrator_id`, `scope_profile`, and `namespace_read_prefixes` so skills auto-resolve identity without prompting the user.
|
|
30
31
|
- **F1 — `validate_task_payload` validator tool** (commit `cf6c961`) — client-side payload validation before any write reaches Convex.
|
|
@@ -96,8 +97,87 @@ The server also reads `CONVEX_URL` from `.env.local` in the parent directory if
|
|
|
96
97
|
### Profiles (3)
|
|
97
98
|
`get_profile`, `update_profile`, `list_peers`
|
|
98
99
|
|
|
99
|
-
### Tasks (
|
|
100
|
-
`create_task`, `list_tasks`, `list_tasks_by_mission`, `update_task`, `start_task`, `complete_task`, `checkout_task`, `delete_task`, `block_task`, `add_task_dependency`
|
|
100
|
+
### Tasks (11)
|
|
101
|
+
`create_task`, `list_tasks`, `list_tasks_by_mission`, `update_task`, `start_task`, `complete_task`, `checkout_task`, `delete_task`, `block_task`, `add_task_dependency`, `bulk_complete_tasks`
|
|
102
|
+
|
|
103
|
+
#### `list_tasks` — args schema + `excludeAutoGenerated` filter (PR-E)
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
list_tasks(assignedTo?, status?, missionId?, createdBy?, updatedSince?, createdBefore?, limit?, cursor?, fields?, excludeAutoGenerated?)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
| Arg | Type | Default | Notes |
|
|
110
|
+
|-----|------|---------|-------|
|
|
111
|
+
| `assignedTo` | string | — | Filter by assignee (e.g. `"pi"`). |
|
|
112
|
+
| `status` | string \| string[] \| alias | — | Single status, array, or alias (`"open"`, `"active"`, `"all"`). |
|
|
113
|
+
| `missionId` | string | — | Filter to tasks in a specific mission. |
|
|
114
|
+
| `createdBy` | string | — | Filter by creator (e.g. `"sigma"`). |
|
|
115
|
+
| `updatedSince` | number | — | Epoch ms. Returns tasks with `updatedAt >= this`. |
|
|
116
|
+
| `createdBefore` | number | — | Epoch ms. Pagination anchor (legacy; prefer `cursor`). |
|
|
117
|
+
| `limit` | number 1–200 | `50` | Page size. |
|
|
118
|
+
| `cursor` | string | — | Opaque token from prior `nextCursor`. |
|
|
119
|
+
| `fields` | `"lite"\|"full"` | `"full"` | `"lite"` returns `{_id, _creationTime, title, status, priority, assignedTo, missionId}`. |
|
|
120
|
+
| `excludeAutoGenerated` | boolean | `false` | When `true`, filters tasks where `createdBy ~ /^cron-/i` OR `title ~ /^\/?check-messages$/i`. Default `false` — backward-compatible. |
|
|
121
|
+
|
|
122
|
+
**`excludeAutoGenerated` cron contract:**
|
|
123
|
+
- `createdBy` matches `/^cron-/i` (dash mandatory): `cron-bot` is filtered, `cronus` is **not** filtered.
|
|
124
|
+
- `title` matches `/^\/?check-messages$/i` (whole-string, optional leading slash, case-insensitive).
|
|
125
|
+
- Filter applied in-memory after existing query filters, before envelope assembly.
|
|
126
|
+
- **Post-filter pages may be smaller than `limit`** — filtered rows do not count toward limit. Acceptable for cron-spam catalog (small, narrowly targeted).
|
|
127
|
+
|
|
128
|
+
Example — Pi queue cleaned of cron-spam:
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"tool": "list_tasks",
|
|
132
|
+
"arguments": { "assignedTo": "pi", "status": "open", "excludeAutoGenerated": true, "limit": 50 }
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Returns `{ items: Task[], nextCursor: string | null }`. `nextCursor` is `null` on the last page.
|
|
137
|
+
|
|
138
|
+
#### `bulk_complete_tasks` — args schema + dry-run-default safety (PR-F)
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
bulk_complete_tasks(filter, dryRun?, completionNoteTemplate?, callerOrchestrator?)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
| Arg | Type | Default | Notes |
|
|
145
|
+
|-----|------|---------|-------|
|
|
146
|
+
| `filter` | object | (required) | Filter object. Currently: `{ autoGeneratedOnly?: boolean }`. |
|
|
147
|
+
| `filter.autoGeneratedOnly` | boolean | `false` | When `true`, matches tasks where `createdBy ~ /^cron-/i` OR `title ~ /^\/?check-messages$/i`. |
|
|
148
|
+
| `dryRun` | boolean | `true` | **Safety default.** When `true`, returns a preview `{count, sampleIds, bulkRunId}` without mutating. Pass `false` explicitly to commit. |
|
|
149
|
+
| `completionNoteTemplate` | string | (see below) | Template string for the `completionNote` written to each closed task. Supports `{{day}}`, `{{bulkRunId}}`, `{{executedAt}}` interpolation. Default: `"bulk-cleanup: cron-spam day {{day}} runId={{bulkRunId}} executedAt={{executedAt}}"`. |
|
|
150
|
+
| `callerOrchestrator` | string | — | Caller identity for RBAC. When provided and not `"system"`, every matched task must have `createdBy` or `assignedTo` equal to the caller — otherwise throws `RBAC_DENIED`. |
|
|
151
|
+
|
|
152
|
+
**`dryRun` safety note:** `bulk_complete_tasks` always defaults `dryRun` to `true`. Calling the tool without `dryRun=false` never mutates the database. This mirrors the two-step pattern required for all destructive bulk operations: preview first, then commit.
|
|
153
|
+
|
|
154
|
+
**`excludeAutoGenerated` cron contract** (same as `list_tasks`):
|
|
155
|
+
- `createdBy` matches `/^cron-/i` (dash mandatory): `cron-bot` is filtered, `cronus` is **not** filtered.
|
|
156
|
+
- `title` matches `/^\/?check-messages$/i` (whole-string, optional leading slash, case-insensitive).
|
|
157
|
+
- Filter applied in-memory against all non-done tasks.
|
|
158
|
+
- **Post-filter count may be smaller than expected** — same trade-off as `list_tasks excludeAutoGenerated`.
|
|
159
|
+
|
|
160
|
+
Examples:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
// Step 1 — dry-run preview (default dryRun=true)
|
|
164
|
+
{
|
|
165
|
+
"tool": "bulk_complete_tasks",
|
|
166
|
+
"arguments": { "filter": { "autoGeneratedOnly": true }, "callerOrchestrator": "system" }
|
|
167
|
+
}
|
|
168
|
+
// → { "count": 152, "sampleIds": ["k17...", "k18..."], "bulkRunId": "bulk-1782050000000-a3f2" }
|
|
169
|
+
|
|
170
|
+
// Step 2 — commit (explicit dryRun=false)
|
|
171
|
+
{
|
|
172
|
+
"tool": "bulk_complete_tasks",
|
|
173
|
+
"arguments": { "filter": { "autoGeneratedOnly": true }, "dryRun": false, "callerOrchestrator": "system" }
|
|
174
|
+
}
|
|
175
|
+
// → { "count": 152, "sampleIds": ["k17...", "k18..."], "bulkRunId": "bulk-1782050000000-a3f2", "executedAt": 1782050000000 }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Returns `{ count, sampleIds, bulkRunId, executedAt? }`:
|
|
179
|
+
- `dryRun=true` — `{ count, sampleIds, bulkRunId }` (no `executedAt`).
|
|
180
|
+
- `dryRun=false` — `{ count, sampleIds, bulkRunId, executedAt }` — `bulkRunId` is the Day-76 evidence token; `executedAt` is the mutation epoch ms.
|
|
101
181
|
|
|
102
182
|
### Missions (6)
|
|
103
183
|
`create_mission`, `list_missions`, `update_mission`, `update_mission_status`, `get_mission_template`, `get_mission`
|
|
@@ -114,9 +194,45 @@ The server also reads `CONVEX_URL` from `.env.local` in the parent directory if
|
|
|
114
194
|
### Briefing Notes (2)
|
|
115
195
|
`create_briefing_note`, `list_briefing_notes`
|
|
116
196
|
|
|
197
|
+
#### `list_briefing_notes` — VP-Sources doctrine (PR-H)
|
|
198
|
+
|
|
199
|
+
Exports `LIST_BRIEFING_NOTES_TOOL_DESCRIPTION` from `mcp-server/src/tools.ts`.
|
|
200
|
+
|
|
201
|
+
Same two advisory VP-Sources doctrine paragraphs appended after the existing description (identical strings, see `recall` in Search / RAG above).
|
|
202
|
+
|
|
203
|
+
#### `search_briefing_notes_by_keyword` — VP-Sources doctrine (PR-H)
|
|
204
|
+
|
|
205
|
+
Exports `SEARCH_BRIEFING_NOTES_BY_KEYWORD_TOOL_DESCRIPTION` from `mcp-server/src/tools.ts`.
|
|
206
|
+
|
|
207
|
+
Same two advisory VP-Sources doctrine paragraphs appended after the existing description (identical strings, see `recall` in Search / RAG above).
|
|
208
|
+
|
|
117
209
|
### Search / RAG (3)
|
|
118
210
|
`search_fix_patterns_by_semantic` (alias `search_fix_patterns`), `search_memories_by_keyword` (alias `text_search`), `hybrid_search`
|
|
119
211
|
|
|
212
|
+
#### `recall` — VP-Sources doctrine (PR-H)
|
|
213
|
+
|
|
214
|
+
Alias of `search_memories_by_semantic`. Exports `RECALL_TOOL_DESCRIPTION` from `mcp-server/src/tools.ts`.
|
|
215
|
+
|
|
216
|
+
The description now embeds two advisory VP-Sources doctrine paragraphs appended after the existing text:
|
|
217
|
+
|
|
218
|
+
> VP-Sources doctrine: MUST be called before any factual claim about fleet state, audits, dette tooling, mission/task/client status, incident history, doctrine references.
|
|
219
|
+
>
|
|
220
|
+
> Cite returned ids in the answer footer as 'VP-Sources: recall("\<q\>")→[ids] | none-needed:\<reason\>'.
|
|
221
|
+
|
|
222
|
+
Doctrine is advisory-only — no hook blocks on absence. Client LLMs read the doctrine at tool-list time.
|
|
223
|
+
|
|
224
|
+
#### `text_search` — VP-Sources doctrine (PR-H)
|
|
225
|
+
|
|
226
|
+
Alias of `search_memories_by_keyword`. Exports `TEXT_SEARCH_TOOL_DESCRIPTION` from `mcp-server/src/tools.ts`.
|
|
227
|
+
|
|
228
|
+
Same two advisory VP-Sources doctrine paragraphs appended after the existing description (identical strings, see `recall` above).
|
|
229
|
+
|
|
230
|
+
#### `hybrid_search` — VP-Sources doctrine (PR-H)
|
|
231
|
+
|
|
232
|
+
Exports `HYBRID_SEARCH_TOOL_DESCRIPTION` from `mcp-server/src/tools.ts`.
|
|
233
|
+
|
|
234
|
+
Same two advisory VP-Sources doctrine paragraphs appended after the existing description (identical strings, see `recall` above).
|
|
235
|
+
|
|
120
236
|
### Issues (6)
|
|
121
237
|
`get_issue`, `list_issues`, `update_issue_status`, `verify_issue`, `issue_stats`, `link_commit_to_issue`
|
|
122
238
|
|
|
@@ -227,12 +343,58 @@ Example:
|
|
|
227
343
|
### Deployments & Repos (5)
|
|
228
344
|
`add_deployment`, `remove_deployment`, `list_repo_mappings`, `add_repo_mapping`, `remove_repo_mapping`
|
|
229
345
|
|
|
346
|
+
#### `list_repo_mappings` — args schema + defaults (PR-C)
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
list_repo_mappings(limit?, cursor?, fields?)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
| Arg | Type | Default | Notes |
|
|
353
|
+
|-----|------|---------|-------|
|
|
354
|
+
| `limit` | number 1–200 | `20` | Page size. Capped at `200` server-side. |
|
|
355
|
+
| `cursor` | string | — | Opaque token from prior `nextCursor`. |
|
|
356
|
+
| `fields` | `"lite"\|"full"` | `"full"` | `"lite"` returns `{_id, _creationTime, repo, orchestrator, project}`. `"full"` returns complete mapping object (including `active`, `lastDeployedSHA`, `lastDeployedAt`). |
|
|
357
|
+
|
|
358
|
+
Returns `{ items: RepoMapping[], nextCursor: string | null }`. `nextCursor` is `null` on the last page.
|
|
359
|
+
|
|
230
360
|
### Business Units (5)
|
|
231
361
|
`create_bu`, `list_bus`, `get_bu`, `update_bu`, `delete_bu`
|
|
232
362
|
|
|
363
|
+
#### `list_bus` — args schema + defaults (PR-A)
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
list_bus(orchestratorId?, status?, limit?, cursor?, fields?)
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
| Arg | Type | Default | Notes |
|
|
370
|
+
|-----|------|---------|-------|
|
|
371
|
+
| `orchestratorId` | string | — | Filter by lead orchestrator (e.g. `"sigma"`). |
|
|
372
|
+
| `status` | `"idea"\|"building"\|"live"\|"revenue"` | — | Filter by lifecycle status. |
|
|
373
|
+
| `limit` | number 1–200 | `20` | Page size. Capped at `200` server-side. |
|
|
374
|
+
| `cursor` | string | — | Opaque token from prior `nextCursor`. |
|
|
375
|
+
| `fields` | `"lite"\|"full"` | `"full"` | `"lite"` returns `{_id, name, status, orchestratorId, _creationTime}`. `"full"` returns complete BU object (18+ keys). |
|
|
376
|
+
|
|
377
|
+
Returns `{ items: BusinessUnit[], nextCursor: string | null }`. `nextCursor` is `null` on the last page.
|
|
378
|
+
|
|
233
379
|
### Components (6)
|
|
234
380
|
`register_component`, `list_components`, `get_component`, `update_component`, `delete_component`, `search_components_by_keyword` (alias `search_components`)
|
|
235
381
|
|
|
382
|
+
#### `list_components` — args schema + defaults (PR-B)
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
list_components(type?, team?, limit?, cursor?, fields?)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
| Arg | Type | Default | Notes |
|
|
389
|
+
|-----|------|---------|-------|
|
|
390
|
+
| `type` | `"agent"\|"skill"\|"hook"\|"plugin"` | — | Filter by component type. |
|
|
391
|
+
| `team` | string | — | Filter by team (e.g. `"development"`). |
|
|
392
|
+
| `limit` | number 1–200 | `20` | Page size. Capped at `200` server-side. |
|
|
393
|
+
| `cursor` | string | — | Opaque token from prior `nextCursor`. |
|
|
394
|
+
| `fields` | `"lite"\|"full"` | `"full"` | `"lite"` returns `{_id, _creationTime, name, type, team}`. `"full"` returns complete component object. |
|
|
395
|
+
|
|
396
|
+
Returns `{ items: Component[], nextCursor: string | null }`. `nextCursor` is `null` on the last page.
|
|
397
|
+
|
|
236
398
|
### Mandates (6)
|
|
237
399
|
`create_mandate`, `list_mandates`, `accept_mandate`, `update_mandate`, `validate_mandate_spending`, `settle_mandate`
|
|
238
400
|
|
|
@@ -242,11 +404,61 @@ Example:
|
|
|
242
404
|
### Session (1)
|
|
243
405
|
`set_summary`
|
|
244
406
|
|
|
407
|
+
### Observability (1)
|
|
408
|
+
`improvisation_digest`
|
|
409
|
+
|
|
410
|
+
#### `improvisation_digest` — weekly advisory digest (PR-I)
|
|
411
|
+
|
|
412
|
+
Scans a rolling time window of VP tasks, messages, and memories for records carrying fleet/state tokens (commit SHA, PR#, VP id, decisive verb) with **no VP-Sources footer** — the Eta heuristic proxy for "made a fleet-state claim without a prior `recall` upstream".
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
improvisation_digest(windowDays?, orchestrators?)
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
| Arg | Type | Default | Notes |
|
|
419
|
+
|-----|------|---------|-------|
|
|
420
|
+
| `windowDays` | number | `7` | Days to look back. |
|
|
421
|
+
| `orchestrators` | string[] | — | Scope to these roles only (e.g. `["sigma","pi"]`). Omit for all orchestrators. |
|
|
422
|
+
|
|
423
|
+
**Returns:**
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
{
|
|
427
|
+
countsByOrch: Record<string, number>, // hit count per orchestrator
|
|
428
|
+
countsByCategory: Record<string, number>, // hit count per record type (task/message/memory)
|
|
429
|
+
samples: Array<{
|
|
430
|
+
id: string,
|
|
431
|
+
category: string,
|
|
432
|
+
orchestrator: string,
|
|
433
|
+
snippet: string
|
|
434
|
+
}> // up to 50 representative snippets
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**ADVISORY-only.** Pure read query — never blocks any action. Results are informational: a high improvisation rate suggests a team should increase VP-Sources citation hygiene, but the tool itself takes no automated action.
|
|
439
|
+
|
|
440
|
+
**V1 scope (Option C):** scans VP records (tasks + messages + memories) only. Per Pi Day-113 arbitration (msg `k97a0pp6kq1axkj6cmc4pecpy989ce1w`), fallback if V1 misses too many = **Option B** (new dedicated `sessions` Convex table), not Option A (JSONL replay).
|
|
441
|
+
|
|
442
|
+
**Detection heuristic (Eta A5 scope filter):**
|
|
443
|
+
- Flag condition 1: record body contains a durable-artifact token (7–40 hex SHA, `#NNN`, Convex ID prefix, or decisive verb `merged/deployed/approved/shipped/released/fixed`).
|
|
444
|
+
- Flag condition 2: record body does NOT contain the `VP-Sources:` footer substring.
|
|
445
|
+
- A5 scope: excludes `system`, `cron-*`, and webhook-sourced entries.
|
|
446
|
+
|
|
447
|
+
Examples:
|
|
448
|
+
|
|
449
|
+
```json
|
|
450
|
+
// Default 7-day window, all orchestrators
|
|
451
|
+
{ "tool": "improvisation_digest", "arguments": { "windowDays": 7 } }
|
|
452
|
+
|
|
453
|
+
// Scoped to one orchestrator
|
|
454
|
+
{ "tool": "improvisation_digest", "arguments": { "windowDays": 14, "orchestrators": ["sigma"] } }
|
|
455
|
+
```
|
|
456
|
+
|
|
245
457
|
## Compact payloads and status aliases (v2.12.0 — feature since v2.3.0)
|
|
246
458
|
|
|
247
459
|
### `fields=lite` — reduced token payloads
|
|
248
460
|
|
|
249
|
-
`list_tasks`, `list_tasks_by_mission`, `list_missions`, and `
|
|
461
|
+
`list_tasks`, `list_tasks_by_mission`, `list_missions`, `list_briefing_notes`, `list_bus`, `list_components`, and `list_repo_mappings` accept an optional `fields` parameter:
|
|
250
462
|
|
|
251
463
|
| Value | Behaviour |
|
|
252
464
|
|-------|-----------|
|
|
@@ -260,6 +472,9 @@ Lite projections per entity:
|
|
|
260
472
|
| `list_tasks` / `list_tasks_by_mission` | `_id`, `_creationTime`, `title`, `status`, `priority`, `assignedTo`, `missionId` |
|
|
261
473
|
| `list_missions` | `_id`, `_creationTime`, `name`, `status`, `pilot`, `priority`, `project` |
|
|
262
474
|
| `list_briefing_notes` | `_id`, `_creationTime`, `topic`, `title`, `participants`, `createdBy` |
|
|
475
|
+
| `list_bus` | `_id`, `_creationTime`, `name`, `status`, `orchestratorId` — PR-A activated actual projection (was no-op since v2.4.12) |
|
|
476
|
+
| `list_components` | `_id`, `_creationTime`, `name`, `type`, `team` — PR-B activated actual projection (was no-op — returned full row) |
|
|
477
|
+
| `list_repo_mappings` | `_id`, `_creationTime`, `repo`, `orchestrator`, `project` — PR-C activated actual projection (excludes `active`, `lastDeployedSHA`, `lastDeployedAt`) |
|
|
263
478
|
|
|
264
479
|
Example (tasks lite):
|
|
265
480
|
```json
|
package/dist/server.js
CHANGED
|
File without changes
|
package/dist/src/paging.d.ts
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const pagingArgsSchema: z.ZodObject<{
|
|
3
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
4
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
5
|
+
fields: z.ZodOptional<z.ZodEnum<{
|
|
6
|
+
lite: "lite";
|
|
7
|
+
full: "full";
|
|
8
|
+
}>>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export type PagingArgs = z.infer<typeof pagingArgsSchema>;
|
|
11
|
+
export interface PagingDefaults {
|
|
12
|
+
limit: number;
|
|
13
|
+
cap: number;
|
|
14
|
+
fields: "lite" | "full";
|
|
15
|
+
}
|
|
16
|
+
export declare const DEFAULT_PAGING: PagingDefaults;
|
|
17
|
+
export declare function applyPagingDefaults(args: PagingArgs, defaults?: PagingDefaults): {
|
|
18
|
+
limit: number;
|
|
19
|
+
cursor: string | undefined;
|
|
20
|
+
fields: "lite" | "full";
|
|
21
|
+
};
|
|
1
22
|
/**
|
|
2
23
|
* Shared paging utility for VP MCP `list_*` tools (S3.3 B8).
|
|
3
24
|
*
|
package/dist/src/paging.js
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
// PR-A envelope safety — shared schema + applyPagingDefaults helper
|
|
4
|
+
// Reusable by list_bus, list_tasks (PR-B), list_memories (PR-C) etc.
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
export const pagingArgsSchema = z.object({
|
|
7
|
+
limit: z.number().int().min(1).max(200).optional(),
|
|
8
|
+
cursor: z.string().optional(),
|
|
9
|
+
fields: z.enum(["lite", "full"]).optional(),
|
|
10
|
+
});
|
|
11
|
+
export const DEFAULT_PAGING = {
|
|
12
|
+
limit: 20,
|
|
13
|
+
cap: 200,
|
|
14
|
+
fields: "full",
|
|
15
|
+
};
|
|
16
|
+
export function applyPagingDefaults(args, defaults = DEFAULT_PAGING) {
|
|
17
|
+
const requested = args.limit ?? defaults.limit;
|
|
18
|
+
const clamped = Math.min(requested, defaults.cap);
|
|
19
|
+
const limit = Math.max(1, clamped);
|
|
20
|
+
return {
|
|
21
|
+
limit,
|
|
22
|
+
cursor: args.cursor,
|
|
23
|
+
fields: args.fields ?? defaults.fields,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1
27
|
/**
|
|
2
28
|
* Shared paging utility for VP MCP `list_*` tools (S3.3 B8).
|
|
3
29
|
*
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
* Claude Code, Codex, IDE…) via the public VantagePeers Cloud surface.
|
|
7
7
|
*
|
|
8
8
|
* **VantagePeers Cloud, multi-tenant**: this is the Cloud product (NOT
|
|
9
|
-
* Self-host).
|
|
10
|
-
*
|
|
9
|
+
* Self-host). The Convex action enforces auth — caller must match the
|
|
10
|
+
* namespace tail when an identity is attached (cross-tenant export
|
|
11
|
+
* forbidden). The Phase 1 hard lock to `project/elpi-corp` was relaxed by
|
|
12
|
+
* B3 (mission k5779qbxh, task k17f3407) so any `team/<orgId>/*` tenant can
|
|
13
|
+
* export their own bundle.
|
|
11
14
|
*
|
|
12
15
|
* RFC parent: decisions/okf-bridge-phase-1-rfc-2026-06-18.md (commit 6613610).
|
|
13
16
|
* ADR: decisions/adr-okf-exporter-arch.md (commit 2cd357e).
|
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
* Claude Code, Codex, IDE…) via the public VantagePeers Cloud surface.
|
|
7
7
|
*
|
|
8
8
|
* **VantagePeers Cloud, multi-tenant**: this is the Cloud product (NOT
|
|
9
|
-
* Self-host).
|
|
10
|
-
*
|
|
9
|
+
* Self-host). The Convex action enforces auth — caller must match the
|
|
10
|
+
* namespace tail when an identity is attached (cross-tenant export
|
|
11
|
+
* forbidden). The Phase 1 hard lock to `project/elpi-corp` was relaxed by
|
|
12
|
+
* B3 (mission k5779qbxh, task k17f3407) so any `team/<orgId>/*` tenant can
|
|
13
|
+
* export their own bundle.
|
|
11
14
|
*
|
|
12
15
|
* RFC parent: decisions/okf-bridge-phase-1-rfc-2026-06-18.md (commit 6613610).
|
|
13
16
|
* ADR: decisions/adr-okf-exporter-arch.md (commit 2cd357e).
|
|
@@ -22,7 +25,11 @@ import { z } from "zod";
|
|
|
22
25
|
export const exportOkfBundleArgsSchema = {
|
|
23
26
|
namespace: z
|
|
24
27
|
.string()
|
|
25
|
-
.describe("OKF export namespace.
|
|
28
|
+
.describe("OKF export namespace prefix. Any prefix the caller has write scope on " +
|
|
29
|
+
"is accepted (e.g. 'project/elpi-corp', 'team/<orgId>', 'org/<slug>'). " +
|
|
30
|
+
"Identity-attached callers must match the namespace tail (cross-tenant " +
|
|
31
|
+
"export forbidden). The 'project/elpi-corp' Phase 1 hard lock was " +
|
|
32
|
+
"removed by B3 (mission k5779qbxh) for multi-tenant Cloud dashboards."),
|
|
26
33
|
types: z
|
|
27
34
|
.array(z.string())
|
|
28
35
|
.nullable()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: import_okf_bundle (OKF Phase 2 — B2 / T-OKF-PHASE2-B).
|
|
3
|
+
*
|
|
4
|
+
* Thin proxy around the Convex `okfBundleNode:importOkfBundle` action. Imports
|
|
5
|
+
* memories / briefing-notes / tasks from an OKF v0.1 bundle into the target
|
|
6
|
+
* namespace, deduplicating by content equality so replays of the same bundle
|
|
7
|
+
* are no-ops.
|
|
8
|
+
*
|
|
9
|
+
* **VantagePeers Cloud, multi-tenant**: this is the Cloud product (NOT
|
|
10
|
+
* Self-host). The Convex action gates cross-tenant writes via the same
|
|
11
|
+
* fail-closed null-identity guard that protects exportOkfBundle (Eta REVISE
|
|
12
|
+
* iter-2 on #888). This wrapper only forwards arguments.
|
|
13
|
+
*
|
|
14
|
+
* Mission: k5779qbxhwrfjmj02t31yvehns8911jp.
|
|
15
|
+
* Task: k17fja9v7pgnf25yvzkwrj5ch5891bb3.
|
|
16
|
+
*
|
|
17
|
+
* Orchestrator: Sigma — VantagePeers | 2026-06-20
|
|
18
|
+
*/
|
|
19
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
20
|
+
import type { ConvexHttpClient } from "convex/browser";
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
export interface ImportOkfBundleResult {
|
|
23
|
+
imported: {
|
|
24
|
+
memories: number;
|
|
25
|
+
briefings: number;
|
|
26
|
+
tasks: number;
|
|
27
|
+
};
|
|
28
|
+
skipped: number;
|
|
29
|
+
conflicts: Array<{
|
|
30
|
+
path: string;
|
|
31
|
+
reason: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export declare const importOkfBundleArgsSchema: {
|
|
35
|
+
bundleUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
36
|
+
storageId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
37
|
+
targetNamespace: z.ZodString;
|
|
38
|
+
mode: z.ZodEnum<{
|
|
39
|
+
"dry-run": "dry-run";
|
|
40
|
+
merge: "merge";
|
|
41
|
+
replace: "replace";
|
|
42
|
+
}>;
|
|
43
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
44
|
+
};
|
|
45
|
+
export declare function registerImportOkfBundle(server: McpServer, convex: ConvexHttpClient): void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: import_okf_bundle (OKF Phase 2 — B2 / T-OKF-PHASE2-B).
|
|
3
|
+
*
|
|
4
|
+
* Thin proxy around the Convex `okfBundleNode:importOkfBundle` action. Imports
|
|
5
|
+
* memories / briefing-notes / tasks from an OKF v0.1 bundle into the target
|
|
6
|
+
* namespace, deduplicating by content equality so replays of the same bundle
|
|
7
|
+
* are no-ops.
|
|
8
|
+
*
|
|
9
|
+
* **VantagePeers Cloud, multi-tenant**: this is the Cloud product (NOT
|
|
10
|
+
* Self-host). The Convex action gates cross-tenant writes via the same
|
|
11
|
+
* fail-closed null-identity guard that protects exportOkfBundle (Eta REVISE
|
|
12
|
+
* iter-2 on #888). This wrapper only forwards arguments.
|
|
13
|
+
*
|
|
14
|
+
* Mission: k5779qbxhwrfjmj02t31yvehns8911jp.
|
|
15
|
+
* Task: k17fja9v7pgnf25yvzkwrj5ch5891bb3.
|
|
16
|
+
*
|
|
17
|
+
* Orchestrator: Sigma — VantagePeers | 2026-06-20
|
|
18
|
+
*/
|
|
19
|
+
import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
export const importOkfBundleArgsSchema = {
|
|
22
|
+
bundleUrl: z
|
|
23
|
+
.string()
|
|
24
|
+
.nullable()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Signed HTTPS URL to a tarball OKF v0.1 bundle. Mutually exclusive with storageId."),
|
|
27
|
+
storageId: z
|
|
28
|
+
.string()
|
|
29
|
+
.nullable()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Convex `_storage` document ID of a previously-uploaded tarball. Mutually exclusive with bundleUrl."),
|
|
32
|
+
targetNamespace: z
|
|
33
|
+
.string()
|
|
34
|
+
.describe("Destination namespace, e.g. 'team/<orgId>' or 'project/<slug>'. Cross-tenant writes are denied."),
|
|
35
|
+
mode: z
|
|
36
|
+
.enum(["dry-run", "merge", "replace"])
|
|
37
|
+
.describe("dry-run = preview counts, no writes. merge = insert new + dedup by content. replace = reserved."),
|
|
38
|
+
idempotencyKey: z
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Caller-supplied replay token. Same key + same content = no duplicate inserts."),
|
|
42
|
+
};
|
|
43
|
+
export function registerImportOkfBundle(server, convex) {
|
|
44
|
+
server.tool("import_okf_bundle", "Import an OKF v0.1 bundle (memories + briefing-notes + tasks) into a target VantagePeers namespace. " +
|
|
45
|
+
"WHEN: use to restore a snapshot, migrate workspace data between tenants, or replay an export. " +
|
|
46
|
+
"EXAMPLE: import_okf_bundle storageId='abc...' targetNamespace='team/iris-rh' mode='merge'.", importOkfBundleArgsSchema, {
|
|
47
|
+
readOnlyHint: false,
|
|
48
|
+
openWorldHint: false,
|
|
49
|
+
destructiveHint: false,
|
|
50
|
+
title: "Import OKF bundle",
|
|
51
|
+
}, async ({ bundleUrl, storageId, targetNamespace, mode, idempotencyKey }) => {
|
|
52
|
+
try {
|
|
53
|
+
const result = (await convex.action("okfBundleNode:importOkfBundle", {
|
|
54
|
+
bundleUrl: bundleUrl ?? null,
|
|
55
|
+
storageId: storageId ?? null,
|
|
56
|
+
targetNamespace,
|
|
57
|
+
mode,
|
|
58
|
+
idempotencyKey,
|
|
59
|
+
}));
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: JSON.stringify(result, null, 2),
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error instanceof McpError)
|
|
71
|
+
throw error;
|
|
72
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
73
|
+
console.error("[import_okf_bundle] action failed", {
|
|
74
|
+
targetNamespace,
|
|
75
|
+
mode,
|
|
76
|
+
errorMessage: message,
|
|
77
|
+
});
|
|
78
|
+
throw new McpError(ErrorCode.InternalError, message);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: validate_okf_bundle (OKF Phase 2 — B1 / T-OKF-PHASE2-A).
|
|
3
|
+
*
|
|
4
|
+
* Thin proxy around the Convex `okfBundleNode:validateOkfBundle` action. Lets
|
|
5
|
+
* any MCP client (Claude.ai, ChatGPT, Claude Code, Codex, IDE…) verify a bundle's
|
|
6
|
+
* conformance to OKF v0.1 (RFC §3.5) before importing it. Read-only — never
|
|
7
|
+
* mutates the database.
|
|
8
|
+
*
|
|
9
|
+
* **VantagePeers Cloud, multi-tenant**: this is the Cloud product (NOT
|
|
10
|
+
* Self-host). The Convex action enforces auth; this wrapper only forwards
|
|
11
|
+
* arguments.
|
|
12
|
+
*
|
|
13
|
+
* RFC parent: decisions/okf-bridge-phase-1-rfc-2026-06-18.md (commit 6613610).
|
|
14
|
+
* Mission: k5779qbxhwrfjmj02t31yvehns8911jp (VP Cloud Dashboard).
|
|
15
|
+
* Task: k1796g7g7y03gn9rd6z7psenk98910vt.
|
|
16
|
+
*
|
|
17
|
+
* Orchestrator: Sigma — VantagePeers | 2026-06-20
|
|
18
|
+
*/
|
|
19
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
20
|
+
import type { ConvexHttpClient } from "convex/browser";
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
export interface ValidateOkfBundleResult {
|
|
23
|
+
valid: boolean;
|
|
24
|
+
schemaVersion: "0.1";
|
|
25
|
+
stats: {
|
|
26
|
+
memoryCount: number;
|
|
27
|
+
briefingCount: number;
|
|
28
|
+
taskCount: number;
|
|
29
|
+
};
|
|
30
|
+
errors?: Array<{
|
|
31
|
+
path: string;
|
|
32
|
+
rule: string;
|
|
33
|
+
message: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export declare const validateOkfBundleArgsSchema: {
|
|
37
|
+
bundleUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
38
|
+
storageId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Register the `validate_okf_bundle` MCP tool against an McpServer instance.
|
|
42
|
+
*/
|
|
43
|
+
export declare function registerValidateOkfBundle(server: McpServer, convex: ConvexHttpClient): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: validate_okf_bundle (OKF Phase 2 — B1 / T-OKF-PHASE2-A).
|
|
3
|
+
*
|
|
4
|
+
* Thin proxy around the Convex `okfBundleNode:validateOkfBundle` action. Lets
|
|
5
|
+
* any MCP client (Claude.ai, ChatGPT, Claude Code, Codex, IDE…) verify a bundle's
|
|
6
|
+
* conformance to OKF v0.1 (RFC §3.5) before importing it. Read-only — never
|
|
7
|
+
* mutates the database.
|
|
8
|
+
*
|
|
9
|
+
* **VantagePeers Cloud, multi-tenant**: this is the Cloud product (NOT
|
|
10
|
+
* Self-host). The Convex action enforces auth; this wrapper only forwards
|
|
11
|
+
* arguments.
|
|
12
|
+
*
|
|
13
|
+
* RFC parent: decisions/okf-bridge-phase-1-rfc-2026-06-18.md (commit 6613610).
|
|
14
|
+
* Mission: k5779qbxhwrfjmj02t31yvehns8911jp (VP Cloud Dashboard).
|
|
15
|
+
* Task: k1796g7g7y03gn9rd6z7psenk98910vt.
|
|
16
|
+
*
|
|
17
|
+
* Orchestrator: Sigma — VantagePeers | 2026-06-20
|
|
18
|
+
*/
|
|
19
|
+
import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
// Zod input schema (RFC §3.5)
|
|
23
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
export const validateOkfBundleArgsSchema = {
|
|
25
|
+
bundleUrl: z
|
|
26
|
+
.string()
|
|
27
|
+
.nullable()
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Optional signed bundle URL — fetched via global `fetch`. " +
|
|
30
|
+
"Mutually exclusive with `storageId`; at least one is required."),
|
|
31
|
+
storageId: z
|
|
32
|
+
.string()
|
|
33
|
+
.nullable()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Optional Convex storage id (`_storage` id) — resolved server-side. " +
|
|
36
|
+
"Mutually exclusive with `bundleUrl`; at least one is required."),
|
|
37
|
+
};
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
// Registration
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
/**
|
|
42
|
+
* Register the `validate_okf_bundle` MCP tool against an McpServer instance.
|
|
43
|
+
*/
|
|
44
|
+
export function registerValidateOkfBundle(server, convex) {
|
|
45
|
+
server.tool("validate_okf_bundle", "Validate an OKF v0.1 bundle (tarball) against the spec (RFC §3.5) without " +
|
|
46
|
+
"importing it. WHEN: use as a preview check before calling import_okf_bundle, " +
|
|
47
|
+
"or to audit a bundle for schema conformance. EXAMPLE: validate_okf_bundle " +
|
|
48
|
+
"storageId='kg2anjqa…' OR validate_okf_bundle bundleUrl='https://…/bundle.tar'.", validateOkfBundleArgsSchema, {
|
|
49
|
+
readOnlyHint: true,
|
|
50
|
+
openWorldHint: false,
|
|
51
|
+
destructiveHint: false,
|
|
52
|
+
title: "Validate OKF bundle",
|
|
53
|
+
}, async ({ bundleUrl, storageId }) => {
|
|
54
|
+
try {
|
|
55
|
+
const result = (await convex.action("okfBundleNode:validateOkfBundle", {
|
|
56
|
+
bundleUrl: bundleUrl ?? null,
|
|
57
|
+
storageId: storageId ?? null,
|
|
58
|
+
}));
|
|
59
|
+
return {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: JSON.stringify(result, null, 2),
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error instanceof McpError)
|
|
70
|
+
throw error;
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
console.error("[validate_okf_bundle] action failed", {
|
|
73
|
+
hasBundleUrl: bundleUrl !== undefined && bundleUrl !== null,
|
|
74
|
+
hasStorageId: storageId !== undefined && storageId !== null,
|
|
75
|
+
errorMessage: message,
|
|
76
|
+
});
|
|
77
|
+
throw new McpError(ErrorCode.InternalError, message);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|