@talkspresso/mcp-server 1.3.2 → 1.4.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/README.md +142 -55
- package/dist/index.js +2 -2
- package/dist/setup-api.d.ts +19 -0
- package/dist/setup-api.js +27 -0
- package/dist/setup.js +147 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @talkspresso/mcp-server
|
|
2
2
|
|
|
3
|
-
Manage your Talkspresso business through Claude
|
|
3
|
+
Manage your Talkspresso business through Claude Code or any MCP-compatible AI assistant.
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
@@ -10,50 +10,50 @@ Perfect for creators, coaches, and consultants who want to manage their Talkspre
|
|
|
10
10
|
|
|
11
11
|
## Quick setup
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Go to [app.talkspresso.com/settings/api-keys](https://app.talkspresso.com/settings/api-keys) and generate a new API key.
|
|
16
|
-
|
|
17
|
-
### 2. Install the package
|
|
13
|
+
The fastest way to get started is the interactive setup wizard:
|
|
18
14
|
|
|
19
15
|
```bash
|
|
20
|
-
|
|
16
|
+
npx @talkspresso/mcp-server --setup
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
This will:
|
|
20
|
+
1. Create your account (or log in)
|
|
21
|
+
2. Generate an API key
|
|
22
|
+
3. Set up your profile
|
|
23
|
+
4. Create your first service
|
|
24
|
+
5. Configure your availability
|
|
25
|
+
6. Connect to Claude Desktop and/or Claude Code
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
npx @talkspresso/mcp-server
|
|
27
|
-
```
|
|
27
|
+
No need to visit talkspresso.com. Everything happens in your terminal.
|
|
28
28
|
|
|
29
|
-
###
|
|
29
|
+
### Manual setup
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
If you prefer to configure manually:
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
#### 1. Get your API key
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
Go to [app.talkspresso.com/settings/api-keys](https://app.talkspresso.com/settings/api-keys) and generate a new API key.
|
|
36
|
+
|
|
37
|
+
#### 2. Configure your AI assistant
|
|
38
|
+
|
|
39
|
+
**For Claude Code** - Add to `~/.claude/mcp.json`:
|
|
37
40
|
|
|
38
41
|
```json
|
|
39
42
|
{
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"TALKSPRESSO_API_KEY": "tsp_your_key_here"
|
|
46
|
-
}
|
|
43
|
+
"talkspresso": {
|
|
44
|
+
"command": "npx",
|
|
45
|
+
"args": ["-y", "@talkspresso/mcp-server"],
|
|
46
|
+
"env": {
|
|
47
|
+
"TALKSPRESSO_API_KEY": "tsp_your_key_here"
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#### For Claude Code
|
|
53
|
+
**For Claude Desktop** - Add to your config file:
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
56
|
+
Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
57
57
|
|
|
58
58
|
```json
|
|
59
59
|
{
|
|
@@ -69,61 +69,148 @@ Add this to your Claude Code settings (`.claude/settings.json` in your project):
|
|
|
69
69
|
}
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
Then restart Claude.
|
|
73
|
+
|
|
72
74
|
## Available tools
|
|
73
75
|
|
|
74
|
-
### Appointments
|
|
75
|
-
- **list-appointments** - View
|
|
76
|
+
### Appointments & Scheduling
|
|
77
|
+
- **list-appointments** - View upcoming or completed appointments
|
|
76
78
|
- **get-appointment** - Get details about a specific appointment
|
|
77
|
-
- **get-pending-bookings** - See
|
|
79
|
+
- **get-pending-bookings** - See bookings waiting for approval
|
|
78
80
|
- **approve-appointment** - Approve a pending booking
|
|
79
81
|
- **decline-appointment** - Decline a booking with optional reason
|
|
82
|
+
- **create-appointment** - Create and send a session invite
|
|
83
|
+
- **send-appointment-invite** - Send invite for a created appointment
|
|
84
|
+
- **cancel-appointment** - Cancel an appointment
|
|
85
|
+
- **reschedule-appointment** - Reschedule to a new date/time
|
|
86
|
+
- **check-availability** - Check open time slots for a date
|
|
87
|
+
- **get-schedule** - Quick view of your next 50 appointments
|
|
80
88
|
|
|
81
89
|
### Clients
|
|
82
|
-
- **list-clients** - View all
|
|
83
|
-
- **get-client** -
|
|
90
|
+
- **list-clients** - View all clients with search
|
|
91
|
+
- **get-client** - Client details and booking history
|
|
92
|
+
- **get-session-history** - Rich session history with summaries
|
|
93
|
+
- **get-client-activity** - Emails, testimonials, engagement stats
|
|
84
94
|
|
|
85
95
|
### Services
|
|
86
|
-
- **list-services** - View all
|
|
87
|
-
- **create-service** - Create a new service
|
|
88
|
-
- **
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- **
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- **
|
|
96
|
-
- **
|
|
96
|
+
- **list-services** - View all service offerings
|
|
97
|
+
- **create-service** - Create a new service
|
|
98
|
+
- **get-service** - Service details
|
|
99
|
+
- **update-service** - Update pricing, description, status
|
|
100
|
+
- **delete-service** - Remove a service
|
|
101
|
+
- **duplicate-service** - Copy an existing service
|
|
102
|
+
- **get-service-bookings** - See who booked a service
|
|
103
|
+
|
|
104
|
+
### Profile & Calendar
|
|
105
|
+
- **get-profile** - View your profile
|
|
106
|
+
- **update-profile** - Update title, bio, categories
|
|
107
|
+
- **get-calendar** - View availability settings
|
|
108
|
+
- **update-calendar** - Update timezone, hours, buffer time
|
|
109
|
+
- **get-booking-link** - Get a shareable booking link
|
|
110
|
+
|
|
111
|
+
### Earnings & Payments
|
|
112
|
+
- **get-earnings** - Transaction history
|
|
113
|
+
- **get-revenue-summary** - Monthly revenue snapshot
|
|
114
|
+
- **get-my-subscription** - Subscription plan details
|
|
115
|
+
- **get-payment-methods** - Saved payment methods
|
|
116
|
+
- **get-stripe-account-link** - Connect/manage Stripe
|
|
117
|
+
- **create-billing-portal-session** - Manage billing
|
|
118
|
+
|
|
119
|
+
### Recordings
|
|
120
|
+
- **list-recordings** - Browse past session recordings
|
|
121
|
+
- **get-recording** - Recording details with transcript
|
|
122
|
+
- **update-recording** - Update title, visibility
|
|
123
|
+
- **delete-recording** - Remove a recording
|
|
124
|
+
- **get-client-recordings** - Recordings with a specific client
|
|
125
|
+
- **get-recording-files** - Download individual recording files
|
|
126
|
+
- **create-product-from-recording** - Turn a recording into a product
|
|
127
|
+
|
|
128
|
+
### Products
|
|
129
|
+
- **list-products** - View digital products
|
|
130
|
+
- **create-product** - Create a new product
|
|
131
|
+
- **get-product** - Product details
|
|
132
|
+
- **update-product** - Update product info
|
|
133
|
+
- **delete-product** - Remove a product
|
|
134
|
+
- **get-product-analytics** - Product performance stats
|
|
135
|
+
- **list-product-purchases** - See all purchases
|
|
136
|
+
- **generate-product-details** - AI-generate product listing
|
|
137
|
+
|
|
138
|
+
### Testimonials
|
|
139
|
+
- **list-testimonials** - View client testimonials
|
|
140
|
+
- **create-testimonial** - Add a testimonial manually
|
|
141
|
+
- **request-testimonial** - Email a client for a testimonial
|
|
142
|
+
- **approve-testimonial** / **reject-testimonial** - Moderate testimonials
|
|
143
|
+
- **toggle-featured-testimonial** - Feature/unfeature
|
|
144
|
+
|
|
145
|
+
### Promo Codes
|
|
146
|
+
- **list-promo-codes** - View all promo codes
|
|
147
|
+
- **create-promo-code** - Create a discount code
|
|
148
|
+
- **update-promo-code** / **delete-promo-code** - Manage codes
|
|
149
|
+
- **toggle-promo-code-active** - Enable/disable
|
|
150
|
+
- **get-promo-code-analytics** - Promo performance
|
|
151
|
+
|
|
152
|
+
### Messaging
|
|
153
|
+
- **list-conversations** - View all client conversations
|
|
154
|
+
- **get-conversation-messages** - Read messages
|
|
155
|
+
- **send-message** - Reply to a client
|
|
156
|
+
- **get-unread-message-count** - Check unread count
|
|
157
|
+
|
|
158
|
+
### Notifications
|
|
159
|
+
- **list-notifications** - View all notifications
|
|
160
|
+
- **mark-notification-read** / **mark-all-notifications-read**
|
|
161
|
+
|
|
162
|
+
### Live Sessions
|
|
163
|
+
- **start-live-session** - Go live with a shareable link
|
|
164
|
+
- **get-active-live-session** - Check if you're live
|
|
165
|
+
- **end-live-session** - End your live session
|
|
166
|
+
- **get-live-session-history** - Past live sessions
|
|
167
|
+
- **send-live-session-invite** - Invite someone to your live
|
|
168
|
+
|
|
169
|
+
### Organizations
|
|
170
|
+
- **list-my-organizations** - Your org memberships
|
|
171
|
+
- **get-organization** / **get-organization-members** / **get-organization-stats**
|
|
172
|
+
- **update-organization** - Update org settings
|
|
173
|
+
- **add-organization-member** / **send-organization-invitation**
|
|
174
|
+
|
|
175
|
+
### Brew AI Mentor
|
|
176
|
+
- **get-brew-status** - Check Brew status
|
|
177
|
+
- **start-brew-conversation** - Start chatting with Brew
|
|
178
|
+
- **send-brew-message** - Get business advice
|
|
179
|
+
- **get-brew-insights** - Proactive coaching
|
|
180
|
+
- **set-brew-goal** - Set a business goal
|
|
97
181
|
|
|
98
182
|
## Environment variables
|
|
99
183
|
|
|
100
184
|
| Variable | Required | Default | Description |
|
|
101
185
|
|----------|----------|---------|-------------|
|
|
102
|
-
| `TALKSPRESSO_API_KEY` | Yes | - | Your API key
|
|
103
|
-
| `TALKSPRESSO_API_URL` | No | `https://api.talkspresso.com` | API base URL
|
|
186
|
+
| `TALKSPRESSO_API_KEY` | Yes | - | Your API key |
|
|
187
|
+
| `TALKSPRESSO_API_URL` | No | `https://api.talkspresso.com` | API base URL |
|
|
104
188
|
|
|
105
189
|
## Example conversations
|
|
106
190
|
|
|
107
|
-
"Show me my appointments for today"
|
|
108
|
-
"Who are my top clients?"
|
|
109
|
-
"Create a new 30-minute coaching call for $100"
|
|
110
|
-
"What are my total earnings this month?"
|
|
111
|
-
"Approve all pending bookings"
|
|
191
|
+
- "Show me my appointments for today"
|
|
192
|
+
- "Who are my top clients?"
|
|
193
|
+
- "Create a new 30-minute coaching call for $100"
|
|
194
|
+
- "What are my total earnings this month?"
|
|
195
|
+
- "Approve all pending bookings"
|
|
196
|
+
- "Connect my Stripe account"
|
|
197
|
+
- "Get my booking link so I can share it"
|
|
198
|
+
- "Set my availability to weekdays 9-5"
|
|
112
199
|
|
|
113
200
|
## Troubleshooting
|
|
114
201
|
|
|
115
202
|
**"TALKSPRESSO_API_KEY environment variable is required"**
|
|
116
|
-
|
|
203
|
+
Run `npx @talkspresso/mcp-server --setup` to set up your API key, or add it manually to your config.
|
|
117
204
|
|
|
118
205
|
**"API request failed"**
|
|
119
|
-
Check that your API key is valid
|
|
206
|
+
Check that your API key is valid. You can generate a new one at [app.talkspresso.com/settings/api-keys](https://app.talkspresso.com/settings/api-keys).
|
|
120
207
|
|
|
121
|
-
**Tools not showing up
|
|
122
|
-
Restart Claude
|
|
208
|
+
**Tools not showing up**
|
|
209
|
+
Restart Claude after adding the config. Make sure the JSON is valid (no trailing commas).
|
|
123
210
|
|
|
124
211
|
## Support
|
|
125
212
|
|
|
126
|
-
Questions? Email [support@talkspresso.com](mailto:support@talkspresso.com)
|
|
213
|
+
Questions? Email [support@talkspresso.com](mailto:support@talkspresso.com)
|
|
127
214
|
|
|
128
215
|
## License
|
|
129
216
|
|
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.4.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.4.0',
|
|
46
46
|
});
|
|
47
47
|
const apiClient = new TalkspressoClient();
|
|
48
48
|
registerAppointmentTools(server, apiClient);
|
package/dist/setup-api.d.ts
CHANGED
|
@@ -13,6 +13,25 @@ export declare class SetupApiClient {
|
|
|
13
13
|
password: string;
|
|
14
14
|
}): Promise<any>;
|
|
15
15
|
createApiKey(name: string): Promise<any>;
|
|
16
|
+
updateProfile(data: {
|
|
17
|
+
expert_title?: string;
|
|
18
|
+
about?: string;
|
|
19
|
+
bio?: string;
|
|
20
|
+
categories?: string[];
|
|
21
|
+
}): Promise<any>;
|
|
22
|
+
createService(data: {
|
|
23
|
+
title: string;
|
|
24
|
+
description: string;
|
|
25
|
+
price: number;
|
|
26
|
+
duration: number;
|
|
27
|
+
type: string;
|
|
28
|
+
}): Promise<any>;
|
|
29
|
+
updateCalendar(data: {
|
|
30
|
+
timezone?: string;
|
|
31
|
+
availability?: Record<string, any>;
|
|
32
|
+
booking_interval_days?: number;
|
|
33
|
+
buffer_minutes?: number;
|
|
34
|
+
}): Promise<any>;
|
|
16
35
|
getStatus(err: unknown): number | undefined;
|
|
17
36
|
private formatError;
|
|
18
37
|
}
|
package/dist/setup-api.js
CHANGED
|
@@ -39,6 +39,33 @@ export class SetupApiClient {
|
|
|
39
39
|
throw this.formatError(err);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
async updateProfile(data) {
|
|
43
|
+
try {
|
|
44
|
+
const response = await this.http.put('/profile', data);
|
|
45
|
+
return response.data?.data;
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
throw this.formatError(err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async createService(data) {
|
|
52
|
+
try {
|
|
53
|
+
const response = await this.http.post('/service', data);
|
|
54
|
+
return response.data?.data;
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
throw this.formatError(err);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async updateCalendar(data) {
|
|
61
|
+
try {
|
|
62
|
+
const response = await this.http.put('/calendar', data);
|
|
63
|
+
return response.data?.data;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
throw this.formatError(err);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
42
69
|
getStatus(err) {
|
|
43
70
|
if (err instanceof Error && 'status' in err)
|
|
44
71
|
return err.status;
|
package/dist/setup.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { confirm, input, password as passwordPrompt } from '@inquirer/prompts';
|
|
2
|
+
import { confirm, input, password as passwordPrompt, select } from '@inquirer/prompts';
|
|
3
3
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
@@ -20,7 +20,7 @@ function getClaudeDesktopConfigPath() {
|
|
|
20
20
|
return join(home, '.config', 'Claude', 'claude_desktop_config.json');
|
|
21
21
|
}
|
|
22
22
|
function getClaudeCodeConfigPath() {
|
|
23
|
-
return join(homedir(), '.claude', '
|
|
23
|
+
return join(homedir(), '.claude', 'mcp.json');
|
|
24
24
|
}
|
|
25
25
|
function readJsonSafe(path) {
|
|
26
26
|
try {
|
|
@@ -49,23 +49,56 @@ 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
|
+
}
|
|
52
86
|
export async function runSetup() {
|
|
53
87
|
process.on('SIGINT', () => {
|
|
54
88
|
console.log(`\n\n ${chalk.dim('Setup cancelled. Run')} npx @talkspresso/mcp-server --setup ${chalk.dim('anytime.')}\n`);
|
|
55
89
|
process.exit(0);
|
|
56
90
|
});
|
|
57
91
|
const api = new SetupApiClient();
|
|
58
|
-
// Welcome
|
|
92
|
+
// ── Welcome ──────────────────────────────────────────
|
|
59
93
|
console.log(LOGO);
|
|
60
94
|
console.log(` ${chalk.white.bold('Manage your business with AI.')}`);
|
|
61
|
-
console.log(` ${chalk.dim("Let's get you
|
|
62
|
-
// Account
|
|
95
|
+
console.log(` ${chalk.dim("Let's get you set up in a few minutes.")}\n`);
|
|
96
|
+
// ── Account ──────────────────────────────────────────
|
|
63
97
|
let accessToken;
|
|
64
98
|
let userName;
|
|
65
99
|
let userEmail;
|
|
66
100
|
const hasAccount = await confirm({ message: 'Do you already have a Talkspresso account?' });
|
|
67
101
|
if (hasAccount) {
|
|
68
|
-
// Login flow
|
|
69
102
|
let attempts = 0;
|
|
70
103
|
while (true) {
|
|
71
104
|
const email = await input({ message: 'Email:' });
|
|
@@ -81,7 +114,7 @@ export async function runSetup() {
|
|
|
81
114
|
catch (err) {
|
|
82
115
|
attempts++;
|
|
83
116
|
if (attempts >= 3) {
|
|
84
|
-
console.log(`\n ${chalk.red('Too many failed attempts.')}
|
|
117
|
+
console.log(`\n ${chalk.red('Too many failed attempts.')} Reset your password at ${chalk.cyan('app.talkspresso.com')}\n`);
|
|
85
118
|
process.exit(1);
|
|
86
119
|
}
|
|
87
120
|
console.log(` ${chalk.red('✗')} Invalid email or password. Try again.\n`);
|
|
@@ -89,10 +122,9 @@ export async function runSetup() {
|
|
|
89
122
|
}
|
|
90
123
|
}
|
|
91
124
|
else {
|
|
92
|
-
|
|
93
|
-
const name = await input({ message: 'Your name:' });
|
|
125
|
+
const name = await input({ message: 'Your full name:' });
|
|
94
126
|
const email = await input({ message: 'Email:' });
|
|
95
|
-
const pw = await passwordPrompt({ message: '
|
|
127
|
+
const pw = await passwordPrompt({ message: 'Create a password (min 8 characters):' });
|
|
96
128
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
97
129
|
try {
|
|
98
130
|
const user = await api.register({ name, email, password: pw, timezone });
|
|
@@ -125,20 +157,105 @@ export async function runSetup() {
|
|
|
125
157
|
}
|
|
126
158
|
}
|
|
127
159
|
}
|
|
128
|
-
//
|
|
160
|
+
// ── API Key ──────────────────────────────────────────
|
|
129
161
|
api.setAccessToken(accessToken);
|
|
130
162
|
let apiKey;
|
|
131
163
|
try {
|
|
132
164
|
const keyData = await api.createApiKey('Claude AI Assistant');
|
|
133
165
|
apiKey = keyData.key;
|
|
134
|
-
console.log(` ${chalk.green('✓')} API key created
|
|
166
|
+
console.log(` ${chalk.green('✓')} API key created\n`);
|
|
135
167
|
}
|
|
136
168
|
catch (err) {
|
|
137
169
|
console.log(` ${chalk.red('Could not create API key:')} ${err.message}`);
|
|
138
170
|
console.log(` ${chalk.dim('Create one manually at')} ${chalk.cyan('app.talkspresso.com/settings/api-keys')}\n`);
|
|
139
171
|
process.exit(1);
|
|
140
172
|
}
|
|
141
|
-
//
|
|
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
|
+
if (expertTitle || about) {
|
|
182
|
+
try {
|
|
183
|
+
await api.updateProfile({
|
|
184
|
+
expert_title: expertTitle || undefined,
|
|
185
|
+
about: about || undefined,
|
|
186
|
+
});
|
|
187
|
+
console.log(` ${chalk.green('✓')} Profile updated\n`);
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
console.log(` ${chalk.yellow('!')} Could not update profile. You can update it later.\n`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// ── First Service ────────────────────────────────────
|
|
194
|
+
console.log(chalk.white.bold(' Create your first offering\n'));
|
|
195
|
+
console.log(` ${chalk.dim('This is what people will book with you.')}\n`);
|
|
196
|
+
const serviceChoice = await select({
|
|
197
|
+
message: 'Pick a starting template:',
|
|
198
|
+
choices: SERVICE_PRESETS,
|
|
199
|
+
});
|
|
200
|
+
if (serviceChoice === 'custom') {
|
|
201
|
+
const title = await input({ message: 'Service title:' });
|
|
202
|
+
const description = await input({ message: 'Short description:' });
|
|
203
|
+
const priceStr = await input({ message: 'Price in dollars (0 for free):' });
|
|
204
|
+
const durationStr = await input({ message: 'Duration in minutes:' });
|
|
205
|
+
const type = await select({
|
|
206
|
+
message: 'Service type:',
|
|
207
|
+
choices: [
|
|
208
|
+
{ name: '1:1 Video Call', value: 'video_call' },
|
|
209
|
+
{ name: 'Group Session', value: 'group_session' },
|
|
210
|
+
{ name: 'Workshop', value: 'workshop' },
|
|
211
|
+
{ name: 'Webinar', value: 'webinar' },
|
|
212
|
+
],
|
|
213
|
+
});
|
|
214
|
+
try {
|
|
215
|
+
await api.createService({
|
|
216
|
+
title,
|
|
217
|
+
description: description || `A ${durationStr}-minute ${type.replace('_', ' ')} session.`,
|
|
218
|
+
price: parseInt(priceStr) || 0,
|
|
219
|
+
duration: parseInt(durationStr) || 30,
|
|
220
|
+
type,
|
|
221
|
+
});
|
|
222
|
+
console.log(` ${chalk.green('✓')} Service "${title}" created\n`);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
console.log(` ${chalk.yellow('!')} Could not create service: ${err.message}. You can create one later.\n`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (serviceChoice !== 'skip') {
|
|
229
|
+
try {
|
|
230
|
+
const preset = serviceChoice;
|
|
231
|
+
await api.createService(preset);
|
|
232
|
+
console.log(` ${chalk.green('✓')} Service "${preset.title}" created ($${preset.price}, ${preset.duration} min)\n`);
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
console.log(` ${chalk.yellow('!')} Could not create service: ${err.message}. You can create one later.\n`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// ── Availability ─────────────────────────────────────
|
|
239
|
+
console.log(chalk.white.bold(' Set your availability\n'));
|
|
240
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
241
|
+
console.log(` ${chalk.dim(`Detected timezone: ${timezone}`)}\n`);
|
|
242
|
+
const availPreset = await select({
|
|
243
|
+
message: 'When are you available for sessions?',
|
|
244
|
+
choices: AVAILABILITY_PRESETS,
|
|
245
|
+
});
|
|
246
|
+
if (availPreset !== 'skip') {
|
|
247
|
+
const availability = buildAvailability(availPreset);
|
|
248
|
+
if (availability) {
|
|
249
|
+
try {
|
|
250
|
+
await api.updateCalendar({ timezone, availability });
|
|
251
|
+
console.log(` ${chalk.green('✓')} Availability set\n`);
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
console.log(` ${chalk.yellow('!')} Could not set availability. You can update it later.\n`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// ── Configure Claude Desktop ─────────────────────────
|
|
142
259
|
const desktopPath = getClaudeDesktopConfigPath();
|
|
143
260
|
const desktopDir = join(desktopPath, '..');
|
|
144
261
|
let configuredDesktop = false;
|
|
@@ -160,7 +277,7 @@ export async function runSetup() {
|
|
|
160
277
|
}
|
|
161
278
|
}
|
|
162
279
|
}
|
|
163
|
-
// Configure Claude Code
|
|
280
|
+
// ── Configure Claude Code ────────────────────────────
|
|
164
281
|
const codePath = getClaudeCodeConfigPath();
|
|
165
282
|
let configuredCode = false;
|
|
166
283
|
const addCode = await confirm({ message: 'Add Talkspresso to Claude Code?' });
|
|
@@ -177,11 +294,17 @@ export async function runSetup() {
|
|
|
177
294
|
console.log();
|
|
178
295
|
}
|
|
179
296
|
}
|
|
180
|
-
// Success
|
|
297
|
+
// ── Success ──────────────────────────────────────────
|
|
181
298
|
console.log(chalk.green.bold('\n You\'re all set!\n'));
|
|
182
299
|
const done = [];
|
|
183
300
|
done.push(`Account: ${userEmail}`);
|
|
184
|
-
done.push(`API key
|
|
301
|
+
done.push(`API key saved`);
|
|
302
|
+
if (expertTitle)
|
|
303
|
+
done.push(`Profile: ${expertTitle}`);
|
|
304
|
+
if (serviceChoice !== 'skip')
|
|
305
|
+
done.push('First service created');
|
|
306
|
+
if (availPreset !== 'skip')
|
|
307
|
+
done.push('Availability configured');
|
|
185
308
|
if (configuredDesktop)
|
|
186
309
|
done.push('Claude Desktop configured');
|
|
187
310
|
if (configuredCode)
|
|
@@ -189,11 +312,15 @@ export async function runSetup() {
|
|
|
189
312
|
for (const item of done) {
|
|
190
313
|
console.log(` ${chalk.green('✓')} ${item}`);
|
|
191
314
|
}
|
|
192
|
-
console.log(`\n ${chalk.bold('
|
|
315
|
+
console.log(`\n ${chalk.bold('What to do next:')}\n`);
|
|
193
316
|
if (configuredDesktop || configuredCode) {
|
|
194
|
-
console.log(` 1. ${chalk.white('Restart Claude')} (if it
|
|
317
|
+
console.log(` 1. ${chalk.white('Restart Claude')} (if it's open)`);
|
|
195
318
|
console.log(` 2. ${chalk.white('Try:')} "Show me my Talkspresso schedule"`);
|
|
319
|
+
console.log(` 3. ${chalk.white('Try:')} "Connect my Stripe account so I can get paid"`);
|
|
320
|
+
console.log(` 4. ${chalk.white('Try:')} "Get my booking link so I can share it"`);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
console.log(` 1. ${chalk.white('Run')} ${chalk.cyan('npx @talkspresso/mcp-server --setup')} ${chalk.white('to connect to Claude')}`);
|
|
196
324
|
}
|
|
197
|
-
console.log(
|
|
198
|
-
console.log(` ${chalk.dim('Brew will help you set up your first session.')}\n`);
|
|
325
|
+
console.log(`\n ${chalk.dim('Need help? Ask Claude: "What can I do with Talkspresso?"')}\n`);
|
|
199
326
|
}
|
package/package.json
CHANGED