@vantageos/vantage-registry-mcp 1.1.1 → 1.2.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.ts +220 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantageos/vantage-registry-mcp",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "MCP server exposing VantageRegistry Convex functions as Claude Code tools",
5
5
  "type": "module",
6
6
  "bin": {
package/server.ts CHANGED
@@ -12,6 +12,7 @@
12
12
  * upsert_prompt, list_prompts, get_prompt
13
13
  * upsert_template, list_templates, get_template
14
14
  * upsert_runbook, get_runbook, list_runbooks, list_runbooks_by_category, list_runbooks_by_team, delete_runbook
15
+ * link_runbook_template, unlink_runbook_template, list_templates_for_runbook, list_runbooks_for_template
15
16
  * get_stats
16
17
  *
17
18
  * Orchestrator: Omega — VantageOS Team | 2026-05-19
@@ -111,6 +112,12 @@ const templateTypeSchema = z
111
112
  .enum(["mission", "document", "checklist"])
112
113
  .describe("Template type");
113
114
 
115
+ const linkTypeSchema = z
116
+ .enum(["uses", "produces", "references"])
117
+ .describe(
118
+ "Link type — uses: template consumed during execution, produces: output document generated, references: informational cross-reference",
119
+ );
120
+
114
121
  // ─────────────────────────────────────────────────────────────────────────────
115
122
  // Server setup
116
123
  // ─────────────────────────────────────────────────────────────────────────────
@@ -120,7 +127,7 @@ const convex = new ConvexHttpClient(convexUrl);
120
127
 
121
128
  const server = new McpServer({
122
129
  name: "vantage-registry",
123
- version: "1.1.1",
130
+ version: "1.2.0",
124
131
  });
125
132
 
126
133
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -1197,6 +1204,218 @@ server.tool(
1197
1204
  },
1198
1205
  );
1199
1206
 
