@kylewadegrove/cutline-mcp-cli 0.6.0 → 0.6.2

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.
@@ -1,35 +1,147 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- firestoreRetry
4
- } from "./chunk-PU7TL6S3.js";
3
+ RunInputSchema
4
+ } from "./chunk-DE7R7WKY.js";
5
5
  import {
6
6
  isWriteTool
7
7
  } from "./chunk-KMUSQOTJ.js";
8
- import "./chunk-IVWF7VYZ.js";
9
8
  import {
10
9
  guardBoundary,
11
10
  guardOutput,
11
+ withPerfTracking
12
+ } from "./chunk-OP4EO6FV.js";
13
+ import {
14
+ cfRegenAssumptions,
15
+ cfRegenExperiments,
16
+ createPremortem,
17
+ getChat,
18
+ getPremortem,
19
+ listPremortems,
12
20
  mapErrorToMcp,
13
21
  requirePremiumWithAutoAuth,
14
22
  resolveAuthContext,
23
+ saveChat,
24
+ updateChat,
25
+ updatePremortem,
15
26
  validateAuth,
16
- validateRequestSize,
17
- withPerfTracking
18
- } from "./chunk-PD2HN2R5.js";
19
- import {
20
- RunInputSchema,
21
- regenerateAssumptions,
22
- regenerateExperiments
23
- } from "./chunk-7FHM2GD3.js";
24
- import "./chunk-JBJYSV4P.js";
27
+ validateRequestSize
28
+ } from "./chunk-7N4HJ3KR.js";
25
29
 
26
30
  // ../mcp/dist/mcp/src/premortem-server.js
27
31
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
28
32
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
29
33
  import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from "@modelcontextprotocol/sdk/types.js";
