vantage-peers-mcp 2.3.5 → 2.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/CHANGELOG.md +104 -0
- package/README.md +14 -3
- package/dist/server-http.js +27 -1
- package/dist/src/auth.js +9 -3
- package/dist/src/tools.js +567 -50
- package/dist/src/ui-resources/index.d.ts +36 -0
- package/dist/src/ui-resources/index.js +100 -0
- package/dist/src/ui-resources/primitives/briefing-note.d.ts +18 -0
- package/dist/src/ui-resources/primitives/briefing-note.js +126 -0
- package/dist/src/ui-resources/primitives/diary-entry.d.ts +18 -0
- package/dist/src/ui-resources/primitives/diary-entry.js +127 -0
- package/dist/src/ui-resources/primitives/memory-quote.d.ts +16 -0
- package/dist/src/ui-resources/primitives/memory-quote.js +109 -0
- package/dist/src/ui-resources/primitives/messages-feed.d.ts +16 -0
- package/dist/src/ui-resources/primitives/messages-feed.js +117 -0
- package/dist/src/ui-resources/primitives/mission-timeline.d.ts +17 -0
- package/dist/src/ui-resources/primitives/mission-timeline.js +157 -0
- package/dist/src/ui-resources/primitives/tasks-table.d.ts +17 -0
- package/dist/src/ui-resources/primitives/tasks-table.js +130 -0
- package/dist/src/ui-resources/schemas.d.ts +124 -0
- package/dist/src/ui-resources/schemas.js +88 -0
- package/dist/src/ui-resources/stream-marker.d.ts +33 -0
- package/dist/src/ui-resources/stream-marker.js +67 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,109 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.0] — 2026-05-28 — M3 iframeEmbedSessions + __VP_TOOL_RESULT__ stream marker + ack-checklist
|
|
4
|
+
|
|
5
|
+
**Mission instance** : `sigma-vantage-peers-mcp-gui-iframe-embed-v1` (k5730xct6rvrwkvxhy5t5js12d87jwfw).
|
|
6
|
+
**Pi sign-off** : PI_AUTHORIZED_TASK_ID=`k1793m1qgn0zaay6r87dhvsh7187kwya` (PROD-DEPLOY-AUTHORIZED).
|
|
7
|
+
**Eta sign-off** : ETA_APPROVED_TASK_ID=`k171ep964sxabbrgmb21fk9axd87ka1n` at commit `338a7b9e6130ce69dc5fe7f3e2e9ecc4648b4f6a` (Day 79 SHA-pinned).
|
|
8
|
+
**Merge** : PR #545 squash `f509c8d92f0b142bc063a0e9dd070e1993cc729b`.
|
|
9
|
+
|
|
10
|
+
M3 delivers the session registry and stream-marker protocol that connects the VP MCP server
|
|
11
|
+
to the Gen UI iframe bridge. All marker emission is gated behind `VP_EMIT_UI_MARKERS=1`
|
|
12
|
+
so production behaviour is unchanged until the bridge is deployed.
|
|
13
|
+
|
|
14
|
+
### Convex schema — `iframeEmbedSessions` table
|
|
15
|
+
|
|
16
|
+
NEW table `iframeEmbedSessions` in `convex/schema.ts` :
|
|
17
|
+
- Fields : `sessionId` (string), `tenantId` (optional string), `origin` (string),
|
|
18
|
+
`userId` (optional string), `createdAt` (number), `lastSeenAt` (number),
|
|
19
|
+
`expiresAt` (number), `revoked` (boolean).
|
|
20
|
+
- Indexes : `by_session_id` on `["sessionId"]`, `by_origin_expires` on `["origin", "expiresAt"]`.
|
|
21
|
+
|
|
22
|
+
NEW `convex/iframeEmbedSessions.ts` — 4 operations :
|
|
23
|
+
- `createSession` mutation — inserts a new session row.
|
|
24
|
+
- `getSession` query — returns session or null (null for expired / revoked).
|
|
25
|
+
- `touchSession` mutation — bumps `lastSeenAt` to now; returns bool.
|
|
26
|
+
- `revokeSession` mutation — sets `revoked=true`; returns bool.
|
|
27
|
+
|
|
28
|
+
### Stream marker — `mcp-server/src/ui-resources/stream-marker.ts`
|
|
29
|
+
|
|
30
|
+
NEW `MARKER_START = "__VP_TOOL_RESULT__"`, `MARKER_END = "__END__"`.
|
|
31
|
+
|
|
32
|
+
NEW `wrapToolResult(payload: VpToolResult): string` :
|
|
33
|
+
- Validates via `VpToolResultSchema`, throws `TypeError` on schema failure.
|
|
34
|
+
- Returns `__VP_TOOL_RESULT__<json>__END__`.
|
|
35
|
+
|
|
36
|
+
NEW `parseToolResult(text: string): VpToolResult | null` :
|
|
37
|
+
- Extracts marker substring (handles bare, embedded, surrounding text).
|
|
38
|
+
- Returns validated `VpToolResult` or null on any failure (no-throw contract).
|
|
39
|
+
|
|
40
|
+
### MCP tools — marker emission gated by `VP_EMIT_UI_MARKERS=1`
|
|
41
|
+
|
|
42
|
+
`mcp-server/src/tools.ts` — 6 tools now append `wrapToolResult(...)` after the JSON payload
|
|
43
|
+
when `VP_EMIT_UI_MARKERS=1` (default OFF) :
|
|
44
|
+
|
|
45
|
+
| Tool | kind |
|
|
46
|
+
|-----------------------|--------------------|
|
|
47
|
+
| `list_tasks` | `tasks-table` |
|
|
48
|
+
| `list_messages` | `messages-feed` |
|
|
49
|
+
| `get_diary` | `diary-entry` |
|
|
50
|
+
| `list_missions` | `mission-timeline` |
|
|
51
|
+
| `list_briefing_notes` | `briefing-note` |
|
|
52
|
+
| `list_memories` | `memory-quote` |
|
|
53
|
+
|
|
54
|
+
Change is surgical — existing return shape is preserved; marker is appended as a new line.
|
|
55
|
+
|
|
56
|
+
### Ack checklist
|
|
57
|
+
|
|
58
|
+
NEW `docs/M3-ACK-CHECKLIST.md` — bilingual FR/EN post-deploy verification checklist
|
|
59
|
+
for Marie + Ismaël. Covers: package install, primitive reads, Shadow DOM scoping,
|
|
60
|
+
stream marker emit + parse, bilingual spot check, WCAG AA (contrast + role attrs),
|
|
61
|
+
default-OFF guard.
|
|
62
|
+
|
|
63
|
+
### Tests
|
|
64
|
+
|
|
65
|
+
15+ new vitest cases (≥264 total after M3, baseline 253 after M2) :
|
|
66
|
+
- `mcp-server/src/__tests__/m3-stream-marker.test.ts` — 14 cases:
|
|
67
|
+
`wrapToolResult` ×6 valid kinds, ×2 throws on invalid, `parseToolResult` roundtrip,
|
|
68
|
+
non-marker text ×2, embedded text, malformed JSON ×2, schema rejects unknown kind ×2.
|
|
69
|
+
- `convex/iframeEmbedSessions.test.ts` — 7 cases:
|
|
70
|
+
create+get, optional fields, getSession unknown, expired session null,
|
|
71
|
+
touchSession updates lastSeenAt, touchSession unknown false,
|
|
72
|
+
revokeSession marks revoked (getSession null), revokeSession unknown false.
|
|
73
|
+
|
|
74
|
+
0 regression on M1+M2 suites (253/253 baseline).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## [Unreleased] — M1 SEP-1865 ui:// resources backend + M2 primitives + Zod schemas
|
|
79
|
+
|
|
80
|
+
**Mission instance** : `sigma-vantage-peers-mcp-gui-iframe-embed-v1` (k5730xct6rvrwkvxhy5t5js12d87jwfw).
|
|
81
|
+
**Template VR consumed** : `gui-iframe-embed-v1` v1.0.0 (jx7bzk0x1086tgwgj2zrssk2pn87k1ga).
|
|
82
|
+
|
|
83
|
+
M1 Foundation (adapted MCP-pure paradigm per Pi arbitrage Day 84) :
|
|
84
|
+
- NEW `mcp-server/src/ui-resources/index.ts` : URI parser `ui://vp/v1/<primitive>?<query>` + primitive registry + handler factory.
|
|
85
|
+
- NEW `mcp-server/src/ui-resources/primitives/tasks-table.ts` : M1 MVP primitive returning HTML inline (Shadow DOM scoped CSS) — WCAG AA + bilingual FR+EN.
|
|
86
|
+
- `mcp-server/server-http.ts` : wired `ListResourcesRequestSchema` + `ReadResourceRequestSchema` MCP handlers on the existing McpServer instance.
|
|
87
|
+
|
|
88
|
+
Tests : 14 new vitest cases (`src/__tests__/ui-resources-sep-1865.test.ts`) — URI parsing, primitive registry, render variants (empty, populated, FR), backend arg forwarding, XSS escape, error fallback, limit clamping, unknown primitive rejection. 0 regression on existing suites.
|
|
89
|
+
|
|
90
|
+
### M2 — Resolve 5 Gaps + Bearer sha256 hardening (adapted MCP-pure paradigm)
|
|
91
|
+
|
|
92
|
+
5 new ui:// primitives :
|
|
93
|
+
- `messages-feed` (`messages:listMessages` backend — channel filter applied client-side)
|
|
94
|
+
- `diary-entry` (`diary:get` single-entry + `diary:list` multi-entry backend)
|
|
95
|
+
- `mission-timeline` (`missions:list` backend with fields=lite)
|
|
96
|
+
- `briefing-note` (`briefingNotes:get` by noteId OR `briefingNotes:list` by topic backend)
|
|
97
|
+
- `memory-quote` (`memories:listMemories` backend — supports both plain-array and paginated result shapes)
|
|
98
|
+
|
|
99
|
+
Zod discriminated union schemas : `mcp-server/src/ui-resources/schemas.ts` exports `VpTaskPayloadSchema` + `VpMessagePayloadSchema` + `VpDiaryEntryPayloadSchema` + `VpMissionPayloadSchema` + `VpBriefingNotePayloadSchema` + `VpMemoryPayloadSchema` + `VpToolResultSchema` (discriminated union by `kind`). Cross-fleet ready for Mu vantage-bridge sidepanel S3 consumer.
|
|
100
|
+
|
|
101
|
+
Bearer sha256 validation : Already in place since v2.3.4 DCR security fix. `mcp-server/src/auth.ts` line 275 calls `sha256Hex(token)` before every Convex lookup (layers 2 and 4). Raw token never reaches Convex. No further hardening needed in M2.
|
|
102
|
+
|
|
103
|
+
Tests : 42 new vitest cases in `src/__tests__/ui-resources-m2-primitives.test.ts` (target was ≥22). Covers : PRIMITIVES registry (6 entries), each of 5 new primitives (empty + populated + FR labels + XSS escape + error fallback = 5 cases each), Zod schema roundtrip (VpToolResultSchema all 6 variants accepted, malformed rejected, individual payload schema validations). 0 regression on M1 17 cases + 194 other MCP tests (253/253 total).
|
|
104
|
+
|
|
105
|
+
M3 next : Registry json-render + `__VP_TOOL_RESULT__<json>` stream marker + smoke E2E + ack-checklist + PI-SIGNED Convex prod deploy + visual ack Marie/Ismaël.
|
|
106
|
+
|
|
3
107
|
## v2.3.5 — 2026-05-28
|
|
4
108
|
|
|
5
109
|
**Critical hotfix** — v2.3.3 (PR #539) shipped the backend filters `createdBy` + `updatedSince` and the Zod schema exports but did NOT wire those params into the 4 list MCP tool args blocks. Pi pull-cycle quickstart `list_tasks createdBy="pi" status="review" fields="lite"` was silently dropping `createdBy` at the MCP boundary and returning all visible tasks. Auto-clamp safeguard (Day 83) also could not trigger because Zod `.default(50)` / `.default(20)` on `limit` overrode the absent-value signal before it reached the backend.
|
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/vantage-peers-mcp)
|
|
4
4
|
[](https://www.npmjs.com/package/vantage-peers-mcp)
|
|
5
5
|
[](https://github.com/vantageos-agency/vantage-peers/blob/main/LICENSE)
|
|
6
|
-
[]()
|
|
7
7
|
|
|
8
8
|
MCP server for [VantagePeers](https://vantagepeers.com) — shared memory, messaging, and task coordination for AI agent teams.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
84 tools across 18 categories: memory, profiles, tasks, missions, mission templates, messages, diary, briefing notes, search (RAG), issues, fix patterns, error monitoring, deployments, business units, components, mandates, recurring tasks, and session. All tools ship with ChatGPT Apps SDK annotations (`readOnlyHint`, `openWorldHint`, `destructiveHint`) for native UX in ChatGPT custom connectors.
|
|
11
11
|
|
|
12
12
|
## Quick start
|
|
13
13
|
|
|
@@ -74,7 +74,7 @@ VantagePeers ships a built-in OAuth 2.1 authorization server so Claude.ai web ca
|
|
|
74
74
|
|
|
75
75
|
The server also reads `CONVEX_URL` from `.env.local` in the parent directory if not set via environment.
|
|
76
76
|
|
|
77
|
-
## Tools (
|
|
77
|
+
## Tools (84)
|
|
78
78
|
|
|
79
79
|
### Memory (6)
|
|
80
80
|
`store_memory`, `recall`, `list_memories`, `soft_delete_memory`, `get_memory`, `store_episode`
|
|
@@ -400,6 +400,17 @@ All orchestrator names are open strings — any lowercase name is accepted. The
|
|
|
400
400
|
|
|
401
401
|
## Changelog
|
|
402
402
|
|
|
403
|
+
### 2.4.1 — 2026-05-30 (Day 88)
|
|
404
|
+
- fix(dcr): `oauthDcr:validateAccessToken` exposed as PUBLIC `query` (was `internalQuery`, unreachable via `ConvexHttpClient.query()` → Path 3 DCR returned 401 even with valid token) — issue #556 / PR #557.
|
|
405
|
+
- fix(dcr): `WWW-Authenticate` header now emits `Bearer resource_metadata="..."` per MCP spec §Protected Resource Metadata Discovery (was `resource="..."` — broke Claude.ai PRM discovery bootstrap on 401) — PR #557.
|
|
406
|
+
- feat(mcp): ChatGPT Apps SDK tool annotations on all 84 tools (`readOnlyHint`, `openWorldHint`, `destructiveHint`) — 34 read-only + 41 write + 9 destructive — PR #555.
|
|
407
|
+
- security(dcr): DCR scope isolation — new `public-readonly` profile + cross-tenant assertion tests + `scopeProfile` forced to `client-generic` for auto-discovery flow (never `master`) — PR #554.
|
|
408
|
+
- docs(cloud): dedicated `/docs/cloud/` section in vantage-peers-site for VantagePeers Cloud (multi-tenant, multi-clients MCP: Claude.ai, ChatGPT, Claude Code, Codex) — site PR #120.
|
|
409
|
+
|
|
410
|
+
### 2.4.0 — 2026-05-29 (Day 86)
|
|
411
|
+
- feat(m3): `iframeEmbedSessions` table + `__VP_TOOL_RESULT__` stream marker + ack-checklist primitive — PR #545.
|
|
412
|
+
- feat(v0.0.2-auth): `credentials:issueBearerFromClerk` httpAction + audit log + iter 2 P1 fixes — PR #546.
|
|
413
|
+
|
|
403
414
|
### 2.3.0 — 2026-05-26
|
|
404
415
|
- `list_tasks`, `list_missions`, `list_tasks_by_mission`, `list_briefing_notes` now accept `fields=lite` for compact payloads (less tokens).
|
|
405
416
|
- Status filters now accept arrays and aliases: `status=["todo","in_progress"]`, `status="open"` (expands to non-terminal), `status="active"` (in_progress only on tasks; plan+execute on missions), `status="all"` (no filter).
|
package/dist/server-http.js
CHANGED
|
@@ -25,13 +25,14 @@
|
|
|
25
25
|
* NODE_ENV — set to "production" on Railway
|
|
26
26
|
*/
|
|
27
27
|
import { readFileSync } from "node:fs";
|
|
28
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
28
|
+
import { McpServer, ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
29
29
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
30
30
|
import { ConvexHttpClient } from "convex/browser";
|
|
31
31
|
import { Hono } from "hono";
|
|
32
32
|
import { cors } from "hono/cors";
|
|
33
33
|
import { bearerAuthMiddleware, internalClient, masterOnlyMiddleware, sha256Base64Url, sha256Hex, } from "./src/auth.js";
|
|
34
34
|
import { registerTools } from "./src/tools.js";
|
|
35
|
+
import { listUiResources, readUiResource } from "./src/ui-resources/index.js";
|
|
35
36
|
let pkg;
|
|
36
37
|
try {
|
|
37
38
|
// Source mode: server-http.ts → ./package.json = mcp-server/package.json
|
|
@@ -563,6 +564,31 @@ app.all("/mcp", bearerAuthMiddleware(), async (c) => {
|
|
|
563
564
|
version: pkg.version,
|
|
564
565
|
});
|
|
565
566
|
registerTools(server, convex, oauthCtx);
|
|
567
|
+
// SEP-1865 ui:// resources for Generative UI primitives
|
|
568
|
+
// Uses McpServer.resource() high-level API with a ResourceTemplate so that
|
|
569
|
+
// resources/list (via listCallback) and resources/read both work.
|
|
570
|
+
// URI pattern: ui://vp/v1/{primitive} — query params read from the URL object.
|
|
571
|
+
const uiResourceTemplate = new ResourceTemplate("ui://vp/v1/{primitive}", {
|
|
572
|
+
list: async () => ({ resources: listUiResources() }),
|
|
573
|
+
});
|
|
574
|
+
server.resource("vp-ui", uiResourceTemplate, {
|
|
575
|
+
description: "SEP-1865 VantagePeers Generative UI primitives (HTML inline, Shadow DOM scoped)",
|
|
576
|
+
}, async (uri) => {
|
|
577
|
+
const fetchConvex = async (functionName, args) => {
|
|
578
|
+
// biome-ignore lint/suspicious/noExplicitAny: Convex string API
|
|
579
|
+
return convex.query(functionName, args);
|
|
580
|
+
};
|
|
581
|
+
const resource = await readUiResource(uri.toString(), fetchConvex);
|
|
582
|
+
return {
|
|
583
|
+
contents: [
|
|
584
|
+
{
|
|
585
|
+
uri: resource.uri,
|
|
586
|
+
mimeType: resource.mimeType,
|
|
587
|
+
text: resource.text,
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
};
|
|
591
|
+
});
|
|
566
592
|
const transport = new WebStandardStreamableHTTPServerTransport();
|
|
567
593
|
await server.connect(transport);
|
|
568
594
|
return transport.handleRequest(c.req.raw);
|
package/dist/src/auth.js
CHANGED
|
@@ -139,11 +139,13 @@ export function checkNamespaceWrite(ctx, namespace) {
|
|
|
139
139
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
140
140
|
export function bearerAuthMiddleware() {
|
|
141
141
|
return async (c, next) => {
|
|
142
|
-
//
|
|
143
|
-
//
|
|
142
|
+
// MCP spec §"Protected Resource Metadata Discovery Requirements" + RFC 6750 §3 —
|
|
143
|
+
// the param MUST be `resource_metadata=` (not `resource=`). Claude.ai's OAuth
|
|
144
|
+
// connector looks for `resource_metadata=` to bootstrap PRM discovery; with
|
|
145
|
+
// `resource=` the entire DCR chain breaks before any token is issued.
|
|
144
146
|
const publicBaseUrl = process.env.PUBLIC_BASE_URL ??
|
|
145
147
|
"https://vantage-peers-production.up.railway.app";
|
|
146
|
-
const wwwAuthHeader = `Bearer
|
|
148
|
+
const wwwAuthHeader = `Bearer resource_metadata="${publicBaseUrl}/.well-known/oauth-protected-resource"`;
|
|
147
149
|
const authHeader = c.req.header("Authorization");
|
|
148
150
|
if (!authHeader?.startsWith("Bearer ")) {
|
|
149
151
|
c.header("WWW-Authenticate", wwwAuthHeader);
|
|
@@ -215,6 +217,10 @@ export function bearerAuthMiddleware() {
|
|
|
215
217
|
// ── (3) DCR OAuth token — check oauthTokens via oauthDcr:validateAccessToken
|
|
216
218
|
// Uses raw token (not hashed) — the DCR table stores tokens in plaintext.
|
|
217
219
|
// This path handles Claude.ai clients registered via POST /register.
|
|
220
|
+
// NOTE: validateAccessToken is exposed as a PUBLIC query (not internalQuery)
|
|
221
|
+
// because ConvexHttpClient.query() only resolves public functions. Making it
|
|
222
|
+
// internal silently breaks the DCR path (#556). Security: lookup is keyed
|
|
223
|
+
// on the high-entropy opaque token; returns null on miss with no PII echo.
|
|
218
224
|
let dcrResult = null;
|
|
219
225
|
try {
|
|
220
226
|
dcrResult = (await internalClient().query(
|