@kylewadegrove/cutline-mcp-cli 0.6.0 → 0.6.1

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.
@@ -0,0 +1,117 @@
1
+ import {
2
+ addEdges,
3
+ addEntity,
4
+ addNodes,
5
+ addTestCases,
6
+ createExplorationSession,
7
+ createPremortem,
8
+ createTemplate,
9
+ deleteAllNodes,
10
+ deleteBinding,
11
+ deleteGraphData,
12
+ generateReadinessReportViaProxy,
13
+ getAllBindings,
14
+ getAllEdges,
15
+ getAllEntities,
16
+ getAllNodes,
17
+ getAllNodesLight,
18
+ getBindingsForEntity,
19
+ getChat,
20
+ getEntitiesWithEmbeddings,
21
+ getEntityById,
22
+ getExplorationSession,
23
+ getGraphMetadata,
24
+ getIdeaReport,
25
+ getNodesByCategories,
26
+ getNodesBySource,
27
+ getNodesMissingEmbeddings,
28
+ getNodesWithEmbeddings,
29
+ getPersona,
30
+ getPremortem,
31
+ getReadinessReport,
32
+ getScanRateLimit,
33
+ getTemplate,
34
+ getTestCasesForEntity,
35
+ getTestCasesForProduct,
36
+ hasConstraints,
37
+ listExplorationSessions,
38
+ listPersonas,
39
+ listPremortems,
40
+ listTemplates,
41
+ recordScoreSnapshot,
42
+ saveChat,
43
+ saveReadinessReport,
44
+ saveScanReport,
45
+ searchNodesByKeywords,
46
+ updateChat,
47
+ updateEntityEmbedding,
48
+ updateExplorationSession,
49
+ updateGraphMetadata,
50
+ updateNodeEmbeddings,
51
+ updatePremortem,
52
+ updateScanRateLimit,
53
+ updateTemplate,
54
+ upsertBindings,
55
+ upsertEdges,
56
+ upsertEntities,
57
+ upsertNodes
58
+ } from "./chunk-PQUAX5YW.js";
59
+ import "./chunk-NUBIEJTU.js";
60
+ export {
61
+ addEdges,
62
+ addEntity,
63
+ addNodes,
64
+ addTestCases,
65
+ createExplorationSession,
66
+ createPremortem,
67
+ createTemplate,
68
+ deleteAllNodes,
69
+ deleteBinding,
70
+ deleteGraphData,
71
+ generateReadinessReportViaProxy,
72
+ getAllBindings,
73
+ getAllEdges,
74
+ getAllEntities,
75
+ getAllNodes,
76
+ getAllNodesLight,
77
+ getBindingsForEntity,
78
+ getChat,
79
+ getEntitiesWithEmbeddings,
80
+ getEntityById,
81
+ getExplorationSession,
82
+ getGraphMetadata,
83
+ getIdeaReport,
84
+ getNodesByCategories,
85
+ getNodesBySource,
86
+ getNodesMissingEmbeddings,
87
+ getNodesWithEmbeddings,
88
+ getPersona,
89
+ getPremortem,
90
+ getReadinessReport,
91
+ getScanRateLimit,
92
+ getTemplate,
93
+ getTestCasesForEntity,
94
+ getTestCasesForProduct,
95
+ hasConstraints,
96
+ listExplorationSessions,
97
+ listPersonas,
98
+ listPremortems,
99
+ listTemplates,
100
+ recordScoreSnapshot,
101
+ saveChat,
102
+ saveReadinessReport,
103
+ saveScanReport,
104
+ searchNodesByKeywords,
105
+ updateChat,
106
+ updateEntityEmbedding,
107
+ updateExplorationSession,
108
+ updateGraphMetadata,
109
+ updateNodeEmbeddings,
110
+ updatePremortem,
111
+ updateScanRateLimit,
112
+ updateTemplate,
113
+ upsertBindings,
114
+ upsertEdges,
115
+ upsertEntities,
116
+ upsertNodes
117
+ };
@@ -1,25 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- firestoreRetry
4
- } from "./chunk-PU7TL6S3.js";
5
- import {
6
- getStoredToken,
7
3
  guardBoundary,
8
4
  guardOutput,
9
- initFirebase,
5
+ withPerfTracking
6
+ } from "./chunk-OP4EO6FV.js";
7
+ import {
8
+ createExplorationSession,
9
+ getExplorationSession,
10
+ listExplorationSessions,
11
+ updateExplorationSession
12
+ } from "./chunk-PQUAX5YW.js";
13
+ import {
10
14
  mapErrorToMcp,
11
15
  requirePremiumWithAutoAuth,
12
- validateRequestSize,
13
- withPerfTracking
14
- } from "./chunk-PD2HN2R5.js";
16
+ validateRequestSize
17
+ } from "./chunk-NUBIEJTU.js";
15
18
 
