@channlize/mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/index.ts","../src/api.ts","../src/config.ts","../src/prompts.ts","../src/docs.ts","../src/resources.ts","../src/tools.ts","../src/http.ts"],"sourcesContent":["/**\n * Channlize MCP server CLI: `npx -y @channlize/mcp [options]`.\n */\nimport { parseArgs } from 'node:util';\nimport {\n ChannlizeMCPServer,\n ConfigError,\n configFromEnv,\n VERSION,\n} from './index';\n\nconst HELP = `Channlize MCP server ${VERSION}\n\nUsage: channlize-mcp [options]\n\nKeys (flags override environment variables):\n --server-api-key <key> Server API key, ch_live_… CHANNLIZE_SERVER_API_KEY\n --widget-key <key> Public widget key, wk_… CHANNLIZE_WIDGET_KEY\n --api-key <key> Either kind, by prefix CHANNLIZE_API_KEY\n --project-id <id> Project (default: the key's first project)\n CHANNLIZE_PROJECT_ID\nOptions:\n --base-url <url> API URL (default https://api.channlize.com)\n CHANNLIZE_BASE_URL\n --timeout <ms> Request timeout (default 10000)\n CHANNLIZE_TIMEOUT\n --transport <t> stdio (default) or http CHANNLIZE_MCP_TRANSPORT\n --host <host> HTTP bind address (default 127.0.0.1)\n --port <port> HTTP port (default 3333) CHANNLIZE_MCP_PORT\n -v, --version Print the version\n -h, --help Show this help\n\nThe server API key enables the inbox, contact, Events and log tools (read\nscope for reads, write scope to send). The widget key adds visitor tools\n(contact form, chat). Create keys in the Channlize dashboard under\nSDK & Integration → API keys.\n\nClaude Code:\n claude mcp add channlize --env CHANNLIZE_SERVER_API_KEY=ch_live_… -- npx -y @channlize/mcp\n\nDocs: https://github.com/channlize/sdk/tree/main/packages/mcp\n`;\n\nfunction fail(message: string): never {\n console.error(\n `channlize-mcp: ${message}\\n\\nRun 'channlize-mcp --help' for usage.`\n );\n process.exit(1);\n}\n\nasync function main() {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n options: {\n 'server-api-key': { type: 'string' },\n 'widget-key': { type: 'string' },\n 'api-key': { type: 'string' },\n 'project-id': { type: 'string' },\n 'base-url': { type: 'string' },\n timeout: { type: 'string' },\n transport: { type: 'string' },\n host: { type: 'string' },\n port: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n },\n strict: true,\n }));\n } catch (err) {\n fail((err as Error).message);\n }\n if (values.help) {\n console.log(HELP);\n return;\n }\n if (values.version) {\n console.log(VERSION);\n return;\n }\n\n const str = (k: string) => values[k] as string | undefined;\n const env = configFromEnv();\n const timeout = str('timeout');\n const config = {\n serverApiKey: str('server-api-key') ?? env.serverApiKey,\n widgetKey: str('widget-key') ?? env.widgetKey,\n apiKey: str('api-key') ?? env.apiKey,\n projectId: str('project-id') ?? env.projectId,\n baseUrl: str('base-url') ?? env.baseUrl,\n timeout: timeout !== undefined ? Number(timeout) : env.timeout,\n };\n\n const transport =\n str('transport') ?? process.env.CHANNLIZE_MCP_TRANSPORT ?? 'stdio';\n if (transport !== 'stdio' && transport !== 'http') {\n fail(`unknown transport \"${transport}\": use stdio or http`);\n }\n\n let server: ChannlizeMCPServer;\n try {\n server = new ChannlizeMCPServer({ config });\n } catch (err) {\n if (err instanceof ConfigError) fail(err.message);\n throw err;\n }\n\n if (transport === 'http') {\n const port = Number(str('port') ?? process.env.CHANNLIZE_MCP_PORT ?? 3333);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n fail(`invalid port \"${str('port') ?? process.env.CHANNLIZE_MCP_PORT}\"`);\n }\n const { url, close } = await server.runHttp({ host: str('host'), port });\n // stdout is free on the HTTP transport; logs still go to stderr.\n console.error(`Channlize MCP server listening on ${url}`);\n const stop = async () => {\n await close();\n process.exit(0);\n };\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n return;\n }\n\n // stdio: stdout carries the protocol, so never log to it.\n const stop = async () => {\n await server.close();\n process.exit(0);\n };\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n await server.runStdio();\n}\n\nmain().catch((err: Error) => {\n console.error('Failed to start the Channlize MCP server:', err.message);\n process.exit(1);\n});\n","/**\n * @channlize/mcp\n * Model Context Protocol (MCP) server for Channlize: lets AI assistants\n * read conversations, contacts, logs and Events, and send Events to Slack.\n */\n\nimport { McpServer } from '@modelcontextprotocol/server';\nimport { StdioServerTransport } from '@modelcontextprotocol/server/stdio';\nimport { ChannlizeApi } from './api';\nimport { resolveConfig, type ResolvedConfig } from './config';\nimport { registerGuidePrompts, registerServerPrompts } from './prompts';\nimport { registerResources } from './resources';\nimport { registerServerTools, registerWidgetTools } from './tools';\nimport type { ChannlizeMCPConfig, MCPServerOptions } from './types';\nimport { startHttpServer, type HttpServerOptions } from './http';\n\ndeclare const __PACKAGE_VERSION__: string;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : '0.0.0';\n\nexport * from './types';\nexport { ConfigError, configFromEnv, resolveConfig, keyKind } from './config';\nexport type { ResolvedConfig, KeyKind } from './config';\nexport { ToolError } from './api';\nexport type { HttpServerOptions } from './http';\n\n// Re-export core types for convenience\nexport type {\n ChannlizeConfig,\n ContactFormData,\n ChatMessage,\n ChatSession,\n FileAttachment,\n CreateContactResponse,\n CreateChatSessionResponse,\n SendMessageResponse,\n ChannlizeError,\n ValidationError,\n AuthenticationError,\n RateLimitError,\n NotifyResponse,\n} from '@channlize/core';\n\nconst INSTRUCTIONS = `Channlize routes website conversations and app events to the team's Slack.\n- Inbox: list_conversations / get_conversation, then contacts. Replies and status changes happen in Slack or the dashboard.\n- Events (notify_event) post a Slack message per event key; list_event_definitions and list_event_deliveries explain what was sent or skipped.\n- Logs: query_logs searches log tracking; track_log records one.\n- Write tools need a server API key with the write scope; a 403 means the key is read-only.`;\n\n/**\n * Builds a configured `McpServer` (tools, resources and prompts) without\n * connecting it. Tools are registered for the keys you pass: server-key\n * tools for `serverApiKey`, visitor tools for `widgetKey`.\n */\nexport function buildServer(\n config: ChannlizeMCPConfig,\n info: { name?: string; version?: string } = {}\n): McpServer {\n const api = new ChannlizeApi(resolveConfig(config));\n const server = new McpServer(\n { name: info.name ?? 'channlize', version: info.version ?? VERSION },\n { instructions: INSTRUCTIONS }\n );\n if (api.hasServerKey) {\n registerServerTools(server, api);\n registerServerPrompts(server);\n }\n if (api.hasWidgetKey) registerWidgetTools(server, api);\n registerResources(server, api);\n registerGuidePrompts(server);\n return server;\n}\n\n/**\n * Channlize MCP server. Validates the configuration on construction (a\n * missing key or a widget key passed as the server key throws\n * `ConfigError`).\n */\nexport class ChannlizeMCPServer {\n private server: McpServer;\n private readonly config: ResolvedConfig;\n private readonly info: { name?: string; version?: string };\n\n constructor(options: MCPServerOptions = {}) {\n this.config = resolveConfig(options.config ?? {});\n this.info = { name: options.name, version: options.version };\n this.server = buildServer(this.config, this.info);\n }\n\n /** The underlying `McpServer`. */\n getServer(): McpServer {\n return this.server;\n }\n\n /** Serve over stdio (what desktop and IDE clients launch). */\n async runStdio(): Promise<void> {\n await this.server.connect(new StdioServerTransport());\n }\n\n /**\n * Serve Streamable HTTP at `http://<host>:<port>/mcp` (default\n * 127.0.0.1:3333). Each request gets a fresh server; nothing is shared.\n */\n async runHttp(options: HttpServerOptions = {}) {\n return startHttpServer(() => buildServer(this.config, this.info), options);\n }\n\n async close(): Promise<void> {\n await this.server.close();\n }\n}\n\n/** Create a new Channlize MCP server. */\nexport function createMCPServer(\n options?: MCPServerOptions\n): ChannlizeMCPServer {\n return new ChannlizeMCPServer(options);\n}\n\nexport default ChannlizeMCPServer;\n","import { ChannlizeClient, ChannlizeError } from '@channlize/core';\nimport type { ResolvedConfig } from './config';\n\n/**\n * A failed Channlize call, worded for the model: what went wrong and how\n * to fix it (wrong key, missing scope, unknown id). Tool handlers throw it\n * and the MCP server returns it as a tool error (`isError: true`).\n */\nexport class ToolError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public code?: string\n ) {\n super(message);\n this.name = 'ToolError';\n }\n}\n\ntype Query = Record<string, string | number | boolean | undefined>;\n\nfunction hintFor(status: number, apiMessage: string): string {\n switch (status) {\n case 401:\n return `${apiMessage}. The server API key is invalid, revoked or expired: create a new one under SDK & Integration → API keys and update CHANNLIZE_SERVER_API_KEY.`;\n case 403:\n return /permission/i.test(apiMessage)\n ? `${apiMessage}. This needs a server API key with the ${\n /write|notify/.test(apiMessage) ? 'write' : 'read'\n } scope: create one under SDK & Integration → API keys.`\n : apiMessage;\n case 404:\n return `${apiMessage}. Check the ID (and CHANNLIZE_PROJECT_ID): it must belong to the key's organization.`;\n case 429:\n return `${apiMessage}. Rate limited: wait a little before retrying.`;\n default:\n return apiMessage;\n }\n}\n\n/** Maps a `@channlize/core` error to a `ToolError` with the same hints. */\nexport function toToolError(err: unknown): ToolError {\n if (err instanceof ToolError) return err;\n if (err instanceof ChannlizeError) {\n return new ToolError(\n err.statusCode ? hintFor(err.statusCode, err.message) : err.message,\n err.statusCode,\n err.code\n );\n }\n return new ToolError(err instanceof Error ? err.message : String(err));\n}\n\n/**\n * Thin client for the API-key endpoints `@channlize/core` doesn't wrap\n * (projects, conversations, contacts, Events and log reads). Widget-key\n * calls and `notify` go through `@channlize/core`.\n */\nexport class ChannlizeApi {\n private projectIdPromise?: Promise<string>;\n private widgetClient?: ChannlizeClient;\n\n constructor(readonly config: ResolvedConfig) {}\n\n get hasServerKey(): boolean {\n return !!this.config.serverApiKey;\n }\n\n get hasWidgetKey(): boolean {\n return !!this.config.widgetKey;\n }\n\n private requireServerKey(): string {\n if (!this.config.serverApiKey) {\n throw new ToolError(\n 'This tool needs a server API key (ch_live_…): set CHANNLIZE_SERVER_API_KEY or pass --server-api-key.'\n );\n }\n return this.config.serverApiKey;\n }\n\n async request<T>(\n method: 'GET' | 'POST',\n path: string,\n options: {\n query?: Query;\n body?: unknown;\n headers?: Record<string, string>;\n } = {}\n ): Promise<T> {\n const key = this.requireServerKey();\n const url = new URL(`${this.config.baseUrl}${path}`);\n for (const [k, v] of Object.entries(options.query ?? {})) {\n if (v !== undefined && v !== '') url.searchParams.set(k, String(v));\n }\n\n let res: Response;\n try {\n res = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${key}`,\n Accept: 'application/json',\n ...(options.body !== undefined\n ? { 'Content-Type': 'application/json' }\n : {}),\n ...options.headers,\n },\n body:\n options.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal: AbortSignal.timeout(this.config.timeout),\n });\n } catch (err) {\n const e = err as Error;\n if (e.name === 'TimeoutError' || e.name === 'AbortError') {\n throw new ToolError(\n `Channlize API timed out after ${this.config.timeout} ms (${method} ${url.pathname}). Retry, or raise CHANNLIZE_TIMEOUT.`,\n 408,\n 'TIMEOUT'\n );\n }\n throw new ToolError(\n `Could not reach the Channlize API at ${this.config.baseUrl}: ${e.message}`\n );\n }\n\n const text = await res.text();\n let data: unknown = undefined;\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n data = undefined;\n }\n }\n\n if (!res.ok) {\n const body = (data ?? {}) as {\n message?: string | string[];\n error?: string;\n code?: string;\n };\n const raw = Array.isArray(body.message)\n ? body.message.join(', ')\n : body.message;\n // `{ statusCode, error: \"NOT_FOUND\", message }`; a few legacy routes\n // put the human text in `error`.\n const apiMessage =\n raw ||\n (typeof body.error === 'string' && /\\s/.test(body.error)\n ? body.error\n : '') ||\n `HTTP ${res.status} ${res.statusText}`.trim();\n throw new ToolError(\n hintFor(res.status, apiMessage.replace(/\\.$/, '')),\n res.status,\n body.code ?? (typeof body.error === 'string' ? body.error : undefined)\n );\n }\n if (data === undefined) {\n throw new ToolError(\n `Unexpected non-JSON response from ${method} ${url.pathname}`\n );\n }\n return data as T;\n }\n\n /**\n * `CHANNLIZE_PROJECT_ID`, or the first project of the key's organization\n * (`GET /projects/me`), looked up once.\n */\n projectId(): Promise<string> {\n if (this.config.projectId) return Promise.resolve(this.config.projectId);\n this.projectIdPromise ??= this.request<{ project: { id: string } }>(\n 'GET',\n '/projects/me'\n )\n .then(r => {\n if (!r.project?.id) {\n throw new ToolError(\n 'Could not find a project for this key: set CHANNLIZE_PROJECT_ID.'\n );\n }\n return r.project.id;\n })\n .catch(err => {\n this.projectIdPromise = undefined;\n throw err;\n });\n return this.projectIdPromise;\n }\n\n /** `@channlize/core` client bound to the widget key (visitor tools). */\n widget(): ChannlizeClient {\n if (!this.config.widgetKey) {\n throw new ToolError(\n 'This tool needs the public widget key (wk_…): set CHANNLIZE_WIDGET_KEY or pass --widget-key.'\n );\n }\n this.widgetClient ??= new ChannlizeClient({\n apiKey: this.config.widgetKey,\n projectId: this.config.projectId ?? '',\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n });\n return this.widgetClient;\n }\n\n /** `@channlize/core` client for `notify` (server key + project). */\n async notifier(): Promise<ChannlizeClient> {\n const serverApiKey = this.requireServerKey();\n return new ChannlizeClient({\n // core requires a widget key; notify only uses serverApiKey.\n apiKey: this.config.widgetKey ?? 'unused',\n serverApiKey,\n projectId: await this.projectId(),\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n });\n }\n}\n","import type { ChannlizeMCPConfig } from './types';\n\nexport const DEFAULT_BASE_URL = 'https://api.channlize.com';\nexport const DEFAULT_TIMEOUT = 10000;\n\n/** A configuration problem the user must fix; the CLI prints it and exits 1. */\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigError';\n }\n}\n\nexport type KeyKind = 'widget' | 'server';\n\n/** `wk_…` is the public widget key; anything else is a server API key (`ch_live_…`). */\nexport function keyKind(key: string): KeyKind {\n return key.startsWith('wk_') ? 'widget' : 'server';\n}\n\nexport interface ResolvedConfig {\n serverApiKey?: string;\n widgetKey?: string;\n projectId?: string;\n baseUrl: string;\n timeout: number;\n}\n\nfunction clean(value: string | undefined): string | undefined {\n const v = value?.trim();\n return v ? v : undefined;\n}\n\n/**\n * Normalizes the config: `apiKey` (either kind, detected by prefix) fills\n * whichever of `serverApiKey` / `widgetKey` is missing, and a key passed in\n * the wrong slot fails with a message that says which one to use.\n */\nexport function resolveConfig(config: ChannlizeMCPConfig): ResolvedConfig {\n let serverApiKey = clean(config.serverApiKey);\n let widgetKey = clean(config.widgetKey);\n const apiKey = clean(config.apiKey);\n\n if (serverApiKey && keyKind(serverApiKey) === 'widget') {\n throw new ConfigError(\n 'CHANNLIZE_SERVER_API_KEY / --server-api-key holds a widget key (wk_…). ' +\n 'Widget keys are public and only work for the visitor tools: pass it as ' +\n 'CHANNLIZE_WIDGET_KEY / --widget-key, and create a server API key (ch_live_…) ' +\n 'under SDK & Integration → API keys in the Channlize dashboard.'\n );\n }\n if (widgetKey && keyKind(widgetKey) === 'server') {\n throw new ConfigError(\n 'CHANNLIZE_WIDGET_KEY / --widget-key holds a server API key. Pass server keys ' +\n '(ch_live_…) as CHANNLIZE_SERVER_API_KEY / --server-api-key; widget keys start with wk_.'\n );\n }\n if (apiKey) {\n if (keyKind(apiKey) === 'widget') widgetKey ??= apiKey;\n else serverApiKey ??= apiKey;\n }\n\n if (!serverApiKey && !widgetKey) {\n throw new ConfigError(\n 'A Channlize key is required. Set CHANNLIZE_SERVER_API_KEY (or --server-api-key) ' +\n 'to a server API key (ch_live_…) from SDK & Integration → API keys in the ' +\n 'Channlize dashboard. Use a read-scoped key for read-only access, or add the ' +\n 'write scope to send events, logs and conversations.'\n );\n }\n\n const timeout = config.timeout ?? DEFAULT_TIMEOUT;\n if (!Number.isFinite(timeout) || timeout <= 0) {\n throw new ConfigError(\n `Invalid timeout \"${config.timeout}\": use milliseconds, e.g. 10000`\n );\n }\n\n const baseUrl = (clean(config.baseUrl) ?? DEFAULT_BASE_URL).replace(\n /\\/+$/,\n ''\n );\n try {\n new URL(baseUrl);\n } catch {\n throw new ConfigError(\n `Invalid base URL \"${config.baseUrl}\": use e.g. ${DEFAULT_BASE_URL}`\n );\n }\n\n return {\n serverApiKey,\n widgetKey,\n projectId: clean(config.projectId),\n baseUrl,\n timeout,\n };\n}\n\n/** Reads `ChannlizeMCPConfig` from the environment (CLI flags override it). */\nexport function configFromEnv(\n env: NodeJS.ProcessEnv = process.env\n): ChannlizeMCPConfig {\n const timeout = clean(env.CHANNLIZE_TIMEOUT);\n return {\n serverApiKey: clean(env.CHANNLIZE_SERVER_API_KEY),\n widgetKey: clean(env.CHANNLIZE_WIDGET_KEY),\n apiKey: clean(env.CHANNLIZE_API_KEY),\n projectId: clean(env.CHANNLIZE_PROJECT_ID),\n baseUrl: clean(env.CHANNLIZE_BASE_URL),\n timeout: timeout ? Number(timeout) : undefined,\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/server';\nimport * as z from 'zod/v4';\nimport { EVENTS, REACT_COMPONENTS } from './docs';\n\nfunction user(text: string) {\n return {\n messages: [\n { role: 'user' as const, content: { type: 'text' as const, text } },\n ],\n };\n}\n\n/** Prompts that use the live tools (need a server API key). */\nexport function registerServerPrompts(server: McpServer) {\n server.registerPrompt(\n 'triage-conversations',\n {\n title: 'Triage open conversations',\n description:\n 'Review open support conversations, rank them by urgency and draft a reply for each.',\n argsSchema: z.object({\n status: z\n .string()\n .optional()\n .describe(\n 'Status to triage: open (default), pending, resolved or closed'\n ),\n limit: z\n .string()\n .optional()\n .describe('How many conversations (default 10)'),\n }),\n },\n ({ status, limit }) =>\n user(`Triage my Channlize support inbox.\n\n1. Call list_conversations with status \"${status || 'open'}\" and limit ${Number(limit) || 10}.\n2. For each conversation, call get_conversation to read the thread.\n3. Return a table sorted by urgency: subject, customer, how long it has waited, current priority, a suggested priority (low / normal / high / urgent) and a one-line reason.\n4. Under the table, draft a short, friendly reply for each conversation that needs one, and flag anything that looks like a bug, an outage or a billing problem.\n\nReplies and status or priority changes are made by the team in the Slack thread or the Channlize dashboard, so present the drafts for me to send; don't invent facts about my product.`)\n );\n\n server.registerPrompt(\n 'summarize-conversation',\n {\n title: 'Summarize a conversation',\n description: 'Summarize one conversation and suggest the next step.',\n argsSchema: z.object({\n conversationId: z.string().describe('Conversation ID'),\n }),\n },\n ({ conversationId }) =>\n user(\n `Call get_conversation with conversationId \"${conversationId}\". Summarize it in five bullet points or fewer: what the customer wants, what has been answered, what is still open, and the customer's mood. Then suggest the next step and draft a reply if one is needed.`\n )\n );\n\n server.registerPrompt(\n 'check-events',\n {\n title: 'Check Events delivery',\n description:\n 'Check that Events reach Slack: list them and explain failed or skipped deliveries.',\n argsSchema: z.object({}),\n },\n () =>\n user(`Check my Channlize Events setup.\n\n1. Call list_event_definitions and list the Events, flagging disabled drafts and Events without a Slack channel.\n2. Call list_event_deliveries (limit 50) and group the deliveries by status.\n3. For each failed or skipped delivery, explain the reason and how to fix it (enable the Event, pick a channel under Events in the dashboard, invite the Slack app to the channel, or connect Slack).`)\n );\n}\n\n/** Integration guides (no key needed beyond startup). */\nexport function registerGuidePrompts(server: McpServer) {\n server.registerPrompt(\n 'setup-events',\n {\n title: 'Add Events to my app',\n description:\n 'Add Channlize Events (notify Slack from server code) to the current codebase.',\n argsSchema: z.object({\n events: z\n .string()\n .optional()\n .describe('Events to add, e.g. \"signup, subscription upgrade\"'),\n }),\n },\n ({ events }) =>\n user(`Add Channlize Events to this codebase${events ? ` for: ${events}` : ''}.\n\nFind where these things happen on the server, then call notify there with a typed event map and an idempotency key derived from the record ID. Never call it from browser code. Read the server key from CHANNLIZE_SERVER_API_KEY and the project from CHANNLIZE_PROJECT_ID, and add both to the env example file. Don't let a notify failure break the request: catch and log it.\n\nReference:\n\n${EVENTS}`)\n );\n\n server.registerPrompt(\n 'setup-live-chat',\n {\n title: 'Add the chat widget',\n description:\n 'Add the Channlize live chat widget to a React or Next.js app.',\n argsSchema: z.object({\n framework: z\n .string()\n .optional()\n .describe('e.g. Next.js App Router, Vite, Remix'),\n }),\n },\n ({ framework }) =>\n user(`Add the Channlize chat widget to this ${framework || 'React'} app: install @channlize/react, render ChannlizeChat once in the root layout (from a 'use client' component on Next.js), read the widget key and project ID from public env variables, and match primaryColor to the app's brand color.\n\nReference:\n\n${REACT_COMPONENTS}`)\n );\n\n server.registerPrompt(\n 'integrate-contact-form',\n {\n title: 'Add a contact form',\n description: 'Add a Channlize contact form page to a React app.',\n argsSchema: z.object({\n styling: z\n .string()\n .optional()\n .describe('Styling approach, e.g. Tailwind or CSS modules'),\n }),\n },\n ({ styling }) =>\n user(`Add a contact page to this app using Channlize. Use the ContactForm component (or useContactForm with a custom form${styling ? ` styled with ${styling}` : ''}) inside ChannlizeProvider, show a clear success state, and surface errors from onError.\n\nReference:\n\n${REACT_COMPONENTS}`)\n );\n}\n","/**\n * Integration docs served as MCP resources and reused by the prompts.\n * Keep in sync with the public API of `@channlize/core` and\n * `@channlize/react` (their `src/index.ts`).\n */\n\nexport const QUICK_START = `# Channlize quick start\n\nChannlize routes website conversations and app events to Slack.\n\n## Keys\n- **Widget key** (\\`wk_…\\`): public, safe in browser code. Used by the chat widget,\n contact form and browser log tracking (\\`apiKey\\` in the SDK config).\n- **Server API key** (\\`ch_live_…\\`): secret, server only (\\`serverApiKey\\`). Scopes:\n \\`read\\` (conversations, contacts, logs, Events) and \\`write\\` (notify, server logs,\n create conversations/contacts). Create both under SDK & Integration → API keys.\n- **Project ID**: shown next to each widget key.\n\n## Install\n\\`\\`\\`bash\nnpm install @channlize/core # any JS runtime\nnpm install @channlize/react # React components and hooks\n\\`\\`\\`\n\n## Browser\n\\`\\`\\`ts\nimport { ChannlizeClient } from '@channlize/core';\n\nconst client = new ChannlizeClient({ apiKey: 'wk_…', projectId: '<project-id>' });\nawait client.submitContactForm({ name: 'Ada', email: 'ada@example.com', message: 'Hi!' });\nawait client.trackEvent('checkout.started', { properties: { cartId: 'c_1' } });\n\\`\\`\\`\n\n## Server\n\\`\\`\\`ts\nimport { createNotifier } from '@channlize/core';\n\n// Reads CHANNLIZE_SERVER_API_KEY (or CHANNLIZE_API_KEY) and CHANNLIZE_PROJECT_ID.\nconst notify = createNotifier();\nawait notify('user.subscribed', { username: 'ada', plan: 'Pro' });\n\\`\\`\\`\n\nErrors are \\`ChannlizeError\\` (\\`statusCode\\`, \\`code\\`), with subclasses\n\\`ValidationError\\` (400), \\`AuthenticationError\\` (401) and \\`RateLimitError\\` (429).\n`;\n\nexport const REACT_COMPONENTS = `# @channlize/react\n\n\\`\\`\\`bash\nnpm install @channlize/react\n\\`\\`\\`\n\n## Floating chat widget (all-in-one)\n\\`ChannlizeChat\\` includes the provider, launcher button and chat window.\n\n\\`\\`\\`tsx\n'use client';\nimport { ChannlizeChat } from '@channlize/react';\n\nexport function SupportWidget() {\n return (\n <ChannlizeChat\n config={{\n apiKey: process.env.NEXT_PUBLIC_CHANNLIZE_WIDGET_KEY!, // wk_…, public\n projectId: process.env.NEXT_PUBLIC_CHANNLIZE_PROJECT_ID!,\n }}\n position=\"bottom-right\"\n primaryColor=\"#2563eb\"\n theme=\"auto\"\n chatProps={{ title: 'Acme Support', greeting: 'Hi there!', welcomeMessage: 'Ask us anything.' }}\n />\n );\n}\n\\`\\`\\`\n\nKey props: \\`position\\` ('bottom-right' | 'bottom-left' | 'top-right' | 'top-left'),\n\\`primaryColor\\`, \\`theme\\` ('auto' | 'light' | 'dark'), \\`defaultOpen\\`, \\`showOnMobile\\`,\n\\`offset\\`, \\`zIndex\\`, \\`onOpen\\`, \\`onClose\\`, and \\`chatProps\\` (SupportChat props).\n\n## Provider + inline components\n\\`\\`\\`tsx\nimport { ChannlizeProvider, SupportChat, ContactForm } from '@channlize/react';\n\n<ChannlizeProvider config={{ apiKey: 'wk_…', projectId: '<project-id>' }}>\n <SupportChat title=\"Need help?\" greeting=\"Hi!\" suggestions={['Pricing', 'Billing']} />\n <ContactForm submitText=\"Send\" successMessage=\"Thanks! We'll reply by email.\" />\n</ChannlizeProvider>\n\\`\\`\\`\n\nSupportChat props include \\`title\\`, \\`greeting\\`, \\`welcomeMessage\\`, \\`suggestions\\`,\n\\`placeholder\\`, \\`allowAttachments\\`, \\`allowEndChat\\`, \\`theme\\`, \\`primaryColor\\`,\n\\`locale\\`, \\`maxLength\\`, \\`labels\\` and the \\`useChatSession\\` options\n(\\`autoConnect\\`, \\`metadata\\`, \\`persistSession\\`, \\`onMessage\\`, \\`onError\\`).\n\nContactForm props: \\`customFields\\`, \\`onSuccess\\`, \\`onError\\`, \\`className\\`, \\`styles\\`,\n\\`submitText\\`, \\`successMessage\\`.\n\n## Hooks (inside ChannlizeProvider)\n- \\`useChatSession(options)\\` → \\`{ session, messages, isConnecting, isConnected, error,\n sendMessage, startSession, endSession, reconnect }\\`\n- \\`useContactForm({ onSuccess, onError })\\` → \\`{ submit, isSubmitting, isSuccess, error, reset }\\`\n- \\`useChannlizeAnalytics()\\` → \\`{ track(name, { properties, severity }) }\\` (log tracking)\n- \\`useChannlize()\\` → \\`{ client, config }\\`\n\n## Next.js App Router\nComponents use state and effects: render them from a \\`'use client'\\` file. The widget\nkey is public (\\`NEXT_PUBLIC_…\\` is fine); never put the server API key in a\n\\`NEXT_PUBLIC_\\` variable.\n`;\n\nexport const EVENTS = `# Events: notify Slack from code\n\nEach event key (e.g. \\`user.subscribed\\`) has a Slack channel and a message template\nwith \\`{{field}}\\` placeholders, set under Events in the dashboard. A key that isn't set\nup yet is saved as a disabled draft the first time it is sent (\\`status: 'skipped'\\`),\nso you can ship code first and configure it after. Server only: needs a server API key\nwith the \\`write\\` scope.\n\n\\`\\`\\`ts\nimport { createNotifier } from '@channlize/core';\n\ntype AppEvents = {\n 'user.subscribed': { username: string; plan: string };\n 'invoice.paid': { amount: string; customer: string };\n};\n\n// Env: CHANNLIZE_SERVER_API_KEY (or CHANNLIZE_API_KEY), CHANNLIZE_PROJECT_ID.\nconst notify = createNotifier<AppEvents>();\n\nconst res = await notify('user.subscribed', { username: 'ada', plan: 'Pro' });\n// res.status: 'queued' | 'skipped' (see res.reason); res.duplicate on a repeated key\n\n// Retry-safe: an idempotency key already used posts nothing.\nawait notify('invoice.paid', { amount: '$49', customer: 'ada@example.com' }, { idempotencyKey: 'inv_123' });\n\\`\\`\\`\n\nTo type keys app-wide instead, augment the interface:\n\\`\\`\\`ts\ndeclare module '@channlize/core' {\n interface ChannlizeEvents {\n 'user.subscribed': { username: string; plan: string };\n }\n}\n\\`\\`\\`\n\nOver HTTP:\n\\`\\`\\`bash\ncurl -X POST https://api.channlize.com/v1/notify \\\\\n -H \"Authorization: Bearer $CHANNLIZE_SERVER_API_KEY\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -H \"Idempotency-Key: signup-42\" \\\\\n -d '{\"projectId\":\"<project-id>\",\"event\":\"user.subscribed\",\"data\":{\"username\":\"ada\"}}'\n\\`\\`\\`\n\nLog tracking is separate: \\`client.trackEvent\\` (browser) / \\`trackServerEvent\\` (server)\nrecord log lines shown under Log tracking.\n`;\n","import type { McpServer } from '@modelcontextprotocol/server';\nimport type { ChannlizeApi } from './api';\nimport { EVENTS, QUICK_START, REACT_COMPONENTS } from './docs';\n\nconst markdown = (uri: string, text: string) => ({\n contents: [{ uri, mimeType: 'text/markdown', text }],\n});\n\nexport function registerResources(server: McpServer, api: ChannlizeApi) {\n server.registerResource(\n 'quick-start',\n 'channlize://docs/quick-start',\n {\n title: 'Channlize quick start',\n description:\n 'Keys, install, and first calls from the browser and the server.',\n mimeType: 'text/markdown',\n },\n uri => markdown(uri.href, QUICK_START)\n );\n server.registerResource(\n 'react-components',\n 'channlize://docs/react-components',\n {\n title: '@channlize/react components and hooks',\n description:\n 'ChannlizeChat, SupportChat, ContactForm, hooks and Next.js notes.',\n mimeType: 'text/markdown',\n },\n uri => markdown(uri.href, REACT_COMPONENTS)\n );\n server.registerResource(\n 'events',\n 'channlize://docs/events',\n {\n title: 'Events: notify Slack from code',\n description:\n 'createNotifier / notify with typed events, idempotency and curl.',\n mimeType: 'text/markdown',\n },\n uri => markdown(uri.href, EVENTS)\n );\n\n if (api.hasServerKey) {\n server.registerResource(\n 'project',\n 'channlize://project',\n {\n title: 'Current Channlize project',\n description:\n \"The key's project: ID, name, totals, permissions and Slack connection.\",\n mimeType: 'application/json',\n },\n async uri => {\n const r = await api.request<{ project: unknown }>(\n 'GET',\n '/projects/me'\n );\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(r.project, null, 2),\n },\n ],\n };\n }\n );\n }\n}\n","/**\n * MCP tools for Channlize.\n *\n * Server-key tools (`ch_live_…`) are registered when a server API key is\n * configured; visitor tools (contact form, chat) when a widget key is.\n * Every tool returns its result as `structuredContent` (matching its\n * `outputSchema`) plus the same JSON as text for clients that ignore it.\n * Failures are tool errors (`isError: true`) with a message that says how\n * to fix them.\n */\nimport type { McpServer } from '@modelcontextprotocol/server';\nimport * as z from 'zod/v4';\nimport { ChannlizeApi, toToolError } from './api';\n\nconst STATUSES = ['open', 'pending', 'resolved', 'closed'] as const;\nconst PRIORITIES = ['low', 'normal', 'high', 'urgent'] as const;\nconst SEVERITIES = ['info', 'warning', 'error'] as const;\nconst EVENT_KEY = /^[a-z0-9][a-z0-9._-]*$/;\n\ntype Json = Record<string, unknown>;\n\nfunction ok(data: Json) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }],\n structuredContent: data,\n };\n}\n\n/** Runs a handler, turning any failure into a readable tool error. */\nasync function run(fn: () => Promise<Json>) {\n try {\n return ok(await fn());\n } catch (err) {\n const e = toToolError(err);\n return {\n content: [{ type: 'text' as const, text: e.message }],\n isError: true,\n };\n }\n}\n\nconst record = z.record(z.string(), z.unknown());\nconst loose = z.looseObject({});\nconst page = {\n total: z.number(),\n limit: z.number(),\n offset: z.number(),\n hasMore: z.boolean(),\n};\n\nconst conversationSummary = z.looseObject({\n id: z.string(),\n subject: z.string().nullable().optional(),\n status: z.string(),\n priority: z.string().nullable().optional(),\n customerEmail: z.string().nullable().optional(),\n customerName: z.string().nullable().optional(),\n tags: z.array(z.string()).nullable().optional(),\n createdAt: z.string().optional(),\n});\n\nconst READ = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n} as const;\n\nexport function registerServerTools(server: McpServer, api: ChannlizeApi) {\n server.registerTool(\n 'get_project',\n {\n title: 'Get project',\n description:\n \"Show the Channlize project behind the server API key: name, ID, totals, the key's permissions and whether Slack is connected. Start here to check the setup.\",\n inputSchema: z.object({}),\n outputSchema: z.object({ project: loose }),\n annotations: READ,\n },\n () =>\n run(async () => {\n const r = await api.request<{ project: Json }>('GET', '/projects/me');\n return { project: r.project };\n })\n );\n\n server.registerTool(\n 'get_analytics',\n {\n title: 'Get analytics',\n description:\n 'Daily support activity for the last 30 days (UTC): conversations created and resolved, customer and agent messages.',\n inputSchema: z.object({}),\n outputSchema: z.object({ analytics: loose }),\n annotations: READ,\n },\n () =>\n run(async () => {\n const r = await api.request<{ analytics: Json }>(\n 'GET',\n '/projects/analytics'\n );\n return { analytics: r.analytics };\n })\n );\n\n server.registerTool(\n 'list_conversations',\n {\n title: 'List conversations',\n description:\n \"List the organization's most recent support conversations (newest first, from the latest 50), optionally filtered by status or priority. Use get_conversation for the messages.\",\n inputSchema: z.object({\n status: z\n .enum(STATUSES)\n .optional()\n .describe('Only conversations with this status'),\n priority: z\n .enum(PRIORITIES)\n .optional()\n .describe('Only conversations with this priority'),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(20)\n .describe('How many to return (1-50, default 20)'),\n }),\n outputSchema: z.object({\n conversations: z.array(conversationSummary),\n returned: z.number(),\n matched: z.number(),\n scanned: z.number(),\n }),\n annotations: READ,\n },\n ({ status, priority, limit }) =>\n run(async () => {\n const r = await api.request<{ conversations: Json[] }>(\n 'GET',\n '/conversations'\n );\n const all = r.conversations ?? [];\n const matched = all.filter(\n c =>\n (!status || c.status === status) &&\n (!priority || c.priority === priority)\n );\n const conversations = matched.slice(0, limit);\n return {\n conversations,\n returned: conversations.length,\n matched: matched.length,\n scanned: all.length,\n };\n })\n );\n\n server.registerTool(\n 'get_conversation',\n {\n title: 'Get conversation',\n description:\n 'Read one conversation with its full message thread (customer, agent and system messages), status, priority and tags.',\n inputSchema: z.object({\n conversationId: z\n .string()\n .uuid()\n .describe('Conversation ID (from list_conversations)'),\n }),\n outputSchema: z.object({ conversation: loose }),\n annotations: READ,\n },\n ({ conversationId }) =>\n run(async () => {\n const conversation = await api.request<Json>(\n 'GET',\n `/conversations/${encodeURIComponent(conversationId)}`\n );\n return { conversation };\n })\n );\n\n server.registerTool(\n 'create_conversation',\n {\n title: 'Create conversation',\n description:\n 'Open a new support conversation on behalf of a customer. It is posted to Slack (the given channel, else routing rules, else the default channel). Needs the write scope. Repeating the same customer, subject and message within 30 seconds returns the existing conversation.',\n inputSchema: z.object({\n customerEmail: z.email().describe(\"Customer's email address\"),\n customerName: z\n .string()\n .max(255)\n .optional()\n .describe(\"Customer's name\"),\n subject: z.string().min(1).max(500).describe('Subject line'),\n message: z.string().min(1).describe('First message, from the customer'),\n channel: z\n .string()\n .optional()\n .describe('Slack channel ID to post to, overriding routing rules'),\n tags: z.array(z.string()).max(20).optional().describe('Tags'),\n }),\n outputSchema: z.object({ conversation: loose }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n args =>\n run(async () => {\n const conversation = await api.request<Json>('POST', '/conversations', {\n body: args,\n });\n return { conversation };\n })\n );\n\n server.registerTool(\n 'list_contacts',\n {\n title: 'List contacts',\n description:\n 'List the customers who contacted the organization, with their conversation count. Paginate with limit/offset.',\n inputSchema: z.object({\n limit: z.number().int().min(1).max(100).default(50),\n offset: z.number().int().min(0).default(0),\n }),\n outputSchema: z.object({ contacts: z.array(loose), ...page }),\n annotations: READ,\n },\n ({ limit, offset }) =>\n run(async () => {\n const r = await api.request<Json>('GET', '/contacts', {\n query: { limit, offset },\n });\n return {\n contacts: (r.contacts as Json[]) ?? [],\n total: Number(r.total ?? 0),\n limit: Number(r.limit ?? limit),\n offset: Number(r.offset ?? offset),\n hasMore: Boolean(r.hasMore),\n };\n })\n );\n\n server.registerTool(\n 'get_contact',\n {\n title: 'Get contact',\n description: 'Read one contact (customer) by ID.',\n inputSchema: z.object({\n contactId: z\n .string()\n .uuid()\n .describe('Contact ID (from list_contacts)'),\n }),\n outputSchema: z.object({ contact: loose }),\n annotations: READ,\n },\n ({ contactId }) =>\n run(async () => {\n const contact = await api.request<Json>(\n 'GET',\n `/contacts/${encodeURIComponent(contactId)}`\n );\n return { contact };\n })\n );\n\n server.registerTool(\n 'create_contact',\n {\n title: 'Create contact',\n description:\n 'Add a customer by email, or return the existing one with that email. Needs the write scope.',\n inputSchema: z.object({\n email: z.email(),\n name: z.string().max(255).optional(),\n company: z.string().optional(),\n phone: z.string().optional(),\n tags: z.array(z.string()).max(20).optional(),\n }),\n outputSchema: z.object({ contact: loose }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n args =>\n run(async () => {\n const contact = await api.request<Json>('POST', '/contacts', {\n body: args,\n });\n return { contact };\n })\n );\n\n server.registerTool(\n 'notify_event',\n {\n title: 'Send an Event to Slack',\n description:\n 'Post an Event to Slack: the event key (e.g. \"user.subscribed\") picks the channel and message template set under Events in the dashboard, and `data` fills its {{placeholders}}. An unknown key is saved as a disabled draft and answered with status \"skipped\". Needs the write scope. Pass an idempotencyKey so a retry never posts twice.',\n inputSchema: z.object({\n event: z\n .string()\n .max(100)\n .regex(\n EVENT_KEY,\n 'lowercase letters, digits, dots, underscores or dashes'\n )\n .describe('Event key, e.g. user.subscribed'),\n data: record\n .optional()\n .describe(\n 'Template fields, e.g. { \"username\": \"ada\", \"plan\": \"Pro\" }'\n ),\n idempotencyKey: z\n .string()\n .min(1)\n .max(255)\n .optional()\n .describe('Send at most once per key (retry-safe)'),\n channel: z\n .string()\n .optional()\n .describe(\"Slack channel ID instead of the event's channel\"),\n }),\n outputSchema: z.looseObject({\n id: z.string(),\n event: z.string(),\n status: z.string(),\n reason: z.string().optional(),\n duplicate: z.boolean().optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n ({ event, data, idempotencyKey, channel }) =>\n run(async () => {\n const client = await api.notifier();\n const r = await client.notify(event, data, { idempotencyKey, channel });\n return {\n id: r.id,\n event: r.event,\n status: r.status,\n ...(r.reason ? { reason: r.reason } : {}),\n ...(r.duplicate ? { duplicate: true } : {}),\n };\n })\n );\n\n server.registerTool(\n 'list_event_definitions',\n {\n title: 'List Events',\n description:\n 'List the Events configured on the project (key, name, Slack channel, message template, enabled), including disabled drafts created by unknown keys sent with notify_event.',\n inputSchema: z.object({}),\n outputSchema: z.object({\n projectId: z.string(),\n definitions: z.array(loose),\n }),\n annotations: READ,\n },\n () =>\n run(async () => {\n const projectId = await api.projectId();\n const r = await api.request<{ definitions: Json[] }>(\n 'GET',\n `/v1/projects/${encodeURIComponent(projectId)}/event-definitions`\n );\n return { projectId, definitions: r.definitions ?? [] };\n })\n );\n\n server.registerTool(\n 'list_event_deliveries',\n {\n title: 'List Event deliveries',\n description:\n 'Recent notify_event deliveries on the project, newest first, with their status (queued, sent, failed, skipped) and the reason when not sent. Use it to check why an Event did not reach Slack.',\n inputSchema: z.object({\n definitionId: z\n .string()\n .uuid()\n .optional()\n .describe('Only this Event (ID from list_event_definitions)'),\n limit: z.number().int().min(1).max(100).default(20),\n }),\n outputSchema: z.object({\n projectId: z.string(),\n deliveries: z.array(loose),\n }),\n annotations: READ,\n },\n ({ definitionId, limit }) =>\n run(async () => {\n const projectId = await api.projectId();\n const r = await api.request<{ deliveries: Json[] }>(\n 'GET',\n `/v1/projects/${encodeURIComponent(projectId)}/event-deliveries`,\n { query: { definitionId, limit } }\n );\n return { projectId, deliveries: r.deliveries ?? [] };\n })\n );\n\n server.registerTool(\n 'query_logs',\n {\n title: 'Query logs',\n description:\n 'Search log tracking (trackEvent / trackServerEvent / track_log), newest first. Filter by severity, source, text (matches the name and properties) and time range; paginate with limit/offset. Covers all projects unless projectId is given.',\n inputSchema: z.object({\n severity: z.enum(SEVERITIES).optional(),\n source: z\n .enum(['client_sdk', 'server_api', 'system'])\n .optional()\n .describe(\n 'client_sdk = browser (widget key), server_api = server key'\n ),\n search: z.string().max(200).optional().describe('Text to look for'),\n from: z.iso\n .datetime({ offset: true })\n .optional()\n .describe('ISO 8601 start'),\n to: z.iso\n .datetime({ offset: true })\n .optional()\n .describe('ISO 8601 end'),\n projectId: z.string().uuid().optional(),\n limit: z.number().int().min(1).max(100).default(50),\n offset: z.number().int().min(0).default(0),\n }),\n outputSchema: z.object({ events: z.array(loose), ...page }),\n annotations: READ,\n },\n args =>\n run(async () => {\n const r = await api.request<Json>('GET', '/v1/events', { query: args });\n return {\n events: (r.events as Json[]) ?? [],\n total: Number(r.total ?? 0),\n limit: Number(r.limit ?? args.limit),\n offset: Number(r.offset ?? args.offset),\n hasMore: Boolean(r.hasMore),\n };\n })\n );\n\n server.registerTool(\n 'track_log',\n {\n title: 'Record a log',\n description:\n 'Record a log line under Log tracking from a trusted server context (source server_api). Needs the write scope. For Slack messages about product events use notify_event instead.',\n inputSchema: z.object({\n name: z\n .string()\n .min(1)\n .max(255)\n .describe('Log name, e.g. payment.failed'),\n severity: z.enum(SEVERITIES).default('info'),\n properties: record.optional().describe('Extra fields'),\n }),\n outputSchema: z.object({ id: z.string(), projectId: z.string() }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n ({ name, severity, properties }) =>\n run(async () => {\n const projectId = await api.projectId();\n const r = await api.request<{ id: string }>('POST', '/v1/events', {\n body: { projectId, name, severity, properties },\n });\n return { id: r.id, projectId };\n })\n );\n}\n\nconst VISITOR = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n} as const;\n\n/** Tools that act as a website visitor, with the public widget key. */\nexport function registerWidgetTools(server: McpServer, api: ChannlizeApi) {\n server.registerTool(\n 'submit_contact_form',\n {\n title: 'Submit contact form',\n description:\n 'Submit the website contact form as a visitor (widget key). Creates a conversation that is posted to Slack. Useful to test the setup end to end.',\n inputSchema: z.object({\n name: z.string().min(1).describe(\"Visitor's name\"),\n email: z.email().describe(\"Visitor's email\"),\n subject: z.string().optional(),\n message: z.string().min(1),\n pageUrl: z.url().optional().describe('Page the form was sent from'),\n }),\n outputSchema: z.looseObject({\n conversationId: z.string().optional(),\n message: z.string().optional(),\n }),\n annotations: VISITOR,\n },\n args =>\n run(async () => {\n const r = await api.widget().submitContactForm(args);\n return { conversationId: r.conversationId, message: r.message };\n })\n );\n\n server.registerTool(\n 'create_chat_session',\n {\n title: 'Start chat session',\n description:\n 'Start a live chat session as a website visitor (widget key). Returns the session ID for send_message.',\n inputSchema: z.object({\n metadata: record\n .optional()\n .describe('Metadata to attach (e.g. user info)'),\n }),\n outputSchema: z.looseObject({\n sessionId: z.string(),\n status: z.string(),\n }),\n annotations: VISITOR,\n },\n ({ metadata }) =>\n run(async () => {\n const r = await api.widget().createChatSession(metadata);\n return {\n sessionId: r.session.id,\n status: r.session.status,\n createdAt: String(r.session.createdAt),\n };\n })\n );\n\n server.registerTool(\n 'send_message',\n {\n title: 'Send chat message',\n description:\n 'Send a visitor message in a chat session (widget key); it is posted to the Slack thread.',\n inputSchema: z.object({\n sessionId: z.string().min(1).describe('From create_chat_session'),\n content: z.string().min(1).max(5000),\n }),\n outputSchema: z.looseObject({\n messageId: z.string(),\n sessionStatus: z.string(),\n }),\n annotations: VISITOR,\n },\n ({ sessionId, content }) =>\n run(async () => {\n const r = await api.widget().sendMessage(sessionId, content);\n return { messageId: r.message.id, sessionStatus: r.session.status };\n })\n );\n\n server.registerTool(\n 'get_chat_messages',\n {\n title: 'Read chat messages',\n description:\n \"Read a chat session's messages, including agent replies from Slack (widget key).\",\n inputSchema: z.object({\n sessionId: z.string().min(1),\n limit: z.number().int().min(1).max(100).default(50),\n offset: z.number().int().min(0).default(0),\n }),\n outputSchema: z.object({\n sessionId: z.string(),\n messages: z.array(loose),\n }),\n annotations: { ...READ, openWorldHint: true },\n },\n ({ sessionId, limit, offset }) =>\n run(async () => {\n const messages = await api\n .widget()\n .getChatMessages(sessionId, limit, offset);\n return {\n sessionId,\n messages: messages.map(m => ({\n id: m.id,\n author: m.author,\n authorName: m.authorData?.name,\n content: m.content,\n timestamp: String(m.timestamp),\n attachments: m.attachments?.length ?? 0,\n })),\n };\n })\n );\n\n server.registerTool(\n 'close_chat_session',\n {\n title: 'End chat session',\n description: 'End a chat session as the visitor (widget key).',\n inputSchema: z.object({ sessionId: z.string().min(1) }),\n outputSchema: z.looseObject({\n sessionId: z.string(),\n status: z.string(),\n }),\n annotations: { ...VISITOR, idempotentHint: true },\n },\n ({ sessionId }) =>\n run(async () => {\n const s = await api.widget().closeChatSession(sessionId);\n return { sessionId: s.id ?? sessionId, status: s.status };\n })\n );\n}\n","import { createServer, type IncomingMessage, type Server } from 'node:http';\nimport {\n createMcpHandler,\n hostHeaderValidationResponse,\n localhostAllowedHostnames,\n localhostAllowedOrigins,\n originValidationResponse,\n type McpServer,\n} from '@modelcontextprotocol/server';\n\nexport interface HttpServerOptions {\n /** Interface to bind (default 127.0.0.1). */\n host?: string;\n /** Port (default 3333). */\n port?: number;\n /** Endpoint path (default /mcp). */\n path?: string;\n}\n\nconst LOCAL_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);\n\nasync function toRequest(\n req: IncomingMessage,\n origin: string\n): Promise<Request> {\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) v.forEach(x => headers.append(k, x));\n else if (v !== undefined) headers.set(k, v);\n }\n let body: Uint8Array<ArrayBuffer> | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n body = new Uint8Array(Buffer.concat(chunks));\n }\n const controller = new AbortController();\n req.on('close', () => {\n if (!req.complete) controller.abort();\n });\n return new Request(new URL(req.url ?? '/', origin), {\n method: req.method,\n headers,\n body,\n signal: controller.signal,\n });\n}\n\n/**\n * Streamable HTTP transport on `node:http`. Stateless: every request is\n * served by a fresh server from `factory`. Bound to localhost by default,\n * with Host and Origin checks against DNS rebinding.\n */\nexport async function startHttpServer(\n factory: () => McpServer,\n options: HttpServerOptions = {}\n): Promise<{ url: string; server: Server; close: () => Promise<void> }> {\n const host = options.host ?? '127.0.0.1';\n const port = options.port ?? 3333;\n const path = options.path ?? '/mcp';\n const local = LOCAL_HOSTS.has(host);\n const handler = createMcpHandler(() => factory(), {\n onerror: err => console.error('[channlize-mcp]', err.message),\n });\n\n const server = createServer(async (req, res) => {\n try {\n const request = await toRequest(\n req,\n `http://${req.headers.host ?? `${host}:${port}`}`\n );\n const url = new URL(request.url);\n if (url.pathname !== path) {\n res\n .writeHead(404, { 'Content-Type': 'text/plain' })\n .end(`Not found: use ${path}`);\n return;\n }\n const rejected = local\n ? (hostHeaderValidationResponse(request, localhostAllowedHostnames()) ??\n originValidationResponse(request, localhostAllowedOrigins()))\n : undefined;\n const response = rejected ?? (await handler.fetch(request));\n res.writeHead(response.status, Object.fromEntries(response.headers));\n if (response.body) {\n for await (const chunk of response.body as unknown as AsyncIterable<Uint8Array>) {\n res.write(chunk);\n }\n }\n res.end();\n } catch (err) {\n console.error('[channlize-mcp]', (err as Error).message);\n if (!res.headersSent)\n res.writeHead(500, { 'Content-Type': 'text/plain' });\n res.end('Internal server error');\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => resolve());\n });\n const address = server.address();\n const actualPort =\n typeof address === 'object' && address ? address.port : port;\n const shownHost = host.includes(':') ? `[${host}]` : host;\n return {\n url: `http://${shownHost}:${actualPort}${path}`,\n server,\n close: () => new Promise<void>(r => server.close(() => r())),\n };\n}\n"],"mappings":"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","names":["import_server","url","z","record","url","url","stop"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/index.ts","../src/api.ts","../src/config.ts","../src/prompts.ts","../src/docs.ts","../src/resources.ts","../src/tools.ts","../src/http.ts"],"sourcesContent":["/**\n * Channlize MCP server CLI: `npx -y @channlize/mcp [options]`.\n */\nimport { parseArgs } from 'node:util';\nimport {\n ChannlizeMCPServer,\n ConfigError,\n configFromEnv,\n VERSION,\n} from './index';\n\nconst HELP = `Channlize MCP server ${VERSION}\n\nUsage: channlize-mcp [options]\n\nKeys (flags override environment variables):\n --server-api-key <key> Server API key, ch_live_… CHANNLIZE_SERVER_API_KEY\n --widget-key <key> Public widget key, wk_… CHANNLIZE_WIDGET_KEY\n --api-key <key> Either kind, by prefix CHANNLIZE_API_KEY\n --project-id <id> Project (default: the key's first project)\n CHANNLIZE_PROJECT_ID\nOptions:\n --base-url <url> API URL (default https://api.channlize.com)\n CHANNLIZE_BASE_URL\n --timeout <ms> Request timeout (default 10000)\n CHANNLIZE_TIMEOUT\n --transport <t> stdio (default) or http CHANNLIZE_MCP_TRANSPORT\n --host <host> HTTP bind address (default 127.0.0.1)\n --port <port> HTTP port (default 3333) CHANNLIZE_MCP_PORT\n -v, --version Print the version\n -h, --help Show this help\n\nThe server API key enables the inbox, contact, Events and log tools (read\nscope for reads, write scope to send). The widget key adds visitor tools\n(contact form, chat). Create keys in the Channlize dashboard under\nSDK & Integration → API keys.\n\nClaude Code:\n claude mcp add channlize --env CHANNLIZE_SERVER_API_KEY=ch_live_… -- npx -y @channlize/mcp\n\nDocs: https://github.com/channlize/sdk/tree/main/packages/mcp\n`;\n\nfunction fail(message: string): never {\n console.error(\n `channlize-mcp: ${message}\\n\\nRun 'channlize-mcp --help' for usage.`\n );\n process.exit(1);\n}\n\nasync function main() {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n options: {\n 'server-api-key': { type: 'string' },\n 'widget-key': { type: 'string' },\n 'api-key': { type: 'string' },\n 'project-id': { type: 'string' },\n 'base-url': { type: 'string' },\n timeout: { type: 'string' },\n transport: { type: 'string' },\n host: { type: 'string' },\n port: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n },\n strict: true,\n }));\n } catch (err) {\n fail((err as Error).message);\n }\n if (values.help) {\n console.log(HELP);\n return;\n }\n if (values.version) {\n console.log(VERSION);\n return;\n }\n\n const str = (k: string) => values[k] as string | undefined;\n const env = configFromEnv();\n const timeout = str('timeout');\n const config = {\n serverApiKey: str('server-api-key') ?? env.serverApiKey,\n widgetKey: str('widget-key') ?? env.widgetKey,\n apiKey: str('api-key') ?? env.apiKey,\n projectId: str('project-id') ?? env.projectId,\n baseUrl: str('base-url') ?? env.baseUrl,\n timeout: timeout !== undefined ? Number(timeout) : env.timeout,\n };\n\n const transport =\n str('transport') ?? process.env.CHANNLIZE_MCP_TRANSPORT ?? 'stdio';\n if (transport !== 'stdio' && transport !== 'http') {\n fail(`unknown transport \"${transport}\": use stdio or http`);\n }\n\n let server: ChannlizeMCPServer;\n try {\n server = new ChannlizeMCPServer({ config });\n } catch (err) {\n if (err instanceof ConfigError) fail(err.message);\n throw err;\n }\n\n if (transport === 'http') {\n const port = Number(str('port') ?? process.env.CHANNLIZE_MCP_PORT ?? 3333);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n fail(`invalid port \"${str('port') ?? process.env.CHANNLIZE_MCP_PORT}\"`);\n }\n const { url, close } = await server.runHttp({ host: str('host'), port });\n // stdout is free on the HTTP transport; logs still go to stderr.\n console.error(`Channlize MCP server listening on ${url}`);\n const stop = async () => {\n await close();\n process.exit(0);\n };\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n return;\n }\n\n // stdio: stdout carries the protocol, so never log to it.\n const stop = async () => {\n await server.close();\n process.exit(0);\n };\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n await server.runStdio();\n}\n\nmain().catch((err: Error) => {\n console.error('Failed to start the Channlize MCP server:', err.message);\n process.exit(1);\n});\n","/**\n * @channlize/mcp\n * Model Context Protocol (MCP) server for Channlize: lets AI assistants\n * read conversations, contacts, logs and Events, and send Events to Slack.\n */\n\nimport { McpServer } from '@modelcontextprotocol/server';\nimport { StdioServerTransport } from '@modelcontextprotocol/server/stdio';\nimport { ChannlizeApi } from './api';\nimport { resolveConfig, type ResolvedConfig } from './config';\nimport { registerGuidePrompts, registerServerPrompts } from './prompts';\nimport { registerResources } from './resources';\nimport { registerServerTools, registerWidgetTools } from './tools';\nimport type { ChannlizeMCPConfig, MCPServerOptions } from './types';\nimport { startHttpServer, type HttpServerOptions } from './http';\n\ndeclare const __PACKAGE_VERSION__: string;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : '0.0.0';\n\nexport * from './types';\nexport { ConfigError, configFromEnv, resolveConfig, keyKind } from './config';\nexport type { ResolvedConfig, KeyKind } from './config';\nexport { ToolError } from './api';\nexport type { HttpServerOptions } from './http';\n\n// Re-export core types for convenience\nexport type {\n ChannlizeConfig,\n ContactFormData,\n ChatMessage,\n ChatSession,\n FileAttachment,\n CreateContactResponse,\n CreateChatSessionResponse,\n SendMessageResponse,\n NotifyResponse,\n} from '@channlize/core';\n\nconst INSTRUCTIONS = `Channlize routes website conversations and app events to the team's Slack.\n- Inbox: list_conversations / get_conversation, then contacts. Replies and status changes happen in Slack or the dashboard.\n- Events (notify_event) post a Slack message per event key; list_event_definitions and list_event_deliveries explain what was sent or skipped.\n- Logs: query_logs searches log tracking; track_log records one.\n- Write tools need a server API key with the write scope; a 403 means the key is read-only.`;\n\n/**\n * Builds a configured `McpServer` (tools, resources and prompts) without\n * connecting it. Tools are registered for the keys you pass: server-key\n * tools for `serverApiKey`, visitor tools for `widgetKey`.\n */\nexport function buildServer(\n config: ChannlizeMCPConfig,\n info: { name?: string; version?: string } = {}\n): McpServer {\n const api = new ChannlizeApi(resolveConfig(config));\n const server = new McpServer(\n { name: info.name ?? 'channlize', version: info.version ?? VERSION },\n { instructions: INSTRUCTIONS }\n );\n if (api.hasServerKey) {\n registerServerTools(server, api);\n registerServerPrompts(server);\n }\n if (api.hasWidgetKey) registerWidgetTools(server, api);\n registerResources(server, api);\n registerGuidePrompts(server);\n return server;\n}\n\n/**\n * Channlize MCP server. Validates the configuration on construction (a\n * missing key or a widget key passed as the server key throws\n * `ConfigError`).\n */\nexport class ChannlizeMCPServer {\n private server: McpServer;\n private readonly config: ResolvedConfig;\n private readonly info: { name?: string; version?: string };\n\n constructor(options: MCPServerOptions = {}) {\n this.config = resolveConfig(options.config ?? {});\n this.info = { name: options.name, version: options.version };\n this.server = buildServer(this.config, this.info);\n }\n\n /** The underlying `McpServer`. */\n getServer(): McpServer {\n return this.server;\n }\n\n /** Serve over stdio (what desktop and IDE clients launch). */\n async runStdio(): Promise<void> {\n await this.server.connect(new StdioServerTransport());\n }\n\n /**\n * Serve Streamable HTTP at `http://<host>:<port>/mcp` (default\n * 127.0.0.1:3333). Each request gets a fresh server; nothing is shared.\n */\n async runHttp(options: HttpServerOptions = {}) {\n return startHttpServer(() => buildServer(this.config, this.info), options);\n }\n\n async close(): Promise<void> {\n await this.server.close();\n }\n}\n\n/** Create a new Channlize MCP server. */\nexport function createMCPServer(\n options?: MCPServerOptions\n): ChannlizeMCPServer {\n return new ChannlizeMCPServer(options);\n}\n\nexport default ChannlizeMCPServer;\n\n// Error classes as values, so `instanceof` works without importing core.\nexport {\n ChannlizeError,\n ValidationError,\n AuthenticationError,\n RateLimitError,\n} from '@channlize/core';\n","import {\n ChannlizeClient,\n ChannlizeError,\n parseApiError,\n} from '@channlize/core';\nimport type { ResolvedConfig } from './config';\n\n/**\n * A failed Channlize call, worded for the model: what went wrong and how\n * to fix it (wrong key, missing scope, unknown id). Tool handlers throw it\n * and the MCP server returns it as a tool error (`isError: true`).\n */\nexport class ToolError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public code?: string\n ) {\n super(message);\n this.name = 'ToolError';\n }\n}\n\ntype Query = Record<string, string | number | boolean | undefined>;\n\nfunction hintFor(status: number, apiMessage: string): string {\n switch (status) {\n case 401:\n return `${apiMessage}. The server API key is invalid, revoked or expired: create a new one under SDK & Integration → API keys and update CHANNLIZE_SERVER_API_KEY.`;\n case 403:\n return /permission/i.test(apiMessage)\n ? `${apiMessage}. This needs a server API key with the ${\n /write|notify/.test(apiMessage) ? 'write' : 'read'\n } scope: create one under SDK & Integration → API keys.`\n : apiMessage;\n case 404:\n return `${apiMessage}. Check the ID (and CHANNLIZE_PROJECT_ID): it must belong to the key's organization.`;\n case 429:\n return `${apiMessage}. Rate limited: wait a little before retrying.`;\n default:\n return apiMessage;\n }\n}\n\n/** Maps a `@channlize/core` error to a `ToolError` with the same hints. */\nexport function toToolError(err: unknown): ToolError {\n if (err instanceof ToolError) return err;\n if (err instanceof ChannlizeError) {\n return new ToolError(\n err.statusCode\n ? hintFor(err.statusCode, err.message.replace(/\\.$/, ''))\n : err.message,\n err.statusCode,\n err.code\n );\n }\n return new ToolError(err instanceof Error ? err.message : String(err));\n}\n\n/**\n * Thin client for the API-key endpoints `@channlize/core` doesn't wrap\n * (projects, conversations, contacts, Events and log reads). Widget-key\n * calls and `notify` go through `@channlize/core`.\n */\nexport class ChannlizeApi {\n private projectIdPromise?: Promise<string>;\n private widgetClient?: ChannlizeClient;\n\n constructor(readonly config: ResolvedConfig) {}\n\n get hasServerKey(): boolean {\n return !!this.config.serverApiKey;\n }\n\n get hasWidgetKey(): boolean {\n return !!this.config.widgetKey;\n }\n\n private requireServerKey(): string {\n if (!this.config.serverApiKey) {\n throw new ToolError(\n 'This tool needs a server API key (ch_live_…): set CHANNLIZE_SERVER_API_KEY or pass --server-api-key.'\n );\n }\n return this.config.serverApiKey;\n }\n\n async request<T>(\n method: 'GET' | 'POST',\n path: string,\n options: {\n query?: Query;\n body?: unknown;\n headers?: Record<string, string>;\n } = {}\n ): Promise<T> {\n const key = this.requireServerKey();\n const url = new URL(`${this.config.baseUrl}${path}`);\n for (const [k, v] of Object.entries(options.query ?? {})) {\n if (v !== undefined && v !== '') url.searchParams.set(k, String(v));\n }\n\n let res: Response;\n try {\n res = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${key}`,\n Accept: 'application/json',\n ...(options.body !== undefined\n ? { 'Content-Type': 'application/json' }\n : {}),\n ...options.headers,\n },\n // oxlint-disable-next-line unicorn/no-invalid-fetch-options -- `method` is dynamic; GET calls never pass a body.\n body:\n options.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal: AbortSignal.timeout(this.config.timeout),\n });\n } catch (err) {\n const e = err as Error;\n if (e.name === 'TimeoutError' || e.name === 'AbortError') {\n throw new ToolError(\n `Channlize API timed out after ${this.config.timeout} ms (${method} ${url.pathname}). Retry, or raise CHANNLIZE_TIMEOUT.`,\n 408,\n 'TIMEOUT'\n );\n }\n throw new ToolError(\n `Could not reach the Channlize API at ${this.config.baseUrl}: ${e.message}`\n );\n }\n\n const text = await res.text();\n let data: unknown = undefined;\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n data = undefined;\n }\n }\n\n if (!res.ok) {\n const { message, code } = parseApiError(res.status, data, res.statusText);\n throw new ToolError(\n hintFor(res.status, message.replace(/\\.$/, '')),\n res.status,\n code\n );\n }\n if (data === undefined) {\n throw new ToolError(\n `Unexpected non-JSON response from ${method} ${url.pathname}`\n );\n }\n return data as T;\n }\n\n /**\n * `CHANNLIZE_PROJECT_ID`, or the first project of the key's organization\n * (`GET /projects/me`), looked up once.\n */\n projectId(): Promise<string> {\n if (this.config.projectId) return Promise.resolve(this.config.projectId);\n this.projectIdPromise ??= this.request<{ project: { id: string } }>(\n 'GET',\n '/projects/me'\n )\n .then(r => {\n if (!r.project?.id) {\n throw new ToolError(\n 'Could not find a project for this key: set CHANNLIZE_PROJECT_ID.'\n );\n }\n return r.project.id;\n })\n .catch(err => {\n this.projectIdPromise = undefined;\n throw err;\n });\n return this.projectIdPromise;\n }\n\n /** `@channlize/core` client bound to the widget key (visitor tools). */\n widget(): ChannlizeClient {\n if (!this.config.widgetKey) {\n throw new ToolError(\n 'This tool needs the public widget key (wk_…): set CHANNLIZE_WIDGET_KEY or pass --widget-key.'\n );\n }\n this.widgetClient ??= new ChannlizeClient({\n apiKey: this.config.widgetKey,\n projectId: this.config.projectId ?? '',\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n });\n return this.widgetClient;\n }\n\n /** `@channlize/core` client for `notify` (server key + project). */\n async notifier(): Promise<ChannlizeClient> {\n const serverApiKey = this.requireServerKey();\n return new ChannlizeClient({\n // core requires a widget key; notify only uses serverApiKey.\n apiKey: this.config.widgetKey ?? 'unused',\n serverApiKey,\n projectId: await this.projectId(),\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n });\n }\n}\n","import {\n DEFAULT_BASE_URL,\n DEFAULT_TIMEOUT,\n keyKind,\n readChannlizeEnv,\n} from '@channlize/core';\nimport type { ChannlizeMCPConfig } from './types';\n\n// Key detection lives in @channlize/core; re-exported for compatibility.\nexport { keyKind };\nexport type { KeyKind } from '@channlize/core';\n\n/** A configuration problem the user must fix; the CLI prints it and exits 1. */\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigError';\n }\n}\n\nexport interface ResolvedConfig {\n serverApiKey?: string;\n widgetKey?: string;\n projectId?: string;\n baseUrl: string;\n timeout: number;\n}\n\nfunction clean(value: string | undefined): string | undefined {\n const v = value?.trim();\n return v ? v : undefined;\n}\n\n/**\n * Normalizes the config: `apiKey` (either kind, detected by prefix) fills\n * whichever of `serverApiKey` / `widgetKey` is missing, and a key passed in\n * the wrong slot fails with a message that says which one to use.\n */\nexport function resolveConfig(config: ChannlizeMCPConfig): ResolvedConfig {\n let serverApiKey = clean(config.serverApiKey);\n let widgetKey = clean(config.widgetKey);\n const apiKey = clean(config.apiKey);\n\n if (serverApiKey && keyKind(serverApiKey) === 'widget') {\n throw new ConfigError(\n 'CHANNLIZE_SERVER_API_KEY / --server-api-key holds a widget key (wk_…). ' +\n 'Widget keys are public and only work for the visitor tools: pass it as ' +\n 'CHANNLIZE_WIDGET_KEY / --widget-key, and create a server API key (ch_live_…) ' +\n 'under SDK & Integration → API keys in the Channlize dashboard.'\n );\n }\n if (widgetKey && keyKind(widgetKey) === 'server') {\n throw new ConfigError(\n 'CHANNLIZE_WIDGET_KEY / --widget-key holds a server API key. Pass server keys ' +\n '(ch_live_…) as CHANNLIZE_SERVER_API_KEY / --server-api-key; widget keys start with wk_.'\n );\n }\n if (apiKey) {\n if (keyKind(apiKey) === 'widget') widgetKey ??= apiKey;\n else serverApiKey ??= apiKey;\n }\n\n if (!serverApiKey && !widgetKey) {\n throw new ConfigError(\n 'A Channlize key is required. Set CHANNLIZE_SERVER_API_KEY (or --server-api-key) ' +\n 'to a server API key (ch_live_…) from SDK & Integration → API keys in the ' +\n 'Channlize dashboard. Use a read-scoped key for read-only access, or add the ' +\n 'write scope to send events, logs and conversations.'\n );\n }\n\n const timeout = config.timeout ?? DEFAULT_TIMEOUT;\n if (!Number.isFinite(timeout) || timeout <= 0) {\n throw new ConfigError(\n `Invalid timeout \"${config.timeout}\": use milliseconds, e.g. 10000`\n );\n }\n\n const baseUrl = (clean(config.baseUrl) ?? DEFAULT_BASE_URL).replace(\n /\\/+$/,\n ''\n );\n try {\n new URL(baseUrl);\n } catch {\n throw new ConfigError(\n `Invalid base URL \"${config.baseUrl}\": use e.g. ${DEFAULT_BASE_URL}`\n );\n }\n\n return {\n serverApiKey,\n widgetKey,\n projectId: clean(config.projectId),\n baseUrl,\n timeout,\n };\n}\n\n/** Reads `ChannlizeMCPConfig` from the environment (CLI flags override it). */\nexport function configFromEnv(\n env: NodeJS.ProcessEnv = process.env\n): ChannlizeMCPConfig {\n const { timeout, ...rest } = readChannlizeEnv(env);\n return { ...rest, timeout: timeout ? Number(timeout) : undefined };\n}\n","import type { McpServer } from '@modelcontextprotocol/server';\nimport * as z from 'zod/v4';\nimport { EVENTS, REACT_COMPONENTS } from './docs';\n\nfunction user(text: string) {\n return {\n messages: [\n { role: 'user' as const, content: { type: 'text' as const, text } },\n ],\n };\n}\n\n/** Prompts that use the live tools (need a server API key). */\nexport function registerServerPrompts(server: McpServer) {\n server.registerPrompt(\n 'triage-conversations',\n {\n title: 'Triage open conversations',\n description:\n 'Review open support conversations, rank them by urgency and draft a reply for each.',\n argsSchema: z.object({\n status: z\n .string()\n .optional()\n .describe(\n 'Status to triage: open (default), pending, resolved or closed'\n ),\n limit: z\n .string()\n .optional()\n .describe('How many conversations (default 10)'),\n }),\n },\n ({ status, limit }) =>\n user(`Triage my Channlize support inbox.\n\n1. Call list_conversations with status \"${status || 'open'}\" and limit ${Number(limit) || 10}.\n2. For each conversation, call get_conversation to read the thread.\n3. Return a table sorted by urgency: subject, customer, how long it has waited, current priority, a suggested priority (low / normal / high / urgent) and a one-line reason.\n4. Under the table, draft a short, friendly reply for each conversation that needs one, and flag anything that looks like a bug, an outage or a billing problem.\n\nReplies and status or priority changes are made by the team in the Slack thread or the Channlize dashboard, so present the drafts for me to send; don't invent facts about my product.`)\n );\n\n server.registerPrompt(\n 'summarize-conversation',\n {\n title: 'Summarize a conversation',\n description: 'Summarize one conversation and suggest the next step.',\n argsSchema: z.object({\n conversationId: z.string().describe('Conversation ID'),\n }),\n },\n ({ conversationId }) =>\n user(\n `Call get_conversation with conversationId \"${conversationId}\". Summarize it in five bullet points or fewer: what the customer wants, what has been answered, what is still open, and the customer's mood. Then suggest the next step and draft a reply if one is needed.`\n )\n );\n\n server.registerPrompt(\n 'check-events',\n {\n title: 'Check Events delivery',\n description:\n 'Check that Events reach Slack: list them and explain failed or skipped deliveries.',\n argsSchema: z.object({}),\n },\n () =>\n user(`Check my Channlize Events setup.\n\n1. Call list_event_definitions and list the Events, flagging disabled drafts and Events without a Slack channel.\n2. Call list_event_deliveries (limit 50) and group the deliveries by status.\n3. For each failed or skipped delivery, explain the reason and how to fix it (enable the Event, pick a channel under Events in the dashboard, invite the Slack app to the channel, or connect Slack).`)\n );\n}\n\n/** Integration guides (no key needed beyond startup). */\nexport function registerGuidePrompts(server: McpServer) {\n server.registerPrompt(\n 'setup-events',\n {\n title: 'Add Events to my app',\n description:\n 'Add Channlize Events (notify Slack from server code) to the current codebase.',\n argsSchema: z.object({\n events: z\n .string()\n .optional()\n .describe('Events to add, e.g. \"signup, subscription upgrade\"'),\n }),\n },\n ({ events }) =>\n user(`Add Channlize Events to this codebase${events ? ` for: ${events}` : ''}.\n\nFind where these things happen on the server, then call notify there with a typed event map and an idempotency key derived from the record ID. Never call it from browser code. Read the server key from CHANNLIZE_SERVER_API_KEY and the project from CHANNLIZE_PROJECT_ID, and add both to the env example file. Don't let a notify failure break the request: catch and log it.\n\nReference:\n\n${EVENTS}`)\n );\n\n server.registerPrompt(\n 'setup-live-chat',\n {\n title: 'Add the chat widget',\n description:\n 'Add the Channlize live chat widget to a React or Next.js app.',\n argsSchema: z.object({\n framework: z\n .string()\n .optional()\n .describe('e.g. Next.js App Router, Vite, Remix'),\n }),\n },\n ({ framework }) =>\n user(`Add the Channlize chat widget to this ${framework || 'React'} app: install @channlize/react, render ChannlizeChat once in the root layout (from a 'use client' component on Next.js), read the widget key and project ID from public env variables, and match primaryColor to the app's brand color.\n\nReference:\n\n${REACT_COMPONENTS}`)\n );\n\n server.registerPrompt(\n 'integrate-contact-form',\n {\n title: 'Add a contact form',\n description: 'Add a Channlize contact form page to a React app.',\n argsSchema: z.object({\n styling: z\n .string()\n .optional()\n .describe('Styling approach, e.g. Tailwind or CSS modules'),\n }),\n },\n ({ styling }) =>\n user(`Add a contact page to this app using Channlize. Use the ContactForm component (or useContactForm with a custom form${styling ? ` styled with ${styling}` : ''}) inside ChannlizeProvider, show a clear success state, and surface errors from onError.\n\nReference:\n\n${REACT_COMPONENTS}`)\n );\n}\n","/**\n * Integration docs served as MCP resources and reused by the prompts.\n * Keep in sync with the public API of `@channlize/core` and\n * `@channlize/react` (their `src/index.ts`).\n */\n\nexport const QUICK_START = `# Channlize quick start\n\nChannlize routes website conversations and app events to Slack.\n\n## Keys\n- **Widget key** (\\`wk_…\\`): public, safe in browser code. Used by the chat widget,\n contact form and browser log tracking (\\`apiKey\\` in the SDK config).\n- **Server API key** (\\`ch_live_…\\`): secret, server only (\\`serverApiKey\\`). Scopes:\n \\`read\\` (conversations, contacts, logs, Events) and \\`write\\` (notify, server logs,\n create conversations/contacts). Create both under SDK & Integration → API keys.\n- **Project ID**: shown next to each widget key.\n\n## Install\n\\`\\`\\`bash\nnpm install @channlize/core # any JS runtime\nnpm install @channlize/react # React components and hooks\n\\`\\`\\`\n\n## Browser\n\\`\\`\\`ts\nimport { ChannlizeClient } from '@channlize/core';\n\nconst client = new ChannlizeClient({ apiKey: 'wk_…', projectId: '<project-id>' });\nawait client.submitContactForm({ name: 'Ada', email: 'ada@example.com', message: 'Hi!' });\nawait client.trackEvent('checkout.started', { properties: { cartId: 'c_1' } });\n\\`\\`\\`\n\n## Server\n\\`\\`\\`ts\nimport { createNotifier } from '@channlize/core';\n\n// Reads CHANNLIZE_SERVER_API_KEY (or CHANNLIZE_API_KEY) and CHANNLIZE_PROJECT_ID.\nconst notify = createNotifier();\nawait notify('user.subscribed', { username: 'ada', plan: 'Pro' });\n\\`\\`\\`\n\nErrors are \\`ChannlizeError\\` (\\`statusCode\\`, \\`code\\`), with subclasses\n\\`ValidationError\\` (400), \\`AuthenticationError\\` (401) and \\`RateLimitError\\` (429).\n`;\n\nexport const REACT_COMPONENTS = `# @channlize/react\n\n\\`\\`\\`bash\nnpm install @channlize/react\n\\`\\`\\`\n\n## Floating chat widget (all-in-one)\n\\`ChannlizeChat\\` includes the provider, launcher button and chat window.\n\n\\`\\`\\`tsx\n'use client';\nimport { ChannlizeChat } from '@channlize/react';\n\nexport function SupportWidget() {\n return (\n <ChannlizeChat\n config={{\n apiKey: process.env.NEXT_PUBLIC_CHANNLIZE_WIDGET_KEY!, // wk_…, public\n projectId: process.env.NEXT_PUBLIC_CHANNLIZE_PROJECT_ID!,\n }}\n position=\"bottom-right\"\n primaryColor=\"#2563eb\"\n theme=\"auto\"\n chatProps={{ title: 'Acme Support', greeting: 'Hi there!', welcomeMessage: 'Ask us anything.' }}\n />\n );\n}\n\\`\\`\\`\n\nKey props: \\`position\\` ('bottom-right' | 'bottom-left' | 'top-right' | 'top-left'),\n\\`primaryColor\\`, \\`theme\\` ('auto' | 'light' | 'dark'), \\`defaultOpen\\`, \\`showOnMobile\\`,\n\\`offset\\`, \\`zIndex\\`, \\`onOpen\\`, \\`onClose\\`, and \\`chatProps\\` (SupportChat props).\n\n## Provider + inline components\n\\`\\`\\`tsx\nimport { ChannlizeProvider, SupportChat, ContactForm } from '@channlize/react';\n\n<ChannlizeProvider config={{ apiKey: 'wk_…', projectId: '<project-id>' }}>\n <SupportChat title=\"Need help?\" greeting=\"Hi!\" suggestions={['Pricing', 'Billing']} />\n <ContactForm submitText=\"Send\" successMessage=\"Thanks! We'll reply by email.\" />\n</ChannlizeProvider>\n\\`\\`\\`\n\nSupportChat props include \\`title\\`, \\`greeting\\`, \\`welcomeMessage\\`, \\`suggestions\\`,\n\\`placeholder\\`, \\`allowAttachments\\`, \\`allowEndChat\\`, \\`theme\\`, \\`primaryColor\\`,\n\\`locale\\`, \\`maxLength\\`, \\`labels\\` and the \\`useChatSession\\` options\n(\\`autoConnect\\`, \\`metadata\\`, \\`persistSession\\`, \\`onMessage\\`, \\`onError\\`).\n\nContactForm props: \\`customFields\\`, \\`onSuccess\\`, \\`onError\\`, \\`className\\`, \\`styles\\`,\n\\`submitText\\`, \\`successMessage\\`.\n\n## Hooks (inside ChannlizeProvider)\n- \\`useChatSession(options)\\` → \\`{ session, messages, isConnecting, isConnected, error,\n sendMessage, startSession, endSession, reconnect }\\`\n- \\`useContactForm({ onSuccess, onError })\\` → \\`{ submit, isSubmitting, isSuccess, error, reset }\\`\n- \\`useChannlizeAnalytics()\\` → \\`{ track(name, { properties, severity }) }\\` (log tracking)\n- \\`useChannlize()\\` → \\`{ client, config }\\`\n\n## Next.js App Router\nComponents use state and effects: render them from a \\`'use client'\\` file. The widget\nkey is public (\\`NEXT_PUBLIC_…\\` is fine); never put the server API key in a\n\\`NEXT_PUBLIC_\\` variable.\n`;\n\nexport const EVENTS = `# Events: notify Slack from code\n\nEach event key (e.g. \\`user.subscribed\\`) has a Slack channel and a message template\nwith \\`{{field}}\\` placeholders, set under Events in the dashboard. A key that isn't set\nup yet is saved as a disabled draft the first time it is sent (\\`status: 'skipped'\\`),\nso you can ship code first and configure it after. Server only: needs a server API key\nwith the \\`write\\` scope.\n\n\\`\\`\\`ts\nimport { createNotifier } from '@channlize/core';\n\ntype AppEvents = {\n 'user.subscribed': { username: string; plan: string };\n 'invoice.paid': { amount: string; customer: string };\n};\n\n// Env: CHANNLIZE_SERVER_API_KEY (or CHANNLIZE_API_KEY), CHANNLIZE_PROJECT_ID.\nconst notify = createNotifier<AppEvents>();\n\nconst res = await notify('user.subscribed', { username: 'ada', plan: 'Pro' });\n// res.status: 'queued' | 'skipped' (see res.reason); res.duplicate on a repeated key\n\n// Retry-safe: an idempotency key already used posts nothing.\nawait notify('invoice.paid', { amount: '$49', customer: 'ada@example.com' }, { idempotencyKey: 'inv_123' });\n\\`\\`\\`\n\nTo type keys app-wide instead, augment the interface:\n\\`\\`\\`ts\ndeclare module '@channlize/core' {\n interface ChannlizeEvents {\n 'user.subscribed': { username: string; plan: string };\n }\n}\n\\`\\`\\`\n\nOver HTTP:\n\\`\\`\\`bash\ncurl -X POST https://api.channlize.com/v1/notify \\\\\n -H \"Authorization: Bearer $CHANNLIZE_SERVER_API_KEY\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -H \"Idempotency-Key: signup-42\" \\\\\n -d '{\"projectId\":\"<project-id>\",\"event\":\"user.subscribed\",\"data\":{\"username\":\"ada\"}}'\n\\`\\`\\`\n\nLog tracking is separate: \\`client.trackEvent\\` (browser) / \\`trackServerEvent\\` (server)\nrecord log lines shown under Log tracking.\n`;\n","import type { McpServer } from '@modelcontextprotocol/server';\nimport type { ChannlizeApi } from './api';\nimport { EVENTS, QUICK_START, REACT_COMPONENTS } from './docs';\n\nconst markdown = (uri: string, text: string) => ({\n contents: [{ uri, mimeType: 'text/markdown', text }],\n});\n\nexport function registerResources(server: McpServer, api: ChannlizeApi) {\n server.registerResource(\n 'quick-start',\n 'channlize://docs/quick-start',\n {\n title: 'Channlize quick start',\n description:\n 'Keys, install, and first calls from the browser and the server.',\n mimeType: 'text/markdown',\n },\n uri => markdown(uri.href, QUICK_START)\n );\n server.registerResource(\n 'react-components',\n 'channlize://docs/react-components',\n {\n title: '@channlize/react components and hooks',\n description:\n 'ChannlizeChat, SupportChat, ContactForm, hooks and Next.js notes.',\n mimeType: 'text/markdown',\n },\n uri => markdown(uri.href, REACT_COMPONENTS)\n );\n server.registerResource(\n 'events',\n 'channlize://docs/events',\n {\n title: 'Events: notify Slack from code',\n description:\n 'createNotifier / notify with typed events, idempotency and curl.',\n mimeType: 'text/markdown',\n },\n uri => markdown(uri.href, EVENTS)\n );\n\n if (api.hasServerKey) {\n server.registerResource(\n 'project',\n 'channlize://project',\n {\n title: 'Current Channlize project',\n description:\n \"The key's project: ID, name, totals, permissions and Slack connection.\",\n mimeType: 'application/json',\n },\n async uri => {\n const r = await api.request<{ project: unknown }>(\n 'GET',\n '/projects/me'\n );\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(r.project, null, 2),\n },\n ],\n };\n }\n );\n }\n}\n","/**\n * MCP tools for Channlize.\n *\n * Server-key tools (`ch_live_…`) are registered when a server API key is\n * configured; visitor tools (contact form, chat) when a widget key is.\n * Every tool returns its result as `structuredContent` (matching its\n * `outputSchema`) plus the same JSON as text for clients that ignore it.\n * Failures are tool errors (`isError: true`) with a message that says how\n * to fix them.\n */\nimport type { McpServer } from '@modelcontextprotocol/server';\nimport * as z from 'zod/v4';\nimport { EVENT_KEY_PATTERN, EVENT_SEVERITIES } from '@channlize/core';\nimport { ChannlizeApi, toToolError } from './api';\n\nconst STATUSES = ['open', 'pending', 'resolved', 'closed'] as const;\nconst PRIORITIES = ['low', 'normal', 'high', 'urgent'] as const;\n\ntype Json = Record<string, unknown>;\n\nfunction ok(data: Json) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }],\n structuredContent: data,\n };\n}\n\n/** Runs a handler, turning any failure into a readable tool error. */\nasync function run(fn: () => Promise<Json>) {\n try {\n return ok(await fn());\n } catch (err) {\n const e = toToolError(err);\n return {\n content: [{ type: 'text' as const, text: e.message }],\n isError: true,\n };\n }\n}\n\nconst record = z.record(z.string(), z.unknown());\nconst loose = z.looseObject({});\nconst page = {\n total: z.number(),\n limit: z.number(),\n offset: z.number(),\n hasMore: z.boolean(),\n};\n\nconst conversationSummary = z.looseObject({\n id: z.string(),\n subject: z.string().nullable().optional(),\n status: z.string(),\n priority: z.string().nullable().optional(),\n customerEmail: z.string().nullable().optional(),\n customerName: z.string().nullable().optional(),\n tags: z.array(z.string()).nullable().optional(),\n createdAt: z.string().optional(),\n});\n\nconst READ = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n} as const;\n\nexport function registerServerTools(server: McpServer, api: ChannlizeApi) {\n server.registerTool(\n 'get_project',\n {\n title: 'Get project',\n description:\n \"Show the Channlize project behind the server API key: name, ID, totals, the key's permissions and whether Slack is connected. Start here to check the setup.\",\n inputSchema: z.object({}),\n outputSchema: z.object({ project: loose }),\n annotations: READ,\n },\n () =>\n run(async () => {\n const r = await api.request<{ project: Json }>('GET', '/projects/me');\n return { project: r.project };\n })\n );\n\n server.registerTool(\n 'get_analytics',\n {\n title: 'Get analytics',\n description:\n 'Daily support activity for the last 30 days (UTC): conversations created and resolved, customer and agent messages.',\n inputSchema: z.object({}),\n outputSchema: z.object({ analytics: loose }),\n annotations: READ,\n },\n () =>\n run(async () => {\n const r = await api.request<{ analytics: Json }>(\n 'GET',\n '/projects/analytics'\n );\n return { analytics: r.analytics };\n })\n );\n\n server.registerTool(\n 'list_conversations',\n {\n title: 'List conversations',\n description:\n \"List the organization's most recent support conversations (newest first, from the latest 50), optionally filtered by status or priority. Use get_conversation for the messages.\",\n inputSchema: z.object({\n status: z\n .enum(STATUSES)\n .optional()\n .describe('Only conversations with this status'),\n priority: z\n .enum(PRIORITIES)\n .optional()\n .describe('Only conversations with this priority'),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(20)\n .describe('How many to return (1-50, default 20)'),\n }),\n outputSchema: z.object({\n conversations: z.array(conversationSummary),\n returned: z.number(),\n matched: z.number(),\n scanned: z.number(),\n }),\n annotations: READ,\n },\n ({ status, priority, limit }) =>\n run(async () => {\n const r = await api.request<{ conversations: Json[] }>(\n 'GET',\n '/conversations'\n );\n const all = r.conversations ?? [];\n const matched = all.filter(\n c =>\n (!status || c.status === status) &&\n (!priority || c.priority === priority)\n );\n const conversations = matched.slice(0, limit);\n return {\n conversations,\n returned: conversations.length,\n matched: matched.length,\n scanned: all.length,\n };\n })\n );\n\n server.registerTool(\n 'get_conversation',\n {\n title: 'Get conversation',\n description:\n 'Read one conversation with its full message thread (customer, agent and system messages), status, priority and tags.',\n inputSchema: z.object({\n conversationId: z\n .string()\n .uuid()\n .describe('Conversation ID (from list_conversations)'),\n }),\n outputSchema: z.object({ conversation: loose }),\n annotations: READ,\n },\n ({ conversationId }) =>\n run(async () => {\n const conversation = await api.request<Json>(\n 'GET',\n `/conversations/${encodeURIComponent(conversationId)}`\n );\n return { conversation };\n })\n );\n\n server.registerTool(\n 'create_conversation',\n {\n title: 'Create conversation',\n description:\n 'Open a new support conversation on behalf of a customer. It is posted to Slack (the given channel, else routing rules, else the default channel). Needs the write scope. Repeating the same customer, subject and message within 30 seconds returns the existing conversation.',\n inputSchema: z.object({\n customerEmail: z.email().describe(\"Customer's email address\"),\n customerName: z\n .string()\n .max(255)\n .optional()\n .describe(\"Customer's name\"),\n subject: z.string().min(1).max(500).describe('Subject line'),\n message: z.string().min(1).describe('First message, from the customer'),\n channel: z\n .string()\n .optional()\n .describe('Slack channel ID to post to, overriding routing rules'),\n tags: z.array(z.string()).max(20).optional().describe('Tags'),\n }),\n outputSchema: z.object({ conversation: loose }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n args =>\n run(async () => {\n const conversation = await api.request<Json>('POST', '/conversations', {\n body: args,\n });\n return { conversation };\n })\n );\n\n server.registerTool(\n 'list_contacts',\n {\n title: 'List contacts',\n description:\n 'List the customers who contacted the organization, with their conversation count. Paginate with limit/offset.',\n inputSchema: z.object({\n limit: z.number().int().min(1).max(100).default(50),\n offset: z.number().int().min(0).default(0),\n }),\n outputSchema: z.object({ contacts: z.array(loose), ...page }),\n annotations: READ,\n },\n ({ limit, offset }) =>\n run(async () => {\n const r = await api.request<Json>('GET', '/contacts', {\n query: { limit, offset },\n });\n return {\n contacts: (r.contacts as Json[]) ?? [],\n total: Number(r.total ?? 0),\n limit: Number(r.limit ?? limit),\n offset: Number(r.offset ?? offset),\n hasMore: Boolean(r.hasMore),\n };\n })\n );\n\n server.registerTool(\n 'get_contact',\n {\n title: 'Get contact',\n description: 'Read one contact (customer) by ID.',\n inputSchema: z.object({\n contactId: z\n .string()\n .uuid()\n .describe('Contact ID (from list_contacts)'),\n }),\n outputSchema: z.object({ contact: loose }),\n annotations: READ,\n },\n ({ contactId }) =>\n run(async () => {\n const contact = await api.request<Json>(\n 'GET',\n `/contacts/${encodeURIComponent(contactId)}`\n );\n return { contact };\n })\n );\n\n server.registerTool(\n 'create_contact',\n {\n title: 'Create contact',\n description:\n 'Add a customer by email, or return the existing one with that email. Needs the write scope.',\n inputSchema: z.object({\n email: z.email(),\n name: z.string().max(255).optional(),\n company: z.string().optional(),\n phone: z.string().optional(),\n tags: z.array(z.string()).max(20).optional(),\n }),\n outputSchema: z.object({ contact: loose }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n args =>\n run(async () => {\n const contact = await api.request<Json>('POST', '/contacts', {\n body: args,\n });\n return { contact };\n })\n );\n\n server.registerTool(\n 'notify_event',\n {\n title: 'Send an Event to Slack',\n description:\n 'Post an Event to Slack: the event key (e.g. \"user.subscribed\") picks the channel and message template set under Events in the dashboard, and `data` fills its {{placeholders}}. An unknown key is saved as a disabled draft and answered with status \"skipped\". Needs the write scope. Pass an idempotencyKey so a retry never posts twice.',\n inputSchema: z.object({\n event: z\n .string()\n .max(100)\n .regex(\n EVENT_KEY_PATTERN,\n 'lowercase letters, digits, dots, underscores or dashes'\n )\n .describe('Event key, e.g. user.subscribed'),\n data: record\n .optional()\n .describe(\n 'Template fields, e.g. { \"username\": \"ada\", \"plan\": \"Pro\" }'\n ),\n idempotencyKey: z\n .string()\n .min(1)\n .max(255)\n .optional()\n .describe('Send at most once per key (retry-safe)'),\n channel: z\n .string()\n .optional()\n .describe(\"Slack channel ID instead of the event's channel\"),\n }),\n outputSchema: z.looseObject({\n id: z.string(),\n event: z.string(),\n status: z.string(),\n reason: z.string().optional(),\n duplicate: z.boolean().optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n },\n ({ event, data, idempotencyKey, channel }) =>\n run(async () => {\n const client = await api.notifier();\n const r = await client.notify(event, data, { idempotencyKey, channel });\n return {\n id: r.id,\n event: r.event,\n status: r.status,\n ...(r.reason ? { reason: r.reason } : {}),\n ...(r.duplicate ? { duplicate: true } : {}),\n };\n })\n );\n\n server.registerTool(\n 'list_event_definitions',\n {\n title: 'List Events',\n description:\n 'List the Events configured on the project (key, name, Slack channel, message template, enabled), including disabled drafts created by unknown keys sent with notify_event.',\n inputSchema: z.object({}),\n outputSchema: z.object({\n projectId: z.string(),\n definitions: z.array(loose),\n }),\n annotations: READ,\n },\n () =>\n run(async () => {\n const projectId = await api.projectId();\n const r = await api.request<{ definitions: Json[] }>(\n 'GET',\n `/v1/projects/${encodeURIComponent(projectId)}/event-definitions`\n );\n return { projectId, definitions: r.definitions ?? [] };\n })\n );\n\n server.registerTool(\n 'list_event_deliveries',\n {\n title: 'List Event deliveries',\n description:\n 'Recent notify_event deliveries on the project, newest first, with their status (queued, sent, failed, skipped) and the reason when not sent. Use it to check why an Event did not reach Slack.',\n inputSchema: z.object({\n definitionId: z\n .string()\n .uuid()\n .optional()\n .describe('Only this Event (ID from list_event_definitions)'),\n limit: z.number().int().min(1).max(100).default(20),\n }),\n outputSchema: z.object({\n projectId: z.string(),\n deliveries: z.array(loose),\n }),\n annotations: READ,\n },\n ({ definitionId, limit }) =>\n run(async () => {\n const projectId = await api.projectId();\n const r = await api.request<{ deliveries: Json[] }>(\n 'GET',\n `/v1/projects/${encodeURIComponent(projectId)}/event-deliveries`,\n { query: { definitionId, limit } }\n );\n return { projectId, deliveries: r.deliveries ?? [] };\n })\n );\n\n server.registerTool(\n 'query_logs',\n {\n title: 'Query logs',\n description:\n 'Search log tracking (trackEvent / trackServerEvent / track_log), newest first. Filter by severity, source, text (matches the name and properties) and time range; paginate with limit/offset. Covers all projects unless projectId is given.',\n inputSchema: z.object({\n severity: z.enum(EVENT_SEVERITIES).optional(),\n source: z\n .enum(['client_sdk', 'server_api', 'system'])\n .optional()\n .describe(\n 'client_sdk = browser (widget key), server_api = server key'\n ),\n search: z.string().max(200).optional().describe('Text to look for'),\n from: z.iso\n .datetime({ offset: true })\n .optional()\n .describe('ISO 8601 start'),\n to: z.iso\n .datetime({ offset: true })\n .optional()\n .describe('ISO 8601 end'),\n projectId: z.string().uuid().optional(),\n limit: z.number().int().min(1).max(100).default(50),\n offset: z.number().int().min(0).default(0),\n }),\n outputSchema: z.object({ events: z.array(loose), ...page }),\n annotations: READ,\n },\n args =>\n run(async () => {\n const r = await api.request<Json>('GET', '/v1/events', { query: args });\n return {\n events: (r.events as Json[]) ?? [],\n total: Number(r.total ?? 0),\n limit: Number(r.limit ?? args.limit),\n offset: Number(r.offset ?? args.offset),\n hasMore: Boolean(r.hasMore),\n };\n })\n );\n\n server.registerTool(\n 'track_log',\n {\n title: 'Record a log',\n description:\n 'Record a log line under Log tracking from a trusted server context (source server_api). Needs the write scope. For Slack messages about product events use notify_event instead.',\n inputSchema: z.object({\n name: z\n .string()\n .min(1)\n .max(255)\n .describe('Log name, e.g. payment.failed'),\n severity: z.enum(EVENT_SEVERITIES).default('info'),\n properties: record.optional().describe('Extra fields'),\n }),\n outputSchema: z.object({ id: z.string(), projectId: z.string() }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n ({ name, severity, properties }) =>\n run(async () => {\n const projectId = await api.projectId();\n const r = await api.request<{ id: string }>('POST', '/v1/events', {\n body: { projectId, name, severity, properties },\n });\n return { id: r.id, projectId };\n })\n );\n}\n\nconst VISITOR = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n} as const;\n\n/** Tools that act as a website visitor, with the public widget key. */\nexport function registerWidgetTools(server: McpServer, api: ChannlizeApi) {\n server.registerTool(\n 'submit_contact_form',\n {\n title: 'Submit contact form',\n description:\n 'Submit the website contact form as a visitor (widget key). Creates a conversation that is posted to Slack. Useful to test the setup end to end.',\n inputSchema: z.object({\n name: z.string().min(1).describe(\"Visitor's name\"),\n email: z.email().describe(\"Visitor's email\"),\n subject: z.string().optional(),\n message: z.string().min(1),\n pageUrl: z.url().optional().describe('Page the form was sent from'),\n }),\n outputSchema: z.looseObject({\n conversationId: z.string().optional(),\n message: z.string().optional(),\n }),\n annotations: VISITOR,\n },\n args =>\n run(async () => {\n const r = await api.widget().submitContactForm(args);\n return { conversationId: r.conversationId, message: r.message };\n })\n );\n\n server.registerTool(\n 'create_chat_session',\n {\n title: 'Start chat session',\n description:\n 'Start a live chat session as a website visitor (widget key). Returns the session ID for send_message.',\n inputSchema: z.object({\n metadata: record\n .optional()\n .describe('Metadata to attach (e.g. user info)'),\n }),\n outputSchema: z.looseObject({\n sessionId: z.string(),\n status: z.string(),\n }),\n annotations: VISITOR,\n },\n ({ metadata }) =>\n run(async () => {\n const r = await api.widget().createChatSession(metadata);\n return {\n sessionId: r.session.id,\n status: r.session.status,\n createdAt: String(r.session.createdAt),\n };\n })\n );\n\n server.registerTool(\n 'send_message',\n {\n title: 'Send chat message',\n description:\n 'Send a visitor message in a chat session (widget key); it is posted to the Slack thread.',\n inputSchema: z.object({\n sessionId: z.string().min(1).describe('From create_chat_session'),\n content: z.string().min(1).max(5000),\n }),\n outputSchema: z.looseObject({\n messageId: z.string(),\n sessionStatus: z.string(),\n }),\n annotations: VISITOR,\n },\n ({ sessionId, content }) =>\n run(async () => {\n const r = await api.widget().sendMessage(sessionId, content);\n return { messageId: r.message.id, sessionStatus: r.session.status };\n })\n );\n\n server.registerTool(\n 'get_chat_messages',\n {\n title: 'Read chat messages',\n description:\n \"Read a chat session's messages, including agent replies from Slack (widget key).\",\n inputSchema: z.object({\n sessionId: z.string().min(1),\n limit: z.number().int().min(1).max(100).default(50),\n offset: z.number().int().min(0).default(0),\n }),\n outputSchema: z.object({\n sessionId: z.string(),\n messages: z.array(loose),\n }),\n annotations: { ...READ, openWorldHint: true },\n },\n ({ sessionId, limit, offset }) =>\n run(async () => {\n const messages = await api\n .widget()\n .getChatMessages(sessionId, limit, offset);\n return {\n sessionId,\n messages: messages.map(m => ({\n id: m.id,\n author: m.author,\n authorName: m.authorData?.name,\n content: m.content,\n timestamp: String(m.timestamp),\n attachments: m.attachments?.length ?? 0,\n })),\n };\n })\n );\n\n server.registerTool(\n 'close_chat_session',\n {\n title: 'End chat session',\n description: 'End a chat session as the visitor (widget key).',\n inputSchema: z.object({ sessionId: z.string().min(1) }),\n outputSchema: z.looseObject({\n sessionId: z.string(),\n status: z.string(),\n }),\n annotations: { ...VISITOR, idempotentHint: true },\n },\n ({ sessionId }) =>\n run(async () => {\n const s = await api.widget().closeChatSession(sessionId);\n return { sessionId: s.id ?? sessionId, status: s.status };\n })\n );\n}\n","import { createServer, type IncomingMessage, type Server } from 'node:http';\nimport {\n createMcpHandler,\n hostHeaderValidationResponse,\n localhostAllowedHostnames,\n localhostAllowedOrigins,\n originValidationResponse,\n type McpServer,\n} from '@modelcontextprotocol/server';\n\nexport interface HttpServerOptions {\n /** Interface to bind (default 127.0.0.1). */\n host?: string;\n /** Port (default 3333). */\n port?: number;\n /** Endpoint path (default /mcp). */\n path?: string;\n}\n\nconst LOCAL_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);\n\nasync function toRequest(\n req: IncomingMessage,\n origin: string\n): Promise<Request> {\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) v.forEach(x => headers.append(k, x));\n else if (v !== undefined) headers.set(k, v);\n }\n let body: Uint8Array<ArrayBuffer> | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n body = new Uint8Array(Buffer.concat(chunks));\n }\n const controller = new AbortController();\n req.on('close', () => {\n if (!req.complete) controller.abort();\n });\n return new Request(new URL(req.url ?? '/', origin), {\n method: req.method,\n headers,\n body,\n signal: controller.signal,\n });\n}\n\n/**\n * Streamable HTTP transport on `node:http`. Stateless: every request is\n * served by a fresh server from `factory`. Bound to localhost by default,\n * with Host and Origin checks against DNS rebinding.\n */\nexport async function startHttpServer(\n factory: () => McpServer,\n options: HttpServerOptions = {}\n): Promise<{ url: string; server: Server; close: () => Promise<void> }> {\n const host = options.host ?? '127.0.0.1';\n const port = options.port ?? 3333;\n const path = options.path ?? '/mcp';\n const local = LOCAL_HOSTS.has(host);\n const handler = createMcpHandler(() => factory(), {\n onerror: err => console.error('[channlize-mcp]', err.message),\n });\n\n const server = createServer(async (req, res) => {\n try {\n const request = await toRequest(\n req,\n `http://${req.headers.host ?? `${host}:${port}`}`\n );\n const url = new URL(request.url);\n if (url.pathname !== path) {\n res\n .writeHead(404, { 'Content-Type': 'text/plain' })\n .end(`Not found: use ${path}`);\n return;\n }\n const rejected = local\n ? (hostHeaderValidationResponse(request, localhostAllowedHostnames()) ??\n originValidationResponse(request, localhostAllowedOrigins()))\n : undefined;\n const response = rejected ?? (await handler.fetch(request));\n res.writeHead(response.status, Object.fromEntries(response.headers));\n if (response.body) {\n for await (const chunk of response.body as unknown as AsyncIterable<Uint8Array>) {\n res.write(chunk);\n }\n }\n res.end();\n } catch (err) {\n console.error('[channlize-mcp]', (err as Error).message);\n if (!res.headersSent)\n res.writeHead(500, { 'Content-Type': 'text/plain' });\n res.end('Internal server error');\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => resolve());\n });\n const address = server.address();\n const actualPort =\n typeof address === 'object' && address ? address.port : port;\n const shownHost = host.includes(':') ? `[${host}]` : host;\n return {\n url: `http://${shownHost}:${actualPort}${path}`,\n server,\n close: () => new Promise<void>(r => server.close(() => r())),\n };\n}\n"],"mappings":"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","names":["import_server","url","import_core","z","import_core","record","url","import_core","url","stop"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@channlize/mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Model Context Protocol (MCP) server for Channlize - AI agent integration",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -21,8 +21,8 @@
21
21
  "scripts": {
22
22
  "build": "tsup",
23
23
  "dev": "tsup --watch",
24
- "lint": "eslint src",
25
- "lint:fix": "eslint src --fix",
24
+ "lint": "oxlint src && prettier --check src",
25
+ "lint:fix": "oxlint --fix src && prettier --write src",
26
26
  "type-check": "tsc6 --noEmit",
27
27
  "clean": "rm -rf dist",
28
28
  "test": "yarn build && node --test test/*.test.mjs"
@@ -39,14 +39,13 @@
39
39
  "author": "Channlize Team",
40
40
  "license": "MIT",
41
41
  "dependencies": {
42
- "@channlize/core": "^0.2.0",
42
+ "@channlize/core": "^0.4.0",
43
43
  "@modelcontextprotocol/server": "^2.4.0",
44
44
  "zod": "^4.2.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@modelcontextprotocol/client": "^2.4.0",
48
48
  "@types/node": "^26.0.0",
49
- "eslint": "^10.0.0",
50
49
  "tsup": "^9.0.0",
51
50
  "typescript": "npm:@typescript/typescript6@^6.0.2"
52
51
  },