@talkspresso/mcp-server 1.4.3 → 1.5.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/dist/index.js +2 -2
- package/dist/setup-api.d.ts +1 -0
- package/dist/setup.js +20 -160
- package/dist/tools/brew.js +30 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ else if (args.includes('--help')) {
|
|
|
14
14
|
process.exit(0);
|
|
15
15
|
}
|
|
16
16
|
else if (args.includes('--version')) {
|
|
17
|
-
console.log('1.
|
|
17
|
+
console.log('1.5.0');
|
|
18
18
|
process.exit(0);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
@@ -42,7 +42,7 @@ else {
|
|
|
42
42
|
const { registerSubscriptionTools } = await import('./tools/subscription.js');
|
|
43
43
|
const server = new McpServer({
|
|
44
44
|
name: 'talkspresso',
|
|
45
|
-
version: '1.
|
|
45
|
+
version: '1.5.0',
|
|
46
46
|
});
|
|
47
47
|
const apiClient = new TalkspressoClient();
|
|
48
48
|
registerAppointmentTools(server, apiClient);
|
package/dist/setup-api.d.ts
CHANGED
package/dist/setup.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { confirm, input, password as passwordPrompt
|
|
2
|
+
import { confirm, input, password as passwordPrompt } from '@inquirer/prompts';
|
|
3
3
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
@@ -49,40 +49,6 @@ function mcpEntry(apiKey) {
|
|
|
49
49
|
env: { TALKSPRESSO_API_KEY: apiKey },
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
const SERVICE_PRESETS = [
|
|
53
|
-
{ name: '1:1 Video Call (30 min, $100)', value: { title: '1:1 Video Call', description: 'A private 30-minute video session.', price: 100, duration: 30, type: 'video_call' } },
|
|
54
|
-
{ name: '1:1 Video Call (60 min, $200)', value: { title: '1:1 Video Call', description: 'A private 60-minute video session.', price: 200, duration: 60, type: 'video_call' } },
|
|
55
|
-
{ name: 'Group Workshop (60 min, $50)', value: { title: 'Group Workshop', description: 'A 60-minute interactive group session.', price: 50, duration: 60, type: 'workshop' } },
|
|
56
|
-
{ name: 'Custom (I\'ll set it up)', value: 'custom' },
|
|
57
|
-
{ name: 'Skip for now', value: 'skip' },
|
|
58
|
-
];
|
|
59
|
-
const AVAILABILITY_PRESETS = [
|
|
60
|
-
{ name: 'Weekdays 9 AM - 5 PM', value: 'weekdays-9-5' },
|
|
61
|
-
{ name: 'Weekdays 10 AM - 6 PM', value: 'weekdays-10-6' },
|
|
62
|
-
{ name: 'Every day 9 AM - 9 PM', value: 'everyday-9-9' },
|
|
63
|
-
{ name: 'Skip for now', value: 'skip' },
|
|
64
|
-
];
|
|
65
|
-
function buildAvailability(preset) {
|
|
66
|
-
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
|
|
67
|
-
const weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
|
|
68
|
-
const make = (selectedDays, start, end) => {
|
|
69
|
-
const result = {};
|
|
70
|
-
for (const day of days) {
|
|
71
|
-
result[day] = {
|
|
72
|
-
is_selected: selectedDays.includes(day),
|
|
73
|
-
start_time: start,
|
|
74
|
-
end_time: end,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
return result;
|
|
78
|
-
};
|
|
79
|
-
switch (preset) {
|
|
80
|
-
case 'weekdays-9-5': return make(weekdays, '09:00', '17:00');
|
|
81
|
-
case 'weekdays-10-6': return make(weekdays, '10:00', '18:00');
|
|
82
|
-
case 'everyday-9-9': return make(days, '09:00', '21:00');
|
|
83
|
-
default: return null;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
52
|
export async function runSetup() {
|
|
87
53
|
process.on('SIGINT', () => {
|
|
88
54
|
console.log(`\n\n ${chalk.dim('Setup cancelled. Run')} npx @talkspresso/mcp-server --setup ${chalk.dim('anytime.')}\n`);
|
|
@@ -92,7 +58,7 @@ export async function runSetup() {
|
|
|
92
58
|
// ── Welcome ──────────────────────────────────────────
|
|
93
59
|
console.log(LOGO);
|
|
94
60
|
console.log(` ${chalk.white.bold('Manage your business with AI.')}`);
|
|
95
|
-
console.log(` ${chalk.dim("Let's
|
|
61
|
+
console.log(` ${chalk.dim("Let's connect your account. Takes about 60 seconds.")}\n`);
|
|
96
62
|
// ── Account ──────────────────────────────────────────
|
|
97
63
|
let accessToken;
|
|
98
64
|
let userName;
|
|
@@ -170,18 +136,10 @@ export async function runSetup() {
|
|
|
170
136
|
console.log(` ${chalk.dim('Create one manually at')} ${chalk.cyan('app.talkspresso.com/settings/api-keys')}\n`);
|
|
171
137
|
process.exit(1);
|
|
172
138
|
}
|
|
173
|
-
// ── Profile Setup ────────────────────────────────────
|
|
174
|
-
console.log(chalk.white.bold(' Set up your profile\n'));
|
|
175
|
-
const expertTitle = await input({
|
|
176
|
-
message: 'Your professional title (e.g., "Executive Coach", "Fitness Creator"):',
|
|
177
|
-
});
|
|
178
|
-
const about = await input({
|
|
179
|
-
message: 'One line about what you offer:',
|
|
180
|
-
});
|
|
181
139
|
// ── Handle / Vanity URL ────────────────────────────
|
|
182
140
|
let profileHandle = '';
|
|
183
141
|
const defaultHandle = userName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
|
|
184
|
-
console.log(
|
|
142
|
+
console.log(` ${chalk.dim('Your booking page will be:')} ${chalk.cyan(`app.talkspresso.com/`)}${chalk.cyan.bold('<your-handle>')}\n`);
|
|
185
143
|
let handleAttempts = 0;
|
|
186
144
|
while (handleAttempts < 5) {
|
|
187
145
|
const handle = await input({
|
|
@@ -205,100 +163,13 @@ export async function runSetup() {
|
|
|
205
163
|
handleAttempts++;
|
|
206
164
|
}
|
|
207
165
|
}
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
message: 'What best describes you?',
|
|
211
|
-
choices: [
|
|
212
|
-
{ name: 'Creator / Influencer', value: 'creator' },
|
|
213
|
-
{ name: 'Coach', value: 'coaching' },
|
|
214
|
-
{ name: 'Consultant', value: 'consulting' },
|
|
215
|
-
{ name: 'Therapist / Counselor', value: 'therapy' },
|
|
216
|
-
{ name: 'Tutor / Educator', value: 'education' },
|
|
217
|
-
{ name: 'Other', value: '' },
|
|
218
|
-
],
|
|
219
|
-
});
|
|
220
|
-
// Save profile
|
|
221
|
-
const profileData = {};
|
|
222
|
-
if (expertTitle)
|
|
223
|
-
profileData.expert_title = expertTitle;
|
|
224
|
-
if (about)
|
|
225
|
-
profileData.about = about;
|
|
226
|
-
if (profileHandle)
|
|
227
|
-
profileData.profile_handle = profileHandle;
|
|
228
|
-
if (category)
|
|
229
|
-
profileData.categories = [category];
|
|
230
|
-
if (Object.keys(profileData).length > 0) {
|
|
166
|
+
// Save handle to profile
|
|
167
|
+
if (profileHandle) {
|
|
231
168
|
try {
|
|
232
|
-
await api.updateProfile(
|
|
233
|
-
console.log(` ${chalk.green('✓')} Profile updated\n`);
|
|
169
|
+
await api.updateProfile({ profile_handle: profileHandle });
|
|
234
170
|
}
|
|
235
171
|
catch {
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
// ── First Service ────────────────────────────────────
|
|
240
|
-
console.log(chalk.white.bold(' Create your first offering\n'));
|
|
241
|
-
console.log(` ${chalk.dim('This is what people will book with you.')}\n`);
|
|
242
|
-
const serviceChoice = await select({
|
|
243
|
-
message: 'Pick a starting template:',
|
|
244
|
-
choices: SERVICE_PRESETS,
|
|
245
|
-
});
|
|
246
|
-
if (serviceChoice === 'custom') {
|
|
247
|
-
const title = await input({ message: 'Service title:' });
|
|
248
|
-
const description = await input({ message: 'Short description:' });
|
|
249
|
-
const priceStr = await input({ message: 'Price in dollars (0 for free):' });
|
|
250
|
-
const durationStr = await input({ message: 'Duration in minutes:' });
|
|
251
|
-
const type = await select({
|
|
252
|
-
message: 'Service type:',
|
|
253
|
-
choices: [
|
|
254
|
-
{ name: '1:1 Video Call', value: 'video_call' },
|
|
255
|
-
{ name: 'Group Session', value: 'group_session' },
|
|
256
|
-
{ name: 'Workshop', value: 'workshop' },
|
|
257
|
-
{ name: 'Webinar', value: 'webinar' },
|
|
258
|
-
],
|
|
259
|
-
});
|
|
260
|
-
try {
|
|
261
|
-
await api.createService({
|
|
262
|
-
title,
|
|
263
|
-
description: description || `A ${durationStr}-minute ${type.replace('_', ' ')} session.`,
|
|
264
|
-
price: parseInt(priceStr) || 0,
|
|
265
|
-
duration: parseInt(durationStr) || 30,
|
|
266
|
-
type,
|
|
267
|
-
});
|
|
268
|
-
console.log(` ${chalk.green('✓')} Service "${title}" created\n`);
|
|
269
|
-
}
|
|
270
|
-
catch (err) {
|
|
271
|
-
console.log(` ${chalk.yellow('!')} Could not create service: ${err.message}. You can create one later.\n`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
else if (serviceChoice !== 'skip') {
|
|
275
|
-
try {
|
|
276
|
-
const preset = serviceChoice;
|
|
277
|
-
await api.createService(preset);
|
|
278
|
-
console.log(` ${chalk.green('✓')} Service "${preset.title}" created ($${preset.price}, ${preset.duration} min)\n`);
|
|
279
|
-
}
|
|
280
|
-
catch (err) {
|
|
281
|
-
console.log(` ${chalk.yellow('!')} Could not create service: ${err.message}. You can create one later.\n`);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
// ── Availability ─────────────────────────────────────
|
|
285
|
-
console.log(chalk.white.bold(' Set your availability\n'));
|
|
286
|
-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
287
|
-
console.log(` ${chalk.dim(`Detected timezone: ${timezone}`)}\n`);
|
|
288
|
-
const availPreset = await select({
|
|
289
|
-
message: 'When are you available for sessions?',
|
|
290
|
-
choices: AVAILABILITY_PRESETS,
|
|
291
|
-
});
|
|
292
|
-
if (availPreset !== 'skip') {
|
|
293
|
-
const availability = buildAvailability(availPreset);
|
|
294
|
-
if (availability) {
|
|
295
|
-
try {
|
|
296
|
-
await api.updateCalendar({ timezone, availability });
|
|
297
|
-
console.log(` ${chalk.green('✓')} Availability set\n`);
|
|
298
|
-
}
|
|
299
|
-
catch {
|
|
300
|
-
console.log(` ${chalk.yellow('!')} Could not set availability. You can update it later.\n`);
|
|
301
|
-
}
|
|
172
|
+
// Non-fatal, handle might already be set
|
|
302
173
|
}
|
|
303
174
|
}
|
|
304
175
|
// ── Configure Claude Desktop ─────────────────────────
|
|
@@ -341,18 +212,12 @@ export async function runSetup() {
|
|
|
341
212
|
}
|
|
342
213
|
}
|
|
343
214
|
// ── Success ──────────────────────────────────────────
|
|
344
|
-
console.log(chalk.green.bold('\n You\'re
|
|
215
|
+
console.log(chalk.green.bold('\n You\'re connected!\n'));
|
|
345
216
|
const done = [];
|
|
346
217
|
done.push(`Account: ${userEmail}`);
|
|
347
218
|
done.push(`API key saved`);
|
|
348
|
-
if (expertTitle)
|
|
349
|
-
done.push(`Profile: ${expertTitle}`);
|
|
350
219
|
if (profileHandle)
|
|
351
|
-
done.push(`Handle:
|
|
352
|
-
if (serviceChoice !== 'skip')
|
|
353
|
-
done.push('First service created');
|
|
354
|
-
if (availPreset !== 'skip')
|
|
355
|
-
done.push('Availability configured');
|
|
220
|
+
done.push(`Handle: app.talkspresso.com/${profileHandle}`);
|
|
356
221
|
if (configuredDesktop)
|
|
357
222
|
done.push('Claude Desktop configured');
|
|
358
223
|
if (configuredCode)
|
|
@@ -360,24 +225,19 @@ export async function runSetup() {
|
|
|
360
225
|
for (const item of done) {
|
|
361
226
|
console.log(` ${chalk.green('✓')} ${item}`);
|
|
362
227
|
}
|
|
363
|
-
|
|
364
|
-
console.log(`\n ${chalk.bold('Your booking page:')}`);
|
|
365
|
-
console.log(` ${chalk.cyan.bold(`https://app.talkspresso.com/${profileHandle}`)}`);
|
|
366
|
-
}
|
|
367
|
-
console.log(`\n ${chalk.bold('What to do next:')}\n`);
|
|
228
|
+
console.log(`\n ${chalk.bold('Now the fun part:')}\n`);
|
|
368
229
|
if (configuredDesktop || configuredCode) {
|
|
369
|
-
console.log(` 1. ${chalk.white('Restart Claude')} (
|
|
370
|
-
console.log(` 2. ${chalk.white('
|
|
371
|
-
console.log(
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
230
|
+
console.log(` 1. ${chalk.white('Restart Claude')} (quit and reopen)`);
|
|
231
|
+
console.log(` 2. ${chalk.white('Say:')} ${chalk.cyan('"Help me set up my Talkspresso business"')}`);
|
|
232
|
+
console.log();
|
|
233
|
+
console.log(` ${chalk.dim('Brew, your AI business advisor, will:')}`);
|
|
234
|
+
console.log(` ${chalk.dim(' - Ask about what you do')}`);
|
|
235
|
+
console.log(` ${chalk.dim(' - Suggest sessions and pricing for your niche')}`);
|
|
236
|
+
console.log(` ${chalk.dim(' - Create your services and set up your availability')}`);
|
|
237
|
+
console.log(` ${chalk.dim(' - Get your booking page ready to share')}`);
|
|
378
238
|
}
|
|
379
239
|
else {
|
|
380
|
-
console.log(`
|
|
240
|
+
console.log(` Run ${chalk.cyan('npx @talkspresso/mcp-server --setup')} to connect to Claude.`);
|
|
381
241
|
}
|
|
382
|
-
console.log(`\n ${chalk.dim('
|
|
242
|
+
console.log(`\n ${chalk.dim('Your entire business, built through conversation.')}\n`);
|
|
383
243
|
}
|
package/dist/tools/brew.js
CHANGED
|
@@ -5,11 +5,24 @@ export function registerBrewTools(server, client) {
|
|
|
5
5
|
const data = await client.get('/guide/status');
|
|
6
6
|
return formatMcpResponse(data);
|
|
7
7
|
});
|
|
8
|
-
server.tool('start-brew-conversation',
|
|
8
|
+
server.tool('start-brew-conversation', `Start a new conversation with Brew or resume your existing one. Brew is your AI business mentor on Talkspresso.
|
|
9
|
+
|
|
10
|
+
IMPORTANT FOR NEW USERS: If the user just set up their account or says "help me set up my business", start a Brew conversation first. Brew will detect they are new and guide them through:
|
|
11
|
+
1. Understanding what they do and who they serve
|
|
12
|
+
2. Suggesting personalized session types and pricing for their niche
|
|
13
|
+
3. Creating their first services (use confirm-brew-action to execute proposals)
|
|
14
|
+
4. Setting up availability and profile
|
|
15
|
+
5. Getting their booking page ready to share
|
|
16
|
+
|
|
17
|
+
Brew knows the user's full context (profile, services, bookings, stage) and gives niche-specific advice.`, {}, async () => {
|
|
9
18
|
const data = await client.post('/guide/start');
|
|
10
19
|
return formatMcpResponse(data);
|
|
11
20
|
});
|
|
12
|
-
server.tool('send-brew-message',
|
|
21
|
+
server.tool('send-brew-message', `Send a message to Brew and get AI-powered business advice. Brew can help with pricing, services, profile optimization, and growth strategy.
|
|
22
|
+
|
|
23
|
+
When Brew proposes an action (like creating a service or updating availability), the response will include a write_proposal with actionData and a messageId. To execute the proposed action, call confirm-brew-action with the conversationId, actionType, and messageId.
|
|
24
|
+
|
|
25
|
+
Brew can propose these actions: create_service, update_service, convert_service_type, add_package_session, update_service_capacity, update_availability, update_profile, connect_stripe, create_appointment, cancel_appointment.`, {
|
|
13
26
|
conversationId: z.string().describe('The Brew conversation ID (get from start-brew-conversation)'),
|
|
14
27
|
message: z.string().describe('Your message to Brew'),
|
|
15
28
|
}, async (params) => {
|
|
@@ -18,6 +31,21 @@ export function registerBrewTools(server, client) {
|
|
|
18
31
|
});
|
|
19
32
|
return formatMcpResponse(data);
|
|
20
33
|
});
|
|
34
|
+
server.tool('confirm-brew-action', `Execute a proposed action from Brew. When Brew suggests creating a service, updating availability, or making other changes, it returns a write_proposal with a messageId. Call this tool to confirm and execute that action.
|
|
35
|
+
|
|
36
|
+
Supported action types: create_service, update_service, convert_service_type, add_package_session, update_service_capacity, update_availability, update_profile, connect_stripe, create_appointment, cancel_appointment.
|
|
37
|
+
|
|
38
|
+
Always confirm with the user before executing Brew's proposals.`, {
|
|
39
|
+
conversationId: z.string().describe('The Brew conversation ID'),
|
|
40
|
+
actionType: z.string().describe('The action type from the write_proposal (e.g., "create_service", "update_availability")'),
|
|
41
|
+
messageId: z.string().describe('The message ID from the write_proposal response'),
|
|
42
|
+
}, async (params) => {
|
|
43
|
+
const data = await client.post(`/guide/${params.conversationId}/confirm-action`, {
|
|
44
|
+
actionType: params.actionType,
|
|
45
|
+
messageId: params.messageId,
|
|
46
|
+
});
|
|
47
|
+
return formatMcpResponse(data);
|
|
48
|
+
});
|
|
21
49
|
server.tool('get-brew-conversation-history', 'Get the message history for a Brew conversation.', {
|
|
22
50
|
conversationId: z.string().describe('The Brew conversation ID'),
|
|
23
51
|
}, async (params) => {
|
package/package.json
CHANGED