@codespar/mcp-take-blip 0.1.2 → 0.2.1

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/README.md CHANGED
@@ -51,10 +51,10 @@ Add to `.cursor/mcp.json` or `.vscode/mcp.json`:
51
51
  }
52
52
  ```
53
53
 
54
- ## Tools
54
+ ## Tools (18)
55
55
 
56
- | Tool | Description |
57
- |------|-------------|
56
+ | Tool | Purpose |
57
+ |---|---|
58
58
  | `send_message` | Send a message to a contact via Take Blip |
59
59
  | `get_contacts` | List contacts in Take Blip |
60
60
  | `create_contact` | Create a contact in Take Blip |
@@ -63,6 +63,16 @@ Add to `.cursor/mcp.json` or `.vscode/mcp.json`:
63
63
  | `get_analytics` | Get chatbot analytics and metrics |
64
64
  | `create_broadcast` | Create a broadcast distribution list and send messages |
65
65
  | `get_chatbot_flow` | Get chatbot flow/builder configuration |
66
+ | `update_contact` | Merge/update fields on an existing contact |
67
+ | `delete_contact` | Delete a contact by identity |
68
+ | `get_contact` | Get a single contact by identity |
69
+ | `get_thread` | Get the message thread between the bot and a specific identity |
70
+ | `create_ticket` | Open a support ticket / human handoff for a contact |
71
+ | `close_ticket` | Close an open support ticket |
72
+ | `list_tickets` | List tickets, optionally filtering by status |
73
+ | `track_event` | Track a custom analytics event in the bot event tracker |
74
+ | `set_bot_resource` | Set a bot resource value (used as bot variables / state via /resources bucket) |
75
+ | `get_bot_resource` | Get a bot resource value by name (variable / state) |
66
76
 
67
77
  ## Authentication
68
78
 
package/dist/index.js CHANGED
@@ -2,21 +2,31 @@
2
2
  /**
3
3
  * MCP Server for Take Blip — Brazilian chatbot and messaging platform.
4
4
  *
5
- * Tools:
5
+ * Tools (18):
6
6
  * - send_message: Send a message to a contact
7
7
  * - get_contacts: List contacts
8
8
  * - create_contact: Create a contact
9
+ * - update_contact: Merge/update a contact
10
+ * - delete_contact: Delete a contact
11
+ * - get_contact: Get a single contact by identity
9
12
  * - get_threads: Get message threads
13
+ * - get_thread: Get a thread between bot and an identity
10
14
  * - send_notification: Send a notification/broadcast message
11
15
  * - get_analytics: Get chatbot analytics
12
16
  * - create_broadcast: Create a broadcast list and send
13
17
  * - get_chatbot_flow: Get chatbot flow configuration
18
+ * - create_ticket: Open a support ticket / human handoff
19
+ * - close_ticket: Close an open ticket
20
+ * - list_tickets: List tickets in a queue
21
+ * - track_event: Track a custom analytics event
22
+ * - set_bot_resource: Set a bot resource (variable / bucket value)
23
+ * - get_bot_resource: Get a bot resource (variable / bucket value)
14
24
  *
15
25
  * Environment:
16
26
  * TAKE_BLIP_BOT_ID — Bot identifier
17
27
  * TAKE_BLIP_ACCESS_KEY — Bot access key
18
28
  *
19
- * Note: Take Blip uses a JSON-based messaging protocol.
29
+ * Note: Take Blip uses a JSON-based messaging protocol (LIME/BLiP HTTP API).
20
30
  * Requests go as POST to /commands with type/method/uri in body.
21
31
  */
22
32
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -66,7 +76,7 @@ async function blipMessage(to, type, content) {
66
76
  }
67
77
  return res.json();
68
78
  }
69
- const server = new Server({ name: "mcp-take-blip", version: "0.1.0" }, { capabilities: { tools: {} } });
79
+ const server = new Server({ name: "mcp-take-blip", version: "0.2.1" }, { capabilities: { tools: {} } });
70
80
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
71
81
  tools: [
72
82
  {
@@ -177,6 +187,129 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
177
187
  },
178
188
  },
179
189
  },
190
+ {
191
+ name: "update_contact",
192
+ description: "Merge/update fields on an existing contact",
193
+ inputSchema: {
194
+ type: "object",
195
+ properties: {
196
+ identity: { type: "string", description: "Contact identity (e.g., 5511999999999@wa.gw.msging.net)" },
197
+ name: { type: "string", description: "Contact name" },
198
+ email: { type: "string", description: "Contact email" },
199
+ phoneNumber: { type: "string", description: "Phone number" },
200
+ group: { type: "string", description: "Contact group" },
201
+ extras: { type: "object", description: "Custom extras key/value object" },
202
+ },
203
+ required: ["identity"],
204
+ },
205
+ },
206
+ {
207
+ name: "delete_contact",
208
+ description: "Delete a contact by identity",
209
+ inputSchema: {
210
+ type: "object",
211
+ properties: {
212
+ identity: { type: "string", description: "Contact identity" },
213
+ },
214
+ required: ["identity"],
215
+ },
216
+ },
217
+ {
218
+ name: "get_contact",
219
+ description: "Get a single contact by identity",
220
+ inputSchema: {
221
+ type: "object",
222
+ properties: {
223
+ identity: { type: "string", description: "Contact identity" },
224
+ },
225
+ required: ["identity"],
226
+ },
227
+ },
228
+ {
229
+ name: "get_thread",
230
+ description: "Get the message thread between the bot and a specific identity",
231
+ inputSchema: {
232
+ type: "object",
233
+ properties: {
234
+ identity: { type: "string", description: "Contact identity" },
235
+ take: { type: "number", description: "Number of messages to return (default 20)" },
236
+ },
237
+ required: ["identity"],
238
+ },
239
+ },
240
+ {
241
+ name: "create_ticket",
242
+ description: "Open a support ticket / human handoff for a contact",
243
+ inputSchema: {
244
+ type: "object",
245
+ properties: {
246
+ customerIdentity: { type: "string", description: "Contact identity to open ticket for" },
247
+ team: { type: "string", description: "Agent team / queue name" },
248
+ },
249
+ required: ["customerIdentity"],
250
+ },
251
+ },
252
+ {
253
+ name: "close_ticket",
254
+ description: "Close an open support ticket",
255
+ inputSchema: {
256
+ type: "object",
257
+ properties: {
258
+ ticketId: { type: "string", description: "Ticket id to close" },
259
+ },
260
+ required: ["ticketId"],
261
+ },
262
+ },
263
+ {
264
+ name: "list_tickets",
265
+ description: "List tickets, optionally filtering by status",
266
+ inputSchema: {
267
+ type: "object",
268
+ properties: {
269
+ status: { type: "string", description: "Ticket status filter (e.g., Open, Waiting, Closed)" },
270
+ skip: { type: "number", description: "Pagination skip" },
271
+ take: { type: "number", description: "Pagination take (default 20)" },
272
+ },
273
+ },
274
+ },
275
+ {
276
+ name: "track_event",
277
+ description: "Track a custom analytics event in the bot event tracker",
278
+ inputSchema: {
279
+ type: "object",
280
+ properties: {
281
+ category: { type: "string", description: "Event category" },
282
+ action: { type: "string", description: "Event action" },
283
+ extras: { type: "object", description: "Additional event metadata" },
284
+ contactIdentity: { type: "string", description: "Contact identity associated with the event" },
285
+ },
286
+ required: ["category", "action"],
287
+ },
288
+ },
289
+ {
290
+ name: "set_bot_resource",
291
+ description: "Set a bot resource value (used as bot variables / state via /resources bucket)",
292
+ inputSchema: {
293
+ type: "object",
294
+ properties: {
295
+ name: { type: "string", description: "Resource name (key)" },
296
+ value: { description: "Resource value (string, number, object)" },
297
+ type: { type: "string", description: "MIME type (default text/plain; use application/json for objects)" },
298
+ },
299
+ required: ["name", "value"],
300
+ },
301
+ },
302
+ {
303
+ name: "get_bot_resource",
304
+ description: "Get a bot resource value by name (variable / state)",
305
+ inputSchema: {
306
+ type: "object",
307
+ properties: {
308
+ name: { type: "string", description: "Resource name (key)" },
309
+ },
310
+ required: ["name"],
311
+ },
312
+ },
180
313
  ],
181
314
  }));
182
315
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -239,6 +372,63 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
239
372
  const uri = args?.flowId ? `/buckets/blip_portal:builder_working_flow_${args.flowId}` : "/buckets/blip_portal:builder_working_flow";
240
373
  return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", uri), null, 2) }] };
241
374
  }
375
+ case "update_contact": {
376
+ const resource = { identity: args?.identity };
377
+ if (args?.name)
378
+ resource.name = args.name;
379
+ if (args?.email)
380
+ resource.email = args.email;
381
+ if (args?.phoneNumber)
382
+ resource.phoneNumber = args.phoneNumber;
383
+ if (args?.group)
384
+ resource.group = args.group;
385
+ if (args?.extras)
386
+ resource.extras = args.extras;
387
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "merge", "/contacts", "application/vnd.lime.contact+json", resource), null, 2) }] };
388
+ }
389
+ case "delete_contact": {
390
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "delete", `/contacts/${encodeURIComponent(String(args?.identity))}`), null, 2) }] };
391
+ }
392
+ case "get_contact": {
393
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/contacts/${encodeURIComponent(String(args?.identity))}`), null, 2) }] };
394
+ }
395
+ case "get_thread": {
396
+ const take = args?.take ? `$take=${args.take}` : "$take=20";
397
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/threads/${encodeURIComponent(String(args?.identity))}?${take}`), null, 2) }] };
398
+ }
399
+ case "create_ticket": {
400
+ const resource = { customerIdentity: args?.customerIdentity };
401
+ if (args?.team)
402
+ resource.team = args.team;
403
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", "/tickets", "application/vnd.iris.ticket+json", resource), null, 2) }] };
404
+ }
405
+ case "close_ticket": {
406
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", `/tickets/${encodeURIComponent(String(args?.ticketId))}/change-status`, "application/vnd.iris.ticket+json", { status: "ClosedAttendant" }), null, 2) }] };
407
+ }
408
+ case "list_tickets": {
409
+ const filters = [];
410
+ if (args?.status)
411
+ filters.push(`$filter=${encodeURIComponent(`status eq '${args.status}'`)}`);
412
+ if (args?.skip)
413
+ filters.push(`$skip=${args.skip}`);
414
+ filters.push(args?.take ? `$take=${args.take}` : "$take=20");
415
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/tickets?${filters.join("&")}`), null, 2) }] };
416
+ }
417
+ case "track_event": {
418
+ const resource = { category: args?.category, action: args?.action };
419
+ if (args?.extras)
420
+ resource.extras = args.extras;
421
+ if (args?.contactIdentity)
422
+ resource.contactIdentity = args.contactIdentity;
423
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", "/event-track", "application/vnd.iris.eventTrack+json", resource), null, 2) }] };
424
+ }
425
+ case "set_bot_resource": {
426
+ const type = String(args?.type || (typeof args?.value === "object" ? "application/json" : "text/plain"));
427
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", `/resources/${encodeURIComponent(String(args?.name))}`, type, args?.value), null, 2) }] };
428
+ }
429
+ case "get_bot_resource": {
430
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/resources/${encodeURIComponent(String(args?.name))}`), null, 2) }] };
431
+ }
242
432
  default:
243
433
  return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
244
434
  }
@@ -265,7 +455,7 @@ async function main() {
265
455
  const t = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (id) => { transports.set(id, t); } });
266
456
  t.onclose = () => { if (t.sessionId)
267
457
  transports.delete(t.sessionId); };
268
- const s = new Server({ name: "mcp-take-blip", version: "0.1.0" }, { capabilities: { tools: {} } });
458
+ const s = new Server({ name: "mcp-take-blip", version: "0.2.1" }, { capabilities: { tools: {} } });
269
459
  server._requestHandlers.forEach((v, k) => s._requestHandlers.set(k, v));
270
460
  server._notificationHandlers?.forEach((v, k) => s._notificationHandlers.set(k, v));
271
461
  await s.connect(t);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codespar/mcp-take-blip",
3
- "version": "0.1.2",
4
- "description": "MCP server for Take Blip chatbots, messaging, contacts, broadcasts",
3
+ "version": "0.2.1",
4
+ "description": "MCP server for Take Blip \u2014 chatbots, messaging, contacts, broadcasts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "source": "github",
8
8
  "subfolder": "packages/communication/take-blip"
9
9
  },
10
- "version": "0.1.2",
10
+ "version": "0.2.1",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@codespar/mcp-take-blip",
15
- "version": "0.1.2",
15
+ "version": "0.2.1",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },
package/src/index.ts CHANGED
@@ -3,21 +3,31 @@
3
3
  /**
4
4
  * MCP Server for Take Blip — Brazilian chatbot and messaging platform.
5
5
  *
6
- * Tools:
6
+ * Tools (18):
7
7
  * - send_message: Send a message to a contact
8
8
  * - get_contacts: List contacts
9
9
  * - create_contact: Create a contact
10
+ * - update_contact: Merge/update a contact
11
+ * - delete_contact: Delete a contact
12
+ * - get_contact: Get a single contact by identity
10
13
  * - get_threads: Get message threads
14
+ * - get_thread: Get a thread between bot and an identity
11
15
  * - send_notification: Send a notification/broadcast message
12
16
  * - get_analytics: Get chatbot analytics
13
17
  * - create_broadcast: Create a broadcast list and send
14
18
  * - get_chatbot_flow: Get chatbot flow configuration
19
+ * - create_ticket: Open a support ticket / human handoff
20
+ * - close_ticket: Close an open ticket
21
+ * - list_tickets: List tickets in a queue
22
+ * - track_event: Track a custom analytics event
23
+ * - set_bot_resource: Set a bot resource (variable / bucket value)
24
+ * - get_bot_resource: Get a bot resource (variable / bucket value)
15
25
  *
16
26
  * Environment:
17
27
  * TAKE_BLIP_BOT_ID — Bot identifier
18
28
  * TAKE_BLIP_ACCESS_KEY — Bot access key
19
29
  *
20
- * Note: Take Blip uses a JSON-based messaging protocol.
30
+ * Note: Take Blip uses a JSON-based messaging protocol (LIME/BLiP HTTP API).
21
31
  * Requests go as POST to /commands with type/method/uri in body.
22
32
  */
23
33
 
@@ -76,7 +86,7 @@ async function blipMessage(to: string, type: string, content: unknown): Promise<
76
86
  }
77
87
 
78
88
  const server = new Server(
79
- { name: "mcp-take-blip", version: "0.1.0" },
89
+ { name: "mcp-take-blip", version: "0.2.1" },
80
90
  { capabilities: { tools: {} } }
81
91
  );
82
92
 
@@ -190,6 +200,129 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
190
200
  },
191
201
  },
192
202
  },
203
+ {
204
+ name: "update_contact",
205
+ description: "Merge/update fields on an existing contact",
206
+ inputSchema: {
207
+ type: "object",
208
+ properties: {
209
+ identity: { type: "string", description: "Contact identity (e.g., 5511999999999@wa.gw.msging.net)" },
210
+ name: { type: "string", description: "Contact name" },
211
+ email: { type: "string", description: "Contact email" },
212
+ phoneNumber: { type: "string", description: "Phone number" },
213
+ group: { type: "string", description: "Contact group" },
214
+ extras: { type: "object", description: "Custom extras key/value object" },
215
+ },
216
+ required: ["identity"],
217
+ },
218
+ },
219
+ {
220
+ name: "delete_contact",
221
+ description: "Delete a contact by identity",
222
+ inputSchema: {
223
+ type: "object",
224
+ properties: {
225
+ identity: { type: "string", description: "Contact identity" },
226
+ },
227
+ required: ["identity"],
228
+ },
229
+ },
230
+ {
231
+ name: "get_contact",
232
+ description: "Get a single contact by identity",
233
+ inputSchema: {
234
+ type: "object",
235
+ properties: {
236
+ identity: { type: "string", description: "Contact identity" },
237
+ },
238
+ required: ["identity"],
239
+ },
240
+ },
241
+ {
242
+ name: "get_thread",
243
+ description: "Get the message thread between the bot and a specific identity",
244
+ inputSchema: {
245
+ type: "object",
246
+ properties: {
247
+ identity: { type: "string", description: "Contact identity" },
248
+ take: { type: "number", description: "Number of messages to return (default 20)" },
249
+ },
250
+ required: ["identity"],
251
+ },
252
+ },
253
+ {
254
+ name: "create_ticket",
255
+ description: "Open a support ticket / human handoff for a contact",
256
+ inputSchema: {
257
+ type: "object",
258
+ properties: {
259
+ customerIdentity: { type: "string", description: "Contact identity to open ticket for" },
260
+ team: { type: "string", description: "Agent team / queue name" },
261
+ },
262
+ required: ["customerIdentity"],
263
+ },
264
+ },
265
+ {
266
+ name: "close_ticket",
267
+ description: "Close an open support ticket",
268
+ inputSchema: {
269
+ type: "object",
270
+ properties: {
271
+ ticketId: { type: "string", description: "Ticket id to close" },
272
+ },
273
+ required: ["ticketId"],
274
+ },
275
+ },
276
+ {
277
+ name: "list_tickets",
278
+ description: "List tickets, optionally filtering by status",
279
+ inputSchema: {
280
+ type: "object",
281
+ properties: {
282
+ status: { type: "string", description: "Ticket status filter (e.g., Open, Waiting, Closed)" },
283
+ skip: { type: "number", description: "Pagination skip" },
284
+ take: { type: "number", description: "Pagination take (default 20)" },
285
+ },
286
+ },
287
+ },
288
+ {
289
+ name: "track_event",
290
+ description: "Track a custom analytics event in the bot event tracker",
291
+ inputSchema: {
292
+ type: "object",
293
+ properties: {
294
+ category: { type: "string", description: "Event category" },
295
+ action: { type: "string", description: "Event action" },
296
+ extras: { type: "object", description: "Additional event metadata" },
297
+ contactIdentity: { type: "string", description: "Contact identity associated with the event" },
298
+ },
299
+ required: ["category", "action"],
300
+ },
301
+ },
302
+ {
303
+ name: "set_bot_resource",
304
+ description: "Set a bot resource value (used as bot variables / state via /resources bucket)",
305
+ inputSchema: {
306
+ type: "object",
307
+ properties: {
308
+ name: { type: "string", description: "Resource name (key)" },
309
+ value: { description: "Resource value (string, number, object)" },
310
+ type: { type: "string", description: "MIME type (default text/plain; use application/json for objects)" },
311
+ },
312
+ required: ["name", "value"],
313
+ },
314
+ },
315
+ {
316
+ name: "get_bot_resource",
317
+ description: "Get a bot resource value by name (variable / state)",
318
+ inputSchema: {
319
+ type: "object",
320
+ properties: {
321
+ name: { type: "string", description: "Resource name (key)" },
322
+ },
323
+ required: ["name"],
324
+ },
325
+ },
193
326
  ],
194
327
  }));
195
328
 
@@ -254,6 +387,53 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
254
387
  const uri = args?.flowId ? `/buckets/blip_portal:builder_working_flow_${args.flowId}` : "/buckets/blip_portal:builder_working_flow";
255
388
  return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", uri), null, 2) }] };
256
389
  }
390
+ case "update_contact": {
391
+ const resource: Record<string, unknown> = { identity: args?.identity };
392
+ if (args?.name) resource.name = args.name;
393
+ if (args?.email) resource.email = args.email;
394
+ if (args?.phoneNumber) resource.phoneNumber = args.phoneNumber;
395
+ if (args?.group) resource.group = args.group;
396
+ if (args?.extras) resource.extras = args.extras;
397
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "merge", "/contacts", "application/vnd.lime.contact+json", resource), null, 2) }] };
398
+ }
399
+ case "delete_contact": {
400
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "delete", `/contacts/${encodeURIComponent(String(args?.identity))}`), null, 2) }] };
401
+ }
402
+ case "get_contact": {
403
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/contacts/${encodeURIComponent(String(args?.identity))}`), null, 2) }] };
404
+ }
405
+ case "get_thread": {
406
+ const take = args?.take ? `$take=${args.take}` : "$take=20";
407
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/threads/${encodeURIComponent(String(args?.identity))}?${take}`), null, 2) }] };
408
+ }
409
+ case "create_ticket": {
410
+ const resource: Record<string, unknown> = { customerIdentity: args?.customerIdentity };
411
+ if (args?.team) resource.team = args.team;
412
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", "/tickets", "application/vnd.iris.ticket+json", resource), null, 2) }] };
413
+ }
414
+ case "close_ticket": {
415
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", `/tickets/${encodeURIComponent(String(args?.ticketId))}/change-status`, "application/vnd.iris.ticket+json", { status: "ClosedAttendant" }), null, 2) }] };
416
+ }
417
+ case "list_tickets": {
418
+ const filters: string[] = [];
419
+ if (args?.status) filters.push(`$filter=${encodeURIComponent(`status eq '${args.status}'`)}`);
420
+ if (args?.skip) filters.push(`$skip=${args.skip}`);
421
+ filters.push(args?.take ? `$take=${args.take}` : "$take=20");
422
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/tickets?${filters.join("&")}`), null, 2) }] };
423
+ }
424
+ case "track_event": {
425
+ const resource: Record<string, unknown> = { category: args?.category, action: args?.action };
426
+ if (args?.extras) resource.extras = args.extras;
427
+ if (args?.contactIdentity) resource.contactIdentity = args.contactIdentity;
428
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", "/event-track", "application/vnd.iris.eventTrack+json", resource), null, 2) }] };
429
+ }
430
+ case "set_bot_resource": {
431
+ const type = String(args?.type || (typeof args?.value === "object" ? "application/json" : "text/plain"));
432
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "set", `/resources/${encodeURIComponent(String(args?.name))}`, type, args?.value), null, 2) }] };
433
+ }
434
+ case "get_bot_resource": {
435
+ return { content: [{ type: "text", text: JSON.stringify(await blipCommand(crypto.randomUUID(), "get", `/resources/${encodeURIComponent(String(args?.name))}`), null, 2) }] };
436
+ }
257
437
  default:
