vectorvesper 2.1.1 → 2.4.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/README.md +34 -0
- package/dist/hooks.json +2328 -244
- package/dist/index.js +200 -67
- package/dist/mcp-UEQ2Y6FU.js +300 -0
- package/dist/{server-WQ564YNA.js → server-H4XNBFKQ.js} +497 -33
- package/package.json +17 -5
- package/dist/mcp-FCM3FZSK.js +0 -116
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadHookManifest
|
|
3
|
+
} from "./chunk-CPZKZO3A.js";
|
|
4
|
+
import {
|
|
5
|
+
getAuthToken
|
|
6
|
+
} from "./chunk-SFP5K3ZO.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/mcp.ts
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
|
|
11
|
+
// src/utils/mcp-install.ts
|
|
12
|
+
import fs from "fs";
|
|
13
|
+
import os from "os";
|
|
14
|
+
import path from "path";
|
|
15
|
+
var CLIENT_IDS = ["claude", "cursor", "antigravity", "opencode"];
|
|
16
|
+
var SERVER_NAME = "vectorvesper";
|
|
17
|
+
var ARGS = ["-y", "vectorvesper@latest", "mcp", "--stdio"];
|
|
18
|
+
function home(...parts) {
|
|
19
|
+
return path.join(os.homedir(), ...parts);
|
|
20
|
+
}
|
|
21
|
+
var CLIENTS = {
|
|
22
|
+
claude: {
|
|
23
|
+
label: "Claude Code",
|
|
24
|
+
projectPath: ".mcp.json",
|
|
25
|
+
globalPath: home(".claude.json"),
|
|
26
|
+
dialect: "mcpServers",
|
|
27
|
+
note: "Project scope is committed with the repo, so teammates get it too."
|
|
28
|
+
},
|
|
29
|
+
cursor: {
|
|
30
|
+
label: "Cursor",
|
|
31
|
+
projectPath: path.join(".cursor", "mcp.json"),
|
|
32
|
+
globalPath: home(".cursor", "mcp.json"),
|
|
33
|
+
dialect: "mcpServers"
|
|
34
|
+
},
|
|
35
|
+
antigravity: {
|
|
36
|
+
label: "Antigravity",
|
|
37
|
+
// Workspace scope lives under .agents/; the global file is shared by the
|
|
38
|
+
// IDE, the CLI and Antigravity 2.0, so configuring once covers all three.
|
|
39
|
+
projectPath: path.join(".agents", "mcp_config.json"),
|
|
40
|
+
globalPath: home(".gemini", "config", "mcp_config.json"),
|
|
41
|
+
dialect: "mcpServers",
|
|
42
|
+
note: "The global file is shared by the Antigravity IDE, CLI and 2.0."
|
|
43
|
+
},
|
|
44
|
+
opencode: {
|
|
45
|
+
label: "opencode",
|
|
46
|
+
projectPath: null,
|
|
47
|
+
globalPath: home(".config", "opencode", "opencode.jsonc"),
|
|
48
|
+
dialect: "opencode",
|
|
49
|
+
note: "Servers are keyed directly under `mcp` \u2014 there is no `servers` layer."
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
function serverEntry(dialect) {
|
|
53
|
+
return dialect === "opencode" ? { type: "local", command: ["npx", ...ARGS], enabled: true } : { command: "npx", args: ARGS };
|
|
54
|
+
}
|
|
55
|
+
function snippet(client) {
|
|
56
|
+
const spec = CLIENTS[client];
|
|
57
|
+
const body = spec.dialect === "opencode" ? {
|
|
58
|
+
$schema: "https://opencode.ai/config.json",
|
|
59
|
+
mcp: { [SERVER_NAME]: serverEntry("opencode") }
|
|
60
|
+
} : { mcpServers: { [SERVER_NAME]: serverEntry("mcpServers") } };
|
|
61
|
+
return JSON.stringify(body, null, 2);
|
|
62
|
+
}
|
|
63
|
+
function readConfig(file) {
|
|
64
|
+
if (!fs.existsSync(file)) return {};
|
|
65
|
+
const raw = fs.readFileSync(file, "utf-8").trim();
|
|
66
|
+
if (!raw) return {};
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(raw);
|
|
69
|
+
} catch {
|
|
70
|
+
try {
|
|
71
|
+
const stripped = raw.replace(/^\s*\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/,(\s*[}\]])/g, "$1");
|
|
72
|
+
return JSON.parse(stripped);
|
|
73
|
+
} catch {
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function installClient(client, opts = {}) {
|
|
79
|
+
const spec = CLIENTS[client];
|
|
80
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
81
|
+
const useGlobal = opts.global || !spec.projectPath;
|
|
82
|
+
const file = useGlobal ? spec.globalPath : path.join(cwd, spec.projectPath);
|
|
83
|
+
const existing = readConfig(file);
|
|
84
|
+
if (existing === void 0) {
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
client,
|
|
88
|
+
file,
|
|
89
|
+
action: "manual",
|
|
90
|
+
reason: "the file has content this command could not parse, so it was left untouched"
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const existed = fs.existsSync(file) && fs.readFileSync(file, "utf-8").trim().length > 0;
|
|
94
|
+
const entry = serverEntry(spec.dialect);
|
|
95
|
+
let changed = false;
|
|
96
|
+
if (spec.dialect === "opencode") {
|
|
97
|
+
const mcp = existing.mcp ?? {};
|
|
98
|
+
if (JSON.stringify(mcp[SERVER_NAME]) !== JSON.stringify(entry)) {
|
|
99
|
+
mcp[SERVER_NAME] = entry;
|
|
100
|
+
changed = true;
|
|
101
|
+
}
|
|
102
|
+
existing.mcp = mcp;
|
|
103
|
+
if (!existing.$schema) existing.$schema = "https://opencode.ai/config.json";
|
|
104
|
+
} else {
|
|
105
|
+
const servers = existing.mcpServers ?? {};
|
|
106
|
+
if (JSON.stringify(servers[SERVER_NAME]) !== JSON.stringify(entry)) {
|
|
107
|
+
servers[SERVER_NAME] = entry;
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
existing.mcpServers = servers;
|
|
111
|
+
}
|
|
112
|
+
if (!changed) return { ok: true, client, file, action: "already-present" };
|
|
113
|
+
try {
|
|
114
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
115
|
+
fs.writeFileSync(file, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
116
|
+
} catch (error) {
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
client,
|
|
120
|
+
file,
|
|
121
|
+
action: "manual",
|
|
122
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return { ok: true, client, file, action: existed ? "updated" : "created" };
|
|
126
|
+
}
|
|
127
|
+
function detectClients(cwd = process.cwd()) {
|
|
128
|
+
const found = [];
|
|
129
|
+
for (const id of CLIENT_IDS) {
|
|
130
|
+
const spec = CLIENTS[id];
|
|
131
|
+
const project = spec.projectPath ? path.join(cwd, spec.projectPath) : null;
|
|
132
|
+
const globalDir = path.dirname(spec.globalPath);
|
|
133
|
+
if (project && fs.existsSync(project) || fs.existsSync(spec.globalPath) || fs.existsSync(globalDir)) {
|
|
134
|
+
found.push(id);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return found;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/commands/mcp.ts
|
|
141
|
+
var VERSION = true ? "2.4.0" : "0.0.0-dev";
|
|
142
|
+
var CONFIG_SNIPPET = `{
|
|
143
|
+
"mcpServers": {
|
|
144
|
+
"vectorvesper": {
|
|
145
|
+
"command": "npx",
|
|
146
|
+
"args": ["-y", "vectorvesper@latest", "mcp"]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}`;
|
|
150
|
+
function protectStdout() {
|
|
151
|
+
const toStderr = (...args) => {
|
|
152
|
+
console.error(...args);
|
|
153
|
+
};
|
|
154
|
+
console.log = toStderr;
|
|
155
|
+
console.info = toStderr;
|
|
156
|
+
console.debug = toStderr;
|
|
157
|
+
}
|
|
158
|
+
function printStatus() {
|
|
159
|
+
const manifest = loadHookManifest();
|
|
160
|
+
const authed = Boolean(getAuthToken());
|
|
161
|
+
const ok = (s) => `${pc.green("\u2714")} ${s}`;
|
|
162
|
+
const bad = (s) => `${pc.red("\u2717")} ${s}`;
|
|
163
|
+
console.log("");
|
|
164
|
+
console.log(pc.bold(pc.cyan(" Vector Vesper MCP\n")));
|
|
165
|
+
console.log(` ${pc.bold("CLI version:")} ${VERSION}`);
|
|
166
|
+
if (manifest) {
|
|
167
|
+
const hookCount = manifest.hooks.filter((h) => h.category !== "core").length;
|
|
168
|
+
const coreCount = manifest.hooks.length - hookCount;
|
|
169
|
+
const patternCount = manifest.patterns?.length ?? 0;
|
|
170
|
+
console.log(
|
|
171
|
+
` ${ok(
|
|
172
|
+
`Hook manifest: ${hookCount} hooks, ${coreCount} core primitives, ${patternCount} patterns, engine v${manifest.engineVersion}`
|
|
173
|
+
)}`
|
|
174
|
+
);
|
|
175
|
+
console.log(` ${pc.dim(`Contract level: ${manifest.contractLevel}`)}`);
|
|
176
|
+
} else {
|
|
177
|
+
console.log(` ${bad("Hook manifest: MISSING")}`);
|
|
178
|
+
console.log(` ${pc.dim("Reinstall with: npm i -g vectorvesper@latest")}`);
|
|
179
|
+
}
|
|
180
|
+
console.log(
|
|
181
|
+
` ${authed ? ok("Authenticated \u2014 Pro components available") : pc.dim("\u25CB Not authenticated \u2014 free components only")}`
|
|
182
|
+
);
|
|
183
|
+
console.log("");
|
|
184
|
+
console.log(pc.bold(" Register with an agent"));
|
|
185
|
+
console.log(pc.dim(" Claude Code:"));
|
|
186
|
+
console.log(` ${pc.cyan("claude mcp add -s user vectorvesper -- npx -y vectorvesper@latest mcp")}`);
|
|
187
|
+
console.log(pc.dim(" Cursor / Claude Desktop / other \u2014 add to the client's MCP config:"));
|
|
188
|
+
console.log(
|
|
189
|
+
CONFIG_SNIPPET.split("\n").map((l) => ` ${pc.dim(l)}`).join("\n")
|
|
190
|
+
);
|
|
191
|
+
console.log("");
|
|
192
|
+
console.log(
|
|
193
|
+
pc.dim(
|
|
194
|
+
" Tools: list_hooks \xB7 get_hook \xB7 list_patterns \xB7 get_pattern \xB7 list_components \xB7 get_component \xB7 get_setup_guidance \xB7 search \xB7 check_motion"
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
console.log("");
|
|
198
|
+
}
|
|
199
|
+
function printInteractiveHelp() {
|
|
200
|
+
console.log("");
|
|
201
|
+
console.log(pc.bold(pc.cyan(" Vector Vesper MCP server")));
|
|
202
|
+
console.log("");
|
|
203
|
+
console.log(" This command speaks the Model Context Protocol over stdin/stdout.");
|
|
204
|
+
console.log(" It is meant to be launched by an AI coding agent, not run by hand \u2014");
|
|
205
|
+
console.log(" started from a terminal it would just wait for a client that never connects.");
|
|
206
|
+
console.log("");
|
|
207
|
+
console.log(` ${pc.bold("Check your setup:")} ${pc.cyan("vv mcp status")}`);
|
|
208
|
+
console.log(` ${pc.bold("Add to Claude Code:")} ${pc.cyan("claude mcp add vectorvesper -- npx -y vectorvesper@latest mcp")}`);
|
|
209
|
+
console.log("");
|
|
210
|
+
console.log(pc.dim(" To run the server here anyway (for debugging): vv mcp --stdio"));
|
|
211
|
+
console.log("");
|
|
212
|
+
}
|
|
213
|
+
function runInstall(client, options) {
|
|
214
|
+
const targets = client ? CLIENT_IDS.includes(client) ? [client] : [] : detectClients();
|
|
215
|
+
if (client && targets.length === 0) {
|
|
216
|
+
console.error(
|
|
217
|
+
`
|
|
218
|
+
${pc.red("\u2717")} Unknown client "${client}".
|
|
219
|
+
|
|
220
|
+
Known: ${CLIENT_IDS.map((c) => pc.cyan(c)).join(", ")}
|
|
221
|
+
`
|
|
222
|
+
);
|
|
223
|
+
process.exitCode = 1;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (targets.length === 0) {
|
|
227
|
+
console.log(
|
|
228
|
+
`
|
|
229
|
+
${pc.yellow("!")} No known MCP client detected on this machine.
|
|
230
|
+
|
|
231
|
+
Name one explicitly: ${pc.cyan("vv mcp install <client>")}
|
|
232
|
+
Known: ${CLIENT_IDS.map((c) => pc.cyan(c)).join(", ")}
|
|
233
|
+
`
|
|
234
|
+
);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
console.log("");
|
|
238
|
+
for (const id of targets) {
|
|
239
|
+
const spec = CLIENTS[id];
|
|
240
|
+
const result = installClient(id, { global: options.global });
|
|
241
|
+
if (!result.ok) {
|
|
242
|
+
console.log(`${pc.yellow("!")} ${pc.bold(spec.label)} \u2014 ${result.reason}`);
|
|
243
|
+
console.log(pc.dim(` ${result.file}`));
|
|
244
|
+
console.log(pc.dim(" Add this by hand:\n"));
|
|
245
|
+
console.log(
|
|
246
|
+
snippet(id).split("\n").map((l) => " " + pc.dim(l)).join("\n")
|
|
247
|
+
);
|
|
248
|
+
console.log("");
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const verb = result.action === "already-present" ? pc.dim("already configured") : pc.green(result.action);
|
|
252
|
+
console.log(`${pc.green("\u2714")} ${pc.bold(spec.label)} \u2014 ${verb}`);
|
|
253
|
+
console.log(pc.dim(` ${result.file}`));
|
|
254
|
+
if (spec.note) console.log(pc.dim(` ${spec.note}`));
|
|
255
|
+
}
|
|
256
|
+
console.log("");
|
|
257
|
+
console.log(pc.dim(" Restart the client so it picks up the new server."));
|
|
258
|
+
console.log(pc.dim(` Then check with: ${pc.cyan("vv mcp status")}`));
|
|
259
|
+
console.log("");
|
|
260
|
+
}
|
|
261
|
+
async function mcpCommand(action, options = {}) {
|
|
262
|
+
if (action === "status" || action === "info") {
|
|
263
|
+
printStatus();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (action === "install" || action === "setup") {
|
|
267
|
+
runInstall(options.client, { global: options.global });
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (action !== void 0) {
|
|
271
|
+
console.error(
|
|
272
|
+
`
|
|
273
|
+
${pc.red("\u2717")} Unknown argument "${action}" for \`vv mcp\`.
|
|
274
|
+
|
|
275
|
+
${pc.cyan("vv mcp")} start the MCP server (for agents)
|
|
276
|
+
${pc.cyan("vv mcp status")} check the setup and print client config
|
|
277
|
+
${pc.cyan("vv mcp install [client]")} write the config for an agent
|
|
278
|
+
`
|
|
279
|
+
);
|
|
280
|
+
process.exitCode = 1;
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (process.stdin.isTTY && !options.stdio) {
|
|
284
|
+
printInteractiveHelp();
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
protectStdout();
|
|
288
|
+
const { startMcpServer } = await import("./server-H4XNBFKQ.js");
|
|
289
|
+
try {
|
|
290
|
+
await startMcpServer();
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error(
|
|
293
|
+
`vectorvesper mcp: failed to start \u2014 ${error instanceof Error ? error.message : String(error)}`
|
|
294
|
+
);
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
export {
|
|
299
|
+
mcpCommand
|
|
300
|
+
};
|