30
- import admin from "firebase-admin";
31
- import { getApps, getApp } from "firebase-admin/app";
32
- import { getFirestore } from "firebase-admin/firestore";
34
+
35
+ // ../mcp/dist/mcp/src/premortem-handoff.js
36
+ function buildBrief(ctx) {
37
+ if (!ctx)
38
+ return "";
39
+ const parts = [];
40
+ if (ctx.brief)
41
+ parts.push(ctx.brief);
42
+ if (ctx.problemSolved && !ctx.brief?.toLowerCase().includes(ctx.problemSolved.toLowerCase().slice(0, 20)))
43
+ parts.push(`Problem: ${ctx.problemSolved}`);
44
+ if (ctx.uniqueValue && !ctx.brief?.toLowerCase().includes(ctx.uniqueValue.toLowerCase().slice(0, 20)))
45
+ parts.push(`Unique value: ${ctx.uniqueValue}`);
46
+ if (ctx.targetUser && !ctx.brief?.toLowerCase().includes(ctx.targetUser.toLowerCase().slice(0, 15)))
47
+ parts.push(`Target users: ${ctx.targetUser}`);
48
+ if (ctx.businessModel && !ctx.brief?.toLowerCase().includes(ctx.businessModel.toLowerCase().slice(0, 15)))
49
+ parts.push(`Business model: ${ctx.businessModel}`);
50
+ return parts.join(". ").trim() || "No description provided.";
51
+ }
52
+ function buildReferenceClasses(competitors) {
53
+ if (competitors && competitors.length > 0) {
54
+ return competitors.filter((c) => c.name && c.name.length > 0).map((c) => c.name).slice(0, 5);
55
+ }
56
+ return ["General market alternatives"];
57
+ }
58
+ function buildSeedPersonas(ctx) {
59
+ if (!ctx.productContext?.targetUser)
60
+ return void 0;
61
+ return {
62
+ user_personas: [{ name: "Primary User", description: ctx.productContext.targetUser }]
63
+ };
64
+ }
65
+ function buildRunInput(request) {
66
+ const { projectName, conversationalContext: ctx, mode = "product", clientContext } = request;
67
+ let brief = buildBrief(ctx.productContext);
68
+ if (ctx.risks.length > 0) {
69
+ const topRisks = ctx.risks.filter((r) => r.severity === "critical" || r.severity === "high").slice(0, 2).map((r) => r.title);
70
+ if (topRisks.length > 0)
71
+ brief += ` Key concerns to investigate: ${topRisks.join(", ")}.`;
72
+ }
73
+ if (ctx.verdict?.summary)
74
+ brief += ` Initial assessment: ${ctx.verdict.summary}`;
75
+ const runInput = {
76
+ mode,
77
+ project: { name: projectName, brief, reference_classes: buildReferenceClasses(ctx.competitors) }
78
+ };
79
+ if (mode === "consulting" && clientContext) {
80
+ runInput.client = {
81
+ name: clientContext.name,
82
+ industry: clientContext.industry,
83
+ size: clientContext.size,
84
+ stakeholders: clientContext.stakeholders
85
+ };
86
+ }
87
+ const seedPersonas = buildSeedPersonas(ctx);
88
+ if (seedPersonas)
89
+ runInput.seed_personas = seedPersonas;
90
+ if (ctx.risks.length > 0 || ctx.assumptions.length > 0 || ctx.competitors.length > 0) {
91
+ runInput.conversational_artifacts = {
92
+ risks: ctx.risks.length > 0 ? ctx.risks.map((r) => ({
93
+ title: r.title,
94
+ description: r.description,
95
+ category: r.category,
96
+ severity: r.severity,
97
+ likelihood: r.likelihood,
98
+ impact: r.impact
99
+ })) : void 0,
100
+ assumptions: ctx.assumptions.length > 0 ? ctx.assumptions.map((a) => ({
101
+ statement: a.statement,
102
+ category: a.category,
103
+ confidence: a.confidence,
104
+ importance: a.importance
105
+ })) : void 0,
106
+ competitors: ctx.competitors.length > 0 ? ctx.competitors.map((c) => ({
107
+ name: c.name,
108
+ description: c.description,
109
+ threat_level: c.threatLevel
110
+ })) : void 0,
111
+ conversation_summary: ctx.verdict?.summary
112
+ };
113
+ }
114
+ return runInput;
115
+ }
116
+ function validateForGraduation(ctx) {
117
+ const errors = [];
118
+ const warnings = [];
119
+ if (!ctx.productContext?.brief && !ctx.productContext?.problemSolved)
120
+ errors.push("No product description found. Please describe what you're building first.");
121
+ if (ctx.assumptions.length === 0)
122
+ warnings.push("No assumptions were surfaced. The full analysis will discover them.");
123
+ if (ctx.risks.length === 0)
124
+ warnings.push("No risks were identified. The full analysis will analyze risks in depth.");
125
+ if (ctx.competitors.length === 0)
126
+ warnings.push("No competitors were discussed. Provide reference companies for better analysis.");
127
+ return { valid: errors.length === 0, errors, warnings };
128
+ }
129
+ function buildGraduationMetadata(sessionId, ctx, currentAct) {
130
+ return {
131
+ sourceType: "conversational_premortem",
132
+ sourceSessionId: sessionId,
133
+ graduatedAt: Date.now(),
134
+ conversationSummary: {
135
+ actsCompleted: currentAct,
136
+ assumptionsCount: ctx.assumptions.length,
137
+ risksCount: ctx.risks.length,
138
+ competitorsCount: ctx.competitors.length,
139
+ hasVerdict: !!ctx.verdict
140
+ }
141
+ };
142
+ }
143
+
144
+ // ../mcp/dist/mcp/src/premortem-server.js
33
145
  import { GoogleAuth } from "google-auth-library";
34
146
  var PREMORTEM_CHAT_FUNCTION_URL = process.env.PREMORTEM_CHAT_AGENT_FUNCTION_URL || "https://us-central1-cutline-prod.cloudfunctions.net/premortemChatAgent";
35
147
  var PREMORTEM_KICK_FUNCTION_URL = process.env.PREMORTEM_KICK_FUNCTION_URL || "https://us-central1-cutline-prod.cloudfunctions.net/premortemKick";
