vantage-peers-mcp 2.14.0 → 2.14.2

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.14.2 — 2026-06-30
4
+
5
+ - fix(oauth): DCR `/register` rejects empty/missing/malformed `redirect_uris` (RFC 7591 §3.2.2 `invalid_redirect_uri`). Closes zombie-client class — clients with empty `redirectUris` arrays can no longer be created. Defense-in-depth: same guard at Convex `registerPublicClient`. TDD-strict RED-then-GREEN.
6
+
3
7
  ## [Unreleased]
4
8
 
5
9
  ### Added
package/README.md CHANGED
@@ -171,7 +171,7 @@ VantagePeers ships a built-in OAuth 2.1 authorization server so Claude.ai web ca
171
171
  |--------|------|-------------|
172
172
  | `GET` | `/.well-known/oauth-authorization-server` | Authorization Server Metadata (RFC 8414) — advertises supported grant types, endpoints, and capabilities |
173
173
  | `GET` | `/.well-known/oauth-protected-resource` | Protected Resource Metadata (RFC 9728) — links back to the authorization server |
174
- | `POST` | `/register` | Dynamic Client Registration (RFC 7591) — Claude.ai registers itself automatically on first connect |
174
+ | `POST` | `/register` | Dynamic Client Registration (RFC 7591) — Claude.ai registers itself automatically on first connect. `redirect_uris` MUST be a non-empty array of valid `https://` URIs (or `http://localhost` / `http://127.0.0.1` for dev); absent, empty, non-string, unparseable, non-https, or fragment-bearing entries are rejected with `invalid_redirect_uri` (RFC 7591 §3.2.2, commit `2f3e653`). |
175
175
  | `GET` | `/authorize` | Authorization endpoint — redirects the user to grant access |
176
176
  | `POST` | `/token` | Token endpoint — issues access tokens per OAuth 2.1 |
177
177
 
@@ -27,11 +27,11 @@
27
27
  import { readFileSync } from "node:fs";
