@omnifox/mcp-server 0.2.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/.env.example +27 -0
- package/LICENSE +21 -0
- package/README.md +252 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/omnifox/client.d.ts +74 -0
- package/dist/omnifox/client.d.ts.map +1 -0
- package/dist/omnifox/client.js +295 -0
- package/dist/omnifox/client.js.map +1 -0
- package/dist/omnifox/types.d.ts +53 -0
- package/dist/omnifox/types.d.ts.map +1 -0
- package/dist/omnifox/types.js +9 -0
- package/dist/omnifox/types.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +51 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/comments.d.ts +16 -0
- package/dist/tools/comments.d.ts.map +1 -0
- package/dist/tools/comments.js +31 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/contacts.d.ts +11 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +84 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/conversations.d.ts +13 -0
- package/dist/tools/conversations.d.ts.map +1 -0
- package/dist/tools/conversations.js +91 -0
- package/dist/tools/conversations.js.map +1 -0
- package/dist/tools/extras.d.ts +12 -0
- package/dist/tools/extras.d.ts.map +1 -0
- package/dist/tools/extras.js +105 -0
- package/dist/tools/extras.js.map +1 -0
- package/dist/tools/messaging.d.ts +18 -0
- package/dist/tools/messaging.d.ts.map +1 -0
- package/dist/tools/messaging.js +127 -0
- package/dist/tools/messaging.js.map +1 -0
- package/dist/tools/workspace.d.ts +12 -0
- package/dist/tools/workspace.d.ts.map +1 -0
- package/dist/tools/workspace.js +110 -0
- package/dist/tools/workspace.js.map +1 -0
- package/dist/transport/http.d.ts +12 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +65 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/stdio.d.ts +6 -0
- package/dist/transport/stdio.d.ts.map +1 -0
- package/dist/transport/stdio.js +12 -0
- package/dist/transport/stdio.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Omnifox V1 REST client — a thin fetch wrapper used by every MCP tool.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Bearer-token auth via OMNIFOX_API_KEY.
|
|
6
|
+
* - Cursor pagination helpers.
|
|
7
|
+
* - Retry on 429 (respecting Retry-After) and on transient 5xx, up to N attempts.
|
|
8
|
+
* - Typed error envelopes via OmnifoxApiError.
|
|
9
|
+
*/
|
|
10
|
+
/** Custom error carrying the canonical Omnifox error envelope. */
|
|
11
|
+
export class OmnifoxApiError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
code;
|
|
14
|
+
details;
|
|
15
|
+
traceId;
|
|
16
|
+
constructor(status, envelope) {
|
|
17
|
+
super(`HTTP ${status}: ${envelope.message}${describeDetails(status, envelope.details)}`);
|
|
18
|
+
this.name = "OmnifoxApiError";
|
|
19
|
+
this.status = status;
|
|
20
|
+
this.code = envelope.code;
|
|
21
|
+
this.details = envelope.details;
|
|
22
|
+
this.traceId = envelope.traceId;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const DEFAULT_BASE_URL = "https://omnifox.io/api/v1";
|
|
26
|
+
const SERVER_VERSION = "0.2.0";
|
|
27
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
28
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
29
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
30
|
+
export class OmnifoxClient {
|
|
31
|
+
apiKey;
|
|
32
|
+
baseUrl;
|
|
33
|
+
workspaceId;
|
|
34
|
+
timeoutMs;
|
|
35
|
+
maxRetries;
|
|
36
|
+
fetchImpl;
|
|
37
|
+
constructor(opts = {}) {
|
|
38
|
+
const apiKey = opts.apiKey ?? process.env.OMNIFOX_API_KEY;
|
|
39
|
+
if (!apiKey) {
|
|
40
|
+
throw new Error("OMNIFOX_API_KEY is required. Set it in your environment or pass apiKey to OmnifoxClient.");
|
|
41
|
+
}
|
|
42
|
+
this.apiKey = apiKey;
|
|
43
|
+
this.baseUrl = (opts.baseUrl ?? process.env.OMNIFOX_BASE_URL ?? DEFAULT_BASE_URL)
|
|
44
|
+
.replace(/\/+$/, "");
|
|
45
|
+
const rawWorkspace = opts.workspaceId ?? process.env.OMNIFOX_WORKSPACE_ID;
|
|
46
|
+
this.workspaceId =
|
|
47
|
+
rawWorkspace === undefined || rawWorkspace === "" ? undefined : Number(rawWorkspace);
|
|
48
|
+
this.timeoutMs = opts.timeoutMs
|
|
49
|
+
?? (Number(process.env.OMNIFOX_TIMEOUT_MS) || DEFAULT_TIMEOUT_MS);
|
|
50
|
+
this.maxRetries = opts.maxRetries
|
|
51
|
+
?? (Number(process.env.OMNIFOX_MAX_RETRIES) || DEFAULT_MAX_RETRIES);
|
|
52
|
+
this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
53
|
+
}
|
|
54
|
+
/** Add `workspace_id` unless the caller set one explicitly. */
|
|
55
|
+
withWorkspace(query, override) {
|
|
56
|
+
const wsId = override ?? this.workspaceId;
|
|
57
|
+
if (wsId === undefined)
|
|
58
|
+
return query;
|
|
59
|
+
if (query && query.workspace_id !== undefined)
|
|
60
|
+
return query;
|
|
61
|
+
return { ...(query ?? {}), workspace_id: wsId };
|
|
62
|
+
}
|
|
63
|
+
/** Build a fully-qualified URL with optional query string. */
|
|
64
|
+
buildUrl(path, query) {
|
|
65
|
+
const url = new URL(path.startsWith("/") ? `${this.baseUrl}${path}` : `${this.baseUrl}/${path}`);
|
|
66
|
+
if (query) {
|
|
67
|
+
for (const [key, value] of Object.entries(query)) {
|
|
68
|
+
if (value === undefined || value === null)
|
|
69
|
+
continue;
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
for (const v of value)
|
|
72
|
+
url.searchParams.append(key, String(v));
|
|
73
|
+
}
|
|
74
|
+
else if (typeof value === "object") {
|
|
75
|
+
url.searchParams.append(key, JSON.stringify(value));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
url.searchParams.append(key, String(value));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return url.toString();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Default headers.
|
|
86
|
+
*
|
|
87
|
+
* There is deliberately no `X-Workspace-Id` here: the API never reads that
|
|
88
|
+
* header. It resolves the workspace from the token (tokens minted in the
|
|
89
|
+
* API-keys screen are pinned to one) and otherwise from the `workspace_id`
|
|
90
|
+
* parameter, which {@link buildUrl} adds to every request.
|
|
91
|
+
*/
|
|
92
|
+
buildHeaders() {
|
|
93
|
+
return new Headers({
|
|
94
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
95
|
+
Accept: "application/json",
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
"User-Agent": `omnifox-mcp-server/${SERVER_VERSION}`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/** Core request method with retry + abort support. */
|
|
101
|
+
async request(opts) {
|
|
102
|
+
const url = this.buildUrl(opts.path, this.withWorkspace(opts.query, opts.workspaceId));
|
|
103
|
+
const init = {
|
|
104
|
+
method: opts.method,
|
|
105
|
+
headers: this.buildHeaders(),
|
|
106
|
+
};
|
|
107
|
+
if (opts.body !== undefined && opts.method !== "GET") {
|
|
108
|
+
init.body = JSON.stringify(opts.body);
|
|
109
|
+
}
|
|
110
|
+
let lastErr;
|
|
111
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
112
|
+
const controller = new AbortController();
|
|
113
|
+
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
114
|
+
try {
|
|
115
|
+
const res = await this.fetchImpl(url, { ...init, signal: controller.signal });
|
|
116
|
+
clearTimeout(timeout);
|
|
117
|
+
// 204 No Content
|
|
118
|
+
if (res.status === 204)
|
|
119
|
+
return undefined;
|
|
120
|
+
// Retryable: rate limit
|
|
121
|
+
if (res.status === 429 && attempt < this.maxRetries) {
|
|
122
|
+
const retryAfter = Number(res.headers.get("Retry-After")) || 1;
|
|
123
|
+
await sleep(retryAfter * 1000);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
// Retryable: transient 5xx
|
|
127
|
+
if (res.status >= 500 && res.status < 600 && attempt < this.maxRetries) {
|
|
128
|
+
await sleep(2 ** attempt * 500);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const text = await res.text();
|
|
132
|
+
const parsed = text ? safeJson(text) : null;
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
const env = normalizeError(parsed, res.status);
|
|
135
|
+
throw new OmnifoxApiError(res.status, env);
|
|
136
|
+
}
|
|
137
|
+
return unwrapEnvelope(parsed);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
clearTimeout(timeout);
|
|
141
|
+
lastErr = err;
|
|
142
|
+
if (err instanceof OmnifoxApiError)
|
|
143
|
+
throw err;
|
|
144
|
+
if (attempt >= this.maxRetries)
|
|
145
|
+
break;
|
|
146
|
+
await sleep(2 ** attempt * 500);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
throw lastErr instanceof Error
|
|
150
|
+
? lastErr
|
|
151
|
+
: new Error("Omnifox request failed after retries");
|
|
152
|
+
}
|
|
153
|
+
// ---------- Convenience verbs ----------
|
|
154
|
+
get(path, query) {
|
|
155
|
+
return this.request({ method: "GET", path, query });
|
|
156
|
+
}
|
|
157
|
+
post(path, body, query) {
|
|
158
|
+
return this.request({ method: "POST", path, body, query });
|
|
159
|
+
}
|
|
160
|
+
patch(path, body) {
|
|
161
|
+
return this.request({ method: "PATCH", path, body });
|
|
162
|
+
}
|
|
163
|
+
put(path, body) {
|
|
164
|
+
return this.request({ method: "PUT", path, body });
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* DELETE, optionally with a body — `DELETE /contacts/{id}/tags-by-name`
|
|
168
|
+
* carries the tag names to detach, so a body-less delete is not enough.
|
|
169
|
+
*/
|
|
170
|
+
delete(path, body, query) {
|
|
171
|
+
return this.request({ method: "DELETE", path, body, query });
|
|
172
|
+
}
|
|
173
|
+
// ---------- Pagination helper ----------
|
|
174
|
+
/**
|
|
175
|
+
* Build the cursor-pagination query block accepted by every list endpoint.
|
|
176
|
+
* Pass through additional filters via `extra`.
|
|
177
|
+
*/
|
|
178
|
+
buildListQuery(opts = {}) {
|
|
179
|
+
// Cursor mode is only requested when the caller actually wants to walk a
|
|
180
|
+
// cursor; asking for it unconditionally makes page-based endpoints return
|
|
181
|
+
// an envelope the caller then has to special-case.
|
|
182
|
+
const q = {};
|
|
183
|
+
if (opts.cursorId) {
|
|
184
|
+
q.pagination = "cursor";
|
|
185
|
+
q.cursorId = opts.cursorId;
|
|
186
|
+
}
|
|
187
|
+
if (opts.page)
|
|
188
|
+
q.page = opts.page;
|
|
189
|
+
if (opts.limit)
|
|
190
|
+
q.per_page = opts.limit;
|
|
191
|
+
if (opts.search)
|
|
192
|
+
q.search = opts.search;
|
|
193
|
+
if (opts.sort)
|
|
194
|
+
q.sort = opts.sort;
|
|
195
|
+
if (opts.extra) {
|
|
196
|
+
for (const [k, v] of Object.entries(opts.extra)) {
|
|
197
|
+
if (v !== undefined && v !== null)
|
|
198
|
+
q[k] = v;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return q;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// ---------- helpers ----------
|
|
205
|
+
function safeJson(text) {
|
|
206
|
+
try {
|
|
207
|
+
return JSON.parse(text);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return { raw: text };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Turn the error body into guidance the calling model can act on:
|
|
215
|
+
* per-field validation messages, and a plain-language note for the two status
|
|
216
|
+
* codes whose bare message explains nothing.
|
|
217
|
+
*/
|
|
218
|
+
function describeDetails(status, details) {
|
|
219
|
+
const parts = [];
|
|
220
|
+
if (details && typeof details === "object" && !Array.isArray(details)) {
|
|
221
|
+
const lines = Object.entries(details).map(([field, msgs]) => {
|
|
222
|
+
const first = Array.isArray(msgs) ? msgs[0] : msgs;
|
|
223
|
+
return `${field}: ${String(first)}`;
|
|
224
|
+
});
|
|
225
|
+
if (lines.length)
|
|
226
|
+
parts.push(lines.join(" · "));
|
|
227
|
+
}
|
|
228
|
+
if (status === 402) {
|
|
229
|
+
parts.push("The workspace plan or AI wallet does not cover this call.");
|
|
230
|
+
}
|
|
231
|
+
else if (status === 403) {
|
|
232
|
+
parts.push("The token may be missing this module's ability (read:/write:crm, read:/write:projects), " +
|
|
233
|
+
"or the workspace plan does not include the module.");
|
|
234
|
+
}
|
|
235
|
+
else if (status === 404) {
|
|
236
|
+
parts.push("Ids are workspace-scoped — check the record belongs to this workspace.");
|
|
237
|
+
}
|
|
238
|
+
return parts.length ? ` (${parts.join(" — ")})` : "";
|
|
239
|
+
}
|
|
240
|
+
function normalizeError(parsed, status) {
|
|
241
|
+
if (parsed && typeof parsed === "object") {
|
|
242
|
+
const obj = parsed;
|
|
243
|
+
// Laravel sometimes nests under { error: {...} } or returns flat.
|
|
244
|
+
const root = obj.error && typeof obj.error === "object"
|
|
245
|
+
? obj.error
|
|
246
|
+
: obj;
|
|
247
|
+
return {
|
|
248
|
+
code: typeof root.code === "string" ? root.code : `http_${status}`,
|
|
249
|
+
message: typeof root.message === "string"
|
|
250
|
+
? root.message
|
|
251
|
+
: `Omnifox request failed with status ${status}`,
|
|
252
|
+
details: root.details ?? root.errors ?? undefined,
|
|
253
|
+
traceId: typeof root.traceId === "string" ? root.traceId : undefined,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
code: `http_${status}`,
|
|
258
|
+
message: `Omnifox request failed with status ${status}`,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Normalise a response into the smallest thing a model can reason about.
|
|
263
|
+
*
|
|
264
|
+
* Two transformations, both about token economy and clarity:
|
|
265
|
+
*
|
|
266
|
+
* 1. Strip the `{success, message, data}` wrapper the API puts around every
|
|
267
|
+
* successful response.
|
|
268
|
+
* 2. Flatten Laravel's paginator. Handing a model `first_page_url`,
|
|
269
|
+
* `prev_page_url`, `links[]` and `path` is noise it has to read past on
|
|
270
|
+
* every listing; `{items, page, last_page, total}` says the same thing.
|
|
271
|
+
*/
|
|
272
|
+
function unwrapEnvelope(payload) {
|
|
273
|
+
let value = payload;
|
|
274
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
275
|
+
const obj = value;
|
|
276
|
+
if ("success" in obj && "data" in obj)
|
|
277
|
+
value = obj.data;
|
|
278
|
+
}
|
|
279
|
+
return simplifyPaginator(value);
|
|
280
|
+
}
|
|
281
|
+
function simplifyPaginator(value) {
|
|
282
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
283
|
+
return value;
|
|
284
|
+
const obj = value;
|
|
285
|
+
if (!Array.isArray(obj.data) || obj.current_page === undefined)
|
|
286
|
+
return value;
|
|
287
|
+
return {
|
|
288
|
+
items: obj.data,
|
|
289
|
+
page: obj.current_page,
|
|
290
|
+
last_page: obj.last_page ?? null,
|
|
291
|
+
per_page: obj.per_page ?? null,
|
|
292
|
+
total: obj.total ?? null,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/omnifox/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Omnifox V1 API — type definitions used by the MCP tool layer.
|
|
3
|
+
*
|
|
4
|
+
* These are intentionally hand-written and tight, NOT generated from OpenAPI.
|
|
5
|
+
* The goal is to keep the tool surface ergonomic for LLM callers and avoid
|
|
6
|
+
* leaking every internal detail of the Laravel response envelopes.
|
|
7
|
+
*/
|
|
8
|
+
/** Standard error envelope returned by every Omnifox 4xx / 5xx response. */
|
|
9
|
+
export interface OmnifoxErrorEnvelope {
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
details?: unknown;
|
|
13
|
+
traceId?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Cursor-paginated list envelope. */
|
|
16
|
+
export interface OmnifoxPaginatedResponse<T> {
|
|
17
|
+
data: T[];
|
|
18
|
+
pagination: {
|
|
19
|
+
cursor: string | null;
|
|
20
|
+
hasMore: boolean;
|
|
21
|
+
perPage: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Plain success envelope for single-resource endpoints. */
|
|
25
|
+
export interface OmnifoxResource<T> {
|
|
26
|
+
data: T;
|
|
27
|
+
}
|
|
28
|
+
/** Lifecycle stages — Omnifox extension. */
|
|
29
|
+
export type LifecycleStage = "lead" | "marketing-qualified" | "sales-qualified" | "opportunity" | "customer" | "evangelist" | "other" | string;
|
|
30
|
+
/** Conversation status values accepted by the API. */
|
|
31
|
+
export type ConversationStatus = "open" | "closed" | "resolved" | "pending";
|
|
32
|
+
/** Channel sources supported by Omnifox. */
|
|
33
|
+
export type ChannelSource = "whatsapp" | "whatsapp-cloud" | "instagram" | "messenger" | "telegram" | "webchat" | "sms" | "email" | "voice" | string;
|
|
34
|
+
/** Message content types accepted by send_message. */
|
|
35
|
+
export type MessageContentType = "text" | "attachment" | "template" | "interactive" | "location" | "contact";
|
|
36
|
+
/** Options accepted by every list_* tool. */
|
|
37
|
+
export interface ListOptions {
|
|
38
|
+
limit?: number;
|
|
39
|
+
cursorId?: string;
|
|
40
|
+
search?: string;
|
|
41
|
+
filter?: Record<string, unknown>;
|
|
42
|
+
sort?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Inputs to the low-level fetch helper. */
|
|
45
|
+
export interface RequestOptions {
|
|
46
|
+
method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
|
|
47
|
+
path: string;
|
|
48
|
+
query?: Record<string, unknown>;
|
|
49
|
+
body?: unknown;
|
|
50
|
+
/** Override workspace for this single request. */
|
|
51
|
+
workspaceId?: string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/omnifox/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sCAAsC;AACtC,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,UAAU,EAAE;QACV,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,4DAA4D;AAC5D,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC;CACT;AAED,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,qBAAqB,GACrB,iBAAiB,GACjB,aAAa,GACb,UAAU,GACV,YAAY,GACZ,OAAO,GACP,MAAM,CAAC;AAEX,sDAAsD;AACtD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAE5E,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,gBAAgB,GAChB,WAAW,GACX,WAAW,GACX,UAAU,GACV,SAAS,GACT,KAAK,GACL,OAAO,GACP,OAAO,GACP,MAAM,CAAC;AAEX,sDAAsD;AACtD,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,YAAY,GACZ,UAAU,GACV,aAAa,GACb,UAAU,GACV,SAAS,CAAC;AAEd,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Omnifox V1 API — type definitions used by the MCP tool layer.
|
|
3
|
+
*
|
|
4
|
+
* These are intentionally hand-written and tight, NOT generated from OpenAPI.
|
|
5
|
+
* The goal is to keep the tool surface ergonomic for LLM callers and avoid
|
|
6
|
+
* leaking every internal detail of the Laravel response envelopes.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/omnifox/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the MCP Server instance and registers every tool.
|
|
3
|
+
*/
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { OmnifoxClient, type OmnifoxClientOptions } from "./omnifox/client.js";
|
|
6
|
+
export declare const SERVER_NAME = "omnifox-mcp-server";
|
|
7
|
+
export declare const SERVER_VERSION = "0.2.0";
|
|
8
|
+
export interface BuildServerOptions {
|
|
9
|
+
client?: OmnifoxClient;
|
|
10
|
+
clientOptions?: OmnifoxClientOptions;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Construct an Omnifox MCP server with every tool wired up.
|
|
14
|
+
* Pass `client` to inject a pre-configured / mocked client (useful for tests).
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildServer(opts?: BuildServerOptions): McpServer;
|
|
17
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAQ/E,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAChD,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,SAAS,CAuCpE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the MCP Server instance and registers every tool.
|
|
3
|
+
*/
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { OmnifoxClient } from "./omnifox/client.js";
|
|
6
|
+
import { registerContactTools } from "./tools/contacts.js";
|
|
7
|
+
import { registerMessagingTools } from "./tools/messaging.js";
|
|
8
|
+
import { registerConversationTools } from "./tools/conversations.js";
|
|
9
|
+
import { registerCommentTools } from "./tools/comments.js";
|
|
10
|
+
import { registerWorkspaceTools } from "./tools/workspace.js";
|
|
11
|
+
import { registerExtraTools } from "./tools/extras.js";
|
|
12
|
+
export const SERVER_NAME = "omnifox-mcp-server";
|
|
13
|
+
export const SERVER_VERSION = "0.2.0";
|
|
14
|
+
/**
|
|
15
|
+
* Construct an Omnifox MCP server with every tool wired up.
|
|
16
|
+
* Pass `client` to inject a pre-configured / mocked client (useful for tests).
|
|
17
|
+
*/
|
|
18
|
+
export function buildServer(opts = {}) {
|
|
19
|
+
const client = opts.client ?? new OmnifoxClient(opts.clientOptions);
|
|
20
|
+
const server = new McpServer({
|
|
21
|
+
name: SERVER_NAME,
|
|
22
|
+
version: SERVER_VERSION,
|
|
23
|
+
}, {
|
|
24
|
+
capabilities: {
|
|
25
|
+
tools: {},
|
|
26
|
+
logging: {},
|
|
27
|
+
},
|
|
28
|
+
instructions: "Omnifox MCP server — the Omnifox.io customer-messaging platform " +
|
|
29
|
+
"(WhatsApp, Instagram, Messenger, Telegram, webchat, SMS, email, voice) " +
|
|
30
|
+
"with its CRM, broadcasts and automations.\n\n" +
|
|
31
|
+
"Every id is a positive integer, never a UUID. Contacts additionally " +
|
|
32
|
+
"accept a kind:value selector — 'email:foo@bar.com', 'phone:+593...', " +
|
|
33
|
+
"'external:abc' — anywhere an identifier is asked for.\n\n" +
|
|
34
|
+
"Start with list_channels and list_users to discover the ids you need. " +
|
|
35
|
+
"To message somebody, send_message is usually right: it finds or opens " +
|
|
36
|
+
"the conversation for you. Use send_conversation_message only when you " +
|
|
37
|
+
"already hold a conversation id.\n\n" +
|
|
38
|
+
"WhatsApp only accepts free-form text within 24 hours of the customer's " +
|
|
39
|
+
"last message; outside that window send a template (list_templates).\n\n" +
|
|
40
|
+
"Authentication is a Sanctum personal access token in OMNIFOX_API_KEY; " +
|
|
41
|
+
"set OMNIFOX_WORKSPACE_ID too if the token is not pinned to a workspace.",
|
|
42
|
+
});
|
|
43
|
+
registerContactTools(server, client);
|
|
44
|
+
registerMessagingTools(server, client);
|
|
45
|
+
registerConversationTools(server, client);
|
|
46
|
+
registerCommentTools(server, client);
|
|
47
|
+
registerWorkspaceTools(server, client);
|
|
48
|
+
registerExtraTools(server, client);
|
|
49
|
+
return server;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAOtC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B,EAAE;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAEpE,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;KACxB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;SACZ;QACD,YAAY,EACV,kEAAkE;YAClE,yEAAyE;YACzE,+CAA+C;YAC/C,sEAAsE;YACtE,uEAAuE;YACvE,2DAA2D;YAC3D,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,qCAAqC;YACrC,yEAAyE;YACzE,yEAAyE;YACzE,wEAAwE;YACxE,yEAAyE;KAC5E,CACF,CAAC;IAEF,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal notes.
|
|
3
|
+
*
|
|
4
|
+
* The endpoint validates `text` and `mentioned_user_ids`. 0.1.0 sent
|
|
5
|
+
* `{body, mentions}` — `text` is required, so every note was rejected.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import type { OmnifoxClient } from "../omnifox/client.js";
|
|
10
|
+
export declare const commentInputSchema: {
|
|
11
|
+
readonly conversationId: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
|
|
12
|
+
readonly text: z.ZodString;
|
|
13
|
+
readonly mentioned_user_ids: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
14
|
+
};
|
|
15
|
+
export declare function registerCommentTools(server: McpServer, client: OmnifoxClient): void;
|
|
16
|
+
//# sourceMappingURL=comments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/tools/comments.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAM1D,eAAO,MAAM,kBAAkB;;;;CAarB,CAAC;AAEX,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAanF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal notes.
|
|
3
|
+
*
|
|
4
|
+
* The endpoint validates `text` and `mentioned_user_ids`. 0.1.0 sent
|
|
5
|
+
* `{body, mentions}` — `text` is required, so every note was rejected.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
const ok = (data) => ({
|
|
9
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
10
|
+
});
|
|
11
|
+
export const commentInputSchema = {
|
|
12
|
+
conversationId: z
|
|
13
|
+
.union([z.number().int().positive(), z.string().regex(/^\d+$/)])
|
|
14
|
+
.describe("Numeric id of the conversation."),
|
|
15
|
+
text: z
|
|
16
|
+
.string()
|
|
17
|
+
.min(1)
|
|
18
|
+
.max(5000)
|
|
19
|
+
.describe("Note body. Visible to teammates only — the customer never sees it."),
|
|
20
|
+
mentioned_user_ids: z
|
|
21
|
+
.array(z.number().int())
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Teammate ids to @-mention; each one gets a notification."),
|
|
24
|
+
};
|
|
25
|
+
export function registerCommentTools(server, client) {
|
|
26
|
+
server.tool("create_comment", "Add an internal note to a conversation. Notes are visible to teammates only.", commentInputSchema, async ({ conversationId, text, mentioned_user_ids }) => ok(await client.post(`/conversations/${encodeURIComponent(String(conversationId))}/notes`, {
|
|
27
|
+
text,
|
|
28
|
+
...(mentioned_user_ids?.length ? { mentioned_user_ids } : {}),
|
|
29
|
+
})));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=comments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/tools/comments.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,EAAE,GAAG,CAAC,IAAa,EAAE,EAAE,CAAC,CAAC;IAC7B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;CAC1E,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,cAAc,EAAE,CAAC;SACd,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;SAC/D,QAAQ,CAAC,iCAAiC,CAAC;IAC9C,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,IAAI,CAAC;SACT,QAAQ,CAAC,oEAAoE,CAAC;IACjF,kBAAkB,EAAE,CAAC;SAClB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;SACvB,QAAQ,EAAE;SACV,QAAQ,CAAC,0DAA0D,CAAC;CAC/D,CAAC;AAEX,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAqB;IAC3E,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,8EAA8E,EAC9E,kBAAkB,EAClB,KAAK,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,CACrD,EAAE,CACA,MAAM,MAAM,CAAC,IAAI,CAAC,kBAAkB,kBAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;QACtF,IAAI;QACJ,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC,CACH,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contact tools.
|
|
3
|
+
*
|
|
4
|
+
* Field names here are the ones the API validates — snake_case throughout.
|
|
5
|
+
* 0.1.0 used camelCase (`firstName`, `countryCode`, `customFields`) and omitted
|
|
6
|
+
* the required `display_name`, so create and update were rejected every time.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import type { OmnifoxClient } from "../omnifox/client.js";
|
|
10
|
+
export declare function registerContactTools(server: McpServer, client: OmnifoxClient): void;
|
|
11
|
+
//# sourceMappingURL=contacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../src/tools/contacts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA+B1D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAqInF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contact tools.
|
|
3
|
+
*
|
|
4
|
+
* Field names here are the ones the API validates — snake_case throughout.
|
|
5
|
+
* 0.1.0 used camelCase (`firstName`, `countryCode`, `customFields`) and omitted
|
|
6
|
+
* the required `display_name`, so create and update were rejected every time.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
const identifierSchema = z
|
|
10
|
+
.string()
|
|
11
|
+
.min(1)
|
|
12
|
+
.describe("Contact identifier — a numeric id, or a kind:value selector: " +
|
|
13
|
+
"'email:foo@bar.com', 'phone:+593987654321', 'external:abc-xyz'.");
|
|
14
|
+
/** Attributes shared by create and update. */
|
|
15
|
+
const contactAttributes = {
|
|
16
|
+
first_name: z.string().max(255).optional(),
|
|
17
|
+
last_name: z.string().max(255).optional(),
|
|
18
|
+
email: z.string().email().max(255).optional(),
|
|
19
|
+
phone: z.string().max(50).optional().describe("E.164 preferred, e.g. +593987654321."),
|
|
20
|
+
avatar_url: z.string().url().max(500).optional(),
|
|
21
|
+
country: z.string().length(2).optional().describe("ISO 3166-1 alpha-2, e.g. EC."),
|
|
22
|
+
city: z.string().max(255).optional(),
|
|
23
|
+
locale: z.string().max(10).optional(),
|
|
24
|
+
gender: z.enum(["male", "female", "other", "unknown"]).optional(),
|
|
25
|
+
company: z.string().max(255).optional(),
|
|
26
|
+
job_title: z.string().max(255).optional(),
|
|
27
|
+
notes: z.string().optional(),
|
|
28
|
+
external_id: z.string().max(255).optional(),
|
|
29
|
+
};
|
|
30
|
+
const ok = (data) => ({
|
|
31
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
32
|
+
});
|
|
33
|
+
export function registerContactTools(server, client) {
|
|
34
|
+
server.tool("get_contact", "Fetch a single contact by id or by a kind:value selector (email:, phone:, external:).", { identifier: identifierSchema }, async ({ identifier }) => ok(await client.get(`/contacts/${encodeURIComponent(identifier)}`)));
|
|
35
|
+
server.tool("create_contact", "Create a contact. `display_name` is the only required field; use create_or_update_contact when the person may already exist.", {
|
|
36
|
+
display_name: z.string().min(1).max(255).describe("Name shown in the inbox."),
|
|
37
|
+
...contactAttributes,
|
|
38
|
+
tags: z.array(z.number().int()).optional().describe("Tag ids to attach."),
|
|
39
|
+
}, async (params) => ok(await client.post("/contacts", params)));
|
|
40
|
+
server.tool("update_contact", "Update an existing contact's attributes. Only the fields you pass change; everything else is left alone.", {
|
|
41
|
+
identifier: identifierSchema,
|
|
42
|
+
patch: z
|
|
43
|
+
.object({ display_name: z.string().max(255).optional(), ...contactAttributes })
|
|
44
|
+
.describe("Fields to change; anything omitted is left alone."),
|
|
45
|
+
}, async ({ identifier, patch }) => ok(await client.put(`/contacts/${encodeURIComponent(identifier)}`, patch)));
|
|
46
|
+
server.tool("delete_contact", "Permanently delete a contact and everything hanging off it. Irreversible — prefer leaving the contact and closing its conversation unless deletion was explicitly asked for.", { identifier: identifierSchema }, async ({ identifier }) => ok(await client.delete(`/contacts/${encodeURIComponent(identifier)}`)));
|
|
47
|
+
server.tool("list_contacts", "List contacts, most recently active first. Use search_contacts when you are looking for somebody by name, email or phone.", {
|
|
48
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
49
|
+
page: z.number().int().min(1).optional(),
|
|
50
|
+
search: z.string().optional().describe("Free-text over name, email and phone."),
|
|
51
|
+
tag_id: z.number().int().optional(),
|
|
52
|
+
email: z.string().optional(),
|
|
53
|
+
phone: z.string().optional(),
|
|
54
|
+
country: z.string().length(2).optional(),
|
|
55
|
+
}, async ({ limit, page, search, tag_id, email, phone, country }) => ok(await client.get("/contacts", client.buildListQuery({
|
|
56
|
+
limit,
|
|
57
|
+
page,
|
|
58
|
+
search,
|
|
59
|
+
extra: { tag_id, email, phone, country },
|
|
60
|
+
}))));
|
|
61
|
+
server.tool("search_contacts", "Free-text contact search over name, email and phone. The query must be at least 2 characters.", { query: z.string().min(2), limit: z.number().int().min(1).max(100).optional() }, async ({ query, limit }) => ok(await client.get("/contacts/search", { q: query, ...(limit ? { limit } : {}) })));
|
|
62
|
+
server.tool("add_contact_tags", "Attach tags to a contact BY NAME, creating any that do not exist yet.", {
|
|
63
|
+
identifier: identifierSchema,
|
|
64
|
+
names: z.array(z.string().min(1).max(64)).min(1).max(25),
|
|
65
|
+
}, async ({ identifier, names }) => ok(await client.post(`/contacts/${encodeURIComponent(identifier)}/tags-by-name`, { names })));
|
|
66
|
+
server.tool("remove_contact_tags", "Detach tags from a contact by name. Tags not currently attached are ignored.", {
|
|
67
|
+
identifier: identifierSchema,
|
|
68
|
+
names: z.array(z.string().min(1).max(64)).min(1).max(25),
|
|
69
|
+
}, async ({ identifier, names }) => ok(await client.delete(`/contacts/${encodeURIComponent(identifier)}/tags-by-name`, { names })));
|
|
70
|
+
server.tool("create_or_update_contact", "Idempotent upsert: finds the contact by the chosen keys and creates it if there is no match.", {
|
|
71
|
+
unique_by: z
|
|
72
|
+
.array(z.enum(["phone", "email", "external_id"]))
|
|
73
|
+
.min(1)
|
|
74
|
+
.describe("Which fields identify the contact. Each one listed must also be supplied."),
|
|
75
|
+
...contactAttributes,
|
|
76
|
+
display_name: z.string().max(255).optional(),
|
|
77
|
+
}, async (params) => ok(await client.post("/contacts/upsert", params)));
|
|
78
|
+
server.tool("merge_contacts", "Merge one contact into another. The primary survives; the merged record's conversations, deals and activities are reparented onto it.", {
|
|
79
|
+
primary_contact_id: z.number().int().positive().describe("The contact that survives."),
|
|
80
|
+
merged_contact_id: z.number().int().positive().describe("The contact folded into it."),
|
|
81
|
+
}, async ({ primary_contact_id, merged_contact_id }) => ok(await client.post("/contacts/merge", { primary_contact_id, merged_contact_id })));
|
|
82
|
+
server.tool("list_contact_channels", "List every channel identity attached to a contact (WhatsApp number, IG handle, email…).", { identifier: identifierSchema }, async ({ identifier }) => ok(await client.get(`/contacts/${encodeURIComponent(identifier)}/channels`)));
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=contacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contacts.js","sourceRoot":"","sources":["../../src/tools/contacts.ts"],"names":[],"mappings":"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"}
|