@@ -54,22 +166,12 @@ var chatSessionCache = /* @__PURE__ */ new Map();
54
166
  function generateChatSessionId() {
55
167
  return `pmc_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
56
168
  }
57
- function getDb() {
58
- const app = getApps().length > 0 ? getApp() : void 0;
59
- if (!app)
60
- return null;
61
- return getFirestore(app);
62
- }
63
169
  async function saveChatSession(session) {
64
170
  session.updatedAt = Date.now();
65
171
  chatSessionCache.set(session.id, session);
66
- const db = getDb();
67
- if (db && session.uid) {
172
+ if (session.uid) {
68
173
  try {
69
- await firestoreRetry(() => db.collection("premortem_chats").doc(session.id).set({
70
- ...session,
71
- updatedAt: admin.firestore.FieldValue.serverTimestamp()
72
- }, { merge: true }), { operationName: "premortem_chat_persist" });
174
+ await saveChat(session.id, { ...session });
73
175
  } catch (e) {
74
176
  console.error("[PremortemChat] Failed to persist session:", e);
75
177
  }
@@ -79,18 +181,14 @@ async function getChatSession(sessionId) {
79
181
  if (chatSessionCache.has(sessionId)) {
80
182
  return chatSessionCache.get(sessionId);
81
183
  }
82
- const db = getDb();
83
- if (db) {
84
- try {
85
- const doc = await db.collection("premortem_chats").doc(sessionId).get();
86
- if (doc.exists) {
87
- const data = doc.data();
88
- chatSessionCache.set(sessionId, data);
89
- return data;
90
- }
91
- } catch (e) {
92
- console.error("[PremortemChat] Failed to load session:", e);
184
+ try {
185
+ const data = await getChat(sessionId);
186
+ if (data) {
187
+ chatSessionCache.set(sessionId, data);
188
+ return data;
93
189
  }
190
+ } catch (e) {
191
+ console.error("[PremortemChat] Failed to load session:", e);
94
192
  }
95
193
  return null;
96
194
  }
@@ -398,23 +496,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
398
496
  console.error(`[Premortem DEBUG] Step 2: Parsing input...`);
399
497
  const parsedInput = RunInputSchema.parse(input);
400
498
  console.error(`[Premortem DEBUG] Step 2 done: project=${parsedInput.project.name}`);
401
- console.error(`[Premortem DEBUG] Step 3: Getting Firebase app...`);
402
- const app = getApps().length > 0 ? getApp() : void 0;
403
- if (!app)
404
- throw new McpError(ErrorCode.InternalError, "Firebase Admin not initialized");
405
- const db = getFirestore(app);
406
- console.error(`[Premortem DEBUG] Step 3 done: Firebase ready`);
407
499
  console.error(`[Premortem] Queuing analysis for: ${parsedInput.project.name}`);
408
500
  const startTime = Date.now();
409
501
  console.error(`[Premortem DEBUG] Step 4: Creating job document...`);
410
- const docRef = await firestoreRetry(() => db.collection("premortem_jobs").add({
502
+ const { id: jobId } = await createPremortem({
411
503
  status: "queued",
412
504
  payload: parsedInput,
413
505
  uid: decoded?.uid || null,
414
- source: "mcp_sync",
415
- createdAt: admin.firestore.FieldValue.serverTimestamp()
416
- }), { operationName: "premortem_job_create" });
417
- const jobId = docRef.id;
506
+ source: "mcp_sync"
507
+ });
418
508
  console.error(`[Premortem DEBUG] Step 4 done: jobId=${jobId}`);
419
509
  console.error(`[Premortem] Job queued: ${jobId}, polling for completion...`);
420
510
  const maxWaitMs = 10 * 60 * 1e3;
@@ -423,8 +513,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
423
513
  let kickedFallback = false;
424
514
  while (Date.now() - startTime < maxWaitMs) {
425
515
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
426
- const snap = await docRef.get();
427
- const data = snap.data() || {};
516
+ const data = await getPremortem(jobId) || {};
428
517
  if (!kickedFallback && data.status === "queued" && Date.now() - startTime > 1e4) {
429
518
  console.error(`[Premortem] Job still queued after 10s, kicking via Cloud Function...`);
430
519
  kickedFallback = true;
@@ -475,31 +564,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
475
564
  const { input, auth_token } = args;
476
565
  const decoded = await requirePremiumWithAutoAuth(auth_token);
477
566
  const parsedInput = RunInputSchema.parse(input);
478
- const app = getApps().length > 0 ? getApp() : void 0;
479
- if (!app)
480
- throw new McpError(ErrorCode.InternalError, "Firebase Admin not initialized");
481
- const db = getFirestore(app);
482
- const docRef = await firestoreRetry(() => db.collection("premortem_jobs").add({
567
+ const { id: queuedJobId } = await createPremortem({
483
568
  status: "queued",
484
569
  payload: parsedInput,
485
- createdAt: admin.firestore.FieldValue.serverTimestamp(),
486
570
  uid: decoded?.uid || null
487
- }), { operationName: "premortem_queue_create" });
571
+ });
488
572
  return {
489
- content: [{ type: "text", text: JSON.stringify({ jobId: docRef.id }) }]
573
+ content: [{ type: "text", text: JSON.stringify({ jobId: queuedJobId }) }]
490
574
  };
491
575
  }
492
576
  case "premortem_status": {
493
577
  const { jobId, auth_token } = args;
494
578
  const { effectiveUid } = await resolveAuthContext(auth_token);
495
- const app = getApps().length > 0 ? getApp() : void 0;
496
- if (!app)
497
- throw new McpError(ErrorCode.InternalError, "Firebase Admin not initialized");
498
- const firestore = getFirestore(app);
499
- const snap = await firestore.collection("premortem_jobs").doc(jobId).get();
500
- if (!snap.exists)
579
+ const data = await getPremortem(jobId);
580
+ if (!data)
501
581
  throw new McpError(ErrorCode.InvalidRequest, "Job not found");
502
- const data = snap.data() || {};
503
582
  const allowPublic = process.env.ALLOW_PUBLIC_PREMORTEM === "true";
504
583
  if (!allowPublic && effectiveUid && data.uid && data.uid !== effectiveUid) {
505
584
  throw new McpError(ErrorCode.InvalidRequest, "You do not have permission to access this job");
@@ -550,7 +629,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
550
629
  case "premortem_regen_assumptions": {
551
630
  const { input, doc, auth_token } = args;
552
631
  await requirePremiumWithAutoAuth(auth_token);
553
- const out = await regenerateAssumptions(input, doc);
632
+ const out = await cfRegenAssumptions(input, doc);
554
633
  return {
555
634
  content: [{ type: "text", text: JSON.stringify(out) }]
556
635
  };
@@ -558,7 +637,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
558
637
  case "premortem_regen_experiments": {
559
638
  const { input, doc, auth_token } = args;
560
639
  await requirePremiumWithAutoAuth(auth_token);
561
- const out = await regenerateExperiments(input, doc);
640
+ const out = await cfRegenExperiments(input, doc);
562
641
  return {
563
642
  content: [{ type: "text", text: JSON.stringify(out) }]
564
643
  };
@@ -566,27 +645,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
566
645
  case "premortem_list": {
567
646
  const { limit = 10, auth_token } = args;
568
647
  const { effectiveUid } = await resolveAuthContext(auth_token);
569
- const app = getApps().length > 0 ? getApp() : void 0;
570
- if (!app)
571
- throw new McpError(ErrorCode.InternalError, "Firebase Admin not initialized");
572
- const firestore = getFirestore(app);
573
- const snapshot = await firestore.collection("premortem_jobs").where("uid", "==", effectiveUid).orderBy("createdAt", "desc").limit(limit).get();
574
- const premortems = snapshot.docs.map((doc) => {
575
- const data = doc.data();
576
- return {
577
- id: doc.id,
578
- uid: data.uid,
579
- status: data.status,
580
- stage: data.stage,
581
- stage_label: data.stage_label,
582
- progress: data.progress,
583
- createdAt: data.createdAt?.toDate()?.toISOString(),
584
- startedAt: data.startedAt?.toDate()?.toISOString(),
585
- updatedAt: data.updatedAt?.toDate()?.toISOString(),
586
- productName: data.payload?.project?.name || data.result?.project?.name || "Untitled",
587
- productDescription: data.payload?.project?.brief || data.result?.project?.brief || ""
588
- };
589
- });
648
+ const premortems = await listPremortems({ limit });
590
649
  return {
591
650
  content: [{ type: "text", text: JSON.stringify(premortems, null, 2) }]
592
651
  };
@@ -603,11 +662,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
603
662
  throw new McpError(ErrorCode.InvalidParams, "conversational_context is required");
604
663
  }
605
664
  const decoded = await requirePremiumWithAutoAuth(auth_token);
606
- const app = getApps().length > 0 ? getApp() : void 0;
607
- if (!app)
608
- throw new McpError(ErrorCode.InternalError, "Firebase Admin not initialized");
609
- const db = getFirestore(app);
610
- const { buildRunInput, validateForGraduation, buildGraduationMetadata } = await import("./premortem-handoff-XT4K3YDJ.js");
611
665
  const validation = validateForGraduation(conversational_context);
612
666
  if (!validation.valid) {
613
667
  throw new McpError(ErrorCode.InvalidParams, `Cannot graduate: ${validation.errors.join(", ")}`);
@@ -624,24 +678,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
624
678
  conversational_context.verdict ? 5 : 4
625
679
  // Estimate current act
626
680
  );
627
- const docRef = await firestoreRetry(() => db.collection("premortem_jobs").add({
681
+ const { id: gradJobId } = await createPremortem({
628
682
  status: "queued",
629
683
  payload: parsedInput,
630
- createdAt: admin.firestore.FieldValue.serverTimestamp(),
631
684
  uid: decoded?.uid || null,
632
685
  source: "mcp_graduate",
633
686
  graduation: graduationMetadata
634
- }), { operationName: "premortem_graduate_create" });
635
- console.error(`[Premortem Graduate] Created job ${docRef.id} from session ${session_id}`);
687
+ });
688
+ console.error(`[Premortem Graduate] Created job ${gradJobId} from session ${session_id}`);
636
689
  try {
637
- const sessionRef = db.collection("premortem_jobs").doc(session_id);
638
- const sessionSnap = await sessionRef.get();
639
- if (sessionSnap.exists) {
640
- await firestoreRetry(() => sessionRef.update({
641
- linkedJobId: docRef.id,
642
- graduatedAt: admin.firestore.FieldValue.serverTimestamp()
643
- }), { operationName: "premortem_session_link" });
644
- console.error(`[Premortem Graduate] Linked session ${session_id} to job ${docRef.id}`);
690
+ const sessionData = await getPremortem(session_id);
691
+ if (sessionData) {
692
+ await updatePremortem(session_id, {
693
+ linkedJobId: gradJobId,
694
+ graduatedAt: (/* @__PURE__ */ new Date()).toISOString()
695
+ });
696
+ console.error(`[Premortem Graduate] Linked session ${session_id} to job ${gradJobId}`);
645
697
  }
646
698
  } catch (linkError) {
647
699
  console.error(`[Premortem Graduate] Failed to link session:`, linkError);
@@ -649,11 +701,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
649
701
  return {
650
702
  content: [{ type: "text", text: JSON.stringify({
651
703
  success: true,
652
- jobId: docRef.id,
704
+ jobId: gradJobId,
653
705
  sourceSessionId: session_id,
654
706
  projectName: project_name,
655
707
  warnings: validation.warnings,
656
- message: `\u2615 Full analysis queued! This will take a minute\u2014go grab a cup of coffee. Use premortem_status with jobId "${docRef.id}" to check progress.`
708
+ message: `\u2615 Full analysis queued! This will take a minute\u2014go grab a cup of coffee. Use premortem_status with jobId "${gradJobId}" to check progress.`
657
709
  }, null, 2) }]
658
710
  };
659
711
  }
@@ -856,10 +908,6 @@ Let's start with the basics. Tell me more about what you're building:
856
908
  if (!graduationStatus.canGraduate) {
857
909
  throw new McpError(ErrorCode.InvalidRequest, `Cannot graduate: ${graduationStatus.reason}`);
858
910
  }
859
- const app = getApps().length > 0 ? getApp() : void 0;
860
- if (!app)
861
- throw new McpError(ErrorCode.InternalError, "Firebase Admin not initialized");
862
- const db = getFirestore(app);
863
911
  let productContext = session.productContext;
864
912
  if (!productContext?.brief) {
865
913
  console.error("[PremortemGraduate] Building fallback product context from initialInput");
@@ -878,7 +926,6 @@ Let's start with the basics. Tell me more about what you're building:
878
926
  competitors: session.competitors,
879
927
  verdict: session.verdict
880
928
  };
881
- const { buildRunInput, validateForGraduation, buildGraduationMetadata } = await import("./premortem-handoff-XT4K3YDJ.js");
882
929
  const validation = validateForGraduation(conversational_context);
883
930
  if (!validation.valid) {
884
931
  throw new McpError(ErrorCode.InvalidParams, `Cannot graduate: ${validation.errors.join(", ")}`);
@@ -890,39 +937,35 @@ Let's start with the basics. Tell me more about what you're building:
890
937
  conversationalContext: conversational_context
891
938
  });
892
939
  const parsedInput = RunInputSchema.parse(runInput);
893
- const docRef = await firestoreRetry(() => db.collection("premortem_jobs").add({
940
+ const { id: chatGradJobId } = await createPremortem({
894
941
  status: "queued",
895
942
  payload: parsedInput,
896
943
  uid: decoded?.uid || null,
897
944
  source: "mcp_chat_graduate",
898
- metadata: buildGraduationMetadata({
899
- sessionId: session_id,
900
- conversationalContext: conversational_context
901
- }),
902
- createdAt: admin.firestore.FieldValue.serverTimestamp()
903
- }), { operationName: "premortem_chat_graduate" });
945
+ metadata: buildGraduationMetadata(session_id, conversational_context, conversational_context.verdict ? 5 : 4)
946
+ });
904
947
  session.conversationHistory.push({
905
948
  role: "assistant",
906
949
  content: `\u{1F393} **Graduated to Full Analysis!**
907
950
 
908
951
  \u2615 This will take a minute\u2014go grab a cup of coffee while our 9 AI agents stress-test your idea.
909
952
 
910
- Job ID: \`${docRef.id}\`
953
+ Job ID: \`${chatGradJobId}\`
911
954
 
912
955
  The full pipeline includes deeper competitor research, market sizing, financial modeling, and more.`
913
956
  });
