@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.
- package/CHANGELOG.md +20 -0
- package/README.md +9 -0
- package/dist/index.d.mts +3 -6
- package/dist/index.d.ts +3 -6
- package/dist/index.js +29 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -27
- package/dist/index.mjs.map +1 -1
- package/dist/server.js +20 -32
- package/dist/server.js.map +1 -1
- package/package.json +4 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @channlize/mcp
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Release every `@channlize/*` package under one shared version. From 0.4.0 on, core, react, mcp and skills always publish together at the same version, so matching versions work together.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 5663cd2: Make `@channlize/core` the single source for what the packages share.
|
|
12
|
+
|
|
13
|
+
- core exports `DEFAULT_BASE_URL`, `DEFAULT_TIMEOUT`, `EVENT_SEVERITIES`, `EVENT_KEY_PATTERN`, `isValidEventKey`, `keyKind` (widget vs. server key), `readChannlizeEnv` (the `CHANNLIZE_*` variables) and `parseApiError` (the API's error shape). `createNotifier`, the client and `@channlize/mcp` use them instead of their own copies.
|
|
14
|
+
- `ChannlizeError` gains `requestId` and `details` (the API's error body, e.g. `limit`, `used` and `resetAt` on a plan-limit 429). When a legacy route puts its human-readable text in `error`, it becomes the message instead of `HTTP <status>`.
|
|
15
|
+
- The chat types document where the API differs from them (ISO string timestamps, session summaries without `messages`).
|
|
16
|
+
- `@channlize/react` and `@channlize/mcp` re-export the error classes as values, so `instanceof` works without importing core.
|
|
17
|
+
- mcp tool errors no longer end with a doubled period when a core error message ends with one.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [5663cd2]
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @channlize/core@0.4.0
|
|
22
|
+
|
|
3
23
|
## 0.3.0
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -173,6 +173,15 @@ await server.runStdio(); // or: await server.runHttp({ port: 3333 })
|
|
|
173
173
|
const mcp = buildServer({ serverApiKey: '…' });
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
+
## Documentation
|
|
177
|
+
|
|
178
|
+
- Guide: https://channlize.com/docs/mcp
|
|
179
|
+
- All docs: https://channlize.com/docs (quick start, API keys, troubleshooting)
|
|
180
|
+
|
|
181
|
+
## Changelog
|
|
182
|
+
|
|
183
|
+
[CHANGELOG.md](./CHANGELOG.md) lists every release of `@channlize/mcp`. Product updates: https://channlize.com/docs/changelog
|
|
184
|
+
|
|
176
185
|
## License
|
|
177
186
|
|
|
178
187
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as node_http from 'node:http';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/server';
|
|
3
|
-
export { AuthenticationError, ChannlizeConfig, ChannlizeError, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, FileAttachment, NotifyResponse, RateLimitError, SendMessageResponse, ValidationError } from '@channlize/core';
|
|
3
|
+
export { AuthenticationError, ChannlizeConfig, ChannlizeError, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, FileAttachment, KeyKind, NotifyResponse, RateLimitError, SendMessageResponse, ValidationError, keyKind } from '@channlize/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* MCP-specific types and configuration for Channlize
|
|
@@ -54,9 +54,6 @@ interface HttpServerOptions {
|
|
|
54
54
|
declare class ConfigError extends Error {
|
|
55
55
|
constructor(message: string);
|
|
56
56
|
}
|
|
57
|
-
type KeyKind = 'widget' | 'server';
|
|
58
|
-
/** `wk_…` is the public widget key; anything else is a server API key (`ch_live_…`). */
|
|
59
|
-
declare function keyKind(key: string): KeyKind;
|
|
60
57
|
interface ResolvedConfig {
|
|
61
58
|
serverApiKey?: string;
|
|
62
59
|
widgetKey?: string;
|
|
@@ -123,5 +120,5 @@ declare class ChannlizeMCPServer {
|
|
|
123
120
|
/** Create a new Channlize MCP server. */
|
|
124
121
|
declare function createMCPServer(options?: MCPServerOptions): ChannlizeMCPServer;
|
|
125
122
|
|
|
126
|
-
export { ChannlizeMCPServer, ConfigError, ToolError, VERSION, buildServer, configFromEnv, createMCPServer, ChannlizeMCPServer as default,
|
|
127
|
-
export type { ChannlizeMCPConfig, HttpServerOptions,
|
|
123
|
+
export { ChannlizeMCPServer, ConfigError, ToolError, VERSION, buildServer, configFromEnv, createMCPServer, ChannlizeMCPServer as default, resolveConfig };
|
|
124
|
+
export type { ChannlizeMCPConfig, HttpServerOptions, MCPServerOptions, ResolvedConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as node_http from 'node:http';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/server';
|
|
3
|
-
export { AuthenticationError, ChannlizeConfig, ChannlizeError, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, FileAttachment, NotifyResponse, RateLimitError, SendMessageResponse, ValidationError } from '@channlize/core';
|
|
3
|
+
export { AuthenticationError, ChannlizeConfig, ChannlizeError, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, FileAttachment, KeyKind, NotifyResponse, RateLimitError, SendMessageResponse, ValidationError, keyKind } from '@channlize/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* MCP-specific types and configuration for Channlize
|
|
@@ -54,9 +54,6 @@ interface HttpServerOptions {
|
|
|
54
54
|
declare class ConfigError extends Error {
|
|
55
55
|
constructor(message: string);
|
|
56
56
|
}
|
|
57
|
-
type KeyKind = 'widget' | 'server';
|
|
58
|
-
/** `wk_…` is the public widget key; anything else is a server API key (`ch_live_…`). */
|
|
59
|
-
declare function keyKind(key: string): KeyKind;
|
|
60
57
|
interface ResolvedConfig {
|
|
61
58
|
serverApiKey?: string;
|
|
62
59
|
widgetKey?: string;
|
|
@@ -123,5 +120,5 @@ declare class ChannlizeMCPServer {
|
|
|
123
120
|
/** Create a new Channlize MCP server. */
|
|
124
121
|
declare function createMCPServer(options?: MCPServerOptions): ChannlizeMCPServer;
|
|
125
122
|
|
|
126
|
-
export { ChannlizeMCPServer, ConfigError, ToolError, VERSION, buildServer, configFromEnv, createMCPServer, ChannlizeMCPServer as default,
|
|
127
|
-
export type { ChannlizeMCPConfig, HttpServerOptions,
|
|
123
|
+
export { ChannlizeMCPServer, ConfigError, ToolError, VERSION, buildServer, configFromEnv, createMCPServer, ChannlizeMCPServer as default, resolveConfig };
|
|
124
|
+
export type { ChannlizeMCPConfig, HttpServerOptions, MCPServerOptions, ResolvedConfig };
|
package/dist/index.js
CHANGED
|
@@ -30,15 +30,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AuthenticationError: () => import_core4.AuthenticationError,
|
|
34
|
+
ChannlizeError: () => import_core4.ChannlizeError,
|
|
33
35
|
ChannlizeMCPServer: () => ChannlizeMCPServer,
|
|
34
36
|
ConfigError: () => ConfigError,
|
|
37
|
+
RateLimitError: () => import_core4.RateLimitError,
|
|
35
38
|
ToolError: () => ToolError,
|
|
36
39
|
VERSION: () => VERSION,
|
|
40
|
+
ValidationError: () => import_core4.ValidationError,
|
|
37
41
|
buildServer: () => buildServer,
|
|
38
42
|
configFromEnv: () => configFromEnv,
|
|
39
43
|
createMCPServer: () => createMCPServer,
|
|
40
44
|
default: () => index_default,
|
|
41
|
-
keyKind: () => keyKind,
|
|
45
|
+
keyKind: () => import_core2.keyKind,
|
|
42
46
|
resolveConfig: () => resolveConfig
|
|
43
47
|
});
|
|
44
48
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -75,7 +79,7 @@ function toToolError(err) {
|
|
|
75
79
|
if (err instanceof ToolError) return err;
|
|
76
80
|
if (err instanceof import_core.ChannlizeError) {
|
|
77
81
|
return new ToolError(
|
|
78
|
-
err.statusCode ? hintFor(err.statusCode, err.message) : err.message,
|
|
82
|
+
err.statusCode ? hintFor(err.statusCode, err.message.replace(/\.$/, "")) : err.message,
|
|
79
83
|
err.statusCode,
|
|
80
84
|
err.code
|
|
81
85
|
);
|
|
@@ -119,6 +123,7 @@ var ChannlizeApi = class {
|
|
|
119
123
|
...options.body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
120
124
|
...options.headers
|
|
121
125
|
},
|
|
126
|
+
// oxlint-disable-next-line unicorn/no-invalid-fetch-options -- `method` is dynamic; GET calls never pass a body.
|
|
122
127
|
body: options.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
123
128
|
signal: AbortSignal.timeout(this.config.timeout)
|
|
124
129
|
});
|
|
@@ -145,13 +150,11 @@ var ChannlizeApi = class {
|
|
|
145
150
|
}
|
|
146
151
|
}
|
|
147
152
|
if (!res.ok) {
|
|
148
|
-
const
|
|
149
|
-
const raw = Array.isArray(body.message) ? body.message.join(", ") : body.message;
|
|
150
|
-
const apiMessage = raw || (typeof body.error === "string" && /\s/.test(body.error) ? body.error : "") || `HTTP ${res.status} ${res.statusText}`.trim();
|
|
153
|
+
const { message, code } = (0, import_core.parseApiError)(res.status, data, res.statusText);
|
|
151
154
|
throw new ToolError(
|
|
152
|
-
hintFor(res.status,
|
|
155
|
+
hintFor(res.status, message.replace(/\.$/, "")),
|
|
153
156
|
res.status,
|
|
154
|
-
|
|
157
|
+
code
|
|
155
158
|
);
|
|
156
159
|
}
|
|
157
160
|
if (data === void 0) {
|
|
@@ -213,17 +216,13 @@ var ChannlizeApi = class {
|
|
|
213
216
|
};
|
|
214
217
|
|
|
215
218
|
// src/config.ts
|
|
216
|
-
var
|
|
217
|
-
var DEFAULT_TIMEOUT = 1e4;
|
|
219
|
+
var import_core2 = require("@channlize/core");
|
|
218
220
|
var ConfigError = class extends Error {
|
|
219
221
|
constructor(message) {
|
|
220
222
|
super(message);
|
|
221
223
|
this.name = "ConfigError";
|
|
222
224
|
}
|
|
223
225
|
};
|
|
224
|
-
function keyKind(key) {
|
|
225
|
-
return key.startsWith("wk_") ? "widget" : "server";
|
|
226
|
-
}
|
|
227
226
|
function clean(value) {
|
|
228
227
|
const v = value?.trim();
|
|
229
228
|
return v ? v : void 0;
|
|
@@ -232,18 +231,18 @@ function resolveConfig(config) {
|
|
|
232
231
|
let serverApiKey = clean(config.serverApiKey);
|
|
233
232
|
let widgetKey = clean(config.widgetKey);
|
|
234
233
|
const apiKey = clean(config.apiKey);
|
|
235
|
-
if (serverApiKey && keyKind(serverApiKey) === "widget") {
|
|
234
|
+
if (serverApiKey && (0, import_core2.keyKind)(serverApiKey) === "widget") {
|
|
236
235
|
throw new ConfigError(
|
|
237
236
|
"CHANNLIZE_SERVER_API_KEY / --server-api-key holds a widget key (wk_\u2026). Widget keys are public and only work for the visitor tools: pass it as CHANNLIZE_WIDGET_KEY / --widget-key, and create a server API key (ch_live_\u2026) under SDK & Integration \u2192 API keys in the Channlize dashboard."
|
|
238
237
|
);
|
|
239
238
|
}
|
|
240
|
-
if (widgetKey && keyKind(widgetKey) === "server") {
|
|
239
|
+
if (widgetKey && (0, import_core2.keyKind)(widgetKey) === "server") {
|
|
241
240
|
throw new ConfigError(
|
|
242
241
|
"CHANNLIZE_WIDGET_KEY / --widget-key holds a server API key. Pass server keys (ch_live_\u2026) as CHANNLIZE_SERVER_API_KEY / --server-api-key; widget keys start with wk_."
|
|
243
242
|
);
|
|
244
243
|
}
|
|
245
244
|
if (apiKey) {
|
|
246
|
-
if (keyKind(apiKey) === "widget") widgetKey ??= apiKey;
|
|
245
|
+
if ((0, import_core2.keyKind)(apiKey) === "widget") widgetKey ??= apiKey;
|
|
247
246
|
else serverApiKey ??= apiKey;
|
|
248
247
|
}
|
|
249
248
|
if (!serverApiKey && !widgetKey) {
|
|
@@ -251,13 +250,13 @@ function resolveConfig(config) {
|
|
|
251
250
|
"A Channlize key is required. Set CHANNLIZE_SERVER_API_KEY (or --server-api-key) to a server API key (ch_live_\u2026) from SDK & Integration \u2192 API keys in the Channlize dashboard. Use a read-scoped key for read-only access, or add the write scope to send events, logs and conversations."
|
|
252
251
|
);
|
|
253
252
|
}
|
|
254
|
-
const timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
253
|
+
const timeout = config.timeout ?? import_core2.DEFAULT_TIMEOUT;
|
|
255
254
|
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
256
255
|
throw new ConfigError(
|
|
257
256
|
`Invalid timeout "${config.timeout}": use milliseconds, e.g. 10000`
|
|
258
257
|
);
|
|
259
258
|
}
|
|
260
|
-
const baseUrl = (clean(config.baseUrl) ?? DEFAULT_BASE_URL).replace(
|
|
259
|
+
const baseUrl = (clean(config.baseUrl) ?? import_core2.DEFAULT_BASE_URL).replace(
|
|
261
260
|
/\/+$/,
|
|
262
261
|
""
|
|
263
262
|
);
|
|
@@ -265,7 +264,7 @@ function resolveConfig(config) {
|
|
|
265
264
|
new URL(baseUrl);
|
|
266
265
|
} catch {
|
|
267
266
|
throw new ConfigError(
|
|
268
|
-
`Invalid base URL "${config.baseUrl}": use e.g. ${DEFAULT_BASE_URL}`
|
|
267
|
+
`Invalid base URL "${config.baseUrl}": use e.g. ${import_core2.DEFAULT_BASE_URL}`
|
|
269
268
|
);
|
|
270
269
|
}
|
|
271
270
|
return {
|
|
@@ -277,15 +276,8 @@ function resolveConfig(config) {
|
|
|
277
276
|
};
|
|
278
277
|
}
|
|
279
278
|
function configFromEnv(env = process.env) {
|
|
280
|
-
const timeout =
|
|
281
|
-
return {
|
|
282
|
-
serverApiKey: clean(env.CHANNLIZE_SERVER_API_KEY),
|
|
283
|
-
widgetKey: clean(env.CHANNLIZE_WIDGET_KEY),
|
|
284
|
-
apiKey: clean(env.CHANNLIZE_API_KEY),
|
|
285
|
-
projectId: clean(env.CHANNLIZE_PROJECT_ID),
|
|
286
|
-
baseUrl: clean(env.CHANNLIZE_BASE_URL),
|
|
287
|
-
timeout: timeout ? Number(timeout) : void 0
|
|
288
|
-
};
|
|
279
|
+
const { timeout, ...rest } = (0, import_core2.readChannlizeEnv)(env);
|
|
280
|
+
return { ...rest, timeout: timeout ? Number(timeout) : void 0 };
|
|
289
281
|
}
|
|
290
282
|
|
|
291
283
|
// src/prompts.ts
|
|
@@ -614,10 +606,9 @@ function registerResources(server, api) {
|
|
|
614
606
|
|
|
615
607
|
// src/tools.ts
|
|
616
608
|
var z2 = __toESM(require("zod/v4"));
|
|
609
|
+
var import_core3 = require("@channlize/core");
|
|
617
610
|
var STATUSES = ["open", "pending", "resolved", "closed"];
|
|
618
611
|
var PRIORITIES = ["low", "normal", "high", "urgent"];
|
|
619
|
-
var SEVERITIES = ["info", "warning", "error"];
|
|
620
|
-
var EVENT_KEY = /^[a-z0-9][a-z0-9._-]*$/;
|
|
621
612
|
function ok(data) {
|
|
622
613
|
return {
|
|
623
614
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
@@ -852,7 +843,7 @@ function registerServerTools(server, api) {
|
|
|
852
843
|
description: '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.',
|
|
853
844
|
inputSchema: z2.object({
|
|
854
845
|
event: z2.string().max(100).regex(
|
|
855
|
-
|
|
846
|
+
import_core3.EVENT_KEY_PATTERN,
|
|
856
847
|
"lowercase letters, digits, dots, underscores or dashes"
|
|
857
848
|
).describe("Event key, e.g. user.subscribed"),
|
|
858
849
|
data: record2.optional().describe(
|
|
@@ -939,7 +930,7 @@ function registerServerTools(server, api) {
|
|
|
939
930
|
title: "Query logs",
|
|
940
931
|
description: "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.",
|
|
941
932
|
inputSchema: z2.object({
|
|
942
|
-
severity: z2.enum(
|
|
933
|
+
severity: z2.enum(import_core3.EVENT_SEVERITIES).optional(),
|
|
943
934
|
source: z2.enum(["client_sdk", "server_api", "system"]).optional().describe(
|
|
944
935
|
"client_sdk = browser (widget key), server_api = server key"
|
|
945
936
|
),
|
|
@@ -971,7 +962,7 @@ function registerServerTools(server, api) {
|
|
|
971
962
|
description: "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.",
|
|
972
963
|
inputSchema: z2.object({
|
|
973
964
|
name: z2.string().min(1).max(255).describe("Log name, e.g. payment.failed"),
|
|
974
|
-
severity: z2.enum(
|
|
965
|
+
severity: z2.enum(import_core3.EVENT_SEVERITIES).default("info"),
|
|
975
966
|
properties: record2.optional().describe("Extra fields")
|
|
976
967
|
}),
|
|
977
968
|
outputSchema: z2.object({ id: z2.string(), projectId: z2.string() }),
|
|
@@ -1191,7 +1182,8 @@ async function startHttpServer(factory, options = {}) {
|
|
|
1191
1182
|
}
|
|
1192
1183
|
|
|
1193
1184
|
// src/index.ts
|
|
1194
|
-
var
|
|
1185
|
+
var import_core4 = require("@channlize/core");
|
|
1186
|
+
var VERSION = true ? "0.4.0" : "0.0.0";
|
|
1195
1187
|
var INSTRUCTIONS = `Channlize routes website conversations and app events to the team's Slack.
|
|
1196
1188
|
- Inbox: list_conversations / get_conversation, then contacts. Replies and status changes happen in Slack or the dashboard.
|
|
1197
1189
|
- Events (notify_event) post a Slack message per event key; list_event_definitions and list_event_deliveries explain what was sent or skipped.
|
|
@@ -1246,10 +1238,14 @@ function createMCPServer(options) {
|
|
|
1246
1238
|
var index_default = ChannlizeMCPServer;
|
|
1247
1239
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1248
1240
|
0 && (module.exports = {
|
|
1241
|
+
AuthenticationError,
|
|
1242
|
+
ChannlizeError,
|
|
1249
1243
|
ChannlizeMCPServer,
|
|
1250
1244
|
ConfigError,
|
|
1245
|
+
RateLimitError,
|
|
1251
1246
|
ToolError,
|
|
1252
1247
|
VERSION,
|
|
1248
|
+
ValidationError,
|
|
1253
1249
|
buildServer,
|
|
1254
1250
|
configFromEnv,
|
|
1255
1251
|
createMCPServer,
|