258
438
  return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
259
439
  }
@@ -276,7 +456,7 @@ async function main() {
276
456
  if (!sid && isInitializeRequest(req.body)) {
277
457
  const t = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (id) => { transports.set(id, t); } });
278
458
  t.onclose = () => { if (t.sessionId) transports.delete(t.sessionId); };
279
- const s = new Server({ name: "mcp-take-blip", version: "0.1.0" }, { capabilities: { tools: {} } }); (server as any)._requestHandlers.forEach((v: any, k: any) => (s as any)._requestHandlers.set(k, v)); (server as any)._notificationHandlers?.forEach((v: any, k: any) => (s as any)._notificationHandlers.set(k, v)); await s.connect(t);
459
+ const s = new Server({ name: "mcp-take-blip", version: "0.2.1" }, { capabilities: { tools: {} } }); (server as any)._requestHandlers.forEach((v: any, k: any) => (s as any)._requestHandlers.set(k, v)); (server as any)._notificationHandlers?.forEach((v: any, k: any) => (s as any)._notificationHandlers.set(k, v)); await s.connect(t);
280
460
  await t.handleRequest(req, res, req.body); return;
281
461
  }
282
462
  res.status(400).json({ jsonrpc: "2.0", error: { code: -32000, message: "Bad Request" }, id: null });