914
957
  await saveChatSession(session);
915
958
  try {
916
- await firestoreRetry(() => db.collection("premortem_chats").doc(session_id).update({
917
- linkedJobId: docRef.id,
918
- graduatedAt: admin.firestore.FieldValue.serverTimestamp()
919
- }), { operationName: "premortem_chat_link" });
959
+ await updateChat(session_id, {
960
+ linkedJobId: chatGradJobId,
961
+ graduatedAt: (/* @__PURE__ */ new Date()).toISOString()
962
+ });
920
963
  } catch {
921
964
  }
922
965
  return {
923
966
  content: [{ type: "text", text: JSON.stringify({
924
967
  success: true,
925
- jobId: docRef.id,
968
+ jobId: chatGradJobId,
926
969
  sourceSessionId: session_id,
927
970
  projectName: project_name,
928
971
  warnings: validation.warnings,
@@ -932,7 +975,7 @@ The full pipeline includes deeper competitor research, market sizing, financial
932
975
  competitors: session.competitors.length,
933
976
  has_verdict: !!session.verdict
934
977
  },
935
- message: `\u2615 Full analysis queued! This will take a minute\u2014go grab a cup of coffee. Use premortem_status with jobId "${docRef.id}" to check progress.`
978
+ message: `\u2615 Full analysis queued! This will take a minute\u2014go grab a cup of coffee. Use premortem_status with jobId "${chatGradJobId}" to check progress.`
936
979
  }, null, 2) }]