1207
+ // ═══════════════════════════════════════════════════════════════════════════════
1208
+ // RUNBOOK ↔ TEMPLATE LINKS (Sprint B T4 — junction table typed links)
1209
+ // ═══════════════════════════════════════════════════════════════════════════════
1210
+
1211
+ server.tool(
1212
+ "link_runbook_template",
1213
+ "Create or update a typed link between a runbook and a template in the runbook_template_links junction table. " +
1214
+ "Upserts by (runbookId, templateId) pair — at-most-one link per pair. " +
1215
+ "linkType controls the relationship semantics: " +
1216
+ "'uses' = template consumed during execution, " +
1217
+ "'produces' = output document generated by this runbook, " +
1218
+ "'references' = informational cross-reference. " +
1219
+ "Returns {linkId, created: true} on insert or {linkId, created: false} on update.",
1220
+ {
1221
+ runbookId: z.string().describe("Convex document ID for the runbook"),
1222
+ templateId: z.string().describe("Convex document ID for the template"),
1223
+ linkType: linkTypeSchema,
1224
+ usagePhase: z
1225
+ .string()
1226
+ .optional()
1227
+ .describe(
1228
+ "Phase name where this template is used — kebab-case convention e.g. 'bootstrap', 'audit-phase-2'",
1229
+ ),
1230
+ order: z
1231
+ .number()
1232
+ .optional()
1233
+ .describe(
1234
+ "Sort order for template lists — lower numbers appear first (null items sorted last)",
1235
+ ),
1236
+ createdBy: z
1237
+ .string()
1238
+ .optional()
1239
+ .describe("Orchestrator or person creating this link — e.g. 'omega'"),
1240
+ },
1241
+ async (args) => {
1242
+ try {
1243
+ const result = await convex.mutation(
1244
+ api.runbookTemplateLinks.linkRunbookTemplate,
1245
+ {
1246
+ runbookId: args.runbookId as any,
1247
+ templateId: args.templateId as any,
1248
+ linkType: args.linkType,
1249
+ usagePhase: args.usagePhase,
1250
+ order: args.order,
1251
+ createdBy: args.createdBy,
1252
+ },
1253
+ );
1254
+ return {
1255
+ content: [
1256
+ {
1257
+ type: "text",
1258
+ text: JSON.stringify({ success: true, data: result }, null, 2),
1259
+ },
1260
+ ],
1261
+ };
1262
+ } catch (err) {
1263
+ return {
1264
+ content: [
1265
+ {
1266
+ type: "text",
1267
+ text: JSON.stringify(
1268
+ { success: false, error: String(err) },
1269
+ null,
1270
+ 2,
1271
+ ),
1272
+ },
1273
+ ],
1274
+ };
1275
+ }
1276
+ },
1277
+ );
1278
+
1279
+ server.tool(
1280
+ "unlink_runbook_template",
1281
+ "Hard-delete the typed link between a runbook and a template. " +
1282
+ "Links have no lifecycle state — they either exist or they don't (no soft-delete). " +
1283
+ "Returns {unlinked: true} if the link was found and deleted, {unlinked: false} if the pair was not linked.",
1284
+ {
1285
+ runbookId: z.string().describe("Convex document ID for the runbook"),
1286
+ templateId: z.string().describe("Convex document ID for the template"),
1287
+ },
1288
+ async (args) => {
1289
+ try {
1290
+ const result = await convex.mutation(
1291
+ api.runbookTemplateLinks.unlinkRunbookTemplate,
1292
+ {
1293
+ runbookId: args.runbookId as any,
1294
+ templateId: args.templateId as any,
1295
+ },
1296
+ );
1297
+ return {
1298
+ content: [
1299
+ {
1300
+ type: "text",
1301
+ text: JSON.stringify({ success: true, data: result }, null, 2),
1302
+ },
1303
+ ],
1304
+ };
1305
+ } catch (err) {
1306
+ return {
1307
+ content: [
1308
+ {
1309
+ type: "text",
1310
+ text: JSON.stringify(
1311
+ { success: false, error: String(err) },
1312
+ null,
1313
+ 2,
1314
+ ),
1315
+ },
1316
+ ],
1317
+ };
1318
+ }
1319
+ },
1320
+ );
1321
+
1322
+ server.tool(
1323
+ "list_templates_for_runbook",
1324
+ "List all templates linked to a runbook, with enriched template metadata. " +
1325
+ "Returns enriched [{link, template}] objects sorted by link.order ASC then link.createdAt ASC. " +
1326
+ "Optionally filter by linkType ('uses', 'produces', or 'references'). " +
1327
+ "Orphaned links (template deleted) are automatically skipped.",
1328
+ {
1329
+ runbookId: z.string().describe("Convex document ID for the runbook"),
1330
+ linkType: linkTypeSchema
1331
+ .optional()
1332
+ .describe(
1333
+ "Filter by link type — omit to return all link types for this runbook",
1334
+ ),
1335
+ },
1336
+ async (args) => {
1337
+ try {
1338
+ const result = await convex.query(
1339
+ api.runbookTemplateLinks.listTemplatesForRunbook,
1340
+ {
1341
+ runbookId: args.runbookId as any,
1342
+ linkType: args.linkType,
1343
+ },
1344
+ );
1345
+ return {
1346
+ content: [
1347
+ {
1348
+ type: "text",
1349
+ text: JSON.stringify({ success: true, data: result }, null, 2),
1350
+ },
1351
+ ],
1352
+ };
1353
+ } catch (err) {
1354
+ return {
1355
+ content: [
1356
+ {
1357
+ type: "text",
1358
+ text: JSON.stringify(
1359
+ { success: false, error: String(err) },
1360
+ null,
1361
+ 2,
1362
+ ),
1363
+ },
1364
+ ],
1365
+ };
1366
+ }
1367
+ },
1368
+ );
1369
+
1370
+ server.tool(
1371
+ "list_runbooks_for_template",
1372
+ "List all runbooks linked to a template (reverse lookup), with enriched runbook metadata. " +
1373
+ "Symmetric reverse of list_templates_for_runbook — uses the byTemplate index. " +
1374
+ "Returns enriched [{link, runbook}] objects sorted by link.order ASC then link.createdAt ASC. " +
1375
+ "Optionally filter by linkType ('uses', 'produces', or 'references'). " +
1376
+ "Orphaned links (runbook deleted) are automatically skipped.",
1377
+ {
1378
+ templateId: z.string().describe("Convex document ID for the template"),
1379
+ linkType: linkTypeSchema
1380
+ .optional()
1381
+ .describe(
1382
+ "Filter by link type — omit to return all link types for this template",
1383
+ ),
1384
+ },
1385
+ async (args) => {
1386
+ try {
1387
+ const result = await convex.query(
1388
+ api.runbookTemplateLinks.listRunbooksForTemplate,
1389
+ {
1390
+ templateId: args.templateId as any,
1391
+ linkType: args.linkType,
1392
+ },
1393
+ );
1394
+ return {
1395
+ content: [
1396
+ {
1397
+ type: "text",
1398
+ text: JSON.stringify({ success: true, data: result }, null, 2),
1399
+ },
1400
+ ],
1401
+ };
1402
+ } catch (err) {
1403
+ return {
1404
+ content: [
1405
+ {
1406
+ type: "text",
1407
+ text: JSON.stringify(
1408
+ { success: false, error: String(err) },
1409
+ null,
1410
+ 2,
1411
+ ),
1412
+ },
1413
+ ],
1414
+ };
1415
+ }
1416
+ },
1417
+ );
1418
+
1200
1419
  // ═══════════════════════════════════════════════════════════════════════════════
1201
1420
  // STATS
1202
1421
  // ═══════════════════════════════════════════════════════════════════════════════