@vibecheck-ai/mcp 24.6.5 → 24.6.7
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 +2 -20
- package/dist/index.js +206 -25
- package/package.json +19 -17
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
<br />
|
|
4
4
|
|
|
5
|
-
<img src="https://github.com/vibecheck-oss/vibecheck/raw/HEAD/packages/vscode-extension/images/vibecheck_logo_transparent_2x.png" alt="VibeCheck MCP Server" width="80" />
|
|
6
5
|
|
|
7
6
|
<br />
|
|
8
7
|
|
|
@@ -20,12 +19,6 @@ The Model Context Protocol server that lets Cursor, Claude, Windsurf, and any MC
|
|
|
20
19
|
|
|
21
20
|
<br />
|
|
22
21
|
|
|
23
|
-
<p align="center">
|
|
24
|
-
<img src="https://github.com/vibecheck-oss/vibecheck/raw/HEAD/docs/assets/cli-scan-demo.gif" alt="VibeCheck MCP Server running inside Cursor" width="820" />
|
|
25
|
-
</p>
|
|
26
|
-
|
|
27
|
-
<br />
|
|
28
|
-
|
|
29
22
|
---
|
|
30
23
|
|
|
31
24
|
<br />
|
|
@@ -127,11 +120,6 @@ The server communicates over **stdio** using the MCP protocol. No HTTP. No ports
|
|
|
127
120
|
|
|
128
121
|
<br />
|
|
129
122
|
|
|
130
|
-
<p align="center">
|
|
131
|
-
<img src="https://github.com/vibecheck-oss/vibecheck/raw/HEAD/docs/assets/mcp-setup.png" alt="MCP server configuration in Cursor" width="720" />
|
|
132
|
-
</p>
|
|
133
|
-
|
|
134
|
-
<br />
|
|
135
123
|
|
|
136
124
|
---
|
|
137
125
|
|
|
@@ -195,12 +183,6 @@ The agent calls `vibecheck_roast` for an opinionated, brutally honest assessment
|
|
|
195
183
|
|
|
196
184
|
<br />
|
|
197
185
|
|
|
198
|
-
<p align="center">
|
|
199
|
-
<img src="https://github.com/vibecheck-oss/vibecheck/raw/HEAD/docs/assets/mcp-agent-scan.png" alt="AI agent using vibecheck_scan tool" width="720" />
|
|
200
|
-
</p>
|
|
201
|
-
|
|
202
|
-
<br />
|
|
203
|
-
|
|
204
186
|
---
|
|
205
187
|
|
|
206
188
|
<br />
|
|
@@ -290,7 +272,7 @@ The MCP server includes enterprise-grade reliability features:
|
|
|
290
272
|
- **Zero code is transmitted** — ever
|
|
291
273
|
- The MCP server communicates via **stdio only** — no network ports opened
|
|
292
274
|
- Works **fully offline** and in air-gapped environments
|
|
293
|
-
-
|
|
275
|
+
- No telemetry on your code. Tools run in-process.
|
|
294
276
|
|
|
295
277
|
<br />
|
|
296
278
|
|
|
@@ -304,7 +286,7 @@ The MCP server includes enterprise-grade reliability features:
|
|
|
304
286
|
|
|
305
287
|
<br />
|
|
306
288
|
|
|
307
|
-
[
|
|
289
|
+
[vibecheckai.dev](https://vibecheckai.dev) · [founder@vibecheckai.dev](mailto:founder@vibecheckai.dev)
|
|
308
290
|
|
|
309
291
|
<br />
|
|
310
292
|
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from 'module';
|
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
4
4
|
import * as path2 from 'path';
|
|
5
5
|
import path2__default, { dirname, join, extname, resolve, normalize } from 'path';
|
|
6
|
-
import { SCAN_ENGINE_FOCUS_PRESET_NAMES, FEATURE_NAMES, DAILY_SCAN_LIMIT_UPGRADE_URL, formatDailyScanLimitMessage, dashboardFindingUrl, gateCanonicalScanReportFindings, getTrustScoreStatus, formatTrustScoreMcp, buildGatedScanResponse, formatFindingSeverityBreakdown, ENGINE_FOCUS_PRESETS, computeTrustScore, normalizeCanonicalScanReport, planHasApiSurface, canAccessFeature, getMinPlanForApiSurface, buildCliUpgradeBlock, getMinimumPlanForFeature, getQuotas, normalizePlanId, fetchCanonicalAccess } from './chunk-
|
|
6
|
+
import { SCAN_ENGINE_FOCUS_PRESET_NAMES, FEATURE_NAMES, DAILY_SCAN_LIMIT_UPGRADE_URL, formatDailyScanLimitMessage, dashboardFindingUrl, gateCanonicalScanReportFindings, getTrustScoreStatus, formatTrustScoreMcp, buildGatedScanResponse, formatFindingSeverityBreakdown, ENGINE_FOCUS_PRESETS, computeTrustScore, normalizeCanonicalScanReport, planHasApiSurface, canAccessFeature, getMinPlanForApiSurface, buildCliUpgradeBlock, getMinimumPlanForFeature, getQuotas, normalizePlanId, fetchCanonicalAccess } from './chunk-XQUM7V7W.js';
|
|
7
7
|
import './chunk-MUP4JXOF.js';
|
|
8
8
|
import './chunk-DDTUTWRY.js';
|
|
9
9
|
import { require_typescript } from './chunk-QFDZMUGO.js';
|
|
@@ -19910,26 +19910,41 @@ function getGraphNeighbors(graph, filePath) {
|
|
|
19910
19910
|
async function getProactiveContext(engine, rootPath, options) {
|
|
19911
19911
|
const lines = [];
|
|
19912
19912
|
const { focusedFile } = options;
|
|
19913
|
+
const maxItems = Math.max(1, options.maxItems ?? 5);
|
|
19913
19914
|
const fileCtx = engine.getFileContext(focusedFile);
|
|
19914
19915
|
if (fileCtx) {
|
|
19915
|
-
lines.push(`##
|
|
19916
|
-
lines.push(`Role: ${fileCtx.role}`);
|
|
19916
|
+
lines.push(`## Focus: ${focusedFile}`);
|
|
19917
|
+
lines.push(`Role: ${fileCtx.role} | Risk: ${fileCtx.riskLevel}`);
|
|
19918
|
+
if (fileCtx.editGuidance.length > 0) {
|
|
19919
|
+
lines.push(`Top guidance: ${fileCtx.editGuidance[0]}`);
|
|
19920
|
+
}
|
|
19921
|
+
lines.push("");
|
|
19922
|
+
lines.push("## Stay On Target");
|
|
19923
|
+
lines.push("- Edit only this file and direct neighbors unless requirements force expansion.");
|
|
19924
|
+
lines.push("- Reuse existing patterns from related files before creating new abstractions.");
|
|
19925
|
+
lines.push("- If uncertain about API/type existence, verify before generating code.");
|
|
19926
|
+
lines.push("");
|
|
19927
|
+
lines.push("## Immediate Neighbors");
|
|
19917
19928
|
if (fileCtx.dependsOn.length > 0) {
|
|
19918
|
-
lines.push(
|
|
19929
|
+
lines.push(`- Depends on: ${fileCtx.dependsOn.slice(0, maxItems).join(", ")}`);
|
|
19919
19930
|
}
|
|
19920
19931
|
if (fileCtx.dependedOnBy.length > 0) {
|
|
19921
|
-
lines.push(
|
|
19932
|
+
lines.push(`- Depended on by: ${fileCtx.dependedOnBy.slice(0, maxItems).join(", ")}`);
|
|
19922
19933
|
}
|
|
19923
19934
|
if (fileCtx.relatedFiles.length > 0) {
|
|
19924
|
-
lines.push(
|
|
19935
|
+
lines.push(`- Related: ${fileCtx.relatedFiles.slice(0, maxItems).join(", ")}`);
|
|
19925
19936
|
}
|
|
19926
19937
|
lines.push("");
|
|
19938
|
+
} else {
|
|
19939
|
+
lines.push(`## Focus: ${focusedFile}`);
|
|
19940
|
+
lines.push("File context unavailable \u2014 keep scope minimal and verify dependencies manually.");
|
|
19941
|
+
lines.push("");
|
|
19927
19942
|
}
|
|
19928
19943
|
const graph = engine.getGraph();
|
|
19929
19944
|
const neighbors = getGraphNeighbors(graph, focusedFile);
|
|
19930
19945
|
if (neighbors.length > 0) {
|
|
19931
|
-
lines.push("## Graph
|
|
19932
|
-
for (const n of neighbors.slice(0,
|
|
19946
|
+
lines.push("## Graph Adjacency");
|
|
19947
|
+
for (const n of neighbors.slice(0, maxItems)) {
|
|
19933
19948
|
lines.push(`- ${n}`);
|
|
19934
19949
|
}
|
|
19935
19950
|
lines.push("");
|
|
@@ -19938,16 +19953,16 @@ async function getProactiveContext(engine, rootPath, options) {
|
|
|
19938
19953
|
const evolution = await import('./dist-JUOVMQEA.js');
|
|
19939
19954
|
const boosted = await evolution.getBoostedFiles(rootPath, focusedFile);
|
|
19940
19955
|
if (boosted.length > 0) {
|
|
19941
|
-
lines.push("##
|
|
19942
|
-
for (const { file, weight } of boosted.slice(0,
|
|
19943
|
-
lines.push(`- ${file} (
|
|
19956
|
+
lines.push("## Learned Co-Edit Priors");
|
|
19957
|
+
for (const { file, weight } of boosted.slice(0, maxItems)) {
|
|
19958
|
+
lines.push(`- ${file} (affinity: ${weight.toFixed(2)})`);
|
|
19944
19959
|
}
|
|
19945
19960
|
lines.push("");
|
|
19946
19961
|
}
|
|
19947
19962
|
const sequential = await evolution.getSequentialFiles(rootPath, focusedFile);
|
|
19948
19963
|
if (sequential.length > 0) {
|
|
19949
|
-
lines.push("##
|
|
19950
|
-
for (const { file, weight } of sequential.slice(0,
|
|
19964
|
+
lines.push("## Likely Next Files");
|
|
19965
|
+
for (const { file, weight } of sequential.slice(0, maxItems)) {
|
|
19951
19966
|
lines.push(`- ${file} (weight: ${weight.toFixed(2)})`);
|
|
19952
19967
|
}
|
|
19953
19968
|
lines.push("");
|
|
@@ -19963,26 +19978,33 @@ function runKeywordSearch(data, query, limit) {
|
|
|
19963
19978
|
const symbols = [];
|
|
19964
19979
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
19965
19980
|
const seenSymbols = /* @__PURE__ */ new Set();
|
|
19981
|
+
const overlapScores = [];
|
|
19966
19982
|
for (const file of data.files) {
|
|
19967
19983
|
const pathLower = file.relativePath.toLowerCase();
|
|
19968
|
-
|
|
19984
|
+
const overlapCount = words.filter((w) => pathLower.includes(w)).length;
|
|
19985
|
+
if (overlapCount > 0 && !seenFiles.has(file.relativePath)) {
|
|
19969
19986
|
seenFiles.add(file.relativePath);
|
|
19970
19987
|
files.push(file.relativePath);
|
|
19988
|
+
overlapScores.push(overlapCount / Math.max(1, words.length));
|
|
19971
19989
|
}
|
|
19972
19990
|
}
|
|
19973
19991
|
for (const sym of data.symbols) {
|
|
19974
19992
|
const nameLower = sym.name.toLowerCase();
|
|
19975
|
-
|
|
19993
|
+
const overlapCount = words.filter((w) => nameLower.includes(w)).length;
|
|
19994
|
+
if (overlapCount > 0) {
|
|
19976
19995
|
const key = `${sym.filePath}:${sym.name}`;
|
|
19977
19996
|
if (!seenSymbols.has(key)) {
|
|
19978
19997
|
seenSymbols.add(key);
|
|
19979
19998
|
symbols.push({ name: sym.name, file: sym.filePath, kind: sym.kind });
|
|
19999
|
+
overlapScores.push(overlapCount / Math.max(1, words.length));
|
|
19980
20000
|
}
|
|
19981
20001
|
}
|
|
19982
20002
|
}
|
|
20003
|
+
const confidence = overlapScores.length > 0 ? Math.max(...overlapScores) : 0;
|
|
19983
20004
|
return {
|
|
19984
20005
|
files: files.slice(0, limit),
|
|
19985
|
-
symbols: symbols.slice(0, limit)
|
|
20006
|
+
symbols: symbols.slice(0, limit),
|
|
20007
|
+
confidence
|
|
19986
20008
|
};
|
|
19987
20009
|
}
|
|
19988
20010
|
function parseSymbolLocation(loc) {
|
|
@@ -19998,18 +20020,23 @@ function parseSymbolLocation(loc) {
|
|
|
19998
20020
|
async function intentQuery(rootPath, data, query, options = {}) {
|
|
19999
20021
|
const limit = options.limit ?? 10;
|
|
20000
20022
|
const useSemantic = options.useSemantic ?? false;
|
|
20023
|
+
const strictGrounding = options.strictGrounding ?? true;
|
|
20024
|
+
const minConfidence = options.minConfidence ?? 0.35;
|
|
20001
20025
|
const degradations = [];
|
|
20002
20026
|
let files = [];
|
|
20003
20027
|
let symbols = [];
|
|
20004
20028
|
let usedSemantic = false;
|
|
20005
20029
|
let semanticResults = [];
|
|
20030
|
+
let confidence = 0;
|
|
20006
20031
|
if (useSemantic) {
|
|
20007
20032
|
try {
|
|
20008
|
-
const { semanticSearch } = await import('./semantic-
|
|
20033
|
+
const { semanticSearch } = await import('./semantic-3IRDVTDG.js');
|
|
20009
20034
|
const results = await semanticSearch(rootPath, query, { topK: limit * 2, embeddingProvider: options.embeddingProvider });
|
|
20010
20035
|
if (results.length > 0) {
|
|
20011
20036
|
usedSemantic = true;
|
|
20012
20037
|
semanticResults = results;
|
|
20038
|
+
const topSemantic = results.slice(0, Math.max(1, Math.min(3, results.length)));
|
|
20039
|
+
confidence = topSemantic.reduce((sum, r) => sum + Math.max(0, r.score / 100), 0) / topSemantic.length;
|
|
20013
20040
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
20014
20041
|
const seenSymbols = /* @__PURE__ */ new Set();
|
|
20015
20042
|
for (const r of results) {
|
|
@@ -20042,6 +20069,7 @@ async function intentQuery(rootPath, data, query, options = {}) {
|
|
|
20042
20069
|
const kw = runKeywordSearch(data, query, limit);
|
|
20043
20070
|
files = kw.files;
|
|
20044
20071
|
symbols = kw.symbols;
|
|
20072
|
+
confidence = kw.confidence;
|
|
20045
20073
|
}
|
|
20046
20074
|
const snippets = [];
|
|
20047
20075
|
for (const sym of symbols.slice(0, limit)) {
|
|
@@ -20063,16 +20091,28 @@ async function intentQuery(rootPath, data, query, options = {}) {
|
|
|
20063
20091
|
content: `${sym.kind} ${sym.name}`
|
|
20064
20092
|
});
|
|
20065
20093
|
}
|
|
20066
|
-
const
|
|
20094
|
+
const hasMatches = files.length > 0 || symbols.length > 0;
|
|
20095
|
+
const grounded = !strictGrounding || confidence >= minConfidence;
|
|
20096
|
+
const finalFiles = grounded ? files : [];
|
|
20097
|
+
const finalSymbols = grounded ? symbols : [];
|
|
20098
|
+
const finalSnippets = grounded ? snippets : [];
|
|
20099
|
+
const summary = !grounded ? `Withheld low-confidence matches for "${query}" (confidence ${confidence.toFixed(2)} < ${minConfidence.toFixed(2)}). Refine the query or disable strict grounding.` : hasMatches ? `Found ${files.length} files and ${symbols.length} symbols matching "${query}"${usedSemantic ? " (semantic)" : ""}` : `No files or symbols directly matching "${query}"`;
|
|
20067
20100
|
return {
|
|
20068
20101
|
summary,
|
|
20069
|
-
files,
|
|
20070
|
-
symbols,
|
|
20071
|
-
snippets,
|
|
20102
|
+
files: finalFiles,
|
|
20103
|
+
symbols: finalSymbols,
|
|
20104
|
+
snippets: finalSnippets,
|
|
20072
20105
|
execution: {
|
|
20073
20106
|
semanticRequested: useSemantic,
|
|
20074
20107
|
semanticUsed: usedSemantic,
|
|
20075
|
-
degradations
|
|
20108
|
+
degradations,
|
|
20109
|
+
confidence,
|
|
20110
|
+
grounding: {
|
|
20111
|
+
strict: strictGrounding,
|
|
20112
|
+
minConfidence,
|
|
20113
|
+
evidenceCount: finalFiles.length + finalSymbols.length + finalSnippets.length,
|
|
20114
|
+
decision: grounded ? "pass" : "withheld"
|
|
20115
|
+
}
|
|
20076
20116
|
}
|
|
20077
20117
|
};
|
|
20078
20118
|
}
|
|
@@ -21744,6 +21784,64 @@ var MCP_TOOLS = [
|
|
|
21744
21784
|
}
|
|
21745
21785
|
}
|
|
21746
21786
|
}
|
|
21787
|
+
},
|
|
21788
|
+
{
|
|
21789
|
+
name: "isl_studio_apply",
|
|
21790
|
+
description: "Push code into the live ISL Studio editor running inside the user's VS Code / Cursor / Windsurf. Use when the user has ISL Studio open and you want changes to land in the live preview. Writes to .vibecheck/isl-studio-inbox.jsonl which the panel watches. The studio rebuilds the live preview automatically.",
|
|
21791
|
+
inputSchema: {
|
|
21792
|
+
type: "object",
|
|
21793
|
+
properties: {
|
|
21794
|
+
path: {
|
|
21795
|
+
type: "string",
|
|
21796
|
+
description: "Workspace root path. Defaults to current directory."
|
|
21797
|
+
},
|
|
21798
|
+
lang: {
|
|
21799
|
+
type: "string",
|
|
21800
|
+
enum: ["html", "css", "js"],
|
|
21801
|
+
description: "Which editor pane to update."
|
|
21802
|
+
},
|
|
21803
|
+
code: { type: "string", description: "Source code to write." },
|
|
21804
|
+
mode: {
|
|
21805
|
+
type: "string",
|
|
21806
|
+
enum: ["replace", "append"],
|
|
21807
|
+
description: "replace = overwrite the pane contents (default). append = add to end."
|
|
21808
|
+
}
|
|
21809
|
+
},
|
|
21810
|
+
required: ["lang", "code"]
|
|
21811
|
+
}
|
|
21812
|
+
},
|
|
21813
|
+
{
|
|
21814
|
+
name: "isl_studio_send_message",
|
|
21815
|
+
description: "Post a system or assistant message into the ISL Studio chat transcript. Use to surface progress updates, explanations, or follow-up questions while the user has ISL Studio open.",
|
|
21816
|
+
inputSchema: {
|
|
21817
|
+
type: "object",
|
|
21818
|
+
properties: {
|
|
21819
|
+
path: {
|
|
21820
|
+
type: "string",
|
|
21821
|
+
description: "Workspace root path. Defaults to current directory."
|
|
21822
|
+
},
|
|
21823
|
+
role: {
|
|
21824
|
+
type: "string",
|
|
21825
|
+
enum: ["assistant", "system"],
|
|
21826
|
+
description: "Display role for the message."
|
|
21827
|
+
},
|
|
21828
|
+
content: { type: "string", description: "Message body. Markdown is rendered as plain text but fenced code blocks become applyable." }
|
|
21829
|
+
},
|
|
21830
|
+
required: ["content"]
|
|
21831
|
+
}
|
|
21832
|
+
},
|
|
21833
|
+
{
|
|
21834
|
+
name: "isl_studio_get_state",
|
|
21835
|
+
description: "Read the current ISL Studio editor state (last saved html/css/js snapshot) from the workspace. Use before generating changes so you have full context of what the user is working on.",
|
|
21836
|
+
inputSchema: {
|
|
21837
|
+
type: "object",
|
|
21838
|
+
properties: {
|
|
21839
|
+
path: {
|
|
21840
|
+
type: "string",
|
|
21841
|
+
description: "Workspace root path. Defaults to current directory."
|
|
21842
|
+
}
|
|
21843
|
+
}
|
|
21844
|
+
}
|
|
21747
21845
|
}
|
|
21748
21846
|
];
|
|
21749
21847
|
function isKnownToolName(toolName) {
|
|
@@ -21888,7 +21986,7 @@ function createScanIdempotencyKey(prefix) {
|
|
|
21888
21986
|
// src/mcp-scan-meter-client.ts
|
|
21889
21987
|
var MCP_SCAN_METER_CLIENT = {
|
|
21890
21988
|
type: "mcp",
|
|
21891
|
-
version: "24.6.
|
|
21989
|
+
version: "24.6.7"
|
|
21892
21990
|
};
|
|
21893
21991
|
|
|
21894
21992
|
// ../shared/dist/chunk-YYSV5CG4.js
|
|
@@ -22187,6 +22285,36 @@ function resolveWorkspaceRoot(cwd) {
|
|
|
22187
22285
|
const resolvedRoot = path2.resolve(cwd);
|
|
22188
22286
|
return fs4.existsSync(resolvedRoot) ? fs4.realpathSync(resolvedRoot) : resolvedRoot;
|
|
22189
22287
|
}
|
|
22288
|
+
async function appendIslStudioInbox(workspaceRoot, jsonLine) {
|
|
22289
|
+
try {
|
|
22290
|
+
const dir = path2.join(workspaceRoot, ".vibecheck");
|
|
22291
|
+
await fs4.promises.mkdir(dir, { recursive: true });
|
|
22292
|
+
const target = path2.join(dir, "isl-studio-inbox.jsonl");
|
|
22293
|
+
await fs4.promises.appendFile(target, jsonLine + "\n", "utf-8");
|
|
22294
|
+
return { ok: true };
|
|
22295
|
+
} catch (err) {
|
|
22296
|
+
return { ok: false, message: err instanceof Error ? err.message : String(err) };
|
|
22297
|
+
}
|
|
22298
|
+
}
|
|
22299
|
+
async function readIslStudioState(workspaceRoot) {
|
|
22300
|
+
try {
|
|
22301
|
+
const target = path2.join(workspaceRoot, ".vibecheck", "isl-studio", "editor-state.json");
|
|
22302
|
+
const raw = await fs4.promises.readFile(target, "utf-8");
|
|
22303
|
+
const parsed = JSON.parse(raw);
|
|
22304
|
+
return {
|
|
22305
|
+
available: true,
|
|
22306
|
+
html: typeof parsed.html === "string" ? parsed.html : "",
|
|
22307
|
+
css: typeof parsed.css === "string" ? parsed.css : "",
|
|
22308
|
+
js: typeof parsed.js === "string" ? parsed.js : "",
|
|
22309
|
+
source: "editor-state.json"
|
|
22310
|
+
};
|
|
22311
|
+
} catch {
|
|
22312
|
+
return {
|
|
22313
|
+
available: false,
|
|
22314
|
+
hint: "ISL Studio editor state not found. The user must open the ISL Studio panel and edit at least once for state to be persisted to .vibecheck/isl-studio/editor-state.json."
|
|
22315
|
+
};
|
|
22316
|
+
}
|
|
22317
|
+
}
|
|
22190
22318
|
function resolveWorkspaceTargetPath(workspaceRoot, requestedPath) {
|
|
22191
22319
|
const resolvedTarget = path2.resolve(workspaceRoot, requestedPath);
|
|
22192
22320
|
const normalizedTarget = fs4.existsSync(resolvedTarget) ? fs4.realpathSync(resolvedTarget) : path2.normalize(resolvedTarget);
|
|
@@ -22536,7 +22664,7 @@ ${validation.errors.join("\n")}`);
|
|
|
22536
22664
|
if (!fs4.existsSync(absFile) || !fs4.statSync(absFile).isFile()) {
|
|
22537
22665
|
return buildErrorResponse(`Not a file: ${relFile}`);
|
|
22538
22666
|
}
|
|
22539
|
-
const { runGhostTrace } = await import('./dist-
|
|
22667
|
+
const { runGhostTrace } = await import('./dist-2TGNIDV6.js');
|
|
22540
22668
|
const trace = await withTimeout(
|
|
22541
22669
|
runGhostTrace({ workspaceRoot: targetPath, filePath: absFile }),
|
|
22542
22670
|
MCP_TOOL_TIMEOUT_MS,
|
|
@@ -22814,6 +22942,59 @@ This change is synced across all surfaces.`
|
|
|
22814
22942
|
);
|
|
22815
22943
|
}
|
|
22816
22944
|
}
|
|
22945
|
+
case "isl_studio_apply": {
|
|
22946
|
+
const lang = args?.lang;
|
|
22947
|
+
const code = args?.code;
|
|
22948
|
+
const mode = args?.mode === "append" ? "append" : "replace";
|
|
22949
|
+
if (lang !== "html" && lang !== "css" && lang !== "js") {
|
|
22950
|
+
return buildErrorResponse('isl_studio_apply requires lang to be "html", "css", or "js"');
|
|
22951
|
+
}
|
|
22952
|
+
if (typeof code !== "string") {
|
|
22953
|
+
return buildErrorResponse('isl_studio_apply requires "code" (string)');
|
|
22954
|
+
}
|
|
22955
|
+
const ISL_APPLY_MAX_BYTES = 1024 * 1024;
|
|
22956
|
+
const codeByteLen = Buffer.byteLength(code, "utf-8");
|
|
22957
|
+
if (codeByteLen > ISL_APPLY_MAX_BYTES) {
|
|
22958
|
+
return buildErrorResponse(
|
|
22959
|
+
`isl_studio_apply rejected: code is ${(codeByteLen / 1024).toFixed(1)} KB, max is ${ISL_APPLY_MAX_BYTES / 1024} KB. Split the change into smaller updates.`
|
|
22960
|
+
);
|
|
22961
|
+
}
|
|
22962
|
+
const evt = JSON.stringify({ type: "apply", lang, code, mode });
|
|
22963
|
+
const r = await appendIslStudioInbox(workspaceRoot, evt);
|
|
22964
|
+
if (!r.ok) return buildErrorResponse(`isl_studio_apply failed: ${r.message}`);
|
|
22965
|
+
return {
|
|
22966
|
+
content: [
|
|
22967
|
+
{
|
|
22968
|
+
type: "text",
|
|
22969
|
+
text: `Wrote ${code.length} chars of ${lang} to ISL Studio (mode: ${mode}). The live preview will rebuild.`
|
|
22970
|
+
}
|
|
22971
|
+
]
|
|
22972
|
+
};
|
|
22973
|
+
}
|
|
22974
|
+
case "isl_studio_send_message": {
|
|
22975
|
+
const role = args?.role === "system" ? "system" : "assistant";
|
|
22976
|
+
const content = args?.content;
|
|
22977
|
+
if (typeof content !== "string" || !content.trim()) {
|
|
22978
|
+
return buildErrorResponse('isl_studio_send_message requires non-empty "content"');
|
|
22979
|
+
}
|
|
22980
|
+
const ISL_MSG_MAX_BYTES = 64 * 1024;
|
|
22981
|
+
const msgByteLen = Buffer.byteLength(content, "utf-8");
|
|
22982
|
+
if (msgByteLen > ISL_MSG_MAX_BYTES) {
|
|
22983
|
+
return buildErrorResponse(
|
|
22984
|
+
`isl_studio_send_message rejected: content is ${(msgByteLen / 1024).toFixed(1)} KB, max is ${ISL_MSG_MAX_BYTES / 1024} KB.`
|
|
22985
|
+
);
|
|
22986
|
+
}
|
|
22987
|
+
const evt = JSON.stringify({ type: "message", role, content });
|
|
22988
|
+
const r = await appendIslStudioInbox(workspaceRoot, evt);
|
|
22989
|
+
if (!r.ok) return buildErrorResponse(`isl_studio_send_message failed: ${r.message}`);
|
|
22990
|
+
return { content: [{ type: "text", text: "Message posted to ISL Studio chat." }] };
|
|
22991
|
+
}
|
|
22992
|
+
case "isl_studio_get_state": {
|
|
22993
|
+
const r = await readIslStudioState(workspaceRoot);
|
|
22994
|
+
return {
|
|
22995
|
+
content: [{ type: "text", text: JSON.stringify(r, null, 2) }]
|
|
22996
|
+
};
|
|
22997
|
+
}
|
|
22817
22998
|
default:
|
|
22818
22999
|
return buildErrorResponse(`Unknown tool: ${name}`);
|
|
22819
23000
|
}
|
|
@@ -22827,7 +23008,7 @@ function createMcpServer(runtimeOverrides = {}) {
|
|
|
22827
23008
|
const server = new Server(
|
|
22828
23009
|
{
|
|
22829
23010
|
name: "vibecheck-mcp",
|
|
22830
|
-
version: "24.6.
|
|
23011
|
+
version: "24.6.7"
|
|
22831
23012
|
},
|
|
22832
23013
|
{
|
|
22833
23014
|
capabilities: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibecheck-ai/mcp",
|
|
3
|
-
"version": "24.6.
|
|
3
|
+
"version": "24.6.7",
|
|
4
4
|
"description": "The trust layer for AI-generated software. Catches phantom dependencies, ghost API routes, fake SDK methods, and hardcoded secrets — before they ship.",
|
|
5
5
|
"mcpName": "io.github.guardiavault-oss/vibecheck-mcp",
|
|
6
6
|
"type": "module",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
31
|
-
"url": "git+https://
|
|
31
|
+
"url": "git+https://vibecheckai.dev"
|
|
32
32
|
},
|
|
33
|
-
"homepage": "https://
|
|
33
|
+
"homepage": "https://vibecheckai.dev",
|
|
34
34
|
"bugs": {
|
|
35
|
-
"url": "https://
|
|
35
|
+
"url": "https://vibecheckai.dev"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"dist/index.js",
|
|
@@ -43,12 +43,25 @@
|
|
|
43
43
|
"bin": {
|
|
44
44
|
"vibecheck-mcp": "./dist/index.js"
|
|
45
45
|
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"compile": "tsc -p . --noEmit",
|
|
49
|
+
"typecheck": "tsc -p . --noEmit",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"lint": "eslint src/ --max-warnings 0",
|
|
52
|
+
"lint:fix": "eslint src/ --fix --max-warnings 0",
|
|
53
|
+
"test:watch": "vitest",
|
|
54
|
+
"verify-dist": "node scripts/verify-dist.mjs",
|
|
55
|
+
"release:check": "pnpm run build && pnpm run test && pnpm run verify-dist",
|
|
56
|
+
"prepublishOnly": "pnpm run release:check && node scripts/prepublish.cjs",
|
|
57
|
+
"postpublish": "node scripts/postpublish.cjs"
|
|
58
|
+
},
|
|
46
59
|
"dependencies": {
|
|
47
60
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
48
61
|
"@repo/shared": "^0.1.0",
|
|
49
62
|
"@repo/shared-types": "^1.1.0",
|
|
50
63
|
"@repo/subscriptions": "^1.0.0",
|
|
51
|
-
"@vibecheck-ai/cli": "^25.0.
|
|
64
|
+
"@vibecheck-ai/cli": "^25.0.2",
|
|
52
65
|
"@vibecheck/engines": "^2.0.0-beta.1",
|
|
53
66
|
"@vibecheck/roast": "^1.0.0"
|
|
54
67
|
},
|
|
@@ -58,16 +71,5 @@
|
|
|
58
71
|
"tsup": "^8.0.0",
|
|
59
72
|
"typescript": "^5.8.0",
|
|
60
73
|
"vitest": "^2.1.8"
|
|
61
|
-
},
|
|
62
|
-
"scripts": {
|
|
63
|
-
"build": "tsup",
|
|
64
|
-
"compile": "tsc -p . --noEmit",
|
|
65
|
-
"typecheck": "tsc -p . --noEmit",
|
|
66
|
-
"test": "vitest run",
|
|
67
|
-
"lint": "eslint src/ --max-warnings 0",
|
|
68
|
-
"lint:fix": "eslint src/ --fix --max-warnings 0",
|
|
69
|
-
"test:watch": "vitest",
|
|
70
|
-
"verify-dist": "node scripts/verify-dist.mjs",
|
|
71
|
-
"release:check": "pnpm run build && pnpm run test && pnpm run verify-dist"
|
|
72
74
|
}
|
|
73
|
-
}
|
|
75
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 VibeCheck
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|