937
980
  };
938
981
  }
@@ -2,29 +2,26 @@
2
2
  import {
3
3
  isWriteTool
4
4
  } from "./chunk-KMUSQOTJ.js";
5
- import {
6
- applyEditsLogic,
7
- chatWithPersona,
8
- generateChatSuggestion,
9
- generateTrialRun,
10
- getPersona,
11
- getWikiMarkdown,
12
- listPersonas,
13
- saveWikiMarkdown
14
- } from "./chunk-IVWF7VYZ.js";
15
5
  import {
16
6
  guardBoundary,
17
7
  guardOutput,
18
- initFirebase,
8
+ withPerfTracking
9
+ } from "./chunk-OP4EO6FV.js";
10
+ import {
11
+ cfApplyEdits,
12
+ cfChatWithPersona,
13
+ cfGenerateChatSuggestion,
14
+ cfGenerateTrialRun,
15
+ cfGetWikiMarkdown,
16
+ cfSaveWikiMarkdown,
17
+ getPersona,
18
+ getPodcastIntroductions,
19
+ listPersonas,
19
20
  mapErrorToMcp,
20
21
  requirePremiumWithAutoAuth,
21
- resolveAuthContext,
22
22
  validateAuth,
23
- validateRequestSize,
24
- withPerfTracking
25
- } from "./chunk-PD2HN2R5.js";
26
- import "./chunk-7FHM2GD3.js";
27
- import "./chunk-JBJYSV4P.js";
23
+ validateRequestSize
24
+ } from "./chunk-7N4HJ3KR.js";
28
25
 
