@codespar/mcp-take-blip 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +256 -0
- package/package.json +30 -0
- package/src/index.ts +272 -0
- package/tsconfig.json +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server for Take Blip — Brazilian chatbot and messaging platform.
|
|
4
|
+
*
|
|
5
|
+
* Tools:
|
|
6
|
+
* - send_message: Send a message to a contact
|
|
7
|
+
* - get_contacts: List contacts
|
|
8
|
+
* - create_contact: Create a contact
|
|
9
|
+
* - get_threads: Get message threads
|
|
10
|
+
* - send_notification: Send a notification/broadcast message
|
|
11
|
+
* - get_analytics: Get chatbot analytics
|
|
12
|
+
* - create_broadcast: Create a broadcast list and send
|
|
13
|
+
* - get_chatbot_flow: Get chatbot flow configuration
|
|
14
|
+
*
|
|
15
|
+
* Environment:
|
|
16
|
+
* TAKE_BLIP_BOT_ID — Bot identifier
|
|
17
|
+
* TAKE_BLIP_ACCESS_KEY — Bot access key
|
|
18
|
+
*
|
|
19
|
+
* Note: Take Blip uses a JSON-based messaging protocol.
|
|
20
|
+
* Requests go as POST to /commands with type/method/uri in body.
|
|
21
|
+
*/
|
|
22
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
23
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
24
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
25
|
+
const BOT_ID = process.env.TAKE_BLIP_BOT_ID || "";
|
|
26
|
+
const ACCESS_KEY = process.env.TAKE_BLIP_ACCESS_KEY || "";
|
|
27
|
+
const BASE_URL = "https://msging.net";
|
|
28
|
+
function getAuthKey() {
|
|
29
|
+
const raw = `${BOT_ID}:${ACCESS_KEY}`;
|
|
30
|
+
return btoa(raw);
|
|
31
|
+
}
|
|
32
|
+
async function blipCommand(id, method, uri, type, resource) {
|
|
33
|
+
const body = { id, method, uri };
|
|
34
|
+
if (type)
|
|
35
|
+
body.type = type;
|
|
36
|
+
if (resource)
|
|
37
|
+
body.resource = resource;
|
|
38
|
+
const res = await fetch(`${BASE_URL}/commands`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
"Authorization": `Key ${getAuthKey()}`,
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(body),
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
const err = await res.text();
|
|
48
|
+
throw new Error(`Take Blip API ${res.status}: ${err}`);
|
|
49
|
+
}
|
|
50
|
+
return res.json();
|
|
51
|
+
}
|
|
52
|
+
async function blipMessage(to, type, content) {
|
|
53
|
+
const res = await fetch(`${BASE_URL}/messages`, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: {
|
|
56
|
+
"Content-Type": "application/json",
|
|
57
|
+
"Authorization": `Key ${getAuthKey()}`,
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify({ id: crypto.randomUUID(), to, type, content }),
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
const err = await res.text();
|
|
63
|
+
throw new Error(`Take Blip API ${res.status}: ${err}`);
|
|
64
|
+
}
|
|
65
|
+
return res.json();
|
|
66
|
+
}
|
|
67
|
+
const server = new Server({ name: "mcp-take-blip", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
68
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
69
|
+
tools: [
|
|
70
|
+
{
|
|
71
|
+
name: "send_message",
|
|
72
|
+
description: "Send a message to a contact via Take Blip",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: {
|
|
76
|
+
to: { type: "string", description: "Recipient identity (e.g., 5511999999999@wa.gw.msging.net)" },
|
|
77
|
+
content: { type: "string", description: "Message text content" },
|
|
78
|
+
type: { type: "string", description: "Content type (default: text/plain)", enum: ["text/plain", "application/json"] },
|
|
79
|
+
},
|
|
80
|
+
required: ["to", "content"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "get_contacts",
|
|
85
|
+
description: "List contacts in Take Blip",
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
skip: { type: "number", description: "Number of contacts to skip" },
|
|
90
|
+
take: { type: "number", description: "Number of contacts to return (default 20)" },
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "create_contact",
|
|
96
|
+
description: "Create a contact in Take Blip",
|
|
97
|
+
inputSchema: {
|
|
98
|
+
type: "object",
|
|
99
|
+
properties: {
|
|
100
|
+
identity: { type: "string", description: "Contact identity (e.g., 5511999999999@wa.gw.msging.net)" },
|
|
101
|
+
name: { type: "string", description: "Contact name" },
|
|
102
|
+
email: { type: "string", description: "Contact email" },
|
|
103
|
+
phoneNumber: { type: "string", description: "Phone number" },
|
|
104
|
+
group: { type: "string", description: "Contact group" },
|
|
105
|
+
},
|
|
106
|
+
required: ["identity", "name"],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "get_threads",
|
|
111
|
+
description: "Get message threads (recent conversations)",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: "object",
|
|
114
|
+
properties: {
|
|
115
|
+
skip: { type: "number", description: "Number of threads to skip" },
|
|
116
|
+
take: { type: "number", description: "Number of threads to return" },
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "send_notification",
|
|
122
|
+
description: "Send a notification message to a contact",
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: "object",
|
|
125
|
+
properties: {
|
|
126
|
+
to: { type: "string", description: "Recipient identity" },
|
|
127
|
+
templateName: { type: "string", description: "Message template name" },
|
|
128
|
+
templateNamespace: { type: "string", description: "Template namespace" },
|
|
129
|
+
parameters: {
|
|
130
|
+
type: "array",
|
|
131
|
+
description: "Template parameters",
|
|
132
|
+
items: { type: "string" },
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
required: ["to", "templateName"],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "get_analytics",
|
|
140
|
+
description: "Get chatbot analytics and metrics",
|
|
141
|
+
inputSchema: {
|
|
142
|
+
type: "object",
|
|
143
|
+
properties: {
|
|
144
|
+
startDate: { type: "string", description: "Start date (YYYY-MM-DD)" },
|
|
145
|
+
endDate: { type: "string", description: "End date (YYYY-MM-DD)" },
|
|
146
|
+
event: { type: "string", description: "Event category to track" },
|
|
147
|
+
},
|
|
148
|
+
required: ["startDate", "endDate"],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "create_broadcast",
|
|
153
|
+
description: "Create a broadcast distribution list and send messages",
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
listName: { type: "string", description: "Distribution list name" },
|
|
158
|
+
recipients: {
|
|
159
|
+
type: "array",
|
|
160
|
+
description: "List of recipient identities",
|
|
161
|
+
items: { type: "string" },
|
|
162
|
+
},
|
|
163
|
+
message: { type: "string", description: "Message content to broadcast" },
|
|
164
|
+
},
|
|
165
|
+
required: ["listName", "recipients", "message"],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "get_chatbot_flow",
|
|
170
|
+
description: "Get chatbot flow/builder configuration",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
flowId: { type: "string", description: "Flow ID (optional, returns default flow if omitted)" },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
}));
|
|
180
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
181
|
+
const { name, arguments: args } = request.params;
|
|
182
|
+
try {
|
|
183
|
+
switch (name) {
|
|
184
|
+
case "send_message": {
|
|
185
|
+
const contentType = args?.type || "text/plain";
|
|
186
|
+
const content = contentType === "text/plain" ? args?.content : JSON.parse(String(args?.content));
|
|
187
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipMessage(String(args?.to), String(contentType), content), null, 2) }] };
|
|
188
|
+
}
|
|
189
|
+
case "get_contacts": {
|
|
190
|
+
const skip = args?.skip ? `$skip=${args.skip}&` : "";
|
|
191
|
+
const take = args?.take ? `$take=${args.take}` : "$take=20";
|
|
192
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/contacts?${skip}${take}`), null, 2) }] };
|
|
193
|
+
}
|
|
194
|
+
case "create_contact": {
|
|
195
|
+
const resource = {
|
|
196
|
+
identity: args?.identity,
|
|
197
|
+
name: args?.name,
|
|
198
|
+
email: args?.email,
|
|
199
|
+
phoneNumber: args?.phoneNumber,
|
|
200
|
+
group: args?.group,
|
|
201
|
+
};
|
|
202
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", "/contacts", "application/vnd.lime.contact+json", resource), null, 2) }] };
|
|
203
|
+
}
|
|
204
|
+
case "get_threads": {
|
|
205
|
+
const skip = args?.skip ? `$skip=${args.skip}&` : "";
|
|
206
|
+
const take = args?.take ? `$take=${args.take}` : "$take=20";
|
|
207
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/threads?${skip}${take}`), null, 2) }] };
|
|
208
|
+
}
|
|
209
|
+
case "send_notification": {
|
|
210
|
+
const template = {
|
|
211
|
+
name: args?.templateName,
|
|
212
|
+
namespace: args?.templateNamespace,
|
|
213
|
+
language: { code: "pt_BR", policy: "deterministic" },
|
|
214
|
+
};
|
|
215
|
+
if (args?.parameters) {
|
|
216
|
+
template.components = [{ type: "body", parameters: args.parameters.map((p) => ({ type: "text", text: p })) }];
|
|
217
|
+
}
|
|
218
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipMessage(String(args?.to), "application/json", template), null, 2) }] };
|
|
219
|
+
}
|
|
220
|
+
case "get_analytics": {
|
|
221
|
+
const uri = `/event-track/${args?.event || ""}?startDate=${args?.startDate}&endDate=${args?.endDate}`;
|
|
222
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", uri), null, 2) }] };
|
|
223
|
+
}
|
|
224
|
+
case "create_broadcast": {
|
|
225
|
+
// Create the distribution list
|
|
226
|
+
const listIdentity = `${args?.listName}@broadcast.msging.net`;
|
|
227
|
+
await blipCommand(crypto.randomUUID(), "set", "/lists", "application/vnd.iris.distribution-list+json", { identity: listIdentity });
|
|
228
|
+
// Add recipients
|
|
229
|
+
for (const recipient of args?.recipients || []) {
|
|
230
|
+
await blipCommand(crypto.randomUUID(), "set", `/lists/${listIdentity}/recipients`, "application/vnd.lime.identity", recipient);
|
|
231
|
+
}
|
|
232
|
+
// Send message
|
|
233
|
+
const result = await blipMessage(listIdentity, "text/plain", args?.message);
|
|
234
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
235
|
+
}
|
|
236
|
+
case "get_chatbot_flow": {
|
|
237
|
+
const uri = args?.flowId ? `/buckets/blip_portal:builder_working_flow_${args.flowId}` : "/buckets/blip_portal:builder_working_flow";
|
|
238
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", uri), null, 2) }] };
|
|
239
|
+
}
|
|
240
|
+
default:
|
|
241
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
async function main() {
|
|
249
|
+
if (!BOT_ID || !ACCESS_KEY) {
|
|
250
|
+
console.error("TAKE_BLIP_BOT_ID and TAKE_BLIP_ACCESS_KEY environment variables are required");
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
const transport = new StdioServerTransport();
|
|
254
|
+
await server.connect(transport);
|
|
255
|
+
}
|
|
256
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codespar/mcp-take-blip",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Take Blip — chatbots, messaging, contacts, broadcasts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-take-blip": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^25.5.0",
|
|
19
|
+
"typescript": "^5.8.0"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"take-blip",
|
|
25
|
+
"chatbot",
|
|
26
|
+
"messaging",
|
|
27
|
+
"whatsapp",
|
|
28
|
+
"brazil"
|
|
29
|
+
]
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MCP Server for Take Blip — Brazilian chatbot and messaging platform.
|
|
5
|
+
*
|
|
6
|
+
* Tools:
|
|
7
|
+
* - send_message: Send a message to a contact
|
|
8
|
+
* - get_contacts: List contacts
|
|
9
|
+
* - create_contact: Create a contact
|
|
10
|
+
* - get_threads: Get message threads
|
|
11
|
+
* - send_notification: Send a notification/broadcast message
|
|
12
|
+
* - get_analytics: Get chatbot analytics
|
|
13
|
+
* - create_broadcast: Create a broadcast list and send
|
|
14
|
+
* - get_chatbot_flow: Get chatbot flow configuration
|
|
15
|
+
*
|
|
16
|
+
* Environment:
|
|
17
|
+
* TAKE_BLIP_BOT_ID — Bot identifier
|
|
18
|
+
* TAKE_BLIP_ACCESS_KEY — Bot access key
|
|
19
|
+
*
|
|
20
|
+
* Note: Take Blip uses a JSON-based messaging protocol.
|
|
21
|
+
* Requests go as POST to /commands with type/method/uri in body.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
25
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
26
|
+
import {
|
|
27
|
+
CallToolRequestSchema,
|
|
28
|
+
ListToolsRequestSchema,
|
|
29
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
30
|
+
|
|
31
|
+
const BOT_ID = process.env.TAKE_BLIP_BOT_ID || "";
|
|
32
|
+
const ACCESS_KEY = process.env.TAKE_BLIP_ACCESS_KEY || "";
|
|
33
|
+
const BASE_URL = "https://msging.net";
|
|
34
|
+
|
|
35
|
+
function getAuthKey(): string {
|
|
36
|
+
const raw = `${BOT_ID}:${ACCESS_KEY}`;
|
|
37
|
+
return btoa(raw);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function blipCommand(id: string, method: string, uri: string, type?: string, resource?: unknown): Promise<unknown> {
|
|
41
|
+
const body: Record<string, unknown> = { id, method, uri };
|
|
42
|
+
if (type) body.type = type;
|
|
43
|
+
if (resource) body.resource = resource;
|
|
44
|
+
|
|
45
|
+
const res = await fetch(`${BASE_URL}/commands`, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: {
|
|
48
|
+
"Content-Type": "application/json",
|
|
49
|
+
"Authorization": `Key ${getAuthKey()}`,
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify(body),
|
|
52
|
+
});
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
const err = await res.text();
|
|
55
|
+
throw new Error(`Take Blip API ${res.status}: ${err}`);
|
|
56
|
+
}
|
|
57
|
+
return res.json();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function blipMessage(to: string, type: string, content: unknown): Promise<unknown> {
|
|
61
|
+
const res = await fetch(`${BASE_URL}/messages`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json",
|
|
65
|
+
"Authorization": `Key ${getAuthKey()}`,
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify({ id: crypto.randomUUID(), to, type, content }),
|
|
68
|
+
});
|
|
69
|
+
if (!res.ok) {
|
|
70
|
+
const err = await res.text();
|
|
71
|
+
throw new Error(`Take Blip API ${res.status}: ${err}`);
|
|
72
|
+
}
|
|
73
|
+
return res.json();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const server = new Server(
|
|
77
|
+
{ name: "mcp-take-blip", version: "0.1.0" },
|
|
78
|
+
{ capabilities: { tools: {} } }
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
82
|
+
tools: [
|
|
83
|
+
{
|
|
84
|
+
name: "send_message",
|
|
85
|
+
description: "Send a message to a contact via Take Blip",
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
to: { type: "string", description: "Recipient identity (e.g., 5511999999999@wa.gw.msging.net)" },
|
|
90
|
+
content: { type: "string", description: "Message text content" },
|
|
91
|
+
type: { type: "string", description: "Content type (default: text/plain)", enum: ["text/plain", "application/json"] },
|
|
92
|
+
},
|
|
93
|
+
required: ["to", "content"],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "get_contacts",
|
|
98
|
+
description: "List contacts in Take Blip",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
skip: { type: "number", description: "Number of contacts to skip" },
|
|
103
|
+
take: { type: "number", description: "Number of contacts to return (default 20)" },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "create_contact",
|
|
109
|
+
description: "Create a contact in Take Blip",
|
|
110
|
+
inputSchema: {
|
|
111
|
+
type: "object",
|
|
112
|
+
properties: {
|
|
113
|
+
identity: { type: "string", description: "Contact identity (e.g., 5511999999999@wa.gw.msging.net)" },
|
|
114
|
+
name: { type: "string", description: "Contact name" },
|
|
115
|
+
email: { type: "string", description: "Contact email" },
|
|
116
|
+
phoneNumber: { type: "string", description: "Phone number" },
|
|
117
|
+
group: { type: "string", description: "Contact group" },
|
|
118
|
+
},
|
|
119
|
+
required: ["identity", "name"],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "get_threads",
|
|
124
|
+
description: "Get message threads (recent conversations)",
|
|
125
|
+
inputSchema: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
skip: { type: "number", description: "Number of threads to skip" },
|
|
129
|
+
take: { type: "number", description: "Number of threads to return" },
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "send_notification",
|
|
135
|
+
description: "Send a notification message to a contact",
|
|
136
|
+
inputSchema: {
|
|
137
|
+
type: "object",
|
|
138
|
+
properties: {
|
|
139
|
+
to: { type: "string", description: "Recipient identity" },
|
|
140
|
+
templateName: { type: "string", description: "Message template name" },
|
|
141
|
+
templateNamespace: { type: "string", description: "Template namespace" },
|
|
142
|
+
parameters: {
|
|
143
|
+
type: "array",
|
|
144
|
+
description: "Template parameters",
|
|
145
|
+
items: { type: "string" },
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
required: ["to", "templateName"],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "get_analytics",
|
|
153
|
+
description: "Get chatbot analytics and metrics",
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
startDate: { type: "string", description: "Start date (YYYY-MM-DD)" },
|
|
158
|
+
endDate: { type: "string", description: "End date (YYYY-MM-DD)" },
|
|
159
|
+
event: { type: "string", description: "Event category to track" },
|
|
160
|
+
},
|
|
161
|
+
required: ["startDate", "endDate"],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: "create_broadcast",
|
|
166
|
+
description: "Create a broadcast distribution list and send messages",
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: {
|
|
170
|
+
listName: { type: "string", description: "Distribution list name" },
|
|
171
|
+
recipients: {
|
|
172
|
+
type: "array",
|
|
173
|
+
description: "List of recipient identities",
|
|
174
|
+
items: { type: "string" },
|
|
175
|
+
},
|
|
176
|
+
message: { type: "string", description: "Message content to broadcast" },
|
|
177
|
+
},
|
|
178
|
+
required: ["listName", "recipients", "message"],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: "get_chatbot_flow",
|
|
183
|
+
description: "Get chatbot flow/builder configuration",
|
|
184
|
+
inputSchema: {
|
|
185
|
+
type: "object",
|
|
186
|
+
properties: {
|
|
187
|
+
flowId: { type: "string", description: "Flow ID (optional, returns default flow if omitted)" },
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
}));
|
|
193
|
+
|
|
194
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
195
|
+
const { name, arguments: args } = request.params;
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
switch (name) {
|
|
199
|
+
case "send_message": {
|
|
200
|
+
const contentType = args?.type || "text/plain";
|
|
201
|
+
const content = contentType === "text/plain" ? args?.content : JSON.parse(String(args?.content));
|
|
202
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipMessage(String(args?.to), String(contentType), content), null, 2) }] };
|
|
203
|
+
}
|
|
204
|
+
case "get_contacts": {
|
|
205
|
+
const skip = args?.skip ? `$skip=${args.skip}&` : "";
|
|
206
|
+
const take = args?.take ? `$take=${args.take}` : "$take=20";
|
|
207
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/contacts?${skip}${take}`), null, 2) }] };
|
|
208
|
+
}
|
|
209
|
+
case "create_contact": {
|
|
210
|
+
const resource = {
|
|
211
|
+
identity: args?.identity,
|
|
212
|
+
name: args?.name,
|
|
213
|
+
email: args?.email,
|
|
214
|
+
phoneNumber: args?.phoneNumber,
|
|
215
|
+
group: args?.group,
|
|
216
|
+
};
|
|
217
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", "/contacts", "application/vnd.lime.contact+json", resource), null, 2) }] };
|
|
218
|
+
}
|
|
219
|
+
case "get_threads": {
|
|
220
|
+
const skip = args?.skip ? `$skip=${args.skip}&` : "";
|
|
221
|
+
const take = args?.take ? `$take=${args.take}` : "$take=20";
|
|
222
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/threads?${skip}${take}`), null, 2) }] };
|
|
223
|
+
}
|
|
224
|
+
case "send_notification": {
|
|
225
|
+
const template: Record<string, unknown> = {
|
|
226
|
+
name: args?.templateName,
|
|
227
|
+
namespace: args?.templateNamespace,
|
|
228
|
+
language: { code: "pt_BR", policy: "deterministic" },
|
|
229
|
+
};
|
|
230
|
+
if (args?.parameters) {
|
|
231
|
+
template.components = [{ type: "body", parameters: (args.parameters as string[]).map((p: string) => ({ type: "text", text: p })) }];
|
|
232
|
+
}
|
|
233
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipMessage(String(args?.to), "application/json", template), null, 2) }] };
|
|
234
|
+
}
|
|
235
|
+
case "get_analytics": {
|
|
236
|
+
const uri = `/event-track/${args?.event || ""}?startDate=${args?.startDate}&endDate=${args?.endDate}`;
|
|
237
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", uri), null, 2) }] };
|
|
238
|
+
}
|
|
239
|
+
case "create_broadcast": {
|
|
240
|
+
// Create the distribution list
|
|
241
|
+
const listIdentity = `${args?.listName}@broadcast.msging.net`;
|
|
242
|
+
await blipCommand(crypto.randomUUID(), "set", "/lists", "application/vnd.iris.distribution-list+json", { identity: listIdentity });
|
|
243
|
+
// Add recipients
|
|
244
|
+
for (const recipient of (args?.recipients as string[]) || []) {
|
|
245
|
+
await blipCommand(crypto.randomUUID(), "set", `/lists/${listIdentity}/recipients`, "application/vnd.lime.identity", recipient);
|
|
246
|
+
}
|
|
247
|
+
// Send message
|
|
248
|
+
const result = await blipMessage(listIdentity, "text/plain", args?.message);
|
|
249
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
250
|
+
}
|
|
251
|
+
case "get_chatbot_flow": {
|
|
252
|
+
const uri = args?.flowId ? `/buckets/blip_portal:builder_working_flow_${args.flowId}` : "/buckets/blip_portal:builder_working_flow";
|
|
253
|
+
return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", uri), null, 2) }] };
|
|
254
|
+
}
|
|
255
|
+
default:
|
|
256
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
257
|
+
}
|
|
258
|
+
} catch (err) {
|
|
259
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
async function main() {
|
|
264
|
+
if (!BOT_ID || !ACCESS_KEY) {
|
|
265
|
+
console.error("TAKE_BLIP_BOT_ID and TAKE_BLIP_ACCESS_KEY environment variables are required");
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
const transport = new StdioServerTransport();
|
|
269
|
+
await server.connect(transport);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
main().catch(console.error);
|
package/tsconfig.json
ADDED