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