29
26
  // ../mcp/dist/mcp/src/tools-server.js
30
27
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -184,7 +181,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
184
181
  throw new McpError(ErrorCode.InvalidParams, "Missing arguments");
185
182
  validateRequestSize(rawArgs);
186
183
  const { args } = guardBoundary(name, rawArgs);
187
- initFirebase();
188
184
  const rawResponse = await withPerfTracking(name, async () => {
189
185
  if (isWriteTool(name)) {
190
186
  const peekToken = args.auth_token;
@@ -198,7 +194,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
198
194
  switch (name) {
199
195
  case "trial_generate": {
200
196
  const { prompt } = args;
201
- const text = await generateTrialRun(prompt);
197
+ const text = await cfGenerateTrialRun(prompt);
202
198
  return {
203
199
  content: [{ type: "text", text: JSON.stringify({ ok: true, text }) }]
204
200
  };
@@ -206,7 +202,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
206
202
  case "agent_chat": {
207
203
  const { prompt, wikiMarkdown, auth_token } = args;
208
204
  await requirePremiumWithAutoAuth(auth_token);
209
- const text = await generateChatSuggestion(prompt, wikiMarkdown);
205
+ const text = await cfGenerateChatSuggestion(prompt, wikiMarkdown);
210
206
  return {
211
207
  content: [{ type: "text", text: JSON.stringify({ text }) }]
212
208
  };
@@ -214,7 +210,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
214
210
  case "wiki_load": {
215
211
  const { projectId, auth_token } = args;
216
212
  await requirePremiumWithAutoAuth(auth_token);
217
- const markdown = await getWikiMarkdown(projectId);
213
+ const markdown = await cfGetWikiMarkdown(projectId);
218
214
  return {
219
215
  content: [{ type: "text", text: JSON.stringify({ markdown }) }]
220
216
  };
@@ -222,7 +218,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
222
218
  case "wiki_save": {
223
219
  const { projectId, markdown, auth_token } = args;
224
220
  const decoded = await requirePremiumWithAutoAuth(auth_token);
225
- await saveWikiMarkdown(projectId, markdown, decoded?.uid);
221
+ await cfSaveWikiMarkdown(projectId, markdown);
226
222
  return {
227
223
  content: [{ type: "text", text: JSON.stringify({ ok: true }) }]
228
224
  };
@@ -230,7 +226,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
230
226
  case "wiki_apply_edits": {
231
227
  const { edits, auth_token } = args;
232
228
  await requirePremiumWithAutoAuth(auth_token);
233
- const result = await applyEditsLogic(edits);
229
+ const result = await cfApplyEdits(edits);
234
230
  return {
235
231
  content: [{ type: "text", text: JSON.stringify(result) }]
236
232
  };
@@ -238,8 +234,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
238
234
  case "personas_list": {
239
235
  const { productId, auth_token } = args;
240
236
  const normalizedAuthToken = auth_token && auth_token !== "auto" && auth_token.trim() !== "" ? auth_token : void 0;
241
- const { effectiveUid } = await resolveAuthContext(normalizedAuthToken);
242
- const personas = await listPersonas(effectiveUid, productId);
237
+ await requirePremiumWithAutoAuth(normalizedAuthToken);
238
+ const personas = await listPersonas(productId);
243
239
  return {
244
240
  content: [{ type: "text", text: JSON.stringify({ personas }) }]
245
241
  };
@@ -247,8 +243,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
247
243
  case "personas_get": {
248
244
  const { personaId, auth_token } = args;
249
245
  const normalizedAuthToken = auth_token && auth_token !== "auto" && auth_token.trim() !== "" ? auth_token : void 0;
250
- const { effectiveUid } = await resolveAuthContext(normalizedAuthToken);
251
- const persona = await getPersona(effectiveUid, personaId);
246
+ await requirePremiumWithAutoAuth(normalizedAuthToken);
247
+ const persona = await getPersona(personaId);
252
248
  return {
253
249
  content: [{ type: "text", text: JSON.stringify({ persona }) }]
254
250
  };
@@ -257,7 +253,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
257
253
  const { persona, userMessage, product, conversationHistory, auth_token } = args;
258
254
  const normalizedAuthToken = auth_token && auth_token !== "auto" && auth_token.trim() !== "" ? auth_token : void 0;
259
255
  await requirePremiumWithAutoAuth(normalizedAuthToken);
260
- const result = await chatWithPersona(persona, userMessage, product, conversationHistory);
256
+ const result = await cfChatWithPersona(persona, userMessage, product, conversationHistory);
261
257
  return {
262
258
  content: [{ type: "text", text: JSON.stringify(result) }]
263
259
  };
@@ -265,8 +261,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
265
261
  case "podcast_get_participants": {
266
262
  const { productId, format, auth_token } = args;
267
263
  const normalizedAuthToken = auth_token && auth_token !== "auto" && auth_token.trim() !== "" ? auth_token : void 0;
268
- const { effectiveUid } = await resolveAuthContext(normalizedAuthToken);
269
- const result = await (void 0)(effectiveUid, productId, format || "json");
264
+ await requirePremiumWithAutoAuth(normalizedAuthToken);
265
+ const result = await getPodcastIntroductions(productId, format || "json");
270
266
  return {
271
267
  content: [{ type: "text", text: JSON.stringify(result) }]
272
268
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kylewadegrove/cutline-mcp-cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "CLI and MCP servers for Cutline — authenticate, then run constraint-aware MCP servers in Cursor or any MCP client.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -53,24 +53,15 @@
53
53
  "author": "Cutline",
54
54
  "license": "MIT",
55
55
  "dependencies": {
56
- "@google-cloud/storage": "^7.7.0",
57
56
  "@google-cloud/vertexai": "^1.9.2",
58
57
  "@modelcontextprotocol/sdk": "^1.0.0",
59
- "@pdf-lib/fontkit": "^1.1.1",
60
58
  "chalk": "^4.1.2",
61
59
  "commander": "^11.1.0",
62
- "customerio-node": "^4.0.0",
63
60
  "dotenv": "^16.4.5",
64
- "express": "^4.18.2",
65
- "firebase-admin": "^12.0.0",
66
- "firebase-functions": "^6.3.0",
67
61
  "google-auth-library": "^9.14.2",
68
62
  "keytar": "^7.9.0",
69
- "node-fetch": "^3.3.2",
70
63
  "open": "^9.1.0",
71
64
  "ora": "^5.4.1",
72
- "pdf-lib": "^1.17.1",
73
- "stripe": "^14.20.0",
74
65
  "zod": "^3.23.8"
75
66
  },
76
67
  "devDependencies": {