@vornrun/mcp 0.2.0 → 0.2.1-beta.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.
Files changed (2) hide show
  1. package/dist/index.js +119 -51
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -53,6 +53,9 @@ var DEFAULT_WORKSPACE = {
53
53
  iconColor: "#6b7280",
54
54
  order: 0
55
55
  };
56
+ function isTerminalTaskStatus(status) {
57
+ return status === "done" || status === "cancelled";
58
+ }
56
59
 
57
60
  // ../server/src/default-workflows.ts
58
61
  var DEFAULT_TASK_WORKFLOW_ID = "system:default-task-workflow";
@@ -294,7 +297,8 @@ function createSchema() {
294
297
  use_worktree INTEGER DEFAULT 0,
295
298
  created_at TEXT NOT NULL,
296
299
  updated_at TEXT NOT NULL,
297
- completed_at TEXT
300
+ completed_at TEXT,
301
+ archived_at TEXT
298
302
  );
299
303
 
300
304
  CREATE TABLE IF NOT EXISTS sessions (
@@ -373,23 +377,6 @@ function createSchema() {
373
377
  CREATE INDEX IF NOT EXISTS idx_workflow_run_nodes_run ON workflow_run_nodes(run_id);
374
378
  CREATE INDEX IF NOT EXISTS idx_workflow_run_nodes_task ON workflow_run_nodes(task_id);
375
379
 
376
- CREATE TABLE IF NOT EXISTS session_logs (
377
- id INTEGER PRIMARY KEY AUTOINCREMENT,
378
- task_id TEXT NOT NULL,
379
- session_id TEXT NOT NULL,
380
- agent_type TEXT,
381
- branch TEXT,
382
- status TEXT NOT NULL DEFAULT 'running',
383
- started_at TEXT NOT NULL,
384
- completed_at TEXT,
385
- exit_code INTEGER,
386
- logs TEXT,
387
- project_name TEXT
388
- );
389
-
390
- CREATE INDEX IF NOT EXISTS idx_session_logs_task ON session_logs(task_id);
391
- CREATE INDEX IF NOT EXISTS idx_session_logs_session ON session_logs(session_id);
392
-
393
380
  CREATE TABLE IF NOT EXISTS session_events (
394
381
  id INTEGER PRIMARY KEY AUTOINCREMENT,
395
382
  session_id TEXT NOT NULL,
@@ -595,6 +582,15 @@ function migrateSchema(d) {
595
582
  })();
596
583
  logger_default.info("[database] migrated schema to version 9 (connector source connections)");
597
584
  }
585
+ if (version < 10) {
586
+ d.transaction(() => {
587
+ d.exec("DROP TABLE IF EXISTS session_logs");
588
+ d.prepare(
589
+ "INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schema_version', '10')"
590
+ ).run();
591
+ })();
592
+ logger_default.info("[database] migrated schema to version 10 (drop session_logs)");
593
+ }
598
594
  }
599
595
  function verifySchema(d) {
600
596
  const expectedByTable = {
@@ -656,6 +652,10 @@ function verifySchema(d) {
656
652
  {
657
653
  column: "source_external_id",
658
654
  ddl: "ALTER TABLE tasks ADD COLUMN source_external_id TEXT"
655
+ },
656
+ {
657
+ column: "archived_at",
658
+ ddl: "ALTER TABLE tasks ADD COLUMN archived_at TEXT"
659
659
  }
660
660
  ]
661
661
  };
@@ -880,8 +880,8 @@ function saveConfig(config) {
880
880
  }
881
881
  d.prepare("DELETE FROM tasks").run();
882
882
  const insertTask = d.prepare(
883
- `INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, created_at, updated_at, completed_at, source_connector_id, source_external_url, source_external_id)
884
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
883
+ `INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, created_at, updated_at, completed_at, archived_at, source_connector_id, source_external_url, source_external_id)
884
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
885
885
  );
