@vibekiln/cutline-mcp-cli 0.4.2 → 0.4.4
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/commands/init.js +9 -3
- package/dist/commands/setup.js +3 -3
- package/dist/servers/{chunk-6Y3AEXE3.js → chunk-X2B5QUWO.js} +30 -16
- package/dist/servers/cutline-server.js +3 -3
- package/dist/servers/{data-client-PPEF2XUI.js → data-client-AQ5DGSAR.js} +1 -1
- package/dist/servers/exploration-server.js +1 -1
- package/dist/servers/integrations-server.js +1 -1
- package/dist/servers/output-server.js +1 -1
- package/dist/servers/premortem-server.js +1 -1
- package/dist/servers/tools-server.js +1 -1
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -94,7 +94,7 @@ Skip: Pure styling, docs, formatting, non-security dep bumps.
|
|
|
94
94
|
## Magic Phrase
|
|
95
95
|
|
|
96
96
|
If the user invokes Cutline naturally (for example: **"use cutline"**, **"use cutline to..."**, **"using cutline..."**, **"with cutline..."**), route automatically based on tier and intent:
|
|
97
|
-
- Free/default intent: run \`code_audit(project_root)\`
|
|
97
|
+
- Free/default intent: run \`code_audit(project_root)\` (aka "security vibe check")
|
|
98
98
|
- Premium product-linked intent: run \`engineering_audit(product_id, project_root)\`
|
|
99
99
|
- Feature implementation intent: run \`rgr_plan(...)\` then \`constraints_auto(...)\`
|
|
100
100
|
`;
|
|
@@ -109,7 +109,7 @@ alwaysApply: true
|
|
|
109
109
|
|
|
110
110
|
# Cutline Constraints
|
|
111
111
|
|
|
112
|
-
Run \`code_audit(project_root)\` before major implementations to check constraint coverage.
|
|
112
|
+
Run \`code_audit(project_root)\` before major implementations to run a security vibe check on constraint coverage.
|
|
113
113
|
|
|
114
114
|
Severity levels:
|
|
115
115
|
- **CRITICAL**: Must address before proceeding
|
|
@@ -184,7 +184,7 @@ Skip for: pure styling, docs, formatting, non-security dep bumps.
|
|
|
184
184
|
## Magic Phrase
|
|
185
185
|
|
|
186
186
|
If the user invokes Cutline naturally (for example: **"use cutline"**, **"use cutline to..."**, **"using cutline..."**, **"with cutline..."**), route automatically based on tier and intent:
|
|
187
|
-
- Free/default intent: \`code_audit(project_root)\`
|
|
187
|
+
- Free/default intent: \`code_audit(project_root)\` (aka "security vibe check")
|
|
188
188
|
- Premium product-linked intent: \`engineering_audit(product_id, project_root)\`
|
|
189
189
|
- Feature implementation intent: \`rgr_plan(...)\` then \`constraints_auto(...)\`
|
|
190
190
|
`;
|
|
@@ -204,6 +204,9 @@ function ensureGitignore(projectRoot, patterns) {
|
|
|
204
204
|
export async function initCommand(options) {
|
|
205
205
|
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
206
206
|
const config = readCutlineConfig(projectRoot);
|
|
207
|
+
const scanUrl = options.staging
|
|
208
|
+
? 'https://cutline-staging.web.app/scan'
|
|
209
|
+
: 'https://thecutline.ai/scan';
|
|
207
210
|
console.log(chalk.bold('\n🔧 Cutline Init\n'));
|
|
208
211
|
// Authenticate and determine tier
|
|
209
212
|
const spinner = ora('Checking authentication...').start();
|
|
@@ -212,6 +215,8 @@ export async function initCommand(options) {
|
|
|
212
215
|
if (!auth) {
|
|
213
216
|
spinner.warn(chalk.yellow('Not authenticated — generating free-tier rules'));
|
|
214
217
|
console.log(chalk.dim(' Run `cutline-mcp login` to authenticate for richer config.\n'));
|
|
218
|
+
console.log(chalk.dim(' Or run a quick scan in the web app:'), chalk.cyan(scanUrl));
|
|
219
|
+
console.log();
|
|
215
220
|
}
|
|
216
221
|
else {
|
|
217
222
|
tier = auth.tier;
|
|
@@ -292,6 +297,7 @@ export async function initCommand(options) {
|
|
|
292
297
|
else if (tier === 'free') {
|
|
293
298
|
console.log(chalk.dim('\n Upgrade to Premium for product-specific constraint graphs and .cutline.md'));
|
|
294
299
|
console.log(chalk.dim(' →'), chalk.cyan('cutline-mcp upgrade'), chalk.dim('or https://thecutline.ai/upgrade'));
|
|
300
|
+
console.log(chalk.dim(' Free scan in browser:'), chalk.cyan(scanUrl));
|
|
295
301
|
}
|
|
296
302
|
if (generatedApiKey) {
|
|
297
303
|
console.log();
|
package/dist/commands/setup.js
CHANGED
|
@@ -392,8 +392,8 @@ export async function setupCommand(options) {
|
|
|
392
392
|
{ cmd: 'use cutline', desc: 'Magic phrase (also works with "use cutline to...", "using cutline...", "with cutline...") — Cutline infers intent and routes to the right flow' },
|
|
393
393
|
{ cmd: 'Run a deep dive on my product idea', desc: 'Pre-mortem analysis — risks, assumptions, experiments' },
|
|
394
394
|
{ cmd: 'Plan this feature with constraints from my product', desc: 'RGR plan — constraint-aware implementation roadmap' },
|
|
395
|
-
{ cmd: 'Run a
|
|
396
|
-
{ cmd: 'Run an engineering
|
|
395
|
+
{ cmd: 'Run a security vibe check on this codebase', desc: 'Free security vibe check (`code_audit`) — security, reliability, and scalability (generic, not product-linked)' },
|
|
396
|
+
{ cmd: 'Run an engineering vibe check for my product', desc: 'Premium deep vibe check (`engineering_audit`) — product-linked analysis + RGR remediation plan' },
|
|
397
397
|
{ cmd: 'Check constraints for src/api/upload.ts', desc: 'Get NFR boundaries for a specific file' },
|
|
398
398
|
{ cmd: 'Generate .cutline.md for my product', desc: 'Write the constraint routing engine' },
|
|
399
399
|
{ cmd: 'What does my persona think about X?', desc: 'AI persona feedback on features' },
|
|
@@ -407,7 +407,7 @@ export async function setupCommand(options) {
|
|
|
407
407
|
else {
|
|
408
408
|
const items = [
|
|
409
409
|
{ cmd: 'use cutline', desc: 'Magic phrase (also works with "use cutline to...", "using cutline...", "with cutline...") — Cutline routes to the highest-value free flow for your intent' },
|
|
410
|
-
{ cmd: 'Run a
|
|
410
|
+
{ cmd: 'Run a security vibe check on this codebase', desc: 'Free security vibe check (`code_audit`) — security, reliability, and scalability scan (3/month free)' },
|
|
411
411
|
{ cmd: 'Explore a product idea', desc: 'Free 6-act discovery flow to identify pain points and opportunities' },
|
|
412
412
|
{ cmd: 'Continue my exploration session', desc: 'Resume and refine an existing free exploration conversation' },
|
|
413
413
|
];
|
|
@@ -305,13 +305,17 @@ function getHiddenAuditDimensions() {
|
|
|
305
305
|
const normalized = [...new Set(hidden.map((d) => String(d).trim().toLowerCase()).filter((d) => allowed.has(d)))];
|
|
306
306
|
return normalized;
|
|
307
307
|
}
|
|
308
|
-
function getStoredApiKey() {
|
|
308
|
+
function getStoredApiKey(options) {
|
|
309
|
+
const includeConfig = options?.includeConfig ?? true;
|
|
309
310
|
if (process.env.CUTLINE_API_KEY) {
|
|
310
311
|
return {
|
|
311
312
|
apiKey: process.env.CUTLINE_API_KEY,
|
|
312
313
|
environment: process.env.CUTLINE_ENV === "staging" ? "staging" : "production"
|
|
313
314
|
};
|
|
314
315
|
}
|
|
316
|
+
if (!includeConfig) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
315
319
|
const config = readLocalCutlineConfig();
|
|
316
320
|
if (config?.apiKey) {
|
|
317
321
|
return { apiKey: config.apiKey, environment: config.environment };
|
|
@@ -406,12 +410,15 @@ function getSiteUrl(environment) {
|
|
|
406
410
|
return environment === "staging" ? "https://cutline-staging.web.app" : "https://thecutline.ai";
|
|
407
411
|
}
|
|
408
412
|
async function getPublicSiteUrlForCurrentAuth() {
|
|
413
|
+
const stored = await getStoredToken();
|
|
414
|
+
if (stored?.environment) {
|
|
415
|
+
return getSiteUrl(stored.environment);
|
|
416
|
+
}
|
|
409
417
|
const apiKeyInfo = getStoredApiKey();
|
|
410
418
|
if (apiKeyInfo?.environment) {
|
|
411
419
|
return getSiteUrl(apiKeyInfo.environment);
|
|
412
420
|
}
|
|
413
|
-
|
|
414
|
-
return getSiteUrl(stored?.environment);
|
|
421
|
+
return getSiteUrl();
|
|
415
422
|
}
|
|
416
423
|
var cachedBaseUrl;
|
|
417
424
|
var cachedIdToken;
|
|
@@ -455,27 +462,34 @@ async function exchangeRefreshForId(refreshToken, environment) {
|
|
|
455
462
|
return data.id_token;
|
|
456
463
|
}
|
|
457
464
|
async function resolveAuth() {
|
|
458
|
-
const
|
|
459
|
-
if (
|
|
465
|
+
const envApiKeyInfo = getStoredApiKey({ includeConfig: false });
|
|
466
|
+
if (envApiKeyInfo) {
|
|
460
467
|
return {
|
|
461
|
-
baseUrl: getBaseUrl(
|
|
462
|
-
idToken:
|
|
468
|
+
baseUrl: getBaseUrl(envApiKeyInfo.environment),
|
|
469
|
+
idToken: envApiKeyInfo.apiKey
|
|
463
470
|
};
|
|
464
471
|
}
|
|
465
472
|
if (cachedIdToken && Date.now() < tokenExpiresAt && cachedBaseUrl) {
|
|
466
473
|
return { baseUrl: cachedBaseUrl, idToken: cachedIdToken };
|
|
467
474
|
}
|
|
468
475
|
const stored = await getStoredToken();
|
|
469
|
-
if (
|
|
470
|
-
|
|
476
|
+
if (stored) {
|
|
477
|
+
const env = stored.environment || "production";
|
|
478
|
+
const baseUrl = getBaseUrl(env);
|
|
479
|
+
const idToken = await exchangeRefreshForId(stored.refreshToken, env);
|
|
480
|
+
cachedBaseUrl = baseUrl;
|
|
481
|
+
cachedIdToken = idToken;
|
|
482
|
+
tokenExpiresAt = Date.now() + 50 * 60 * 1e3;
|
|
483
|
+
return { baseUrl, idToken };
|
|
484
|
+
}
|
|
485
|
+
const configApiKeyInfo = getStoredApiKey();
|
|
486
|
+
if (configApiKeyInfo) {
|
|
487
|
+
return {
|
|
488
|
+
baseUrl: getBaseUrl(configApiKeyInfo.environment),
|
|
489
|
+
idToken: configApiKeyInfo.apiKey
|
|
490
|
+
};
|
|
471
491
|
}
|
|
472
|
-
|
|
473
|
-
const baseUrl = getBaseUrl(env);
|
|
474
|
-
const idToken = await exchangeRefreshForId(stored.refreshToken, env);
|
|
475
|
-
cachedBaseUrl = baseUrl;
|
|
476
|
-
cachedIdToken = idToken;
|
|
477
|
-
tokenExpiresAt = Date.now() + 50 * 60 * 1e3;
|
|
478
|
-
return { baseUrl, idToken };
|
|
492
|
+
throw new Error("Not authenticated. Run 'cutline-mcp login' or set CUTLINE_API_KEY.");
|
|
479
493
|
}
|
|
480
494
|
async function proxy(action, params = {}) {
|
|
481
495
|
const { baseUrl, idToken } = await resolveAuth();
|
|
@@ -75,7 +75,7 @@ import {
|
|
|
75
75
|
upsertEntities,
|
|
76
76
|
upsertNodes,
|
|
77
77
|
validateRequestSize
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-X2B5QUWO.js";
|
|
79
79
|
import {
|
|
80
80
|
GraphTraverser,
|
|
81
81
|
computeGenericGraphMetrics,
|
|
@@ -8106,7 +8106,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
8106
8106
|
},
|
|
8107
8107
|
{
|
|
8108
8108
|
name: "code_audit",
|
|
8109
|
-
description: "\u{1F513} FREE -
|
|
8109
|
+
description: "\u{1F513} FREE - Security vibe check (code audit). Evaluates your codebase against a stack-aware constraint graph covering security, reliability, and scalability. No deep dive or product_id required \u2014 just point at your codebase. Shows aggregate readiness scores and top critical findings; detailed analysis and remediation require Premium. Requires a Cutline account (free). 3 scans/month.",
|
|
8110
8110
|
inputSchema: {
|
|
8111
8111
|
type: "object",
|
|
8112
8112
|
properties: {
|
|
@@ -8119,7 +8119,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
8119
8119
|
},
|
|
8120
8120
|
{
|
|
8121
8121
|
name: "engineering_audit",
|
|
8122
|
-
description: "\u{1F512} PREMIUM - Engineering audit for your product. Security-focused deep audit that scans local code, cross-references the product constraint graph, extracts security gaps, builds an RGR remediation plan, and optionally queues a deep dive job.",
|
|
8122
|
+
description: "\u{1F512} PREMIUM - Engineering vibe check (engineering audit) for your product. Security-focused deep audit that scans local code, cross-references the product constraint graph, extracts security gaps, builds an RGR remediation plan, and optionally queues a deep dive job.",
|
|
8123
8123
|
inputSchema: {
|
|
8124
8124
|
type: "object",
|
|
8125
8125
|
properties: {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
requirePremiumWithAutoAuth,
|
|
15
15
|
updateExplorationSession,
|
|
16
16
|
validateRequestSize
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-X2B5QUWO.js";
|
|
18
18
|
|
|
19
19
|
// ../mcp/dist/mcp/src/exploration-server.js
|
|
20
20
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
requirePremiumWithAutoAuth,
|
|
14
14
|
validateAuth,
|
|
15
15
|
validateRequestSize
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-X2B5QUWO.js";
|
|
17
17
|
|
|
18
18
|
// ../mcp/dist/mcp/src/integrations-server.js
|
|
19
19
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
mapErrorToMcp,
|
|
14
14
|
requirePremiumWithAutoAuth,
|
|
15
15
|
validateRequestSize
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-X2B5QUWO.js";
|
|
17
17
|
|
|
18
18
|
// ../mcp/dist/mcp/src/output-server.js
|
|
19
19
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
requirePremiumWithAutoAuth,
|
|
22
22
|
validateAuth,
|
|
23
23
|
validateRequestSize
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-X2B5QUWO.js";
|
|
25
25
|
|
|
26
26
|
// ../mcp/dist/mcp/src/tools-server.js
|
|
27
27
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
package/package.json
CHANGED