@channlize/mcp 0.1.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 +394 -0
- package/dist/index.d.mts +118 -0
- package/dist/index.d.ts +118 -0
- package/dist/index.js +1764 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1739 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server.js +1850 -0
- package/dist/server.js.map +1 -0
- package/package.json +60 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,1850 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
7
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
8
|
+
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
9
|
+
|
|
10
|
+
// src/resources/index.ts
|
|
11
|
+
var CONTACT_FORM_SCHEMA = `{
|
|
12
|
+
"name": "ContactFormData",
|
|
13
|
+
"description": "Data structure for submitting a contact form inquiry",
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"name": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Contact's full name",
|
|
19
|
+
"required": true
|
|
20
|
+
},
|
|
21
|
+
"email": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"format": "email",
|
|
24
|
+
"description": "Contact's email address",
|
|
25
|
+
"required": true
|
|
26
|
+
},
|
|
27
|
+
"subject": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Subject line for the inquiry"
|
|
30
|
+
},
|
|
31
|
+
"message": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Message content",
|
|
34
|
+
"required": true
|
|
35
|
+
},
|
|
36
|
+
"customFields": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"description": "Additional custom fields as key-value pairs",
|
|
39
|
+
"additionalProperties": true
|
|
40
|
+
},
|
|
41
|
+
"pageUrl": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"description": "URL of the page where form was submitted"
|
|
44
|
+
},
|
|
45
|
+
"userAgent": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"description": "User agent string of the submitter"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}`;
|
|
51
|
+
var CHAT_SESSION_SCHEMA = `{
|
|
52
|
+
"name": "ChatSession",
|
|
53
|
+
"description": "Real-time chat session structure",
|
|
54
|
+
"type": "object",
|
|
55
|
+
"properties": {
|
|
56
|
+
"id": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"description": "Unique session identifier"
|
|
59
|
+
},
|
|
60
|
+
"status": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"enum": ["active", "closed", "waiting"],
|
|
63
|
+
"description": "Current session status"
|
|
64
|
+
},
|
|
65
|
+
"messages": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"$ref": "#/definitions/ChatMessage"
|
|
69
|
+
},
|
|
70
|
+
"description": "Array of messages in this session"
|
|
71
|
+
},
|
|
72
|
+
"metadata": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"description": "Custom metadata for the session"
|
|
75
|
+
},
|
|
76
|
+
"createdAt": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"format": "date-time",
|
|
79
|
+
"description": "Session creation timestamp"
|
|
80
|
+
},
|
|
81
|
+
"updatedAt": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"format": "date-time",
|
|
84
|
+
"description": "Last update timestamp"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"definitions": {
|
|
88
|
+
"ChatMessage": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"properties": {
|
|
91
|
+
"id": { "type": "string" },
|
|
92
|
+
"content": { "type": "string" },
|
|
93
|
+
"timestamp": { "type": "string", "format": "date-time" },
|
|
94
|
+
"author": { "type": "string", "enum": ["user", "agent"] },
|
|
95
|
+
"authorData": {
|
|
96
|
+
"type": "object",
|
|
97
|
+
"properties": {
|
|
98
|
+
"name": { "type": "string" },
|
|
99
|
+
"email": { "type": "string" },
|
|
100
|
+
"avatarUrl": { "type": "string" }
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"attachments": {
|
|
104
|
+
"type": "array",
|
|
105
|
+
"items": { "$ref": "#/definitions/FileAttachment" }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"FileAttachment": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"properties": {
|
|
112
|
+
"id": { "type": "string" },
|
|
113
|
+
"name": { "type": "string" },
|
|
114
|
+
"size": { "type": "number" },
|
|
115
|
+
"type": { "type": "string" },
|
|
116
|
+
"url": { "type": "string" }
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}`;
|
|
121
|
+
var API_REFERENCE = `# Channlize API Reference
|
|
122
|
+
|
|
123
|
+
## Overview
|
|
124
|
+
Channlize is a developer-first support platform that routes customer conversations directly into Slack.
|
|
125
|
+
|
|
126
|
+
Base URL: \`http://api.channlize.com\` (default) or your configured API endpoint
|
|
127
|
+
|
|
128
|
+
## Authentication
|
|
129
|
+
All API requests require a Widget Key (API key) in the request body or as a header.
|
|
130
|
+
|
|
131
|
+
## Endpoints
|
|
132
|
+
|
|
133
|
+
### Contact Forms
|
|
134
|
+
|
|
135
|
+
**POST /public/contact**
|
|
136
|
+
Submit a contact form inquiry.
|
|
137
|
+
|
|
138
|
+
Request Body:
|
|
139
|
+
\`\`\`json
|
|
140
|
+
{
|
|
141
|
+
"widgetKey": "your-widget-key",
|
|
142
|
+
"name": "John Doe",
|
|
143
|
+
"email": "john@example.com",
|
|
144
|
+
"subject": "Support Request",
|
|
145
|
+
"message": "I need help with...",
|
|
146
|
+
"pageUrl": "https://example.com/contact",
|
|
147
|
+
"userAgent": "Mozilla/5.0..."
|
|
148
|
+
}
|
|
149
|
+
\`\`\`
|
|
150
|
+
|
|
151
|
+
Response:
|
|
152
|
+
\`\`\`json
|
|
153
|
+
{
|
|
154
|
+
"data": {
|
|
155
|
+
"id": "contact_123",
|
|
156
|
+
"status": "received",
|
|
157
|
+
"slackThreadUrl": "https://slack.com/..."
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
\`\`\`
|
|
161
|
+
|
|
162
|
+
### Chat Sessions
|
|
163
|
+
|
|
164
|
+
**POST /v1/chat/sessions**
|
|
165
|
+
Create a new chat session.
|
|
166
|
+
|
|
167
|
+
Request Body:
|
|
168
|
+
\`\`\`json
|
|
169
|
+
{
|
|
170
|
+
"metadata": {
|
|
171
|
+
"pageUrl": "https://example.com",
|
|
172
|
+
"userAgent": "Mozilla/5.0...",
|
|
173
|
+
"customField": "value"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
\`\`\`
|
|
177
|
+
|
|
178
|
+
Response:
|
|
179
|
+
\`\`\`json
|
|
180
|
+
{
|
|
181
|
+
"data": {
|
|
182
|
+
"session": {
|
|
183
|
+
"id": "session_123",
|
|
184
|
+
"status": "active",
|
|
185
|
+
"messages": [],
|
|
186
|
+
"createdAt": "2025-01-15T10:00:00Z"
|
|
187
|
+
},
|
|
188
|
+
"sseEndpoint": "/v1/chat/sessions/session_123/events"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
\`\`\`
|
|
192
|
+
|
|
193
|
+
**POST /v1/chat/sessions/:sessionId/messages**
|
|
194
|
+
Send a message in a chat session.
|
|
195
|
+
|
|
196
|
+
Request: FormData with 'content' field and optional file attachments
|
|
197
|
+
|
|
198
|
+
**GET /v1/chat/sessions/:sessionId/messages**
|
|
199
|
+
Get messages for a session. Query params: limit, offset
|
|
200
|
+
|
|
201
|
+
**POST /v1/chat/sessions/:sessionId/close**
|
|
202
|
+
Close a chat session.
|
|
203
|
+
|
|
204
|
+
## Error Responses
|
|
205
|
+
|
|
206
|
+
Status codes:
|
|
207
|
+
- 400: Validation error
|
|
208
|
+
- 401: Authentication failed
|
|
209
|
+
- 429: Rate limit exceeded
|
|
210
|
+
- 500: Server error
|
|
211
|
+
|
|
212
|
+
Error format:
|
|
213
|
+
\`\`\`json
|
|
214
|
+
{
|
|
215
|
+
"error": "Error message",
|
|
216
|
+
"code": "ERROR_CODE",
|
|
217
|
+
"field": "fieldName" // for validation errors
|
|
218
|
+
}
|
|
219
|
+
\`\`\`
|
|
220
|
+
`;
|
|
221
|
+
var QUICK_START = `# Channlize Quick Start
|
|
222
|
+
|
|
223
|
+
## Installation
|
|
224
|
+
|
|
225
|
+
\`\`\`bash
|
|
226
|
+
# For React applications
|
|
227
|
+
npm install @channlize/react
|
|
228
|
+
|
|
229
|
+
# For non-React applications
|
|
230
|
+
npm install @channlize/core
|
|
231
|
+
\`\`\`
|
|
232
|
+
|
|
233
|
+
## React Setup
|
|
234
|
+
|
|
235
|
+
1. Wrap your app with ChannlizeProvider:
|
|
236
|
+
|
|
237
|
+
\`\`\`tsx
|
|
238
|
+
import { ChannlizeProvider } from '@channlize/react';
|
|
239
|
+
|
|
240
|
+
function App() {
|
|
241
|
+
return (
|
|
242
|
+
<ChannlizeProvider
|
|
243
|
+
config={{
|
|
244
|
+
apiKey: 'your-widget-key',
|
|
245
|
+
projectId: 'your-project-id',
|
|
246
|
+
}}
|
|
247
|
+
>
|
|
248
|
+
<YourApp />
|
|
249
|
+
</ChannlizeProvider>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
\`\`\`
|
|
253
|
+
|
|
254
|
+
2. Use the Form component:
|
|
255
|
+
|
|
256
|
+
\`\`\`tsx
|
|
257
|
+
import { Form } from '@channlize/react';
|
|
258
|
+
|
|
259
|
+
function ContactPage() {
|
|
260
|
+
return (
|
|
261
|
+
<Form
|
|
262
|
+
onSuccess={() => console.log('Form submitted!')}
|
|
263
|
+
submitText="Send Message"
|
|
264
|
+
/>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
\`\`\`
|
|
268
|
+
|
|
269
|
+
3. Add live chat:
|
|
270
|
+
|
|
271
|
+
\`\`\`tsx
|
|
272
|
+
import { Chat } from '@channlize/react';
|
|
273
|
+
|
|
274
|
+
function SupportPage() {
|
|
275
|
+
return (
|
|
276
|
+
<Chat
|
|
277
|
+
autoStart={true}
|
|
278
|
+
title="Customer Support"
|
|
279
|
+
placeholder="How can we help?"
|
|
280
|
+
/>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
\`\`\`
|
|
284
|
+
|
|
285
|
+
## Core SDK Usage
|
|
286
|
+
|
|
287
|
+
For non-React applications:
|
|
288
|
+
|
|
289
|
+
\`\`\`typescript
|
|
290
|
+
import { ChannlizeClient } from '@channlize/core';
|
|
291
|
+
|
|
292
|
+
const client = new ChannlizeClient({
|
|
293
|
+
apiKey: 'your-widget-key',
|
|
294
|
+
projectId: 'your-project-id',
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Submit contact form
|
|
298
|
+
await client.submitContactForm({
|
|
299
|
+
name: 'John Doe',
|
|
300
|
+
email: 'john@example.com',
|
|
301
|
+
message: 'I need help!',
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Create chat session
|
|
305
|
+
const { session } = await client.createChatSession();
|
|
306
|
+
|
|
307
|
+
// Send message
|
|
308
|
+
await client.sendMessage(session.id, 'Hello!');
|
|
309
|
+
\`\`\`
|
|
310
|
+
|
|
311
|
+
## Configuration
|
|
312
|
+
|
|
313
|
+
- \`apiKey\`: Your Channlize widget key (required)
|
|
314
|
+
- \`projectId\`: Your project ID (required)
|
|
315
|
+
- \`baseUrl\`: API base URL (optional, defaults to api.channlize.com)
|
|
316
|
+
- \`timeout\`: Request timeout in ms (optional, defaults to 10000)
|
|
317
|
+
`;
|
|
318
|
+
var REACT_COMPONENTS = `# Channlize React Components
|
|
319
|
+
|
|
320
|
+
## ChannlizeProvider
|
|
321
|
+
|
|
322
|
+
Wrap your app to provide Channlize configuration to all components.
|
|
323
|
+
|
|
324
|
+
\`\`\`tsx
|
|
325
|
+
<ChannlizeProvider config={{ apiKey, projectId }}>
|
|
326
|
+
{children}
|
|
327
|
+
</ChannlizeProvider>
|
|
328
|
+
\`\`\`
|
|
329
|
+
|
|
330
|
+
## Form
|
|
331
|
+
|
|
332
|
+
A complete contact form with validation and submission handling.
|
|
333
|
+
|
|
334
|
+
### Props
|
|
335
|
+
- \`customFields?: Array<CustomField>\` - Additional form fields
|
|
336
|
+
- \`onSuccess?: () => void\` - Success callback
|
|
337
|
+
- \`onError?: (error: Error) => void\` - Error callback
|
|
338
|
+
- \`className?: string\` - CSS class name
|
|
339
|
+
- \`styles?: FormStyles\` - Custom styles object
|
|
340
|
+
- \`submitText?: string\` - Submit button text
|
|
341
|
+
- \`successMessage?: string\` - Success message text
|
|
342
|
+
|
|
343
|
+
### Example
|
|
344
|
+
\`\`\`tsx
|
|
345
|
+
<Form
|
|
346
|
+
customFields={[
|
|
347
|
+
{
|
|
348
|
+
name: 'department',
|
|
349
|
+
label: 'Department',
|
|
350
|
+
type: 'select',
|
|
351
|
+
options: ['Sales', 'Support'],
|
|
352
|
+
required: true,
|
|
353
|
+
},
|
|
354
|
+
]}
|
|
355
|
+
onSuccess={() => alert('Sent!')}
|
|
356
|
+
styles={{
|
|
357
|
+
button: { background: '#007bff', color: 'white' },
|
|
358
|
+
}}
|
|
359
|
+
/>
|
|
360
|
+
\`\`\`
|
|
361
|
+
|
|
362
|
+
## Chat
|
|
363
|
+
|
|
364
|
+
Real-time chat widget with message history and file attachments.
|
|
365
|
+
|
|
366
|
+
### Props
|
|
367
|
+
- \`autoStart?: boolean\` - Auto-start chat session
|
|
368
|
+
- \`metadata?: Record<string, unknown>\` - Session metadata
|
|
369
|
+
- \`onMessage?: (message: ChatMessage) => void\` - New message callback
|
|
370
|
+
- \`onError?: (error: Error) => void\` - Error callback
|
|
371
|
+
- \`className?: string\` - CSS class name
|
|
372
|
+
- \`styles?: ChatStyles\` - Custom styles object
|
|
373
|
+
- \`title?: string\` - Chat header title
|
|
374
|
+
- \`placeholder?: string\` - Input placeholder text
|
|
375
|
+
- \`maxHeight?: string\` - Maximum container height
|
|
376
|
+
|
|
377
|
+
### Example
|
|
378
|
+
\`\`\`tsx
|
|
379
|
+
<Chat
|
|
380
|
+
autoStart={true}
|
|
381
|
+
title="Need Help?"
|
|
382
|
+
placeholder="Type your message..."
|
|
383
|
+
onMessage={(msg) => console.log('New:', msg)}
|
|
384
|
+
styles={{
|
|
385
|
+
container: { width: '400px', height: '500px' },
|
|
386
|
+
header: { background: '#007bff', color: 'white' },
|
|
387
|
+
}}
|
|
388
|
+
/>
|
|
389
|
+
\`\`\`
|
|
390
|
+
|
|
391
|
+
## Hooks
|
|
392
|
+
|
|
393
|
+
### useContactForm()
|
|
394
|
+
Hook for managing contact form state.
|
|
395
|
+
|
|
396
|
+
\`\`\`tsx
|
|
397
|
+
const { submit, isSubmitting, isSuccess, error, reset } = useContactForm({
|
|
398
|
+
onSuccess: (response) => console.log('Submitted:', response),
|
|
399
|
+
onError: (error) => console.error('Failed:', error),
|
|
400
|
+
});
|
|
401
|
+
\`\`\`
|
|
402
|
+
|
|
403
|
+
### useChatSession()
|
|
404
|
+
Hook for managing chat sessions.
|
|
405
|
+
|
|
406
|
+
\`\`\`tsx
|
|
407
|
+
const {
|
|
408
|
+
session,
|
|
409
|
+
messages,
|
|
410
|
+
isConnecting,
|
|
411
|
+
isConnected,
|
|
412
|
+
error,
|
|
413
|
+
sendMessage,
|
|
414
|
+
startSession,
|
|
415
|
+
endSession,
|
|
416
|
+
} = useChatSession({
|
|
417
|
+
autoConnect: false,
|
|
418
|
+
metadata: { page: 'support' },
|
|
419
|
+
onMessage: (message) => console.log('New message:', message),
|
|
420
|
+
});
|
|
421
|
+
\`\`\`
|
|
422
|
+
|
|
423
|
+
## Styling
|
|
424
|
+
|
|
425
|
+
All components accept \`styles\` prop for custom styling or \`className\` for CSS classes.
|
|
426
|
+
|
|
427
|
+
CSS class names:
|
|
428
|
+
- \`.channlize-form\`
|
|
429
|
+
- \`.channlize-field\`
|
|
430
|
+
- \`.channlize-error\`
|
|
431
|
+
- \`.channlize-chat-container\`
|
|
432
|
+
- \`.channlize-chat-header\`
|
|
433
|
+
- \`.channlize-chat-messages\`
|
|
434
|
+
- \`.channlize-message\`
|
|
435
|
+
- \`.channlize-message-user\`
|
|
436
|
+
- \`.channlize-message-agent\`
|
|
437
|
+
`;
|
|
438
|
+
var resources = [
|
|
439
|
+
{
|
|
440
|
+
uri: "channlize://schema/contact-form",
|
|
441
|
+
name: "Contact Form Schema",
|
|
442
|
+
description: "JSON schema for contact form data structure",
|
|
443
|
+
mimeType: "application/json",
|
|
444
|
+
getText: () => CONTACT_FORM_SCHEMA
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
uri: "channlize://schema/chat-session",
|
|
448
|
+
name: "Chat Session Schema",
|
|
449
|
+
description: "JSON schema for chat session data structure",
|
|
450
|
+
mimeType: "application/json",
|
|
451
|
+
getText: () => CHAT_SESSION_SCHEMA
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
uri: "channlize://docs/api-reference",
|
|
455
|
+
name: "API Reference",
|
|
456
|
+
description: "Complete Channlize API reference documentation",
|
|
457
|
+
mimeType: "text/markdown",
|
|
458
|
+
getText: () => API_REFERENCE
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
uri: "channlize://docs/quick-start",
|
|
462
|
+
name: "Quick Start Guide",
|
|
463
|
+
description: "Quick start guide for using Channlize SDK",
|
|
464
|
+
mimeType: "text/markdown",
|
|
465
|
+
getText: () => QUICK_START
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
uri: "channlize://docs/react-components",
|
|
469
|
+
name: "React Components Documentation",
|
|
470
|
+
description: "Documentation for Channlize React components and hooks",
|
|
471
|
+
mimeType: "text/markdown",
|
|
472
|
+
getText: () => REACT_COMPONENTS
|
|
473
|
+
}
|
|
474
|
+
];
|
|
475
|
+
function getResource(uri) {
|
|
476
|
+
return resources.find((r) => r.uri === uri);
|
|
477
|
+
}
|
|
478
|
+
function listResources() {
|
|
479
|
+
return resources;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// src/tools/index.ts
|
|
483
|
+
var import_core = require("@channlize/core");
|
|
484
|
+
function createClient(context) {
|
|
485
|
+
return new import_core.ChannlizeClient({
|
|
486
|
+
apiKey: context.config.apiKey,
|
|
487
|
+
projectId: context.config.projectId || "",
|
|
488
|
+
baseUrl: context.config.baseUrl,
|
|
489
|
+
timeout: context.config.timeout
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
var tools = [
|
|
493
|
+
{
|
|
494
|
+
name: "submit_contact_form",
|
|
495
|
+
description: "Submit a contact form inquiry to Channlize. This creates a new conversation thread in Slack where the team can respond.",
|
|
496
|
+
inputSchema: {
|
|
497
|
+
type: "object",
|
|
498
|
+
properties: {
|
|
499
|
+
name: {
|
|
500
|
+
type: "string",
|
|
501
|
+
description: "Contact's full name"
|
|
502
|
+
},
|
|
503
|
+
email: {
|
|
504
|
+
type: "string",
|
|
505
|
+
description: "Contact's email address"
|
|
506
|
+
},
|
|
507
|
+
subject: {
|
|
508
|
+
type: "string",
|
|
509
|
+
description: "Subject line for the inquiry (optional)"
|
|
510
|
+
},
|
|
511
|
+
message: {
|
|
512
|
+
type: "string",
|
|
513
|
+
description: "The message content"
|
|
514
|
+
},
|
|
515
|
+
customFields: {
|
|
516
|
+
type: "object",
|
|
517
|
+
description: "Additional custom fields as key-value pairs (optional)",
|
|
518
|
+
additionalProperties: true
|
|
519
|
+
},
|
|
520
|
+
pageUrl: {
|
|
521
|
+
type: "string",
|
|
522
|
+
description: "URL of the page where form was submitted (optional)"
|
|
523
|
+
},
|
|
524
|
+
userAgent: {
|
|
525
|
+
type: "string",
|
|
526
|
+
description: "User agent string of the submitter (optional)"
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
required: ["name", "email", "message"]
|
|
530
|
+
},
|
|
531
|
+
handler: async (args2, context) => {
|
|
532
|
+
const client = createClient(context);
|
|
533
|
+
const response = await client.submitContactForm({
|
|
534
|
+
name: args2.name,
|
|
535
|
+
email: args2.email,
|
|
536
|
+
subject: args2.subject,
|
|
537
|
+
message: args2.message,
|
|
538
|
+
customFields: args2.customFields,
|
|
539
|
+
pageUrl: args2.pageUrl,
|
|
540
|
+
userAgent: args2.userAgent
|
|
541
|
+
});
|
|
542
|
+
return {
|
|
543
|
+
success: true,
|
|
544
|
+
contactId: response.id,
|
|
545
|
+
status: response.status,
|
|
546
|
+
slackThreadUrl: response.slackThreadUrl,
|
|
547
|
+
message: "Contact form submitted successfully"
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
name: "create_chat_session",
|
|
553
|
+
description: "Create a new chat session for real-time messaging. Returns a session ID that can be used to send and receive messages.",
|
|
554
|
+
inputSchema: {
|
|
555
|
+
type: "object",
|
|
556
|
+
properties: {
|
|
557
|
+
metadata: {
|
|
558
|
+
type: "object",
|
|
559
|
+
description: "Custom metadata to attach to the session (e.g., page URL, user info)",
|
|
560
|
+
additionalProperties: true
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
handler: async (args2, context) => {
|
|
565
|
+
const client = createClient(context);
|
|
566
|
+
const response = await client.createChatSession(args2.metadata);
|
|
567
|
+
return {
|
|
568
|
+
success: true,
|
|
569
|
+
session: {
|
|
570
|
+
id: response.session.id,
|
|
571
|
+
status: response.session.status,
|
|
572
|
+
createdAt: response.session.createdAt,
|
|
573
|
+
messageCount: response.session.messages?.length || 0
|
|
574
|
+
},
|
|
575
|
+
sseEndpoint: response.sseEndpoint,
|
|
576
|
+
message: "Chat session created successfully"
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
name: "send_message",
|
|
582
|
+
description: "Send a message in an existing chat session. The message will be delivered to the Slack thread and the user can see agent replies in real-time.",
|
|
583
|
+
inputSchema: {
|
|
584
|
+
type: "object",
|
|
585
|
+
properties: {
|
|
586
|
+
sessionId: {
|
|
587
|
+
type: "string",
|
|
588
|
+
description: "The chat session ID"
|
|
589
|
+
},
|
|
590
|
+
content: {
|
|
591
|
+
type: "string",
|
|
592
|
+
description: "The message content to send"
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
required: ["sessionId", "content"]
|
|
596
|
+
},
|
|
597
|
+
handler: async (args2, context) => {
|
|
598
|
+
const client = createClient(context);
|
|
599
|
+
const response = await client.sendMessage(args2.sessionId, args2.content);
|
|
600
|
+
return {
|
|
601
|
+
success: true,
|
|
602
|
+
message: {
|
|
603
|
+
id: response.message.id,
|
|
604
|
+
content: response.message.content,
|
|
605
|
+
timestamp: response.message.timestamp,
|
|
606
|
+
author: response.message.author
|
|
607
|
+
},
|
|
608
|
+
sessionStatus: response.session.status,
|
|
609
|
+
deliveryMessage: "Message sent successfully"
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
name: "get_chat_messages",
|
|
615
|
+
description: "Retrieve messages from a chat session. Useful for viewing conversation history.",
|
|
616
|
+
inputSchema: {
|
|
617
|
+
type: "object",
|
|
618
|
+
properties: {
|
|
619
|
+
sessionId: {
|
|
620
|
+
type: "string",
|
|
621
|
+
description: "The chat session ID"
|
|
622
|
+
},
|
|
623
|
+
limit: {
|
|
624
|
+
type: "number",
|
|
625
|
+
description: "Maximum number of messages to retrieve (default: 50)",
|
|
626
|
+
default: 50
|
|
627
|
+
},
|
|
628
|
+
offset: {
|
|
629
|
+
type: "number",
|
|
630
|
+
description: "Number of messages to skip (default: 0)",
|
|
631
|
+
default: 0
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
required: ["sessionId"]
|
|
635
|
+
},
|
|
636
|
+
handler: async (args2, context) => {
|
|
637
|
+
const client = createClient(context);
|
|
638
|
+
const messages = await client.getChatMessages(
|
|
639
|
+
args2.sessionId,
|
|
640
|
+
args2.limit || 50,
|
|
641
|
+
args2.offset || 0
|
|
642
|
+
);
|
|
643
|
+
return {
|
|
644
|
+
success: true,
|
|
645
|
+
sessionId: args2.sessionId,
|
|
646
|
+
messageCount: messages.length,
|
|
647
|
+
messages: messages.map((msg) => ({
|
|
648
|
+
id: msg.id,
|
|
649
|
+
content: msg.content,
|
|
650
|
+
timestamp: msg.timestamp,
|
|
651
|
+
author: msg.author,
|
|
652
|
+
authorData: msg.authorData,
|
|
653
|
+
hasAttachments: (msg.attachments?.length || 0) > 0
|
|
654
|
+
}))
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
name: "close_chat_session",
|
|
660
|
+
description: "Close an active chat session. This marks the conversation as complete and stops real-time updates.",
|
|
661
|
+
inputSchema: {
|
|
662
|
+
type: "object",
|
|
663
|
+
properties: {
|
|
664
|
+
sessionId: {
|
|
665
|
+
type: "string",
|
|
666
|
+
description: "The chat session ID to close"
|
|
667
|
+
}
|
|
668
|
+
},
|
|
669
|
+
required: ["sessionId"]
|
|
670
|
+
},
|
|
671
|
+
handler: async (args2, context) => {
|
|
672
|
+
const client = createClient(context);
|
|
673
|
+
const session = await client.closeChatSession(args2.sessionId);
|
|
674
|
+
return {
|
|
675
|
+
success: true,
|
|
676
|
+
sessionId: session.id,
|
|
677
|
+
status: session.status,
|
|
678
|
+
closedAt: session.updatedAt,
|
|
679
|
+
message: "Chat session closed successfully"
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
];
|
|
684
|
+
function getTool(name) {
|
|
685
|
+
return tools.find((t) => t.name === name);
|
|
686
|
+
}
|
|
687
|
+
function listTools() {
|
|
688
|
+
return tools;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/prompts/index.ts
|
|
692
|
+
var prompts = [
|
|
693
|
+
{
|
|
694
|
+
name: "integrate-contact-form",
|
|
695
|
+
description: "Guide for adding a Channlize contact form to a React application",
|
|
696
|
+
arguments: [
|
|
697
|
+
{
|
|
698
|
+
name: "framework",
|
|
699
|
+
description: "The React framework being used (e.g., Next.js, Vite, CRA)",
|
|
700
|
+
required: false
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
name: "styling",
|
|
704
|
+
description: "The styling approach (e.g., Tailwind, CSS Modules, styled-components)",
|
|
705
|
+
required: false
|
|
706
|
+
}
|
|
707
|
+
],
|
|
708
|
+
getPrompt: (args2) => {
|
|
709
|
+
const framework = args2?.framework || "React";
|
|
710
|
+
const styling = args2?.styling || "CSS";
|
|
711
|
+
return `# Integrating Channlize Contact Form in ${framework}
|
|
712
|
+
|
|
713
|
+
## Step 1: Install Dependencies
|
|
714
|
+
|
|
715
|
+
\`\`\`bash
|
|
716
|
+
npm install @channlize/react
|
|
717
|
+
\`\`\`
|
|
718
|
+
|
|
719
|
+
## Step 2: Configure Provider
|
|
720
|
+
|
|
721
|
+
Wrap your application with the ChannlizeProvider at the root level:
|
|
722
|
+
|
|
723
|
+
\`\`\`tsx
|
|
724
|
+
import { ChannlizeProvider } from '@channlize/react';
|
|
725
|
+
|
|
726
|
+
function App() {
|
|
727
|
+
return (
|
|
728
|
+
<ChannlizeProvider
|
|
729
|
+
config={{
|
|
730
|
+
apiKey: process.env.NEXT_PUBLIC_CHANNLIZE_API_KEY, // Your widget key
|
|
731
|
+
projectId: process.env.NEXT_PUBLIC_CHANNLIZE_PROJECT_ID,
|
|
732
|
+
baseUrl: process.env.NEXT_PUBLIC_CHANNLIZE_API_URL, // Optional
|
|
733
|
+
}}
|
|
734
|
+
>
|
|
735
|
+
<YourAppContent />
|
|
736
|
+
</ChannlizeProvider>
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
\`\`\`
|
|
740
|
+
|
|
741
|
+
## Step 3: Add Form Component
|
|
742
|
+
|
|
743
|
+
Create a contact page or component:
|
|
744
|
+
|
|
745
|
+
\`\`\`tsx
|
|
746
|
+
import { Form } from '@channlize/react';
|
|
747
|
+
|
|
748
|
+
export default function ContactPage() {
|
|
749
|
+
return (
|
|
750
|
+
<div className="container mx-auto py-8">
|
|
751
|
+
<h1>Contact Us</h1>
|
|
752
|
+
<Form
|
|
753
|
+
onSuccess={() => {
|
|
754
|
+
alert('Thank you! We will get back to you soon.');
|
|
755
|
+
}}
|
|
756
|
+
onError={(error) => {
|
|
757
|
+
console.error('Failed to submit:', error);
|
|
758
|
+
}}
|
|
759
|
+
customFields={[
|
|
760
|
+
{
|
|
761
|
+
name: 'department',
|
|
762
|
+
label: 'Department',
|
|
763
|
+
type: 'select',
|
|
764
|
+
options: ['Sales', 'Support', 'Billing'],
|
|
765
|
+
required: true,
|
|
766
|
+
},
|
|
767
|
+
]}
|
|
768
|
+
${styling === "Tailwind" ? `className="max-w-2xl"` : ""}
|
|
769
|
+
styles={{
|
|
770
|
+
form: { maxWidth: '600px', margin: '0 auto' },
|
|
771
|
+
button: {
|
|
772
|
+
background: '#007bff',
|
|
773
|
+
color: 'white',
|
|
774
|
+
padding: '0.75rem 1.5rem',
|
|
775
|
+
borderRadius: '0.5rem',
|
|
776
|
+
},
|
|
777
|
+
}}
|
|
778
|
+
submitText="Send Message"
|
|
779
|
+
successMessage="Thank you! We'll respond shortly."
|
|
780
|
+
/>
|
|
781
|
+
</div>
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
\`\`\`
|
|
785
|
+
|
|
786
|
+
## Step 4: Environment Variables
|
|
787
|
+
|
|
788
|
+
Add to your \`.env.local\` or \`.env\`:
|
|
789
|
+
|
|
790
|
+
\`\`\`
|
|
791
|
+
NEXT_PUBLIC_CHANNLIZE_API_KEY=your_widget_key_here
|
|
792
|
+
NEXT_PUBLIC_CHANNLIZE_PROJECT_ID=your_project_id_here
|
|
793
|
+
NEXT_PUBLIC_CHANNLIZE_API_URL=http://api.channlize.com # Optional
|
|
794
|
+
\`\`\`
|
|
795
|
+
|
|
796
|
+
## Step 5: Customize (Optional)
|
|
797
|
+
|
|
798
|
+
### Custom Fields
|
|
799
|
+
Add custom fields to gather specific information:
|
|
800
|
+
|
|
801
|
+
\`\`\`tsx
|
|
802
|
+
customFields={[
|
|
803
|
+
{
|
|
804
|
+
name: 'company',
|
|
805
|
+
label: 'Company Name',
|
|
806
|
+
type: 'text',
|
|
807
|
+
required: false,
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
name: 'priority',
|
|
811
|
+
label: 'Priority',
|
|
812
|
+
type: 'select',
|
|
813
|
+
options: ['Low', 'Medium', 'High'],
|
|
814
|
+
required: true,
|
|
815
|
+
},
|
|
816
|
+
]}
|
|
817
|
+
\`\`\`
|
|
818
|
+
|
|
819
|
+
### Custom Styling with ${styling}
|
|
820
|
+
${styling === "Tailwind" ? "Use Tailwind classes with the className prop or override styles." : "Apply custom styles using the styles prop or external CSS."}
|
|
821
|
+
|
|
822
|
+
## Tips
|
|
823
|
+
|
|
824
|
+
- Messages are sent to your configured Slack channel instantly
|
|
825
|
+
- Email fallback is automatic if Slack delivery fails
|
|
826
|
+
- Form includes built-in validation and error handling
|
|
827
|
+
- All fields support accessibility features (ARIA labels, keyboard navigation)
|
|
828
|
+
|
|
829
|
+
## Next Steps
|
|
830
|
+
|
|
831
|
+
- Set up Slack workspace integration in your Channlize dashboard
|
|
832
|
+
- Configure channel routing rules
|
|
833
|
+
- Add webhooks for custom workflows
|
|
834
|
+
`;
|
|
835
|
+
}
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
name: "setup-live-chat",
|
|
839
|
+
description: "Guide for implementing the Channlize live chat widget in a React application",
|
|
840
|
+
arguments: [
|
|
841
|
+
{
|
|
842
|
+
name: "placement",
|
|
843
|
+
description: 'Where to place the chat widget (e.g., "page", "popup", "sidebar")',
|
|
844
|
+
required: false
|
|
845
|
+
}
|
|
846
|
+
],
|
|
847
|
+
getPrompt: (args2) => {
|
|
848
|
+
const placement = args2?.placement || "page";
|
|
849
|
+
return `# Setting Up Channlize Live Chat Widget
|
|
850
|
+
|
|
851
|
+
## Step 1: Install Dependencies
|
|
852
|
+
|
|
853
|
+
\`\`\`bash
|
|
854
|
+
npm install @channlize/react
|
|
855
|
+
\`\`\`
|
|
856
|
+
|
|
857
|
+
## Step 2: Configure Provider
|
|
858
|
+
|
|
859
|
+
Ensure your app is wrapped with ChannlizeProvider:
|
|
860
|
+
|
|
861
|
+
\`\`\`tsx
|
|
862
|
+
import { ChannlizeProvider } from '@channlize/react';
|
|
863
|
+
|
|
864
|
+
function App() {
|
|
865
|
+
return (
|
|
866
|
+
<ChannlizeProvider
|
|
867
|
+
config={{
|
|
868
|
+
apiKey: process.env.NEXT_PUBLIC_CHANNLIZE_API_KEY,
|
|
869
|
+
projectId: process.env.NEXT_PUBLIC_CHANNLIZE_PROJECT_ID,
|
|
870
|
+
}}
|
|
871
|
+
>
|
|
872
|
+
<YourAppContent />
|
|
873
|
+
</ChannlizeProvider>
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
\`\`\`
|
|
877
|
+
|
|
878
|
+
## Step 3: Add Chat Component
|
|
879
|
+
|
|
880
|
+
${placement === "popup" ? `
|
|
881
|
+
### Popup Widget (Bottom-Right Corner)
|
|
882
|
+
|
|
883
|
+
\`\`\`tsx
|
|
884
|
+
import { useState } from 'react';
|
|
885
|
+
import { Chat } from '@channlize/react';
|
|
886
|
+
|
|
887
|
+
export function ChatWidget() {
|
|
888
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
889
|
+
|
|
890
|
+
return (
|
|
891
|
+
<>
|
|
892
|
+
{/* Floating Button */}
|
|
893
|
+
{!isOpen && (
|
|
894
|
+
<button
|
|
895
|
+
onClick={() => setIsOpen(true)}
|
|
896
|
+
style={{
|
|
897
|
+
position: 'fixed',
|
|
898
|
+
bottom: '20px',
|
|
899
|
+
right: '20px',
|
|
900
|
+
width: '60px',
|
|
901
|
+
height: '60px',
|
|
902
|
+
borderRadius: '50%',
|
|
903
|
+
background: '#007bff',
|
|
904
|
+
color: 'white',
|
|
905
|
+
border: 'none',
|
|
906
|
+
fontSize: '24px',
|
|
907
|
+
cursor: 'pointer',
|
|
908
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
|
|
909
|
+
zIndex: 1000,
|
|
910
|
+
}}
|
|
911
|
+
>
|
|
912
|
+
\u{1F4AC}
|
|
913
|
+
</button>
|
|
914
|
+
)}
|
|
915
|
+
|
|
916
|
+
{/* Chat Window */}
|
|
917
|
+
{isOpen && (
|
|
918
|
+
<div
|
|
919
|
+
style={{
|
|
920
|
+
position: 'fixed',
|
|
921
|
+
bottom: '20px',
|
|
922
|
+
right: '20px',
|
|
923
|
+
zIndex: 1000,
|
|
924
|
+
boxShadow: '0 4px 24px rgba(0,0,0,0.15)',
|
|
925
|
+
borderRadius: '12px',
|
|
926
|
+
overflow: 'hidden',
|
|
927
|
+
}}
|
|
928
|
+
>
|
|
929
|
+
<Chat
|
|
930
|
+
autoStart={true}
|
|
931
|
+
title="Customer Support"
|
|
932
|
+
placeholder="Type your message..."
|
|
933
|
+
onMessage={(message) => {
|
|
934
|
+
console.log('New message:', message);
|
|
935
|
+
}}
|
|
936
|
+
styles={{
|
|
937
|
+
container: {
|
|
938
|
+
width: '380px',
|
|
939
|
+
height: '600px',
|
|
940
|
+
display: 'flex',
|
|
941
|
+
flexDirection: 'column',
|
|
942
|
+
background: 'white',
|
|
943
|
+
},
|
|
944
|
+
header: {
|
|
945
|
+
background: '#007bff',
|
|
946
|
+
color: 'white',
|
|
947
|
+
padding: '1rem',
|
|
948
|
+
display: 'flex',
|
|
949
|
+
alignItems: 'center',
|
|
950
|
+
},
|
|
951
|
+
}}
|
|
952
|
+
/>
|
|
953
|
+
<button
|
|
954
|
+
onClick={() => setIsOpen(false)}
|
|
955
|
+
style={{
|
|
956
|
+
position: 'absolute',
|
|
957
|
+
top: '10px',
|
|
958
|
+
right: '10px',
|
|
959
|
+
background: 'rgba(255,255,255,0.2)',
|
|
960
|
+
border: 'none',
|
|
961
|
+
color: 'white',
|
|
962
|
+
cursor: 'pointer',
|
|
963
|
+
fontSize: '20px',
|
|
964
|
+
width: '30px',
|
|
965
|
+
height: '30px',
|
|
966
|
+
borderRadius: '50%',
|
|
967
|
+
}}
|
|
968
|
+
>
|
|
969
|
+
\xD7
|
|
970
|
+
</button>
|
|
971
|
+
</div>
|
|
972
|
+
)}
|
|
973
|
+
</>
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
\`\`\`
|
|
977
|
+
` : `
|
|
978
|
+
### Embedded Chat
|
|
979
|
+
|
|
980
|
+
\`\`\`tsx
|
|
981
|
+
import { Chat } from '@channlize/react';
|
|
982
|
+
|
|
983
|
+
export default function SupportPage() {
|
|
984
|
+
return (
|
|
985
|
+
<div className="container mx-auto py-8">
|
|
986
|
+
<h1>Customer Support</h1>
|
|
987
|
+
<Chat
|
|
988
|
+
autoStart={true}
|
|
989
|
+
title="Live Chat Support"
|
|
990
|
+
placeholder="How can we help you today?"
|
|
991
|
+
onMessage={(message) => {
|
|
992
|
+
// Handle incoming messages
|
|
993
|
+
console.log('New message:', message);
|
|
994
|
+
}}
|
|
995
|
+
onError={(error) => {
|
|
996
|
+
console.error('Chat error:', error);
|
|
997
|
+
}}
|
|
998
|
+
styles={{
|
|
999
|
+
container: {
|
|
1000
|
+
width: '100%',
|
|
1001
|
+
maxWidth: '800px',
|
|
1002
|
+
height: '600px',
|
|
1003
|
+
margin: '0 auto',
|
|
1004
|
+
border: '1px solid #e0e0e0',
|
|
1005
|
+
borderRadius: '12px',
|
|
1006
|
+
},
|
|
1007
|
+
header: {
|
|
1008
|
+
background: '#007bff',
|
|
1009
|
+
color: 'white',
|
|
1010
|
+
},
|
|
1011
|
+
}}
|
|
1012
|
+
maxHeight="600px"
|
|
1013
|
+
/>
|
|
1014
|
+
</div>
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
\`\`\`
|
|
1018
|
+
`}
|
|
1019
|
+
|
|
1020
|
+
## Step 4: Advanced Features
|
|
1021
|
+
|
|
1022
|
+
### Custom Metadata
|
|
1023
|
+
Pass context about the user or page:
|
|
1024
|
+
|
|
1025
|
+
\`\`\`tsx
|
|
1026
|
+
<Chat
|
|
1027
|
+
metadata={{
|
|
1028
|
+
userId: user?.id,
|
|
1029
|
+
userName: user?.name,
|
|
1030
|
+
currentPage: window.location.pathname,
|
|
1031
|
+
plan: 'pro',
|
|
1032
|
+
}}
|
|
1033
|
+
/>
|
|
1034
|
+
\`\`\`
|
|
1035
|
+
|
|
1036
|
+
### Event Handlers
|
|
1037
|
+
React to chat events:
|
|
1038
|
+
|
|
1039
|
+
\`\`\`tsx
|
|
1040
|
+
<Chat
|
|
1041
|
+
onMessage={(message) => {
|
|
1042
|
+
// Track analytics
|
|
1043
|
+
analytics.track('chat_message_received', {
|
|
1044
|
+
author: message.author,
|
|
1045
|
+
timestamp: message.timestamp,
|
|
1046
|
+
});
|
|
1047
|
+
}}
|
|
1048
|
+
onError={(error) => {
|
|
1049
|
+
// Report errors
|
|
1050
|
+
errorReporting.log(error);
|
|
1051
|
+
}}
|
|
1052
|
+
/>
|
|
1053
|
+
\`\`\`
|
|
1054
|
+
|
|
1055
|
+
## Real-Time Features
|
|
1056
|
+
|
|
1057
|
+
- Messages are delivered instantly via Server-Sent Events (SSE)
|
|
1058
|
+
- Agent presence indicators show when team is active
|
|
1059
|
+
- File attachments supported (images, documents)
|
|
1060
|
+
- Automatic reconnection on connection loss
|
|
1061
|
+
- Message history persisted across sessions
|
|
1062
|
+
|
|
1063
|
+
## Tips
|
|
1064
|
+
|
|
1065
|
+
- Chat sessions are automatically created on first message
|
|
1066
|
+
- Sessions remain active until explicitly closed
|
|
1067
|
+
- Messages are threaded in Slack for team collaboration
|
|
1068
|
+
- Supports multiple concurrent chat sessions per project
|
|
1069
|
+
|
|
1070
|
+
## Next Steps
|
|
1071
|
+
|
|
1072
|
+
- Configure Slack notifications for new chats
|
|
1073
|
+
- Set up auto-responses for common questions
|
|
1074
|
+
- Integrate with your analytics platform
|
|
1075
|
+
- Add custom routing based on user context
|
|
1076
|
+
`;
|
|
1077
|
+
}
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
name: "customize-styling",
|
|
1081
|
+
description: "Guide for theming and customizing Channlize components",
|
|
1082
|
+
getPrompt: () => `# Customizing Channlize Component Styling
|
|
1083
|
+
|
|
1084
|
+
Channlize components are designed to be highly customizable to match your brand.
|
|
1085
|
+
|
|
1086
|
+
## Styling Approaches
|
|
1087
|
+
|
|
1088
|
+
### 1. Inline Styles with \`styles\` Prop
|
|
1089
|
+
|
|
1090
|
+
The most direct way to customize appearance:
|
|
1091
|
+
|
|
1092
|
+
\`\`\`tsx
|
|
1093
|
+
<Form
|
|
1094
|
+
styles={{
|
|
1095
|
+
form: {
|
|
1096
|
+
maxWidth: '600px',
|
|
1097
|
+
margin: '0 auto',
|
|
1098
|
+
padding: '2rem',
|
|
1099
|
+
background: '#f9fafb',
|
|
1100
|
+
borderRadius: '8px',
|
|
1101
|
+
},
|
|
1102
|
+
field: {
|
|
1103
|
+
marginBottom: '1.5rem',
|
|
1104
|
+
},
|
|
1105
|
+
label: {
|
|
1106
|
+
display: 'block',
|
|
1107
|
+
marginBottom: '0.5rem',
|
|
1108
|
+
fontWeight: '600',
|
|
1109
|
+
color: '#374151',
|
|
1110
|
+
},
|
|
1111
|
+
input: {
|
|
1112
|
+
width: '100%',
|
|
1113
|
+
padding: '0.75rem',
|
|
1114
|
+
border: '1px solid #d1d5db',
|
|
1115
|
+
borderRadius: '6px',
|
|
1116
|
+
fontSize: '1rem',
|
|
1117
|
+
},
|
|
1118
|
+
textarea: {
|
|
1119
|
+
width: '100%',
|
|
1120
|
+
padding: '0.75rem',
|
|
1121
|
+
border: '1px solid #d1d5db',
|
|
1122
|
+
borderRadius: '6px',
|
|
1123
|
+
fontSize: '1rem',
|
|
1124
|
+
minHeight: '120px',
|
|
1125
|
+
},
|
|
1126
|
+
button: {
|
|
1127
|
+
background: '#3b82f6',
|
|
1128
|
+
color: 'white',
|
|
1129
|
+
padding: '0.75rem 2rem',
|
|
1130
|
+
border: 'none',
|
|
1131
|
+
borderRadius: '6px',
|
|
1132
|
+
fontSize: '1rem',
|
|
1133
|
+
fontWeight: '600',
|
|
1134
|
+
cursor: 'pointer',
|
|
1135
|
+
transition: 'background 0.2s',
|
|
1136
|
+
},
|
|
1137
|
+
error: {
|
|
1138
|
+
color: '#ef4444',
|
|
1139
|
+
fontSize: '0.875rem',
|
|
1140
|
+
marginTop: '0.5rem',
|
|
1141
|
+
},
|
|
1142
|
+
success: {
|
|
1143
|
+
background: '#ecfdf5',
|
|
1144
|
+
border: '1px solid #10b981',
|
|
1145
|
+
padding: '1.5rem',
|
|
1146
|
+
borderRadius: '6px',
|
|
1147
|
+
color: '#065f46',
|
|
1148
|
+
},
|
|
1149
|
+
}}
|
|
1150
|
+
/>
|
|
1151
|
+
\`\`\`
|
|
1152
|
+
|
|
1153
|
+
### 2. CSS Classes with \`className\` Prop
|
|
1154
|
+
|
|
1155
|
+
Use your existing CSS or CSS-in-JS solution:
|
|
1156
|
+
|
|
1157
|
+
\`\`\`tsx
|
|
1158
|
+
<Form className="custom-form" />
|
|
1159
|
+
\`\`\`
|
|
1160
|
+
|
|
1161
|
+
\`\`\`css
|
|
1162
|
+
/* styles.css */
|
|
1163
|
+
.channlize-form {
|
|
1164
|
+
max-width: 600px;
|
|
1165
|
+
margin: 0 auto;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
.channlize-field {
|
|
1169
|
+
margin-bottom: 1.5rem;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
.channlize-field label {
|
|
1173
|
+
font-weight: 600;
|
|
1174
|
+
color: var(--primary-text);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
.channlize-field input,
|
|
1178
|
+
.channlize-field textarea,
|
|
1179
|
+
.channlize-field select {
|
|
1180
|
+
border: 1px solid var(--border-color);
|
|
1181
|
+
border-radius: 6px;
|
|
1182
|
+
padding: 0.75rem;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
.channlize-form button[type="submit"] {
|
|
1186
|
+
background: var(--primary-color);
|
|
1187
|
+
color: white;
|
|
1188
|
+
}
|
|
1189
|
+
\`\`\`
|
|
1190
|
+
|
|
1191
|
+
### 3. Tailwind CSS
|
|
1192
|
+
|
|
1193
|
+
Combine with Tailwind utility classes:
|
|
1194
|
+
|
|
1195
|
+
\`\`\`tsx
|
|
1196
|
+
<Form
|
|
1197
|
+
className="max-w-2xl mx-auto p-8"
|
|
1198
|
+
styles={{
|
|
1199
|
+
input: {
|
|
1200
|
+
// Tailwind styles as objects don't work well
|
|
1201
|
+
// Use className on wrapper or global CSS
|
|
1202
|
+
},
|
|
1203
|
+
}}
|
|
1204
|
+
/>
|
|
1205
|
+
\`\`\`
|
|
1206
|
+
|
|
1207
|
+
\`\`\`css
|
|
1208
|
+
/* globals.css with @layer */
|
|
1209
|
+
@layer components {
|
|
1210
|
+
.channlize-field input {
|
|
1211
|
+
@apply w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
.channlize-field textarea {
|
|
1215
|
+
@apply w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
.channlize-form button[type="submit"] {
|
|
1219
|
+
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 px-6 rounded-lg transition;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
\`\`\`
|
|
1223
|
+
|
|
1224
|
+
## Styling Chat
|
|
1225
|
+
|
|
1226
|
+
\`\`\`tsx
|
|
1227
|
+
<Chat
|
|
1228
|
+
styles={{
|
|
1229
|
+
container: {
|
|
1230
|
+
border: '1px solid #e5e7eb',
|
|
1231
|
+
borderRadius: '12px',
|
|
1232
|
+
overflow: 'hidden',
|
|
1233
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
|
1234
|
+
},
|
|
1235
|
+
header: {
|
|
1236
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
1237
|
+
color: 'white',
|
|
1238
|
+
padding: '1rem',
|
|
1239
|
+
},
|
|
1240
|
+
messages: {
|
|
1241
|
+
background: '#f9fafb',
|
|
1242
|
+
padding: '1rem',
|
|
1243
|
+
},
|
|
1244
|
+
messageUser: {
|
|
1245
|
+
background: '#3b82f6',
|
|
1246
|
+
color: 'white',
|
|
1247
|
+
padding: '0.75rem',
|
|
1248
|
+
borderRadius: '12px 12px 4px 12px',
|
|
1249
|
+
maxWidth: '70%',
|
|
1250
|
+
marginLeft: 'auto',
|
|
1251
|
+
},
|
|
1252
|
+
messageAgent: {
|
|
1253
|
+
background: 'white',
|
|
1254
|
+
color: '#1f2937',
|
|
1255
|
+
padding: '0.75rem',
|
|
1256
|
+
borderRadius: '12px 12px 12px 4px',
|
|
1257
|
+
maxWidth: '70%',
|
|
1258
|
+
border: '1px solid #e5e7eb',
|
|
1259
|
+
},
|
|
1260
|
+
input: {
|
|
1261
|
+
border: '1px solid #d1d5db',
|
|
1262
|
+
borderRadius: '6px',
|
|
1263
|
+
padding: '0.75rem',
|
|
1264
|
+
fontSize: '1rem',
|
|
1265
|
+
},
|
|
1266
|
+
button: {
|
|
1267
|
+
background: '#3b82f6',
|
|
1268
|
+
color: 'white',
|
|
1269
|
+
padding: '0.75rem 1.5rem',
|
|
1270
|
+
borderRadius: '6px',
|
|
1271
|
+
border: 'none',
|
|
1272
|
+
cursor: 'pointer',
|
|
1273
|
+
},
|
|
1274
|
+
}}
|
|
1275
|
+
/>
|
|
1276
|
+
\`\`\`
|
|
1277
|
+
|
|
1278
|
+
## CSS Class Reference
|
|
1279
|
+
|
|
1280
|
+
All Channlize components use semantic CSS classes:
|
|
1281
|
+
|
|
1282
|
+
**Form:**
|
|
1283
|
+
- \`.channlize-form\` - Form container
|
|
1284
|
+
- \`.channlize-form-success\` - Success message container
|
|
1285
|
+
- \`.channlize-field\` - Field wrapper
|
|
1286
|
+
- \`.channlize-error\` - Error message
|
|
1287
|
+
|
|
1288
|
+
**Chat:**
|
|
1289
|
+
- \`.channlize-chat-container\` - Main container
|
|
1290
|
+
- \`.channlize-chat-header\` - Header section
|
|
1291
|
+
- \`.channlize-chat-messages\` - Messages container
|
|
1292
|
+
- \`.channlize-message\` - Individual message
|
|
1293
|
+
- \`.channlize-message-user\` - User message
|
|
1294
|
+
- \`.channlize-message-agent\` - Agent message
|
|
1295
|
+
- \`.channlize-chat-input-container\` - Input area
|
|
1296
|
+
|
|
1297
|
+
## Dark Mode Example
|
|
1298
|
+
|
|
1299
|
+
\`\`\`tsx
|
|
1300
|
+
const darkStyles = {
|
|
1301
|
+
form: {
|
|
1302
|
+
background: '#1f2937',
|
|
1303
|
+
color: '#f9fafb',
|
|
1304
|
+
},
|
|
1305
|
+
input: {
|
|
1306
|
+
background: '#374151',
|
|
1307
|
+
color: '#f9fafb',
|
|
1308
|
+
border: '1px solid #4b5563',
|
|
1309
|
+
},
|
|
1310
|
+
button: {
|
|
1311
|
+
background: '#3b82f6',
|
|
1312
|
+
color: 'white',
|
|
1313
|
+
},
|
|
1314
|
+
};
|
|
1315
|
+
|
|
1316
|
+
<Form styles={darkStyles} />
|
|
1317
|
+
\`\`\`
|
|
1318
|
+
`
|
|
1319
|
+
},
|
|
1320
|
+
{
|
|
1321
|
+
name: "handle-webhooks",
|
|
1322
|
+
description: "Guide for integrating Channlize webhooks into custom workflows",
|
|
1323
|
+
getPrompt: () => `# Integrating Channlize Webhooks
|
|
1324
|
+
|
|
1325
|
+
Channlize can send webhook events to your backend for custom workflows and integrations.
|
|
1326
|
+
|
|
1327
|
+
## Available Webhook Events
|
|
1328
|
+
|
|
1329
|
+
- \`conversation.created\` - New contact form or chat session started
|
|
1330
|
+
- \`message.created\` - New message in a conversation
|
|
1331
|
+
- \`conversation.closed\` - Conversation marked as closed
|
|
1332
|
+
- \`agent.assigned\` - Agent assigned to conversation
|
|
1333
|
+
|
|
1334
|
+
## Setting Up Webhooks
|
|
1335
|
+
|
|
1336
|
+
### 1. Configure Webhook URL
|
|
1337
|
+
|
|
1338
|
+
In your Channlize dashboard:
|
|
1339
|
+
1. Navigate to Project Settings \u2192 Webhooks
|
|
1340
|
+
2. Add your webhook endpoint URL
|
|
1341
|
+
3. Select which events to receive
|
|
1342
|
+
4. Save your secret key for verification
|
|
1343
|
+
|
|
1344
|
+
### 2. Create Webhook Handler (Next.js API Route)
|
|
1345
|
+
|
|
1346
|
+
\`\`\`typescript
|
|
1347
|
+
// app/api/webhooks/channlize/route.ts
|
|
1348
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
1349
|
+
import crypto from 'crypto';
|
|
1350
|
+
|
|
1351
|
+
const WEBHOOK_SECRET = process.env.CHANNLIZE_WEBHOOK_SECRET!;
|
|
1352
|
+
|
|
1353
|
+
function verifySignature(payload: string, signature: string): boolean {
|
|
1354
|
+
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
|
|
1355
|
+
const digest = hmac.update(payload).digest('hex');
|
|
1356
|
+
return crypto.timingSafeEqual(
|
|
1357
|
+
Buffer.from(signature),
|
|
1358
|
+
Buffer.from(digest)
|
|
1359
|
+
);
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
export async function POST(req: NextRequest) {
|
|
1363
|
+
const signature = req.headers.get('x-channlize-signature');
|
|
1364
|
+
const payload = await req.text();
|
|
1365
|
+
|
|
1366
|
+
if (!signature || !verifySignature(payload, signature)) {
|
|
1367
|
+
return NextResponse.json(
|
|
1368
|
+
{ error: 'Invalid signature' },
|
|
1369
|
+
{ status: 401 }
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
const event = JSON.parse(payload);
|
|
1374
|
+
|
|
1375
|
+
// Handle different event types
|
|
1376
|
+
switch (event.type) {
|
|
1377
|
+
case 'conversation.created':
|
|
1378
|
+
await handleNewConversation(event.data);
|
|
1379
|
+
break;
|
|
1380
|
+
|
|
1381
|
+
case 'message.created':
|
|
1382
|
+
await handleNewMessage(event.data);
|
|
1383
|
+
break;
|
|
1384
|
+
|
|
1385
|
+
case 'conversation.closed':
|
|
1386
|
+
await handleConversationClosed(event.data);
|
|
1387
|
+
break;
|
|
1388
|
+
|
|
1389
|
+
default:
|
|
1390
|
+
console.log('Unhandled event type:', event.type);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
return NextResponse.json({ received: true });
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
async function handleNewConversation(data: any) {
|
|
1397
|
+
// Example: Log to analytics
|
|
1398
|
+
await analytics.track('support_conversation_started', {
|
|
1399
|
+
conversationId: data.conversation.id,
|
|
1400
|
+
type: data.conversation.type, // 'contact_form' or 'chat'
|
|
1401
|
+
customerEmail: data.conversation.email,
|
|
1402
|
+
});
|
|
1403
|
+
|
|
1404
|
+
// Example: Notify sales team for high-value customers
|
|
1405
|
+
if (data.conversation.metadata?.customerTier === 'enterprise') {
|
|
1406
|
+
await notifySalesTeam({
|
|
1407
|
+
conversationId: data.conversation.id,
|
|
1408
|
+
customerEmail: data.conversation.email,
|
|
1409
|
+
message: data.conversation.initialMessage,
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
async function handleNewMessage(data: any) {
|
|
1415
|
+
// Example: Auto-tag based on content
|
|
1416
|
+
const message = data.message.content.toLowerCase();
|
|
1417
|
+
|
|
1418
|
+
if (message.includes('bug') || message.includes('error')) {
|
|
1419
|
+
await tagConversation(data.conversation.id, 'bug');
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
if (message.includes('billing') || message.includes('payment')) {
|
|
1423
|
+
await tagConversation(data.conversation.id, 'billing');
|
|
1424
|
+
await assignToDepartment(data.conversation.id, 'billing');
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
// Example: Sentiment analysis
|
|
1428
|
+
const sentiment = await analyzeSentiment(message);
|
|
1429
|
+
if (sentiment === 'negative') {
|
|
1430
|
+
await escalateConversation(data.conversation.id, 'high');
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
async function handleConversationClosed(data: any) {
|
|
1435
|
+
// Example: Send satisfaction survey
|
|
1436
|
+
await sendSurveyEmail({
|
|
1437
|
+
to: data.conversation.email,
|
|
1438
|
+
conversationId: data.conversation.id,
|
|
1439
|
+
resolutionTime: data.metrics.resolutionTime,
|
|
1440
|
+
});
|
|
1441
|
+
|
|
1442
|
+
// Example: Update CRM
|
|
1443
|
+
await updateCRM({
|
|
1444
|
+
email: data.conversation.email,
|
|
1445
|
+
lastInteraction: new Date(),
|
|
1446
|
+
supportTicketId: data.conversation.id,
|
|
1447
|
+
resolved: true,
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
\`\`\`
|
|
1451
|
+
|
|
1452
|
+
### 3. Express.js Example
|
|
1453
|
+
|
|
1454
|
+
\`\`\`typescript
|
|
1455
|
+
import express from 'express';
|
|
1456
|
+
import crypto from 'crypto';
|
|
1457
|
+
|
|
1458
|
+
const app = express();
|
|
1459
|
+
|
|
1460
|
+
// Raw body needed for signature verification
|
|
1461
|
+
app.use('/webhooks/channlize', express.raw({ type: 'application/json' }));
|
|
1462
|
+
|
|
1463
|
+
app.post('/webhooks/channlize', (req, res) => {
|
|
1464
|
+
const signature = req.headers['x-channlize-signature'];
|
|
1465
|
+
const payload = req.body.toString();
|
|
1466
|
+
|
|
1467
|
+
// Verify signature
|
|
1468
|
+
const hmac = crypto.createHmac('sha256', process.env.CHANNLIZE_WEBHOOK_SECRET);
|
|
1469
|
+
const digest = hmac.update(payload).digest('hex');
|
|
1470
|
+
|
|
1471
|
+
if (signature !== digest) {
|
|
1472
|
+
return res.status(401).json({ error: 'Invalid signature' });
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
const event = JSON.parse(payload);
|
|
1476
|
+
|
|
1477
|
+
// Handle event
|
|
1478
|
+
handleEvent(event);
|
|
1479
|
+
|
|
1480
|
+
res.json({ received: true });
|
|
1481
|
+
});
|
|
1482
|
+
\`\`\`
|
|
1483
|
+
|
|
1484
|
+
## Webhook Event Payload Examples
|
|
1485
|
+
|
|
1486
|
+
### conversation.created
|
|
1487
|
+
|
|
1488
|
+
\`\`\`json
|
|
1489
|
+
{
|
|
1490
|
+
"type": "conversation.created",
|
|
1491
|
+
"timestamp": "2025-01-15T10:00:00Z",
|
|
1492
|
+
"data": {
|
|
1493
|
+
"conversation": {
|
|
1494
|
+
"id": "conv_123",
|
|
1495
|
+
"type": "contact_form",
|
|
1496
|
+
"status": "open",
|
|
1497
|
+
"email": "customer@example.com",
|
|
1498
|
+
"name": "John Doe",
|
|
1499
|
+
"initialMessage": "I need help with...",
|
|
1500
|
+
"metadata": {
|
|
1501
|
+
"pageUrl": "https://example.com/contact",
|
|
1502
|
+
"userAgent": "Mozilla/5.0..."
|
|
1503
|
+
},
|
|
1504
|
+
"createdAt": "2025-01-15T10:00:00Z"
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
\`\`\`
|
|
1509
|
+
|
|
1510
|
+
### message.created
|
|
1511
|
+
|
|
1512
|
+
\`\`\`json
|
|
1513
|
+
{
|
|
1514
|
+
"type": "message.created",
|
|
1515
|
+
"timestamp": "2025-01-15T10:05:00Z",
|
|
1516
|
+
"data": {
|
|
1517
|
+
"message": {
|
|
1518
|
+
"id": "msg_456",
|
|
1519
|
+
"conversationId": "conv_123",
|
|
1520
|
+
"content": "Thanks for reaching out!",
|
|
1521
|
+
"author": "agent",
|
|
1522
|
+
"authorData": {
|
|
1523
|
+
"name": "Sarah",
|
|
1524
|
+
"email": "sarah@example.com"
|
|
1525
|
+
},
|
|
1526
|
+
"timestamp": "2025-01-15T10:05:00Z"
|
|
1527
|
+
},
|
|
1528
|
+
"conversation": {
|
|
1529
|
+
"id": "conv_123",
|
|
1530
|
+
"status": "open"
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
\`\`\`
|
|
1535
|
+
|
|
1536
|
+
## Use Cases
|
|
1537
|
+
|
|
1538
|
+
1. **CRM Integration**: Sync conversations to Salesforce, HubSpot, etc.
|
|
1539
|
+
2. **Analytics**: Track support metrics in your data warehouse
|
|
1540
|
+
3. **Auto-routing**: Assign conversations based on content analysis
|
|
1541
|
+
4. **Notifications**: Alert teams via SMS, PagerDuty for urgent issues
|
|
1542
|
+
5. **AI Enhancement**: Feed messages to AI for sentiment/intent analysis
|
|
1543
|
+
6. **Billing**: Track support usage for metered billing
|
|
1544
|
+
|
|
1545
|
+
## Security Best Practices
|
|
1546
|
+
|
|
1547
|
+
- Always verify webhook signatures
|
|
1548
|
+
- Use HTTPS endpoints only
|
|
1549
|
+
- Rotate webhook secrets periodically
|
|
1550
|
+
- Implement rate limiting on webhook endpoints
|
|
1551
|
+
- Log all webhook events for audit trail
|
|
1552
|
+
`
|
|
1553
|
+
}
|
|
1554
|
+
];
|
|
1555
|
+
function getPrompt(name) {
|
|
1556
|
+
return prompts.find((p) => p.name === name);
|
|
1557
|
+
}
|
|
1558
|
+
function listPrompts() {
|
|
1559
|
+
return prompts;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// src/index.ts
|
|
1563
|
+
var ChannlizeMCPServer = class {
|
|
1564
|
+
server;
|
|
1565
|
+
config;
|
|
1566
|
+
constructor(options = {}) {
|
|
1567
|
+
this.config = options.config;
|
|
1568
|
+
this.server = new import_server.Server(
|
|
1569
|
+
{
|
|
1570
|
+
name: options.name || "channlize-mcp",
|
|
1571
|
+
version: options.version || "0.1.0"
|
|
1572
|
+
},
|
|
1573
|
+
{
|
|
1574
|
+
capabilities: {
|
|
1575
|
+
resources: {},
|
|
1576
|
+
tools: {},
|
|
1577
|
+
prompts: {}
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
);
|
|
1581
|
+
this.setupHandlers();
|
|
1582
|
+
}
|
|
1583
|
+
setupHandlers() {
|
|
1584
|
+
this.server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
|
|
1585
|
+
const resources2 = listResources();
|
|
1586
|
+
return {
|
|
1587
|
+
resources: resources2.map((r) => ({
|
|
1588
|
+
uri: r.uri,
|
|
1589
|
+
name: r.name,
|
|
1590
|
+
description: r.description,
|
|
1591
|
+
mimeType: r.mimeType
|
|
1592
|
+
}))
|
|
1593
|
+
};
|
|
1594
|
+
});
|
|
1595
|
+
this.server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
|
|
1596
|
+
const resource = getResource(request.params.uri);
|
|
1597
|
+
if (!resource) {
|
|
1598
|
+
throw new Error(`Resource not found: ${request.params.uri}`);
|
|
1599
|
+
}
|
|
1600
|
+
return {
|
|
1601
|
+
contents: [
|
|
1602
|
+
{
|
|
1603
|
+
uri: resource.uri,
|
|
1604
|
+
mimeType: resource.mimeType,
|
|
1605
|
+
text: resource.getText()
|
|
1606
|
+
}
|
|
1607
|
+
]
|
|
1608
|
+
};
|
|
1609
|
+
});
|
|
1610
|
+
this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
|
|
1611
|
+
const tools2 = listTools();
|
|
1612
|
+
return {
|
|
1613
|
+
tools: tools2.map((t) => ({
|
|
1614
|
+
name: t.name,
|
|
1615
|
+
description: t.description,
|
|
1616
|
+
inputSchema: t.inputSchema
|
|
1617
|
+
}))
|
|
1618
|
+
};
|
|
1619
|
+
});
|
|
1620
|
+
this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
1621
|
+
const tool = getTool(request.params.name);
|
|
1622
|
+
if (!tool) {
|
|
1623
|
+
throw new Error(`Tool not found: ${request.params.name}`);
|
|
1624
|
+
}
|
|
1625
|
+
if (!this.config?.apiKey) {
|
|
1626
|
+
throw new Error(
|
|
1627
|
+
"Channlize API key required. Please configure the MCP server with your API credentials."
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
const context = {
|
|
1631
|
+
config: this.config
|
|
1632
|
+
};
|
|
1633
|
+
try {
|
|
1634
|
+
const result = await tool.handler(request.params.arguments || {}, context);
|
|
1635
|
+
return {
|
|
1636
|
+
content: [
|
|
1637
|
+
{
|
|
1638
|
+
type: "text",
|
|
1639
|
+
text: JSON.stringify(result, null, 2)
|
|
1640
|
+
}
|
|
1641
|
+
]
|
|
1642
|
+
};
|
|
1643
|
+
} catch (error) {
|
|
1644
|
+
return {
|
|
1645
|
+
content: [
|
|
1646
|
+
{
|
|
1647
|
+
type: "text",
|
|
1648
|
+
text: JSON.stringify(
|
|
1649
|
+
{
|
|
1650
|
+
success: false,
|
|
1651
|
+
error: error.message || "Unknown error",
|
|
1652
|
+
code: error.code,
|
|
1653
|
+
statusCode: error.statusCode
|
|
1654
|
+
},
|
|
1655
|
+
null,
|
|
1656
|
+
2
|
|
1657
|
+
)
|
|
1658
|
+
}
|
|
1659
|
+
],
|
|
1660
|
+
isError: true
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
});
|
|
1664
|
+
this.server.setRequestHandler(import_types.ListPromptsRequestSchema, async () => {
|
|
1665
|
+
const prompts2 = listPrompts();
|
|
1666
|
+
return {
|
|
1667
|
+
prompts: prompts2.map((p) => ({
|
|
1668
|
+
name: p.name,
|
|
1669
|
+
description: p.description,
|
|
1670
|
+
arguments: p.arguments
|
|
1671
|
+
}))
|
|
1672
|
+
};
|
|
1673
|
+
});
|
|
1674
|
+
this.server.setRequestHandler(import_types.GetPromptRequestSchema, async (request) => {
|
|
1675
|
+
const prompt = getPrompt(request.params.name);
|
|
1676
|
+
if (!prompt) {
|
|
1677
|
+
throw new Error(`Prompt not found: ${request.params.name}`);
|
|
1678
|
+
}
|
|
1679
|
+
const args2 = request.params.arguments;
|
|
1680
|
+
const text = prompt.getPrompt(args2);
|
|
1681
|
+
return {
|
|
1682
|
+
description: prompt.description,
|
|
1683
|
+
messages: [
|
|
1684
|
+
{
|
|
1685
|
+
role: "user",
|
|
1686
|
+
content: {
|
|
1687
|
+
type: "text",
|
|
1688
|
+
text
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
]
|
|
1692
|
+
};
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Set or update the Channlize configuration
|
|
1697
|
+
*/
|
|
1698
|
+
setConfig(config2) {
|
|
1699
|
+
this.config = config2;
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Get the underlying MCP server instance
|
|
1703
|
+
*/
|
|
1704
|
+
getServer() {
|
|
1705
|
+
return this.server;
|
|
1706
|
+
}
|
|
1707
|
+
/**
|
|
1708
|
+
* Start the server with stdio transport
|
|
1709
|
+
*/
|
|
1710
|
+
async runStdio() {
|
|
1711
|
+
const transport = new import_stdio.StdioServerTransport();
|
|
1712
|
+
await this.server.connect(transport);
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Close the server
|
|
1716
|
+
*/
|
|
1717
|
+
async close() {
|
|
1718
|
+
await this.server.close();
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
|
|
1722
|
+
// src/server.ts
|
|
1723
|
+
var args = process.argv.slice(2);
|
|
1724
|
+
var getArg = (name) => {
|
|
1725
|
+
const index = args.findIndex((arg) => arg === `--${name}` || arg === `-${name[0]}`);
|
|
1726
|
+
return index >= 0 && index + 1 < args.length ? args[index + 1] : void 0;
|
|
1727
|
+
};
|
|
1728
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
1729
|
+
console.log(`
|
|
1730
|
+
Channlize MCP Server
|
|
1731
|
+
|
|
1732
|
+
Usage: channlize-mcp [options]
|
|
1733
|
+
|
|
1734
|
+
Options:
|
|
1735
|
+
--api-key <key> Channlize API key (widget key) [required]
|
|
1736
|
+
--project-id <id> Channlize project ID
|
|
1737
|
+
--base-url <url> Channlize API base URL (default: https://api.channlize.com)
|
|
1738
|
+
--timeout <ms> Request timeout in milliseconds (default: 10000)
|
|
1739
|
+
-h, --help Show this help message
|
|
1740
|
+
|
|
1741
|
+
Environment Variables:
|
|
1742
|
+
CHANNLIZE_API_KEY Alternative to --api-key
|
|
1743
|
+
CHANNLIZE_PROJECT_ID Alternative to --project-id
|
|
1744
|
+
CHANNLIZE_BASE_URL Alternative to --base-url
|
|
1745
|
+
CHANNLIZE_TIMEOUT Alternative to --timeout
|
|
1746
|
+
|
|
1747
|
+
Examples:
|
|
1748
|
+
# Using command line arguments
|
|
1749
|
+
channlize-mcp --api-key wk_123abc --project-id proj_456def
|
|
1750
|
+
|
|
1751
|
+
# Using environment variables
|
|
1752
|
+
export CHANNLIZE_API_KEY=wk_123abc
|
|
1753
|
+
export CHANNLIZE_PROJECT_ID=proj_456def
|
|
1754
|
+
channlize-mcp
|
|
1755
|
+
|
|
1756
|
+
Configuration in MCP Clients (e.g., Claude Desktop):
|
|
1757
|
+
{
|
|
1758
|
+
"mcpServers": {
|
|
1759
|
+
"channlize": {
|
|
1760
|
+
"command": "npx",
|
|
1761
|
+
"args": [
|
|
1762
|
+
"@channlize/mcp",
|
|
1763
|
+
"--api-key",
|
|
1764
|
+
"your-api-key",
|
|
1765
|
+
"--project-id",
|
|
1766
|
+
"your-project-id"
|
|
1767
|
+
]
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
Or with environment variables:
|
|
1773
|
+
{
|
|
1774
|
+
"mcpServers": {
|
|
1775
|
+
"channlize": {
|
|
1776
|
+
"command": "npx",
|
|
1777
|
+
"args": ["@channlize/mcp"],
|
|
1778
|
+
"env": {
|
|
1779
|
+
"CHANNLIZE_API_KEY": "your-api-key",
|
|
1780
|
+
"CHANNLIZE_PROJECT_ID": "your-project-id"
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
Resources:
|
|
1787
|
+
channlize://schema/contact-form - Contact form JSON schema
|
|
1788
|
+
channlize://schema/chat-session - Chat session JSON schema
|
|
1789
|
+
channlize://docs/api-reference - Full API documentation
|
|
1790
|
+
channlize://docs/quick-start - Quick start guide
|
|
1791
|
+
channlize://docs/react-components - React components guide
|
|
1792
|
+
|
|
1793
|
+
Tools:
|
|
1794
|
+
submit_contact_form - Submit a contact form inquiry
|
|
1795
|
+
create_chat_session - Create a new chat session
|
|
1796
|
+
send_message - Send a message in a chat session
|
|
1797
|
+
get_chat_messages - Retrieve chat message history
|
|
1798
|
+
close_chat_session - Close an active chat session
|
|
1799
|
+
|
|
1800
|
+
Prompts:
|
|
1801
|
+
integrate-contact-form - Guide for adding contact form to React app
|
|
1802
|
+
setup-live-chat - Guide for implementing live chat widget
|
|
1803
|
+
customize-styling - Guide for theming components
|
|
1804
|
+
handle-webhooks - Guide for webhook integration
|
|
1805
|
+
|
|
1806
|
+
For more information, visit: https://github.com/channlize/sdk
|
|
1807
|
+
`);
|
|
1808
|
+
process.exit(0);
|
|
1809
|
+
}
|
|
1810
|
+
var config = {
|
|
1811
|
+
apiKey: getArg("api-key") || process.env.CHANNLIZE_API_KEY || "",
|
|
1812
|
+
projectId: getArg("project-id") || process.env.CHANNLIZE_PROJECT_ID,
|
|
1813
|
+
baseUrl: getArg("base-url") || process.env.CHANNLIZE_BASE_URL,
|
|
1814
|
+
timeout: parseInt(
|
|
1815
|
+
getArg("timeout") || process.env.CHANNLIZE_TIMEOUT || "10000",
|
|
1816
|
+
10
|
|
1817
|
+
)
|
|
1818
|
+
};
|
|
1819
|
+
if (!config.apiKey) {
|
|
1820
|
+
console.error(`
|
|
1821
|
+
Error: Channlize API key is required
|
|
1822
|
+
|
|
1823
|
+
Please provide your API key using either:
|
|
1824
|
+
--api-key <key>
|
|
1825
|
+
or set CHANNLIZE_API_KEY environment variable
|
|
1826
|
+
|
|
1827
|
+
Get your API key from your Channlize dashboard.
|
|
1828
|
+
|
|
1829
|
+
Run 'channlize-mcp --help' for more information.
|
|
1830
|
+
`);
|
|
1831
|
+
process.exit(1);
|
|
1832
|
+
}
|
|
1833
|
+
var server = new ChannlizeMCPServer({
|
|
1834
|
+
name: "channlize-mcp",
|
|
1835
|
+
version: "0.1.0",
|
|
1836
|
+
config
|
|
1837
|
+
});
|
|
1838
|
+
process.on("SIGINT", async () => {
|
|
1839
|
+
await server.close();
|
|
1840
|
+
process.exit(0);
|
|
1841
|
+
});
|
|
1842
|
+
process.on("SIGTERM", async () => {
|
|
1843
|
+
await server.close();
|
|
1844
|
+
process.exit(0);
|
|
1845
|
+
});
|
|
1846
|
+
server.runStdio().catch((error) => {
|
|
1847
|
+
console.error("Failed to start Channlize MCP server:", error);
|
|
1848
|
+
process.exit(1);
|
|
1849
|
+
});
|
|
1850
|
+
//# sourceMappingURL=server.js.map
|