@vantageos/vantage-registry-mcp 1.5.0 → 1.6.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  MCP server exposing [VantageRegistry](https://github.com/elpiarthera/vantage-registry) Convex functions as Claude Code tools via stdio transport.
4
4
 
5
- **Version:** 1.1.1
5
+ **Version:** 1.6.1
6
6
  **Backend:** Convex (vibrant-ibex-858)
7
7
  **Transport:** stdio (Claude Code MCP protocol)
8
8
 
@@ -53,7 +53,7 @@ Or set `CONVEX_URL` in `.env.local` at the repo root.
53
53
 
54
54
  | Tool | Description |
55
55
  |------|-------------|
56
- | `upsert_skill` | Create or update a skill (upsert by name) |
56
+ | `upsert_skill` | Create or update a skill (upsert by name). **New in 1.6.0:** optional `vrBody` writes the full SKILL.md body (vrContent/hash/version) in the same call |
57
57
  | `list_skills` | List skills — optional `status` / `team` / `category` filters |
58
58
  | `list_skills_by_team` | List skills for a specific team |
59
59
  | `list_skills_by_category` | List skills for a specific category |
@@ -71,7 +71,7 @@ Or set `CONVEX_URL` in `.env.local` at the repo root.
71
71
 
72
72
  | Tool | Description |
73
73
  |------|-------------|
74
- | `upsert_hook` | Create or update a hook (upsert by name) |
74
+ | `upsert_hook` | Create or update a hook (upsert by name). **New in 1.6.0:** optional `tests` array of hook test file paths |
75
75
  | `list_hooks` | List hooks — optional `status` / `event` / `scope` filters |
76
76
  | `get_hook` | Get a hook by Convex document ID |
77
77
 
@@ -113,6 +113,7 @@ list_templates(team="core", template_type="checklist")
113
113
  | `list_runbooks_by_category` | List runbooks for a specific category (uses byCategory index) |
114
114
  | `list_runbooks_by_team` | List runbooks for a specific team (uses byTeam index) |
115
115
  | `delete_runbook` | Soft-delete a runbook — sets status to `deprecated` |
116
+ | `detect_runbook_drift` | Return per-runbook `vrHash` (sha256 of content) + category + version for drift comparison (added in 1.6.0) |
116
117
 
117
118
  **Runbook status values:** `draft | published | deprecated`
118
119
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@vantageos/vantage-registry-mcp",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "MCP server exposing VantageRegistry Convex functions as Claude Code tools",
5
5
  "type": "module",
6
6
  "bin": {
7
- "vantage-registry": "./server.ts"
7
+ "vantage-registry": "./server.js"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "esbuild server.ts --bundle --platform=node --format=esm --outfile=server.js --external:convex --external:@modelcontextprotocol/sdk --external:zod --external:dotenv",
package/server.js CHANGED
@@ -206,7 +206,7 @@ server.tool(
206
206
  );
207
207
  server.tool(
208
208
  "upsert_skill",
209
- "Create or update a skill in VantageRegistry. Upserts by name+team \u2014 if a skill with the same name and team exists, it is updated.",
209
+ "Create or update a skill in VantageRegistry. Upserts by name+team \u2014 if a skill with the same name and team exists, it is updated. Pass vrBody to write the full SKILL.md body (vrContent/vrContentHash/vrContentVersion) in the SAME call \u2014 no separate upsert_skill_content needed (that tool remains for back-compat). Omit vrBody for metadata-only upsert.",
210
210
  {
211
211
  name: z.string().describe("Skill name \u2014 e.g. 'social-post', 'competitor-watch'"),
212
212
  team: z.string().describe("Team this skill belongs to"),
@@ -222,7 +222,10 @@ server.tool(
222
222
  price: z.number().optional().describe("Price in EUR (if paid)"),
223
223
  license: z.string().optional().describe("License \u2014 e.g. 'MIT', 'proprietary'"),
224
224
  publisherId: z.string().optional().describe("Publisher identifier"),
225
- categories: z.array(z.string()).optional().describe("Categories beyond team name")
225
+ categories: z.array(z.string()).optional().describe("Categories beyond team name"),
226
+ vrBody: z.string().optional().describe(
227
+ "Full SKILL.md body. When passed, writes vrContent/vrContentHash/vrContentVersion in the same call. Omitted \u2192 metadata-only (unchanged)."
228
+ )
226
229
  },
227
230
  async (args) => {
228
231
  const id = await convex.mutation(api.skills.upsert, args);
@@ -666,7 +669,10 @@ server.tool(
666
669
  filePath: z.string().describe("File path relative to project root"),
667
670
  registered: z.boolean().describe("Whether this hook is registered in settings.json"),
668
671
  status: hookStatusSchema,
669
- version: z.string().optional().describe("Semantic version \u2014 e.g. '1.0.0'")
672
+ version: z.string().optional().describe("Semantic version \u2014 e.g. '1.0.0'"),
673
+ tests: z.array(z.string()).optional().describe(
674
+ "Hook test file paths \u2014 e.g. ['hooks/tests/check-pii.test.py']. Omitted \u2192 not sent (back-compat)."
675
+ )
670
676
  },
671
677
  async (args) => {
672
678
  const id = await convex.mutation(api.hooks.upsert, args);
@@ -1261,6 +1267,21 @@ server.tool(
1261
1267
  }
1262
1268
  }
1263
1269
  );
1270
+ server.tool(
1271
+ "detect_runbook_drift",
1272
+ "Return the VR-side sha256 hash (vrHash) plus category and version for each runbook in scope. IMPORTANT: Convex queries have no filesystem access. This tool computes sha256(runbook.content) server-side and returns it as vrHash so the caller can compute disk SHA256 and compare. name=<slug> filters to a single runbook; omit name to return every runbook (bounded to 500).",
1273
+ {
1274
+ name: z.string().optional().describe("Runbook slug \u2014 filter to a single runbook")
1275
+ },
1276
+ async ({ name }) => {
1277
+ const result = await convex.query(api.runbooks.detectRunbookDrift, {
1278
+ name
1279
+ });
1280
+ return {
1281
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1282
+ };
1283
+ }
1284
+ );
1264
1285
  server.tool(
1265
1286
  "link_runbook_template",
1266
1287
  "Create or update a typed link between a runbook and a template in the runbook_template_links junction table. Upserts by (runbookId, templateId) pair \u2014 at-most-one link per pair. linkType controls the relationship semantics: 'uses' = template consumed during execution, 'produces' = output document generated by this runbook, 'references' = informational cross-reference. Returns {linkId, created: true} on insert or {linkId, created: false} on update.",
@@ -1437,7 +1458,16 @@ server.tool(
1437
1458
  }
1438
1459
  }
1439
1460
  );
1440
- var componentKindSchema = z.enum(["skill", "agent", "hook", "plugin", "prompt", "runbook", "template"]).describe("Component kind");
1461
+ var componentKindSchema = z.enum([
1462
+ "skill",
1463
+ "agent",
1464
+ "hook",
1465
+ "plugin",
1466
+ "prompt",
1467
+ "runbook",
1468
+ "template",
1469
+ "ui-component"
1470
+ ]).describe("Component kind");
1441
1471
  var componentStatusSchema = z.enum(["active", "deprecated", "experimental"]).describe("Component status");
1442
1472
  server.tool(
1443
1473
  "register_component",
package/server.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * upsert_hook, list_hooks, get_hook
12
12
  * upsert_prompt, list_prompts, get_prompt
13
13
  * upsert_template, list_templates, get_template, detect_template_drift, list_templates_by_category
14
- * upsert_runbook, get_runbook, list_runbooks, list_runbooks_by_category, list_runbooks_by_team, delete_runbook
14
+ * upsert_runbook, get_runbook, list_runbooks, list_runbooks_by_category, list_runbooks_by_team, delete_runbook, detect_runbook_drift
15
15
  * link_runbook_template, unlink_runbook_template, list_templates_for_runbook, list_runbooks_for_template
16
16
  * register_component, list_components, get_component, search_components, update_component, delete_component
17
17
  * get_stats
@@ -317,7 +317,8 @@ server.tool(
317
317
 
318
318
  server.tool(
319
319
  "upsert_skill",
320
- "Create or update a skill in VantageRegistry. Upserts by name+team — if a skill with the same name and team exists, it is updated.",
320
+ "Create or update a skill in VantageRegistry. Upserts by name+team — if a skill with the same name and team exists, it is updated. " +
321
+ "Pass vrBody to write the full SKILL.md body (vrContent/vrContentHash/vrContentVersion) in the SAME call — no separate upsert_skill_content needed (that tool remains for back-compat). Omit vrBody for metadata-only upsert.",
321
322
  {
322
323
  name: z
323
324
  .string()
@@ -344,6 +345,12 @@ server.tool(
344
345
  .array(z.string())
345
346
  .optional()
346
347
  .describe("Categories beyond team name"),
348
+ vrBody: z
349
+ .string()
350
+ .optional()
351
+ .describe(
352
+ "Full SKILL.md body. When passed, writes vrContent/vrContentHash/vrContentVersion in the same call. Omitted → metadata-only (unchanged).",
353
+ ),
347
354
  },
348
355
  async (args) => {
349
356
  const id = await convex.mutation(api.skills.upsert, args);
@@ -985,6 +992,12 @@ server.tool(
985
992
  .describe("Whether this hook is registered in settings.json"),
986
993
  status: hookStatusSchema,
987
994
  version: z.string().optional().describe("Semantic version — e.g. '1.0.0'"),
995
+ tests: z
996
+ .array(z.string())
997
+ .optional()
998
+ .describe(
999
+ "Hook test file paths — e.g. ['hooks/tests/check-pii.test.py']. Omitted → not sent (back-compat).",
1000
+ ),
988
1001
  },
989
1002
  async (args) => {
990
1003
  const id = await convex.mutation(api.hooks.upsert, args);
@@ -1792,6 +1805,28 @@ server.tool(
1792
1805
  },
1793
1806
  );
1794
1807
 
1808
+ server.tool(
1809
+ "detect_runbook_drift",
1810
+ "Return the VR-side sha256 hash (vrHash) plus category and version for each runbook in scope. " +
1811
+ "IMPORTANT: Convex queries have no filesystem access. This tool computes sha256(runbook.content) " +
1812
+ "server-side and returns it as vrHash so the caller can compute disk SHA256 and compare. " +
1813
+ "name=<slug> filters to a single runbook; omit name to return every runbook (bounded to 500).",
1814
+ {
1815
+ name: z
1816
+ .string()
1817
+ .optional()
1818
+ .describe("Runbook slug — filter to a single runbook"),
1819
+ },
1820
+ async ({ name }) => {
1821
+ const result = await convex.query(api.runbooks.detectRunbookDrift, {
1822
+ name,
1823
+ });
1824
+ return {
1825
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1826
+ };
1827
+ },
1828
+ );
1829
+
1795
1830
  // ═══════════════════════════════════════════════════════════════════════════════
1796
1831
  // RUNBOOK ↔ TEMPLATE LINKS (Sprint B T4 — junction table typed links)
1797
1832
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -2009,7 +2044,16 @@ server.tool(
2009
2044
  // ═══════════════════════════════════════════════════════════════════════════════
2010
2045
 
2011
2046
  const componentKindSchema = z
2012
- .enum(["skill", "agent", "hook", "plugin", "prompt", "runbook", "template"])
2047
+ .enum([
2048
+ "skill",
2049
+ "agent",
2050
+ "hook",
2051
+ "plugin",
2052
+ "prompt",
2053
+ "runbook",
2054
+ "template",
2055
+ "ui-component",
2056
+ ])
2013
2057
  .describe("Component kind");
2014
2058
 
2015
2059
  const componentStatusSchema = z