886
886
  for (const t of config.tasks ?? []) {
887
887
  insertTask.run(
@@ -899,6 +899,7 @@ function saveConfig(config) {
899
899
  t.createdAt,
900
900
  t.updatedAt,
901
901
  t.completedAt ?? null,
902
+ t.archivedAt ?? null,
902
903
  t.sourceConnectorId ?? null,
903
904
  t.sourceExternalUrl ?? null,
904
905
  t.sourceExternalId ?? null
@@ -938,8 +939,8 @@ function dbGetTask(id) {
938
939
  }
939
940
  function dbInsertTask(task) {
940
941
  getDb().prepare(
941
- `INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, created_at, updated_at, completed_at, source_connector_id, source_external_url, source_external_id)
942
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
942
+ `INSERT INTO tasks (id, project_name, title, description, status, "order", assigned_session_id, assigned_agent, agent_session_id, branch, use_worktree, created_at, updated_at, completed_at, archived_at, source_connector_id, source_external_url, source_external_id)
943
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
943
944
  ).run(
944
945
  task.id,
945
946
  task.projectName,
@@ -955,6 +956,7 @@ function dbInsertTask(task) {
955
956
  task.createdAt,
956
957
  task.updatedAt,
957
958
  task.completedAt ?? null,
959
+ task.archivedAt ?? null,
958
960
  task.sourceConnectorId ?? null,
959
961
  task.sourceExternalUrl ?? null,
960
962
  task.sourceExternalId ?? null
@@ -1007,6 +1009,10 @@ function dbUpdateTask(id, updates) {
1007
1009
  sets.push("completed_at = ?");
1008
1010
  params.push(updates.completedAt ?? null);
1009
1011
  }
1012
+ if ("archivedAt" in updates) {
1013
+ sets.push("archived_at = ?");
1014
+ params.push(updates.archivedAt ?? null);
1015
+ }
1010
1016
  if (updates.sourceConnectorId !== void 0) {
1011
1017
  sets.push("source_connector_id = ?");
1012
1018
  params.push(updates.sourceConnectorId);
@@ -1213,6 +1219,7 @@ function rowToTask(r) {
1213
1219
  createdAt: r.created_at,
1214
1220
  updatedAt: r.updated_at,
1215
1221
  ...r.completed_at != null && { completedAt: r.completed_at },
1222
+ ...r.archived_at != null && { archivedAt: r.archived_at },
1216
1223
  ...r.source_connector_id != null && { sourceConnectorId: r.source_connector_id },
1217
1224
  ...r.source_external_url != null && { sourceExternalUrl: r.source_external_url },
1218
1225
  ...r.source_external_id != null && {
@@ -1285,22 +1292,28 @@ function fetchNodesByRunIds(d, runIds) {
1285
1292
  }
1286
1293
  return out;
1287
1294
  }
1288
- function listWorkflowRuns(workflowId, limit = 20) {
1289
- const d = getDb();
1290
- const rows = d.prepare("SELECT * FROM workflow_runs WHERE workflow_id = ? ORDER BY started_at DESC LIMIT ?").all(workflowId, limit);
1291
- const nodesByRun = fetchNodesByRunIds(
1292
- d,
1293
- rows.map((r) => r.id)
1294
- );
1295
+ function mapRunRows(rows, nodesByRun) {
1295
1296
  return rows.map((r) => ({
1296
1297
  workflowId: r.workflow_id,
1297
1298
  startedAt: r.started_at,
1298
1299
  ...r.completed_at != null && { completedAt: r.completed_at },
1299
1300
  status: r.status,
1300
1301
  ...r.trigger_task_id != null && { triggerTaskId: r.trigger_task_id },
1302
+ ...r.workflow_name != null && { workflowName: r.workflow_name },
1301
1303
  nodeStates: nodesByRun.get(r.id) ?? []
1302
1304
  }));
1303
1305
  }
1306
+ function listWorkflowRuns(workflowId, limit = 20) {
1307
+ const d = getDb();
1308
+ const rows = d.prepare("SELECT * FROM workflow_runs WHERE workflow_id = ? ORDER BY started_at DESC LIMIT ?").all(workflowId, limit);
1309
+ return mapRunRows(
1310
+ rows,
1311
+ fetchNodesByRunIds(
1312
+ d,
1313
+ rows.map((r) => r.id)
1314
+ )
1315
+ );
1316
+ }
1304
1317
  function listWorkflowRunsByTask(taskId, limit = 20) {
1305
1318
  const d = getDb();
1306
1319
  const rows = d.prepare(
@@ -1312,19 +1325,13 @@ function listWorkflowRunsByTask(taskId, limit = 20) {
1312
1325
  ORDER BY wr.started_at DESC
1313
1326
  LIMIT ?`
1314
1327
  ).all(taskId, taskId, limit);
1315
- const nodesByRun = fetchNodesByRunIds(
1316
- d,
1317
- rows.map((r) => r.id)
1328
+ return mapRunRows(
1329
+ rows,
1330
+ fetchNodesByRunIds(
1331
+ d,
1332
+ rows.map((r) => r.id)
1333
+ )
1318
1334
  );
1319
- return rows.map((r) => ({
1320
- workflowId: r.workflow_id,
1321
- startedAt: r.started_at,
1322
- ...r.completed_at != null && { completedAt: r.completed_at },
1323
- status: r.status,
1324
- ...r.trigger_task_id != null && { triggerTaskId: r.trigger_task_id },
1325
- ...r.workflow_name != null && { workflowName: r.workflow_name },
1326
- nodeStates: nodesByRun.get(r.id) ?? []
1327
- }));
1328
1335
  }
1329
1336
 
1330
1337
  // ../server/src/config-manager.ts
@@ -1463,15 +1470,19 @@ var AGENT_TYPES = [
1463
1470
  function registerTaskTools(server) {
1464
1471
  server.tool(
1465
1472
  "list_tasks",
1466
- "List tasks, optionally filtered by project, status, assigned agent, or workspace",
1473
+ "List tasks, optionally filtered by project, status, assigned agent, or workspace. Archived tasks are excluded by default; pass include_archived=true to include them.",
1467
1474
  {
1468
1475
  project_name: V.name.optional().describe("Filter by project name"),
1469
1476
  status: z2.enum(TASK_STATUSES).optional().describe("Filter by status"),
1470
1477
  assigned_agent: z2.enum(AGENT_TYPES).optional().describe("Filter by assigned agent type"),
1471
- workspace_id: V.id.optional().describe("Filter by workspace ID (returns tasks from all projects in that workspace)")
1478
+ workspace_id: V.id.optional().describe("Filter by workspace ID (returns tasks from all projects in that workspace)"),
1479
+ include_archived: z2.boolean().optional().describe("Include archived tasks in the result (default: false)")
1472
1480
  },
1473
1481
  async (args) => {
1474
1482
  let tasks = dbListTasks(args.project_name, args.status);
1483
+ if (!args.include_archived) {
1484
+ tasks = tasks.filter((t) => !t.archivedAt);
1485
+ }
1475
1486
  if (args.workspace_id) {
1476
1487
  const projects = dbListProjects();
1477
1488
  const wsProjectNames = new Set(
@@ -1568,11 +1579,14 @@ function registerTaskTools(server) {
1568
1579
  if (args.order !== void 0) updates.order = args.order;
1569
1580
  if (args.status !== void 0) {
1570
1581
  const newStatus = args.status;
1571
- const wasDone = task.status === "done" || task.status === "cancelled";
1572
- const isDone = newStatus === "done" || newStatus === "cancelled";
1582
+ const wasDone = isTerminalTaskStatus(task.status);
1583
+ const isDone = isTerminalTaskStatus(newStatus);
1573
1584
  updates.status = newStatus;
1574
1585
  if (isDone && !wasDone) updates.completedAt = (/* @__PURE__ */ new Date()).toISOString();
1575
- if (!isDone && wasDone) updates.completedAt = void 0;
1586
+ if (!isDone && wasDone) {
1587
+ updates.completedAt = void 0;
1588
+ updates.archivedAt = void 0;
1589
+ }
1576
1590
  }
1577
1591
  dbUpdateTask(args.id, updates);
1578
1592
  dbSignalChange();
@@ -1597,6 +1611,55 @@ function registerTaskTools(server) {
1597
1611
  return { content: [{ type: "text", text: `Deleted task: ${task.title}` }] };
1598
1612
  }
1599
1613
  );
1614
+ server.tool(
1615
+ "archive_task",
1616
+ "Archive a finished task (status must be done or cancelled). Archived tasks are hidden from default views but preserved and restorable.",
1617
+ { id: V.id.describe("Task ID") },
1618
+ async (args) => {
1619
+ const task = dbGetTask(args.id);
1620
+ if (!task) {
1621
+ return {
1622
+ content: [{ type: "text", text: `Error: task "${args.id}" not found` }],
1623
+ isError: true
1624
+ };
1625
+ }
1626
+ if (!isTerminalTaskStatus(task.status)) {
1627
+ return {
1628
+ content: [
1629
+ {
1630
+ type: "text",
1631
+ text: `Error: only done or cancelled tasks can be archived (status: ${task.status})`
1632
+ }
1633
+ ],
1634
+ isError: true
1635
+ };
1636
+ }
1637
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1638
+ dbUpdateTask(args.id, { archivedAt: now, updatedAt: now });
1639
+ dbSignalChange();
1640
+ const updated = dbGetTask(args.id);
1641
+ return { content: [{ type: "text", text: JSON.stringify(updated, null, 2) }] };
1642
+ }
1643
+ );
1644
+ server.tool(
1645
+ "unarchive_task",
1646
+ "Restore an archived task so it shows in default views again.",
1647
+ { id: V.id.describe("Task ID") },
1648
+ async (args) => {
1649
+ const task = dbGetTask(args.id);
1650
+ if (!task) {
1651
+ return {
1652
+ content: [{ type: "text", text: `Error: task "${args.id}" not found` }],
1653
+ isError: true
1654
+ };
1655
+ }
1656
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1657
+ dbUpdateTask(args.id, { archivedAt: void 0, updatedAt: now });
1658
+ dbSignalChange();
1659
+ const updated = dbGetTask(args.id);
1660
+ return { content: [{ type: "text", text: JSON.stringify(updated, null, 2) }] };
1661
+ }
1662
+ );
1600
1663
  server.tool(
1601
1664
  "get_my_context",
1602
1665
  "Get your current task and project context. Auto-detects based on your working directory. Call this at the start of a session to understand what you are working on.",
@@ -2294,10 +2357,10 @@ function registerSessionTools(server) {
2294
2357
  );
2295
2358
  server.tool(
2296
2359
  "list_session_events",
2297
- "List session lifecycle events (created, exited, task_linked, renamed). Use for post-mortem analysis and multi-agent coordination.",
2360
+ "List session lifecycle events (created, exited, renamed). Use for post-mortem analysis and multi-agent coordination.",
2298
2361
  {
2299
2362
  session_id: V.id.optional().describe("Filter by session ID"),
2300
- event_type: z4.enum(["created", "exited", "task_linked", "renamed"]).optional().describe("Filter by event type"),
2363
+ event_type: z4.enum(["created", "exited", "renamed"]).optional().describe("Filter by event type"),
2301
2364
  limit: z4.number().int().min(1).max(200).optional().describe("Max events to return (default: 50)")
2302
2365
  },
2303
2366
  async (args) => {
@@ -2340,7 +2403,9 @@ var launchAgentConfigSchema = z5.object({
2340
2403
  args: z5.array(V.shortText).optional(),
2341
2404
  displayName: V.shortText.optional(),
2342
2405
  branch: V.shortText.optional(),
2343
- useWorktree: z5.boolean().optional(),
2406
+ // boolean | 'fromContext' — `'fromContext'` only valid when the workflow's
2407
+ // manual trigger is contextual (validated at runtime, not here).
2408
+ useWorktree: z5.union([z5.boolean(), z5.literal("fromContext")]).optional(),
2344
2409
  remoteHostId: V.id.optional(),
2345
2410
  prompt: V.prompt.optional(),
2346
2411
  promptDelayMs: z5.number().optional(),
@@ -2348,7 +2413,10 @@ var launchAgentConfigSchema = z5.object({
2348
2413
  taskFromQueue: z5.boolean().optional()
2349
2414
  });
2350
2415
  var triggerConfigSchema = z5.union([
2351
- z5.object({ triggerType: z5.literal("manual") }),
2416
+ z5.object({
2417
+ triggerType: z5.literal("manual"),
2418
+ contextual: z5.boolean().optional()
2419
+ }),
2352
2420
  z5.object({ triggerType: z5.literal("once"), runAt: V.shortText }),
2353
2421
  z5.object({
2354
2422
  triggerType: z5.literal("recurring"),
@@ -2707,7 +2775,7 @@ console.warn = (...args) => _origError("[mcp:warn]", ...args);
2707
2775
  console.error = (...args) => _origError("[mcp:error]", ...args);
2708
2776
  async function main() {
2709
2777
  configManager.init();
2710
- const version = true ? "0.2.0" : createRequire(import.meta.url)("../package.json").version;
2778
+ const version = true ? "0.2.1-beta.2" : createRequire(import.meta.url)("../package.json").version;
2711
2779
  const server = createMcpServer(version);
2712
2780
  const transport = new StdioServerTransport();
2713
2781
  await server.connect(transport);
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@vornrun/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.2",
4
4
  "description": "Vorn MCP server — task management, git, and workflow tools for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Javier Canizalez <javier-canizalez@outlook.com>",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/jcanizalez/vorn.git",
10
+ "url": "git+https://github.com/vorn-run/vorn.git",
11
11
  "directory": "packages/mcp"
12
12
  },
13
13
  "keywords": [
@@ -35,11 +35,11 @@
35
35
  "libsql": "^0.5.29",
36
36
  "pino": "^10.3.1",
37
37
  "ws": "^8.20.0",
38
- "zod": "^4.3.6"
38
+ "zod": "^4.4.3"
39
39
  },
40
40
  "devDependencies": {
41
- "@vornrun/server": "0.1.2",
42
- "@vornrun/shared": "0.1.2",
41
+ "@vornrun/server": "0.2.0",
42
+ "@vornrun/shared": "0.2.0",
43
43
  "tsup": "^8.5.1",
44
44
  "tsx": "^4.21.0",
45
45
  "typescript": "^6.0.3"