@vornrun/mcp 0.8.0-beta.1 → 0.8.0-beta.3

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 +206 -25
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import "module";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
 
7
7
  // ../server/src/config-manager.ts
8
- import fs4 from "fs";
8
+ import fs5 from "fs";
9
9
 
10
10
  // ../shared/src/agent-defaults.ts
11
11
  var DEFAULT_AGENT_COMMANDS = {
@@ -34,9 +34,9 @@ var DEFAULT_AGENT_COMMANDS = {
34
34
 
35
35
  // ../server/src/database.ts
36
36
  import Database from "libsql";
37
- import path3 from "path";
37
+ import path4 from "path";
38
38
  import os from "os";
39
- import fs3 from "fs";
39
+ import fs4 from "fs";
40
40
  import { randomUUID } from "crypto";
41
41
 
42
42
  // ../server/src/logger.ts
@@ -124,6 +124,65 @@ import path2 from "path";
124
124
  import crypto2 from "crypto";
125
125
  var GATE_VIEW_MAX_BYTES = 5 * 1024 * 1024;
126
126
 
127
+ // ../server/src/native-core.ts
128
+ import fs3 from "fs";
129
+ import path3 from "path";
130
+ var NATIVE_CORE_FILE = "vorn_core.node";
131
+ function nativeCoreCandidates(dir, override) {
132
+ const candidates = [
133
+ path3.join(dir, "..", "core", NATIVE_CORE_FILE),
134
+ path3.join(dir, "..", "..", "core", NATIVE_CORE_FILE)
135
+ ];
136
+ return override ? [path3.resolve(override), ...candidates] : candidates;
137
+ }
138
+ function dlopen(file) {
139
+ const mod = { exports: {} };
140
+ process.dlopen(mod, file);
141
+ return mod.exports;
142
+ }
143
+ function loadNativeCore(candidates, deps = {}) {
144
+ const exists = deps.exists ?? fs3.existsSync;
145
+ const open = deps.open ?? dlopen;
146
+ const file = candidates.find((candidate) => exists(candidate));
147
+ if (!file) {
148
+ throw new Error(
149
+ `${NATIVE_CORE_FILE} not found; build it with \`yarn build:core\` (looked in ${candidates.join(", ")})`
150
+ );
151
+ }
152
+ const core = open(file);
153
+ if (typeof core.info !== "function" || typeof core.hello !== "function") {
154
+ throw new Error(`${file} is not a vorn core: it exports no info() or hello()`);
155
+ }
156
+ return core;
157
+ }
158
+ function selectCore(options = {}) {
159
+ const env = options.env ?? process.env;
160
+ const dir = options.dir ?? serverDir();
161
+ const load = options.load ?? ((candidates) => loadNativeCore(candidates));
162
+ try {
163
+ const native2 = load(nativeCoreCandidates(dir, env.VORN_CORE_PATH));
164
+ const info = native2.info();
165
+ if (!info || typeof info.version !== "string") {
166
+ throw new Error("vorn core info() returned no version");
167
+ }
168
+ return { native: native2, info };
169
+ } catch (err) {
170
+ return { native: null, error: err instanceof Error ? err.message : String(err) };
171
+ }
172
+ }
173
+ function serverDir() {
174
+ return typeof __dirname !== "undefined" ? __dirname : path3.dirname(process.argv[1]);
175
+ }
176
+ var active = null;
177
+ var loadOverride;
178
+ function activeCore() {
179
+ active ??= selectCore({ load: loadOverride });
180
+ return active;
181
+ }
182
+ function nativeCore() {
183
+ return activeCore().native;
184
+ }
185
+
127
186
  // ../server/src/default-workflows.ts
128
187
  var DEFAULT_TASK_WORKFLOW_ID = "system:default-task-workflow";
129
188
  var DEV_SERVER_WORKFLOW_ID = "system:dev-server-on-restore";
@@ -201,16 +260,21 @@ function buildDevServerWorkflow() {
201
260
  }
202
261
 
203
262
  // ../server/src/database.ts
204
- var DEFAULT_DATA_DIR = path3.join(os.homedir(), ".vorn");
263
+ var DEFAULT_DATA_DIR = path4.join(os.homedir(), ".vorn");
205
264
  var resolvedDataDir = null;
206
265
  function dbPath() {
207
- return path3.join(getDataDir(), "vorn.db");
266
+ return path4.join(getDataDir(), "vorn.db");
208
267
  }
209
268
  var db = null;
269
+ var native = null;
270
+ var nativeError = null;
210
271
  function getDb() {
211
272
  if (!db) throw new Error("Database not initialized. Call initDatabase() first.");
212
273
  return db;
213
274
  }
275
+ function nativeCall(store, call, ...args) {
276
+ return JSON.parse(store.call(call, JSON.stringify(args)));
277
+ }
214
278
  function getDataDir() {
215
279
  if (!resolvedDataDir) {
216
280
  throw new Error("Data directory not resolved. Call initDatabase() first.");
@@ -219,8 +283,13 @@ function getDataDir() {
219
283
  }
220
284
  function initDatabase(dataDir2) {
221
285
  resolvedDataDir = dataDir2 ?? DEFAULT_DATA_DIR;
222
- if (!fs3.existsSync(getDataDir())) {
223
- fs3.mkdirSync(getDataDir(), { recursive: true, mode: 448 });
286
+ if (!fs4.existsSync(getDataDir())) {
287
+ fs4.mkdirSync(getDataDir(), { recursive: true, mode: 448 });
288
+ }
289
+ if (nativeStoreWanted()) {
290
+ openNativeStore((store) => store.open(dbPath(), nativeOptions()));
291
+ requireForcedNativeStore();
292
+ if (native) return;
224
293
  }
225
294
  try {
226
295
  db = new Database(dbPath());
@@ -241,8 +310,90 @@ function initDatabase(dataDir2) {
241
310
  throw err;
242
311
  }
243
312
  }
313
+ if (!nativeStoreClass() && nativeStoreFlag(readDefault("experimental"))) {
314
+ nativeError = NO_NATIVE_STORE;
315
+ logger_default.warn(`[database] Native store is on, but ${nativeError}; using the TypeScript store`);
316
+ }
317
+ }
318
+ function requireForcedNativeStore() {
319
+ if (process.env.VORN_NATIVE_STORE === "1" && !native)
320
+ throw new Error(`VORN_NATIVE_STORE=1 but the native store did not open: ${nativeError}`);
321
+ }
322
+ var NO_NATIVE_STORE = "the native core is not loaded, or was built without the store";
323
+ function nativeStoreWanted() {
324
+ const forced = process.env.VORN_NATIVE_STORE;
325
+ if (forced === "1") return true;
326
+ if (forced === "0") return false;
327
+ const NativeStoreClass = nativeStoreClass();
328
+ if (!NativeStoreClass) return false;
329
+ try {
330
+ return nativeStoreFlag(NativeStoreClass.readDefault(dbPath(), "experimental"));
331
+ } catch (err) {
332
+ logger_default.warn({ err }, "[database] could not read the Native store switch");
333
+ return false;
334
+ }
335
+ }
336
+ function nativeStoreFlag(experimental) {
337
+ try {
338
+ const flags = experimental ? JSON.parse(experimental) : null;
339
+ return isPlainObject(flags) && flags.nativeStore === true;
340
+ } catch {
341
+ return false;
342
+ }
343
+ }
344
+ function readDefault(key) {
345
+ try {
346
+ const row = getDb().prepare("SELECT value FROM defaults WHERE key = ?").get(key);
347
+ return row?.value ?? null;
348
+ } catch {
349
+ return null;
350
+ }
351
+ }
352
+ function openNativeStore(open) {
353
+ const NativeStoreClass = nativeStoreClass();
354
+ if (!NativeStoreClass) {
355
+ nativeError = NO_NATIVE_STORE;
356
+ logger_default.warn(`[database] Native store is on, but ${nativeError}; using the TypeScript store`);
357
+ return;
358
+ }
359
+ try {
360
+ native = open(NativeStoreClass);
361
+ if (native.recovered) {
362
+ logger_default.warn(
363
+ `[database] the native store replaced a corrupt database; backup at ${native.recovered}`
364
+ );
365
+ }
366
+ nativeError = null;
367
+ logger_default.info("[database] using the native store");
368
+ } catch (err) {
369
+ native = null;
370
+ nativeError = err instanceof Error ? err.message : String(err);
371
+ logger_default.error({ err }, "[database] the native store did not open; using the TypeScript store");
372
+ }
373
+ }
374
+ function nativeStoreClass() {
375
+ const NativeStoreClass = nativeCore()?.NativeStore;
376
+ return typeof NativeStoreClass === "function" ? NativeStoreClass : null;
377
+ }
378
+ function nativeOptions() {
379
+ let ownerName = "owner";
380
+ try {
381
+ ownerName = os.userInfo().username || ownerName;
382
+ } catch {
383
+ }
384
+ return JSON.stringify({
385
+ defaultShell: getDefaultShell(),
386
+ defaultAgentCommands: DEFAULT_AGENT_COMMANDS,
387
+ defaultWorkspace: DEFAULT_WORKSPACE,
388
+ ownerName,
389
+ seedWorkflows: [
390
+ { flag: "hasSeededDefaultTaskWorkflow", workflow: buildDefaultTaskWorkflow() },
391
+ { flag: "hasSeededDevServerWorkflow", workflow: buildDevServerWorkflow() }
392
+ ]
393
+ });
244
394
  }
245
395
  function seedSystemDefaults() {
396
+ if (native) return nativeCall(native, "seedSystemDefaults");
246
397
  seedWorkflowOnce(
247
398
  "hasSeededDefaultTaskWorkflow",
248
399
  DEFAULT_TASK_WORKFLOW_ID,
@@ -294,13 +445,13 @@ function recoverCorruptDatabase() {
294
445
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
295
446
  const backupPath = `${dbPath()}.corrupt-${timestamp}`;
296
447
  try {
297
- if (fs3.existsSync(dbPath())) {
298
- fs3.copyFileSync(dbPath(), backupPath);
448
+ if (fs4.existsSync(dbPath())) {
449
+ fs4.copyFileSync(dbPath(), backupPath);
299
450
  logger_default.info(`[database] Backed up corrupt database to ${backupPath}`);
300
451
  }
301
452
  for (const suffix of ["", "-wal", "-shm"]) {
302
453
  const file = dbPath() + suffix;
303
- if (fs3.existsSync(file)) fs3.unlinkSync(file);
454
+ if (fs4.existsSync(file)) fs4.unlinkSync(file);
304
455
  }
305
456
  } catch (backupErr) {
306
457
  logger_default.error({ backupErr }, "[database] Failed to back up corrupt database:");
@@ -319,6 +470,10 @@ function recoverCorruptDatabase() {
319
470
  logger_default.warn(`[database] Database was corrupted and has been reset. Backup saved to: ${backupPath}`);
320
471
  }
321
472
  function closeDatabase() {
473
+ if (native) {
474
+ native.close();
475
+ native = null;
476
+ }
322
477
  if (db) {
323
478
  db.close();
324
479
  db = null;
@@ -590,6 +745,7 @@ function createSchema() {
590
745
  ON connector_inbox(connection_id, created_at);
591
746
  `);
592
747
  d.exec(ARTIFACT_DDL);
748
+ d.exec(EFFECT_RECEIPTS_DDL);
593
749
  migrateSchema(d);
594
750
  verifySchema(d);
595
751
  seedLegacyConnectorPollState(d);
@@ -1145,7 +1301,25 @@ function migrateSchema(d) {
1145
1301
  })();
1146
1302
  logger_default.info("[database] migrated schema to version 25 (published artifacts and their comments)");
1147
1303
  }
1304
+ if (version < 26) {
1305
+ d.transaction(() => {
1306
+ d.exec(EFFECT_RECEIPTS_DDL);
1307
+ d.prepare(
1308
+ "INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schema_version', '26')"
1309
+ ).run();
1310
+ })();
1311
+ logger_default.info("[database] migrated schema to version 26 (receipts for session effects)");
1312
+ }
1148
1313
  }
1314
+ var EFFECT_RECEIPTS_DDL = `
1315
+ CREATE TABLE IF NOT EXISTS effect_receipts (
1316
+ effect_id TEXT PRIMARY KEY,
1317
+ kind TEXT NOT NULL,
1318
+ received_at INTEGER NOT NULL
1319
+ );
1320
+
1321
+ CREATE INDEX IF NOT EXISTS idx_effect_receipts_received ON effect_receipts(received_at);
1322
+ `;
1149
1323
  var ARTIFACT_DDL = `
1150
1324
  CREATE TABLE IF NOT EXISTS artifacts (
1151
1325
  id TEXT PRIMARY KEY,
@@ -1360,6 +1534,7 @@ function verifySchema(d) {
1360
1534
  }
1361
1535
  }
1362
1536
  function loadConfig() {
1537
+ if (native) return nativeCall(native, "loadConfig");
1363
1538
  const d = getDb();
1364
1539
  const defaults = loadDefaults(d);
1365
1540
  const projects = loadProjects(d);
@@ -1559,7 +1734,13 @@ function pruneMissing(d, table, keyColumn, keep, baseRevision) {
1559
1734
  remove.run(key);
1560
1735
  }
1561
1736
  }
1737
+ function nativeConfig(config) {
1738
+ const deleted = Object.entries(config.defaults).filter(([, value]) => value === void 0).map(([key]) => key);
1739
+ const agentCommands = config.agentCommands && Object.fromEntries(Object.entries(config.agentCommands).map(([key, cmd]) => [key, cmd ?? null]));
1740
+ return [{ ...config, ...agentCommands && { agentCommands } }, deleted];
1741
+ }
1562
1742
  function saveConfig(config) {
1743
+ if (native) return nativeCall(native, "saveConfig", ...nativeConfig(config));
1563
1744
  const d = getDb();
1564
1745
  const run = d.transaction(() => {
1565
1746
  const baseRevision = config.revision ?? Number.MAX_SAFE_INTEGER;
@@ -1951,7 +2132,7 @@ var ConfigManager = class {
1951
2132
  watchDb() {
1952
2133
  if (this.dbWatcher) return;
1953
2134
  try {
1954
- this.dbWatcher = fs4.watch(getDataDir(), (_eventType, filename) => {
2135
+ this.dbWatcher = fs5.watch(getDataDir(), (_eventType, filename) => {
1955
2136
  if (filename !== ".db-signal") return;
1956
2137
  if (this.debounceTimer) clearTimeout(this.debounceTimer);
1957
2138
  this.debounceTimer = setTimeout(() => {
@@ -1984,7 +2165,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1984
2165
 
1985
2166
  // src/tools/tasks.ts
1986
2167
  import crypto3 from "crypto";
1987
- import path5 from "path";
2168
+ import path6 from "path";
1988
2169
  import { z as z2 } from "zod";
1989
2170
 
1990
2171
  // src/validation.ts
@@ -2013,8 +2194,8 @@ var V = {
2013
2194
  };
2014
2195
 
2015
2196
  // ../server/src/rpc-client.ts
2016
- import fs5 from "fs";
2017
- import path4 from "path";
2197
+ import fs6 from "fs";
2198
+ import path5 from "path";
2018
2199
  import os2 from "os";
2019
2200
  import { execFileSync as execFileSync2 } from "child_process";
2020
2201
  import { WebSocket } from "ws";
@@ -2023,13 +2204,13 @@ function named(value) {
2023
2204
  return value?.trim() ? value : void 0;
2024
2205
  }
2025
2206
  function dataDir() {
2026
- return dataDirOverride ?? named(process.env.VORN_DATA_DIR) ?? path4.join(os2.homedir(), ".vorn");
2207
+ return dataDirOverride ?? named(process.env.VORN_DATA_DIR) ?? path5.join(os2.homedir(), ".vorn");
2027
2208
  }
2028
2209
  function portFile() {
2029
- return path4.join(dataDir(), WS_PORT_FILENAME);
2210
+ return path5.join(dataDir(), WS_PORT_FILENAME);
2030
2211
  }
2031
2212
  function localTokenFile() {
2032
- return path4.join(dataDir(), LOCAL_TOKEN_FILENAME);
2213
+ return path5.join(dataDir(), LOCAL_TOKEN_FILENAME);
2033
2214
  }
2034
2215
  function tokenFileMissingMessage() {
2035
2216
  return `Vorn local credential not found (${localTokenFile()}).
@@ -2041,7 +2222,7 @@ MCP included, reaches a server that moved.`;
2041
2222
  }
2042
2223
  function readLocalToken() {
2043
2224
  try {
2044
- const token = fs5.readFileSync(localTokenFile(), "utf-8").trim();
2225
+ const token = fs6.readFileSync(localTokenFile(), "utf-8").trim();
2045
2226
  if (!token) throw new Error("empty");
2046
2227
  return token;
2047
2228
  } catch {
@@ -2161,8 +2342,8 @@ function discoverAndHeal() {
2161
2342
  cacheTimestamp = now;
2162
2343
  if (discovered) {
2163
2344
  try {
2164
- fs5.mkdirSync(dataDir(), { recursive: true });
2165
- fs5.writeFileSync(portFile(), JSON.stringify({ port: discovered }), "utf-8");
2345
+ fs6.mkdirSync(dataDir(), { recursive: true });
2346
+ fs6.writeFileSync(portFile(), JSON.stringify({ port: discovered }), "utf-8");
2166
2347
  } catch {
2167
2348
  }
2168
2349
  return { port: discovered };
@@ -2171,7 +2352,7 @@ function discoverAndHeal() {
2171
2352
  }
2172
2353
  function readPort() {
2173
2354
  try {
2174
- const raw = fs5.readFileSync(portFile(), "utf-8").trim();
2355
+ const raw = fs6.readFileSync(portFile(), "utf-8").trim();
2175
2356
  if (!raw) return { port: null, reason: "invalid" };
2176
2357
  if (raw.startsWith("{")) {
2177
2358
  const parsed = JSON.parse(raw);
@@ -2609,12 +2790,12 @@ function registerTaskTools(server) {
2609
2790
  };
2610
2791
  }
2611
2792
  const cwd = args.cwd || process.cwd();
2612
- const normalizedCwd = path5.resolve(cwd);
2793
+ const normalizedCwd = path6.resolve(cwd);
2613
2794
  const projects = await dbListProjects();
2614
2795
  let matchedProject = null;
2615
2796
  let matchLen = 0;
2616
2797
  for (const p of projects) {
2617
- const normalizedPath = path5.resolve(p.path);
2798
+ const normalizedPath = path6.resolve(p.path);
2618
2799
  if (normalizedCwd.startsWith(normalizedPath) && normalizedPath.length > matchLen) {
2619
2800
  matchedProject = p;
2620
2801
  matchLen = normalizedPath.length;
@@ -2642,7 +2823,7 @@ function registerTaskTools(server) {
2642
2823
  let matchedTask = null;
2643
2824
  for (const t of projectTasks) {
2644
2825
  if (t.worktreePath) {
2645
- const normalizedWorktree = path5.resolve(t.worktreePath);
2826
+ const normalizedWorktree = path6.resolve(t.worktreePath);
2646
2827
  if (normalizedCwd.startsWith(normalizedWorktree)) {
2647
2828
  matchedTask = t;
2648
2829
  break;
@@ -5961,7 +6142,7 @@ console.warn = (...args) => _origError("[mcp:warn]", ...args);
5961
6142
  console.error = (...args) => _origError("[mcp:error]", ...args);
5962
6143
  async function main() {
5963
6144
  configManager.init();
5964
- const version = true ? "0.8.0-beta.1" : createRequire(import.meta.url)("../package.json").version;
6145
+ const version = true ? "0.8.0-beta.3" : createRequire(import.meta.url)("../package.json").version;
5965
6146
  const server = createMcpServer(version);
5966
6147
  const transport = new StdioServerTransport();
5967
6148
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vornrun/mcp",
3
- "version": "0.8.0-beta.1",
3
+ "version": "0.8.0-beta.3",
4
4
  "description": "Vorn MCP server — task management, git, and workflow tools for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,8 +38,8 @@
38
38
  "zod": "^4.5.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@vornrun/server": "0.8.0-beta.1",
42
- "@vornrun/shared": "0.8.0-beta.1",
41
+ "@vornrun/server": "0.8.0-beta.3",
42
+ "@vornrun/shared": "0.8.0-beta.3",
43
43
  "tsup": "^8.5.1",
44
44
  "tsx": "^4.23.1",
45
45
  "typescript": "^6.0.3"