28
28
  import { McpServer, ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
29
29
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
30
+ import { timingSafeEqual } from "@vantageos/cloud-identity";
30
31
  import { ConvexHttpClient } from "convex/browser";
31
32
  import { Hono } from "hono";
32
33
  import { cors } from "hono/cors";
33
34
  import { bearerAuthMiddleware, internalClient, masterOnlyMiddleware, sha256Base64Url, sha256Hex, } from "./src/auth.js";
34
- import { timingSafeEqual } from "@vantageos/cloud-identity";
35
35
  import { registerTools } from "./src/tools.js";
36
36
  import { listUiResources, readUiResource } from "./src/ui-resources/index.js";
37
37
  let pkg;
@@ -262,9 +262,54 @@ app.post("/register", async (c) => {
262
262
  catch {
263
263
  // allow empty body — Claude sometimes posts nothing
264
264
  }
265
- const redirectUris = Array.isArray(body.redirect_uris)
266
- ? body.redirect_uris
267
- : [];
265
+ // RFC 7591 §2: redirect_uris is REQUIRED for authorization_code grant.
266
+ // RFC 7591 §3.2.2: invalid_redirect_uri is the canonical error code for
267
+ // bad, missing, or empty redirect_uris. Reject here so zombie clients
268
+ // (e.g. prod 87abdf5c-616b-4767-8a96-5ca04db88d9f) can never be created.
269
+ if (!Array.isArray(body.redirect_uris) ||
270
+ body.redirect_uris.length === 0) {
271
+ return c.json({
272
+ error: "invalid_redirect_uri",
273
+ error_description: "redirect_uris is required and must be a non-empty array of valid HTTPS URIs",
274
+ }, 400);
275
+ }
276
+ // Validate each URI: must be parseable and https: scheme (or http://localhost
277
+ // for dev). Reject file://, javascript:, data:, fragments, etc.
278
+ for (const uri of body.redirect_uris) {
279
+ if (typeof uri !== "string") {
280
+ return c.json({
281
+ error: "invalid_redirect_uri",
282
+ error_description: "redirect_uris is required and must be a non-empty array of valid HTTPS URIs",
283
+ }, 400);
284
+ }
285
+ let parsed;
286
+ try {
287
+ parsed = new URL(uri);
288
+ }
289
+ catch {
290
+ return c.json({
291
+ error: "invalid_redirect_uri",
292
+ error_description: "redirect_uris is required and must be a non-empty array of valid HTTPS URIs",
293
+ }, 400);
294
+ }
295
+ const isHttpsScheme = parsed.protocol === "https:";
296
+ const isLocalhostHttp = parsed.protocol === "http:" &&
297
+ (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
298
+ if (!isHttpsScheme && !isLocalhostHttp) {
299
+ return c.json({
300
+ error: "invalid_redirect_uri",
301
+ error_description: "redirect_uris is required and must be a non-empty array of valid HTTPS URIs",
302
+ }, 400);
303
+ }
304
+ // Reject URIs with fragments (RFC 6749 §3.1.2)
305
+ if (parsed.hash) {
306
+ return c.json({
307
+ error: "invalid_redirect_uri",
308
+ error_description: "redirect_uris is required and must be a non-empty array of valid HTTPS URIs",
309
+ }, 400);
310
+ }
311
+ }
312
+ const redirectUris = body.redirect_uris;
268
313
  const clientId = crypto.randomUUID();
269
314
  const clientSecret = randomOpaqueToken();
270
315
  const clientSecretHash = await sha256Hex(clientSecret);
package/package.json CHANGED
@@ -1,95 +1,95 @@
1
1
  {
2
- "name": "vantage-peers-mcp",
3
- "version": "2.14.0",
4
- "description": "MCP server for VantagePeers — shared memory, messaging, and task coordination for AI agent teams",
5
- "type": "module",
6
- "main": "./dist/server.js",
7
- "exports": {
8
- ".": "./dist/server.js",
9
- "./api": {
10
- "types": "./dist/api.d.ts",
11
- "default": "./dist/api.js"
12
- }
13
- },
14
- "bin": {
15
- "vantage-peers-mcp": "./dist/server.js"
16
- },
17
- "files": [
18
- "dist/",
19
- "README.md",
20
- "CHANGELOG.md"
21
- ],
22
- "scripts": {
23
- "generate:api": "cd .. && npx convex-helpers ts-api-spec --prod --output-file mcp-server/api.ts",
24
- "build": "tsc --project tsconfig.json",
25
- "prepublishOnly": "npm run build",
26
- "dev": "bun run server.ts",
27
- "start": "bun run dist/server-http.js",
28
- "dev:http": "bun run server-http.ts",
29
- "test": "vitest run",
30
- "test:watch": "vitest",
31
- "test:coverage": "vitest run --coverage"
32
- },
33
- "repository": {
34
- "type": "git",
35
- "url": "https://github.com/vantageos-agency/vantage-peers.git",
36
- "directory": "mcp-server"
37
- },
38
- "homepage": "https://vantagepeers.com/docs",
39
- "bugs": {
40
- "url": "https://github.com/vantageos-agency/vantage-peers/issues"
41
- },
42
- "keywords": [
43
- "mcp",
44
- "claude",
45
- "convex",
46
- "ai-agents",
47
- "memory",
48
- "messaging",
49
- "tasks",
50
- "multi-agent",
51
- "orchestration",
52
- "vantagepeers",
53
- "diary",
54
- "episodes",
55
- "mandates",
56
- "knowledge-base",
57
- "rag",
58
- "vector-search"
59
- ],
60
- "author": "VantageOS AI Orchestrator Team",
61
- "contributors": [
62
- "Pi (π) — Lead orchestrator",
63
- "Laurent Perello — Founder, supervisor",
64
- "ElPi Corp"
65
- ],
66
- "license": "FSL-1.1-Apache-2.0",
67
- "dependencies": {
68
- "@mcp-ui/server": "^6.1.0",
69
- "@modelcontextprotocol/sdk": "^1.29.0",
70
- "@vantageos/cloud-identity": "^0.1.0",
71
- "@vantageos/mosaic": "^0.1.2",
72
- "convex": ">=1.0.0",
73
- "dotenv": "^17.4.2",
74
- "zod": "^4.3.6"
75
- },
76
- "peerDependencies": {
77
- "convex": ">=1.0.0"
78
- },
79
- "devDependencies": {
80
- "@types/node": "^24.12.2",
81
- "@vitest/coverage-v8": "^4.1.8",
82
- "typescript": "^5.9.3",
83
- "vitest": "^4.1.8"
84
- },
85
- "overrides": {
86
- "path-to-regexp": "^8.4.0"
87
- },
88
- "engines": {
89
- "node": ">=20"
90
- },
91
- "publishConfig": {
92
- "access": "public",
93
- "provenance": true
94
- }
2
+ "name": "vantage-peers-mcp",
3
+ "version": "2.14.2",
4
+ "description": "MCP server for VantagePeers — shared memory, messaging, and task coordination for AI agent teams",
5
+ "type": "module",
6
+ "main": "./dist/server.js",
7
+ "exports": {
8
+ ".": "./dist/server.js",
9
+ "./api": {
10
+ "types": "./dist/api.d.ts",
11
+ "default": "./dist/api.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "vantage-peers-mcp": "./dist/server.js"
16
+ },
17
+ "files": [
18
+ "dist/",
19
+ "README.md",
20
+ "CHANGELOG.md"
21
+ ],
22
+ "scripts": {
23
+ "generate:api": "cd .. && npx convex-helpers ts-api-spec --prod --output-file mcp-server/api.ts",
24
+ "build": "tsc --project tsconfig.json",
25
+ "prepublishOnly": "npm run build",
26
+ "dev": "bun run server.ts",
27
+ "start": "bun run dist/server-http.js",
28
+ "dev:http": "bun run server-http.ts",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "test:coverage": "vitest run --coverage"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/vantageos-agency/vantage-peers.git",
36
+ "directory": "mcp-server"
37
+ },
38
+ "homepage": "https://vantagepeers.com/docs",
39
+ "bugs": {
40
+ "url": "https://github.com/vantageos-agency/vantage-peers/issues"
41
+ },
42
+ "keywords": [
43
+ "mcp",
44
+ "claude",
45
+ "convex",
46
+ "ai-agents",
47
+ "memory",
48
+ "messaging",
49
+ "tasks",
50
+ "multi-agent",
51
+ "orchestration",
52
+ "vantagepeers",
53
+ "diary",
54
+ "episodes",
55
+ "mandates",
56
+ "knowledge-base",
57
+ "rag",
58
+ "vector-search"
59
+ ],
60
+ "author": "VantageOS AI Orchestrator Team",
61
+ "contributors": [
62
+ "Pi (π) — Lead orchestrator",
63
+ "Laurent Perello — Founder, supervisor",
64
+ "ElPi Corp"
65
+ ],
66
+ "license": "FSL-1.1-Apache-2.0",
67
+ "dependencies": {
68
+ "@mcp-ui/server": "^6.1.0",
69
+ "@modelcontextprotocol/sdk": "^1.29.0",
70
+ "@vantageos/cloud-identity": "^0.1.0",
71
+ "@vantageos/mosaic": "^0.1.2",
72
+ "convex": ">=1.0.0",
73
+ "dotenv": "^17.4.2",
74
+ "zod": "^4.3.6"
75
+ },
76
+ "peerDependencies": {
77
+ "convex": ">=1.0.0"
78
+ },
79
+ "devDependencies": {
80
+ "@types/node": "^24.12.2",
81
+ "@vitest/coverage-v8": "^4.1.8",
82
+ "typescript": "^5.9.3",
83
+ "vitest": "^4.1.8"
84
+ },
85
+ "overrides": {
86
+ "path-to-regexp": "^8.4.0"
87
+ },
88
+ "engines": {
89
+ "node": ">=20"
90
+ },
91
+ "publishConfig": {
92
+ "access": "public",
93
+ "provenance": true
94
+ }
95
95
  }