@vornrun/mcp 0.4.1 → 0.5.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.
- package/dist/index.js +100 -34
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ import "module";
|
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
6
|
|
|
7
7
|
// ../server/src/config-manager.ts
|
|
8
|
-
import
|
|
9
|
-
import
|
|
8
|
+
import fs3 from "fs";
|
|
9
|
+
import path3 from "path";
|
|
10
10
|
import os2 from "os";
|
|
11
11
|
|
|
12
12
|
// ../shared/src/agent-defaults.ts
|
|
@@ -36,15 +36,65 @@ var DEFAULT_AGENT_COMMANDS = {
|
|
|
36
36
|
|
|
37
37
|
// ../server/src/database.ts
|
|
38
38
|
import Database from "libsql";
|
|
39
|
-
import
|
|
39
|
+
import path2 from "path";
|
|
40
40
|
import os from "os";
|
|
41
|
-
import
|
|
41
|
+
import fs2 from "fs";
|
|
42
42
|
|
|
43
43
|
// ../server/src/logger.ts
|
|
44
44
|
import pino from "pino";
|
|
45
45
|
var log = pino({ level: process.env.VITEST ? "silent" : "info" }, process.stderr);
|
|
46
46
|
var logger_default = log;
|
|
47
47
|
|
|
48
|
+
// ../server/src/process-utils.ts
|
|
49
|
+
import { execFileSync, execFile } from "child_process";
|
|
50
|
+
import fs from "fs";
|
|
51
|
+
import path from "path";
|
|
52
|
+
function getUserShellEnv() {
|
|
53
|
+
if (process.platform === "win32") return { ...process.env };
|
|
54
|
+
try {
|
|
55
|
+
const shell = process.env.SHELL || "/bin/zsh";
|
|
56
|
+
const output = execFileSync(shell, ["-ilc", "env"], {
|
|
57
|
+
encoding: "utf-8",
|
|
58
|
+
timeout: 5e3,
|
|
59
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
60
|
+
});
|
|
61
|
+
const env = {};
|
|
62
|
+
for (const line of output.split("\n")) {
|
|
63
|
+
const idx = line.indexOf("=");
|
|
64
|
+
if (idx > 0) {
|
|
65
|
+
env[line.substring(0, idx)] = line.substring(idx + 1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return env;
|
|
69
|
+
} catch {
|
|
70
|
+
return { ...process.env };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
var resolvedEnv = getUserShellEnv();
|
|
74
|
+
function getDefaultShell(configured) {
|
|
75
|
+
const chosen = configured?.trim();
|
|
76
|
+
if (chosen) return chosen;
|
|
77
|
+
if (process.platform === "win32") return findWindowsShell();
|
|
78
|
+
return process.env.SHELL || "/bin/zsh";
|
|
79
|
+
}
|
|
80
|
+
function findWindowsShell() {
|
|
81
|
+
const pathDirs = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean);
|
|
82
|
+
for (const dir of pathDirs) {
|
|
83
|
+
const candidate = path.join(dir, "pwsh.exe");
|
|
84
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
85
|
+
}
|
|
86
|
+
const systemRoot = process.env.SystemRoot || process.env.windir || "C:\\Windows";
|
|
87
|
+
const windowsPowerShell = path.join(
|
|
88
|
+
systemRoot,
|
|
89
|
+
"System32",
|
|
90
|
+
"WindowsPowerShell",
|
|
91
|
+
"v1.0",
|
|
92
|
+
"powershell.exe"
|
|
93
|
+
);
|
|
94
|
+
if (fs.existsSync(windowsPowerShell)) return windowsPowerShell;
|
|
95
|
+
return process.env.COMSPEC || "cmd.exe";
|
|
96
|
+
}
|
|
97
|
+
|
|
48
98
|
// ../shared/src/types.ts
|
|
49
99
|
var DEFAULT_WORKSPACE = {
|
|
50
100
|
id: "personal",
|
|
@@ -100,16 +150,16 @@ function buildDefaultTaskWorkflow() {
|
|
|
100
150
|
}
|
|
101
151
|
|
|
102
152
|
// ../server/src/database.ts
|
|
103
|
-
var CONFIG_DIR =
|
|
104
|
-
var DB_PATH =
|
|
153
|
+
var CONFIG_DIR = path2.join(os.homedir(), ".vorn");
|
|
154
|
+
var DB_PATH = path2.join(CONFIG_DIR, "vorn.db");
|
|
105
155
|
var db = null;
|
|
106
156
|
function getDb() {
|
|
107
157
|
if (!db) throw new Error("Database not initialized. Call initDatabase() first.");
|
|
108
158
|
return db;
|
|
109
159
|
}
|
|
110
160
|
function initDatabase() {
|
|
111
|
-
if (!
|
|
112
|
-
|
|
161
|
+
if (!fs2.existsSync(CONFIG_DIR)) {
|
|
162
|
+
fs2.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
113
163
|
}
|
|
114
164
|
try {
|
|
115
165
|
db = new Database(DB_PATH);
|
|
@@ -174,13 +224,13 @@ function recoverCorruptDatabase() {
|
|
|
174
224
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
175
225
|
const backupPath = `${DB_PATH}.corrupt-${timestamp}`;
|
|
176
226
|
try {
|
|
177
|
-
if (
|
|
178
|
-
|
|
227
|
+
if (fs2.existsSync(DB_PATH)) {
|
|
228
|
+
fs2.copyFileSync(DB_PATH, backupPath);
|
|
179
229
|
logger_default.info(`[database] Backed up corrupt database to ${backupPath}`);
|
|
180
230
|
}
|
|
181
231
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
182
232
|
const file = DB_PATH + suffix;
|
|
183
|
-
if (
|
|
233
|
+
if (fs2.existsSync(file)) fs2.unlinkSync(file);
|
|
184
234
|
}
|
|
185
235
|
} catch (backupErr) {
|
|
186
236
|
logger_default.error("[database] Failed to back up corrupt database:", backupErr);
|
|
@@ -200,8 +250,8 @@ function recoverCorruptDatabase() {
|
|
|
200
250
|
}
|
|
201
251
|
function dbSignalChange() {
|
|
202
252
|
try {
|
|
203
|
-
const signalPath =
|
|
204
|
-
|
|
253
|
+
const signalPath = path2.join(CONFIG_DIR, ".db-signal");
|
|
254
|
+
fs2.writeFileSync(signalPath, Date.now().toString());
|
|
205
255
|
} catch {
|
|
206
256
|
}
|
|
207
257
|
}
|
|
@@ -369,6 +419,7 @@ function createSchema() {
|
|
|
369
419
|
project_name TEXT,
|
|
370
420
|
project_path TEXT,
|
|
371
421
|
approved_at TEXT,
|
|
422
|
+
diagnostics TEXT,
|
|
372
423
|
FOREIGN KEY (run_id) REFERENCES workflow_runs(id) ON DELETE CASCADE
|
|
373
424
|
);
|
|
374
425
|
|
|
@@ -638,7 +689,11 @@ function verifySchema(d) {
|
|
|
638
689
|
column: "project_path",
|
|
639
690
|
ddl: "ALTER TABLE workflow_run_nodes ADD COLUMN project_path TEXT"
|
|
640
691
|
},
|
|
641
|
-
{ column: "approved_at", ddl: "ALTER TABLE workflow_run_nodes ADD COLUMN approved_at TEXT" }
|
|
692
|
+
{ column: "approved_at", ddl: "ALTER TABLE workflow_run_nodes ADD COLUMN approved_at TEXT" },
|
|
693
|
+
{
|
|
694
|
+
column: "diagnostics",
|
|
695
|
+
ddl: "ALTER TABLE workflow_run_nodes ADD COLUMN diagnostics TEXT"
|
|
696
|
+
}
|
|
642
697
|
],
|
|
643
698
|
tasks: [
|
|
644
699
|
{
|
|
@@ -701,7 +756,12 @@ function loadDefaults(d) {
|
|
|
701
756
|
map[row.key] = JSON.parse(row.value);
|
|
702
757
|
}
|
|
703
758
|
return {
|
|
704
|
-
shell:
|
|
759
|
+
shell: (
|
|
760
|
+
// Not COMSPEC on Windows: that names the .bat interpreter, is always
|
|
761
|
+
// cmd.exe, and seeding it here handed every Windows user the one shell
|
|
762
|
+
// that can report neither exit status nor command text.
|
|
763
|
+
map.shell ?? getDefaultShell()
|
|
764
|
+
),
|
|
705
765
|
fontSize: map.fontSize ?? 13,
|
|
706
766
|
theme: map.theme ?? "dark",
|
|
707
767
|
...map.rowHeight !== void 0 && { rowHeight: map.rowHeight },
|
|
@@ -713,6 +773,10 @@ function loadDefaults(d) {
|
|
|
713
773
|
hasSeenOnboarding: map.hasSeenOnboarding
|
|
714
774
|
},
|
|
715
775
|
...map.reopenSessions !== void 0 && { reopenSessions: map.reopenSessions },
|
|
776
|
+
// Terminal block rendering. Default on; the key only appears once the
|
|
777
|
+
// user has toggled it, so absence means "not yet decided", not "off".
|
|
778
|
+
domBlockRendering: map.domBlockRendering ?? true,
|
|
779
|
+
minimalShellPrompt: map.minimalShellPrompt ?? true,
|
|
716
780
|
...map.widgetEnabled !== void 0 && { widgetEnabled: map.widgetEnabled },
|
|
717
781
|
...map.taskViewMode !== void 0 && {
|
|
718
782
|
taskViewMode: map.taskViewMode
|
|
@@ -1276,7 +1340,8 @@ function mapNodeRow(n) {
|
|
|
1276
1340
|
...n.agent_type != null && { agentType: n.agent_type },
|
|
1277
1341
|
...n.project_name != null && { projectName: n.project_name },
|
|
1278
1342
|
...n.project_path != null && { projectPath: n.project_path },
|
|
1279
|
-
...n.approved_at != null && { approvedAt: n.approved_at }
|
|
1343
|
+
...n.approved_at != null && { approvedAt: n.approved_at },
|
|
1344
|
+
...n.diagnostics != null && { diagnostics: n.diagnostics }
|
|
1280
1345
|
};
|
|
1281
1346
|
}
|
|
1282
1347
|
function fetchNodesByRunIds(d, runIds) {
|
|
@@ -1294,6 +1359,7 @@ function fetchNodesByRunIds(d, runIds) {
|
|
|
1294
1359
|
}
|
|
1295
1360
|
function mapRunRows(rows, nodesByRun) {
|
|
1296
1361
|
return rows.map((r) => ({
|
|
1362
|
+
runId: r.id,
|
|
1297
1363
|
workflowId: r.workflow_id,
|
|
1298
1364
|
startedAt: r.started_at,
|
|
1299
1365
|
...r.completed_at != null && { completedAt: r.completed_at },
|
|
@@ -1335,7 +1401,7 @@ function listWorkflowRunsByTask(taskId, limit = 20) {
|
|
|
1335
1401
|
}
|
|
1336
1402
|
|
|
1337
1403
|
// ../server/src/config-manager.ts
|
|
1338
|
-
var DB_DIR =
|
|
1404
|
+
var DB_DIR = path3.join(os2.homedir(), ".vorn");
|
|
1339
1405
|
var ConfigManager = class {
|
|
1340
1406
|
changeCallbacks = [];
|
|
1341
1407
|
dbWatcher = null;
|
|
@@ -1359,7 +1425,7 @@ var ConfigManager = class {
|
|
|
1359
1425
|
return {
|
|
1360
1426
|
version: 1,
|
|
1361
1427
|
defaults: {
|
|
1362
|
-
shell:
|
|
1428
|
+
shell: getDefaultShell(),
|
|
1363
1429
|
fontSize: 13,
|
|
1364
1430
|
theme: "dark"
|
|
1365
1431
|
},
|
|
@@ -1399,7 +1465,7 @@ var ConfigManager = class {
|
|
|
1399
1465
|
if (this.dbWatcher) return;
|
|
1400
1466
|
const WATCH_SUFFIXES = [".db-signal", ".db-wal", ".db"];
|
|
1401
1467
|
try {
|
|
1402
|
-
this.dbWatcher =
|
|
1468
|
+
this.dbWatcher = fs3.watch(DB_DIR, (eventType, filename) => {
|
|
1403
1469
|
if (!filename || !WATCH_SUFFIXES.some((s) => filename.endsWith(s))) return;
|
|
1404
1470
|
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
1405
1471
|
this.debounceTimer = setTimeout(() => {
|
|
@@ -1432,7 +1498,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
1432
1498
|
|
|
1433
1499
|
// src/tools/tasks.ts
|
|
1434
1500
|
import crypto from "crypto";
|
|
1435
|
-
import
|
|
1501
|
+
import path4 from "path";
|
|
1436
1502
|
import { z as z2 } from "zod";
|
|
1437
1503
|
|
|
1438
1504
|
// src/validation.ts
|
|
@@ -1703,12 +1769,12 @@ function registerTaskTools(server) {
|
|
|
1703
1769
|
};
|
|
1704
1770
|
}
|
|
1705
1771
|
const cwd = args.cwd || process.cwd();
|
|
1706
|
-
const normalizedCwd =
|
|
1772
|
+
const normalizedCwd = path4.resolve(cwd);
|
|
1707
1773
|
const projects = dbListProjects();
|
|
1708
1774
|
let matchedProject = null;
|
|
1709
1775
|
let matchLen = 0;
|
|
1710
1776
|
for (const p of projects) {
|
|
1711
|
-
const normalizedPath =
|
|
1777
|
+
const normalizedPath = path4.resolve(p.path);
|
|
1712
1778
|
if (normalizedCwd.startsWith(normalizedPath) && normalizedPath.length > matchLen) {
|
|
1713
1779
|
matchedProject = p;
|
|
1714
1780
|
matchLen = normalizedPath.length;
|
|
@@ -1736,7 +1802,7 @@ function registerTaskTools(server) {
|
|
|
1736
1802
|
let matchedTask = null;
|
|
1737
1803
|
for (const t of projectTasks) {
|
|
1738
1804
|
if (t.worktreePath) {
|
|
1739
|
-
const normalizedWorktree =
|
|
1805
|
+
const normalizedWorktree = path4.resolve(t.worktreePath);
|
|
1740
1806
|
if (normalizedCwd.startsWith(normalizedWorktree)) {
|
|
1741
1807
|
matchedTask = t;
|
|
1742
1808
|
break;
|
|
@@ -1875,12 +1941,12 @@ function registerProjectTools(server) {
|
|
|
1875
1941
|
import { z as z4 } from "zod";
|
|
1876
1942
|
|
|
1877
1943
|
// src/ws-client.ts
|
|
1878
|
-
import
|
|
1879
|
-
import
|
|
1944
|
+
import fs4 from "fs";
|
|
1945
|
+
import path5 from "path";
|
|
1880
1946
|
import os3 from "os";
|
|
1881
|
-
import { execFileSync } from "child_process";
|
|
1947
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
1882
1948
|
import { WebSocket } from "ws";
|
|
1883
|
-
var PORT_FILE =
|
|
1949
|
+
var PORT_FILE = path5.join(os3.homedir(), ".vorn", "ws-port");
|
|
1884
1950
|
var TIMEOUT_MS = 1e4;
|
|
1885
1951
|
var IS_WIN = process.platform === "win32";
|
|
1886
1952
|
var PORT_FILE_MISSING_MSG = IS_WIN ? `Vorn port file not found (~/.vorn/ws-port).
|
|
@@ -1910,7 +1976,7 @@ var EXEC_OPTS = {
|
|
|
1910
1976
|
function discoverPort() {
|
|
1911
1977
|
try {
|
|
1912
1978
|
if (IS_WIN) {
|
|
1913
|
-
const taskOut =
|
|
1979
|
+
const taskOut = execFileSync2(
|
|
1914
1980
|
"tasklist",
|
|
1915
1981
|
["/FI", "IMAGENAME eq Vorn.exe", "/FO", "CSV", "/NH"],
|
|
1916
1982
|
EXEC_OPTS
|
|
@@ -1918,7 +1984,7 @@ function discoverPort() {
|
|
|
1918
1984
|
const pidMatch = taskOut.match(/"Vorn\.exe","(\d+)"/);
|
|
1919
1985
|
if (!pidMatch) return null;
|
|
1920
1986
|
const pid = pidMatch[1];
|
|
1921
|
-
const lines =
|
|
1987
|
+
const lines = execFileSync2("netstat", ["-ano"], EXEC_OPTS).split("\n");
|
|
1922
1988
|
let fallback = null;
|
|
1923
1989
|
for (const line of lines) {
|
|
1924
1990
|
if (!line.includes("LISTENING") || !line.trim().endsWith(pid)) continue;
|
|
@@ -1929,7 +1995,7 @@ function discoverPort() {
|
|
|
1929
1995
|
}
|
|
1930
1996
|
return fallback;
|
|
1931
1997
|
} else {
|
|
1932
|
-
const lines =
|
|
1998
|
+
const lines = execFileSync2("lsof", ["-iTCP", "-sTCP:LISTEN", "-P", "-n"], EXEC_OPTS).split(
|
|
1933
1999
|
"\n"
|
|
1934
2000
|
);
|
|
1935
2001
|
let fallback = null;
|
|
@@ -1958,8 +2024,8 @@ function discoverAndHeal() {
|
|
|
1958
2024
|
cacheTimestamp = now;
|
|
1959
2025
|
if (discovered) {
|
|
1960
2026
|
try {
|
|
1961
|
-
|
|
1962
|
-
|
|
2027
|
+
fs4.mkdirSync(path5.dirname(PORT_FILE), { recursive: true });
|
|
2028
|
+
fs4.writeFileSync(PORT_FILE, JSON.stringify({ port: discovered }), "utf-8");
|
|
1963
2029
|
} catch {
|
|
1964
2030
|
}
|
|
1965
2031
|
return { port: discovered };
|
|
@@ -1968,7 +2034,7 @@ function discoverAndHeal() {
|
|
|
1968
2034
|
}
|
|
1969
2035
|
function readPort() {
|
|
1970
2036
|
try {
|
|
1971
|
-
const raw =
|
|
2037
|
+
const raw = fs4.readFileSync(PORT_FILE, "utf-8").trim();
|
|
1972
2038
|
if (!raw) return { port: null, reason: "invalid" };
|
|
1973
2039
|
if (raw.startsWith("{")) {
|
|
1974
2040
|
const parsed = JSON.parse(raw);
|
|
@@ -2803,7 +2869,7 @@ console.warn = (...args) => _origError("[mcp:warn]", ...args);
|
|
|
2803
2869
|
console.error = (...args) => _origError("[mcp:error]", ...args);
|
|
2804
2870
|
async function main() {
|
|
2805
2871
|
configManager.init();
|
|
2806
|
-
const version = true ? "0.
|
|
2872
|
+
const version = true ? "0.5.0" : createRequire(import.meta.url)("../package.json").version;
|
|
2807
2873
|
const server = createMcpServer(version);
|
|
2808
2874
|
const transport = new StdioServerTransport();
|
|
2809
2875
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vornrun/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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.4.3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@vornrun/server": "0.
|
|
42
|
-
"@vornrun/shared": "0.
|
|
41
|
+
"@vornrun/server": "0.5.0",
|
|
42
|
+
"@vornrun/shared": "0.5.0",
|
|
43
43
|
"tsup": "^8.5.1",
|
|
44
44
|
"tsx": "^4.23.1",
|
|
45
45
|
"typescript": "^6.0.3"
|