16
19
  // ../mcp/dist/mcp/src/exploration-server.js
17
20
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
18
21
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19
22
  import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from "@modelcontextprotocol/sdk/types.js";
20
- import { getApps, getApp } from "firebase-admin/app";
21
- import { getFirestore } from "firebase-admin/firestore";
22
- import admin from "firebase-admin";
23
23
  import { GoogleAuth } from "google-auth-library";
24
24
  var EXPLORATION_AGENT_FUNCTION_URL = process.env.EXPLORATION_AGENT_FUNCTION_URL || "https://us-central1-cutline-prod.cloudfunctions.net/explorationAgent";
25
25
  var CONSULTING_DISCOVERY_AGENT_FUNCTION_URL = process.env.CONSULTING_DISCOVERY_AGENT_FUNCTION_URL || "https://us-central1-cutline-prod.cloudfunctions.net/consultingDiscoveryAgent";
@@ -48,12 +48,6 @@ function generateId(mode = "product") {
48
48
  const prefix = mode === "consulting" ? "cdisc" : "exp";
49
49
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
50
50
  }
51
- function getDb() {
52
- const app = getApps().length > 0 ? getApp() : void 0;
53
- if (!app)
54
- return null;
55
- return getFirestore(app);
56
- }
57
51
  async function createSession(initialInput, mode = "product", uid) {
58
52
  const session = {
59
53
  id: generateId(mode),
@@ -61,10 +55,8 @@ async function createSession(initialInput, mode = "product", uid) {
61
55
  mode,
62
56
  currentAct: 1,
63
57
  initialInput,
64
- // Product mode fields
65
58
  painPoints: [],
66
59
  ideas: [],
67
- // Consulting mode fields
68
60
  challenges: [],
69
61
  scopeItems: [],
70
62
  approachOptions: [],
@@ -73,18 +65,11 @@ async function createSession(initialInput, mode = "product", uid) {
73
65
  updatedAt: Date.now()
74
66
  };
75
67
  const collectionName = mode === "consulting" ? "consulting_discovery_sessions" : "exploration_sessions";
76
- const db = getDb();
77
- if (db) {
78
- try {
79
- await firestoreRetry(() => db.collection(collectionName).doc(session.id).set({
80
- ...session,
81
- createdAt: admin.firestore.FieldValue.serverTimestamp(),
82
- updatedAt: admin.firestore.FieldValue.serverTimestamp()
83
- }), { operationName: "discovery_session_create" });
84
- console.error(`[Discovery] Session created (${mode}): ${session.id}`);
85
- } catch (err) {
86
- console.error(`[Discovery] Failed to persist session:`, err);
87
- }
68
+ try {
69
+ await createExplorationSession(session.id, { ...session }, collectionName);
70
+ console.error(`[Discovery] Session created (${mode}): ${session.id}`);
71
+ } catch (err) {
72
+ console.error(`[Discovery] Failed to persist session:`, err);
88
73
  }
89
74
  sessionCache.set(session.id, session);
90
75
  return session;
@@ -92,94 +77,70 @@ async function createSession(initialInput, mode = "product", uid) {
92
77
  async function getSession(id) {
93
78
  const isConsulting = id.startsWith("cdisc_");
94
79
  const collectionName = isConsulting ? "consulting_discovery_sessions" : "exploration_sessions";
95
- const db = getDb();
96
- if (db) {
97
- try {
98
- const doc = await db.collection(collectionName).doc(id).get();
99
- if (doc.exists) {
100
- const data = doc.data();
101
- const session = {
102
- id: doc.id,
103
- uid: data.uid,
104
- mode: data.mode || (isConsulting ? "consulting" : "product"),
105
- currentAct: data.currentAct,
106
- initialInput: data.initialInput,
107
- // Product mode fields
108
- domainContext: data.domainContext,
109
- painPoints: data.painPoints || [],
110
- ideas: data.ideas || [],
111
- // Consulting mode fields
112
- clientContext: data.clientContext,
113
- challenges: data.challenges || [],
114
- scopeItems: data.scopeItems || [],
115
- approachOptions: data.approachOptions || [],
116
- fitAssessment: data.fitAssessment,
117
- conversationHistory: data.conversationHistory || [],
118
- createdAt: data.createdAt?.toMillis?.() || data.createdAt || Date.now(),
119
- updatedAt: data.updatedAt?.toMillis?.() || data.updatedAt || Date.now()
120
- };
121
- sessionCache.set(id, session);
122
- return session;
123
- }
124
- } catch (err) {
125
- console.error(`[Discovery] Failed to load session from Firestore:`, err);
80
+ try {
81
+ const data = await getExplorationSession(id, collectionName);
82
+ if (data) {
83
+ const session = {
84
+ id: data.id || id,
85
+ uid: data.uid,
86
+ mode: data.mode || (isConsulting ? "consulting" : "product"),
87
+ currentAct: data.currentAct,
88
+ initialInput: data.initialInput,
89
+ domainContext: data.domainContext,
90
+ painPoints: data.painPoints || [],
91
+ ideas: data.ideas || [],
92
+ clientContext: data.clientContext,
93
+ challenges: data.challenges || [],
94
+ scopeItems: data.scopeItems || [],
95
+ approachOptions: data.approachOptions || [],
96
+ fitAssessment: data.fitAssessment,
97
+ conversationHistory: data.conversationHistory || [],
98
+ createdAt: data.createdAt?.toMillis?.() || data.createdAt || Date.now(),
99
+ updatedAt: data.updatedAt?.toMillis?.() || data.updatedAt || Date.now()
100
+ };
101
+ sessionCache.set(id, session);
102
+ return session;
126
103
  }
104
+ } catch (err) {
105
+ console.error(`[Discovery] Failed to load session:`, err);
127
106
  }
128
107
  return sessionCache.get(id) || null;
129
108
  }
130
109
  async function updateSession(session) {
131
110
  session.updatedAt = Date.now();
132
111
  const collectionName = session.mode === "consulting" ? "consulting_discovery_sessions" : "exploration_sessions";
133
- const db = getDb();
134
- if (db) {
135
- try {
136
- await firestoreRetry(() => db.collection(collectionName).doc(session.id).update({
137
- ...session,
138
- updatedAt: admin.firestore.FieldValue.serverTimestamp()
139
- }), { operationName: "discovery_session_update" });
140
- } catch (err) {
141
- console.error(`[Discovery] Failed to update session:`, err);
142
- }
112
+ try {
113
+ await updateExplorationSession(session.id, { ...session }, collectionName);
114
+ } catch (err) {
115
+ console.error(`[Discovery] Failed to update session:`, err);
143
116
  }
144
117
  sessionCache.set(session.id, session);
145
118
  }
146
119
  async function listUserSessions(uid, mode) {
147
- const db = getDb();
148
- if (!db) {
149
- const sessions = Array.from(sessionCache.values());
150
- return mode ? sessions.filter((s) => s.mode === mode) : sessions;
151
- }
152
120
  try {
153
121
  const collections = mode ? [mode === "consulting" ? "consulting_discovery_sessions" : "exploration_sessions"] : ["exploration_sessions", "consulting_discovery_sessions"];
154
122
  const allSessions = [];
155
123
  for (const collectionName of collections) {
156
- let query = db.collection(collectionName).orderBy("updatedAt", "desc").limit(20);
157
- if (uid) {
158
- query = query.where("uid", "==", uid);
159
- }
160
- const snapshot = await query.get();
161
- const sessions = snapshot.docs.map((doc) => {
162
- const data = doc.data();
163
- const isConsulting = collectionName === "consulting_discovery_sessions";
164
- return {
165
- id: doc.id,
166
- uid: data.uid,
167
- mode: data.mode || (isConsulting ? "consulting" : "product"),
168
- currentAct: data.currentAct,
169
- initialInput: data.initialInput,
170
- domainContext: data.domainContext,
171
- painPoints: data.painPoints || [],
172
- ideas: data.ideas || [],
173
- clientContext: data.clientContext,
174
- challenges: data.challenges || [],
175
- scopeItems: data.scopeItems || [],
176
- approachOptions: data.approachOptions || [],
177
- fitAssessment: data.fitAssessment,
178
- conversationHistory: data.conversationHistory || [],
179
- createdAt: data.createdAt?.toMillis?.() || data.createdAt || Date.now(),
180
- updatedAt: data.updatedAt?.toMillis?.() || data.updatedAt || Date.now()
181
- };
182
- });
124
+ const docs = await listExplorationSessions(collectionName, 20);
125
+ const isConsulting = collectionName === "consulting_discovery_sessions";
126
+ const sessions = docs.map((data) => ({
127
+ id: data.id,
128
+ uid: data.uid,
129
+ mode: data.mode || (isConsulting ? "consulting" : "product"),
130
+ currentAct: data.currentAct,
131
+ initialInput: data.initialInput,
132
+ domainContext: data.domainContext,
133
+ painPoints: data.painPoints || [],
134
+ ideas: data.ideas || [],
135
+ clientContext: data.clientContext,
136
+ challenges: data.challenges || [],
137
+ scopeItems: data.scopeItems || [],
138
+ approachOptions: data.approachOptions || [],
139
+ fitAssessment: data.fitAssessment,
140
+ conversationHistory: data.conversationHistory || [],
141
+ createdAt: data.createdAt?.toMillis?.() || data.createdAt || Date.now(),
142
+ updatedAt: data.updatedAt?.toMillis?.() || data.updatedAt || Date.now()
143
+ }));
183
144
  allSessions.push(...sessions);
184
145
  }
185
146
  return allSessions.sort((a, b) => b.updatedAt - a.updatedAt).slice(0, 20);
@@ -374,13 +335,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
374
335
  }
375
336
  const mode = name === "exploration_start" ? "product" : requestedMode || "product";
376
337
  let uid;
377
- try {
378
- const storedToken = await getStoredToken();
379
- if (storedToken?.environment) {
380
- initFirebase(storedToken.environment);
381
- }
382
- } catch {
383
- }
384
338
  const session = await createSession(input.trim(), mode, uid);
385
339
  const actNames = getActNames(mode);
386
340
  let welcomeMessage;
@@ -449,16 +403,6 @@ And what draws you to explore this area?`;
449
403
  case "discovery_chat":
450
404
  case "exploration_chat": {
451
405
  const { session_id, message, advance_act } = args;
452
- try {
453
- const storedToken = await getStoredToken();
454
- if (storedToken?.environment) {
455
- initFirebase(storedToken.environment);
456
- } else {
457
- initFirebase();
458
- }
459
- } catch {
460
- initFirebase();
461
- }
462
406
  const session = await getSession(session_id);
463
407
  if (!session) {
464
408
  throw new McpError(ErrorCode.InvalidRequest, `Session not found: ${session_id}`);
@@ -619,13 +563,6 @@ And what draws you to explore this area?`;
619
563
  case "discovery_status":
620
564
  case "exploration_status": {
621
565
  const { session_id } = args;
622
- try {
623
- const storedToken = await getStoredToken();
624
- if (storedToken?.environment) {
625
- initFirebase(storedToken.environment);
626
- }
627
- } catch {
628
- }
629
566
  const session = await getSession(session_id);
630
567
  if (!session) {
631
568
  throw new McpError(ErrorCode.InvalidRequest, `Session not found: ${session_id}`);
@@ -717,13 +654,6 @@ And what draws you to explore this area?`;
717
654
  case "discovery_list":
718
655
  case "exploration_list": {
719
656
  const { mode: filterMode } = args;
720
- try {
721
- const storedToken = await getStoredToken();
722
- if (storedToken?.environment) {
723
- initFirebase(storedToken.environment);
724
- }
725
- } catch {
726
- }
727
657
  const effectiveMode = name === "exploration_list" ? "product" : filterMode;
728
658
  const sessions = await listUserSessions(void 0, effectiveMode);
729
659
  const sessionList = sessions.map((s) => {
@@ -765,13 +695,6 @@ And what draws you to explore this area?`;
765
695
  case "discovery_graduate":
766
696
  case "exploration_graduate": {
767
697
  const { session_id, idea_index, approach_index, auth_token } = args;
768
- try {
769
- const storedToken = await getStoredToken();
770
- if (storedToken?.environment) {
771
- initFirebase(storedToken.environment);
772
- }
773
- } catch {
774
- }
775
698
  const session = await getSession(session_id);
776
699
  if (!session) {
777
700
  throw new McpError(ErrorCode.InvalidRequest, `Session not found: ${session_id}`);
@@ -5,19 +5,20 @@ import {
5
5
  import {
6
6
  createLinearIssues,
7
7
  processStripeEvent
8
- } from "./chunk-IVWF7VYZ.js";
8
+ } from "./chunk-M37M2UA4.js";
9
+ import "./chunk-JBJYSV4P.js";
9
10
  import {
10
11
  guardBoundary,
11
12
  guardOutput,
12
- initFirebase,
13
+ withPerfTracking
14
+ } from "./chunk-OP4EO6FV.js";
15
+ import {
13
16
  mapErrorToMcp,
14
17
  requirePremiumWithAutoAuth,
15
18
  validateAuth,
16
- validateRequestSize,
17
- withPerfTracking
18
- } from "./chunk-PD2HN2R5.js";
19
+ validateRequestSize
20
+ } from "./chunk-NUBIEJTU.js";
19
21
  import "./chunk-7FHM2GD3.js";
20
- import "./chunk-JBJYSV4P.js";
21
22
 
22
23
  // ../mcp/dist/mcp/src/integrations-server.js
23
24
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -70,7 +71,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
70
71
  throw new McpError(ErrorCode.InvalidParams, "Missing arguments");
71
72
  validateRequestSize(rawArgs);
72
73
  const { args } = guardBoundary(name, rawArgs);
73
- initFirebase();
74
74
  const rawResponse = await withPerfTracking(name, async () => {
75
75
  if (isWriteTool(name)) {
76
76
  const peekToken = args.auth_token;
@@ -3,20 +3,21 @@ import {
3
3
  buildPdfBuffer,
4
4
  generateAnswer,
5
5
  uploadAndSign
6
- } from "./chunk-IVWF7VYZ.js";
6
+ } from "./chunk-M37M2UA4.js";
7
+ import "./chunk-JBJYSV4P.js";
7
8
  import {
8
9
  guardBoundary,
9
10
  guardOutput,
10
- initFirebase,
11
+ withPerfTracking
12
+ } from "./chunk-OP4EO6FV.js";
13
+ import {
11
14
  mapErrorToMcp,
12
15
  requirePremiumWithAutoAuth,
13
- validateRequestSize,
14
- withPerfTracking
15
- } from "./chunk-PD2HN2R5.js";
16
+ validateRequestSize
17
+ } from "./chunk-NUBIEJTU.js";
16
18
  import {
17
19
  PMJsonSchema
18
20
  } from "./chunk-7FHM2GD3.js";
19
- import "./chunk-JBJYSV4P.js";
20
21
 
21
22
  // ../mcp/dist/mcp/src/output-server.js
22
23
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -68,7 +69,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
68
69
  throw new McpError(ErrorCode.InvalidParams, "Missing arguments");
69
70
  validateRequestSize(rawArgs);
70
71
  const { args } = guardBoundary(name, rawArgs);
71
- initFirebase();
72
72
  const rawResponse = await withPerfTracking(name, async () => {
73
73
  switch (name) {
74
74
  case "premortem_render_pdf": {