@vybit/mcp-server 1.3.0 → 1.5.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 CHANGED
@@ -13,15 +13,17 @@ import { VybitAPIClient } from '@vybit/api-sdk';
13
13
  const API_KEY = process.env.VYBIT_API_KEY;
14
14
  const ACCESS_TOKEN = process.env.VYBIT_ACCESS_TOKEN;
15
15
  const API_URL = process.env.VYBIT_API_URL;
16
- if (!API_KEY && !ACCESS_TOKEN) {
17
- console.error('Error: VYBIT_API_KEY or VYBIT_ACCESS_TOKEN environment variable is required');
18
- process.exit(1);
16
+ // Only initialize API client when credentials are available (not required for export-only usage)
17
+ let vybitClient = null;
18
+ if (API_KEY || ACCESS_TOKEN) {
19
+ vybitClient = new VybitAPIClient({
20
+ ...(API_KEY ? { apiKey: API_KEY } : { accessToken: ACCESS_TOKEN }),
21
+ ...(API_URL && { baseUrl: API_URL })
22
+ });
23
+ }
24
+ else {
25
+ console.warn('Warning: VYBIT_API_KEY or VYBIT_ACCESS_TOKEN not set. MCP server tools will not be available.');
19
26
  }
20
- // Initialize Vybit API client with API key or OAuth2 access token
21
- const vybitClient = new VybitAPIClient({
22
- ...(API_KEY ? { apiKey: API_KEY } : { accessToken: ACCESS_TOKEN }),
23
- ...(API_URL && { baseUrl: API_URL })
24
- });
25
27
  // Shared schema fragments
26
28
  const PAGINATION_SCHEMA = {
27
29
  search: {
@@ -41,21 +43,21 @@ const PAGINATION_SCHEMA = {
41
43
  };
42
44
  const TRIGGER_SETTINGS_SCHEMA = {
43
45
  type: 'object',
44
- description: 'Configuration specific to the trigger type. For schedule triggers, contains crons array. Example: {"crons": [{"cron": "5 14 * * 0", "timeZone": "America/Denver"}]}. Cron format: minute hour day month dayOfWeek (0=Sunday).',
46
+ description: 'Configuration specific to the trigger type. For schedule and reminder triggers, contains crons array. Example: {"crons": [{"cron": "5 14 * * 0", "timeZone": "America/Denver"}]}. Cron format: minute hour day month dayOfWeek (0=Sunday).',
45
47
  properties: {
46
48
  crons: {
47
49
  type: 'array',
48
- description: 'Array of cron schedule definitions (for triggerType="schedule")',
50
+ description: 'Array of cron schedule definitions (for triggerType="schedule and triggerType="reminders)',
49
51
  items: {
50
52
  type: 'object',
51
53
  properties: {
52
54
  cron: {
53
55
  type: 'string',
54
- description: 'Cron expression: minute hour day month dayOfWeek. Example: "0 9 * * *" = every day at 9:00 AM',
56
+ description: 'Cron expression (5 fields): minute hour day month dayOfWeek. Uses 24-hour time. Examples: "0 7 * * *" = 7:00 AM, "0 19 * * *" = 7:00 PM, "30 14 25 12 *" = 2:30 PM on Dec 25',
55
57
  },
56
58
  timeZone: {
57
59
  type: 'string',
58
- description: 'IANA timezone identifier. Example: "America/Denver"',
60
+ description: 'IANA timezone identifier. Defaults to UTC if omitted — always set this to the user\'s local timezone. Examples: "America/New_York", "America/Denver", "America/Los_Angeles", "Europe/London"',
59
61
  },
60
62
  },
61
63
  },
@@ -95,12 +97,12 @@ const GEOFENCE_SCHEMA = {
95
97
  subscribable: {
96
98
  type: 'string',
97
99
  enum: ['yes', 'no'],
98
- description: 'Whether others can subscribe to this geofenced vybit',
100
+ description: 'yes indicates that the geofence will be set on the subscriber\'s device. no indicates that subscribers will receive notifications when the vybit owner triggers the geofence',
99
101
  },
100
102
  },
101
103
  };
102
104
  // Apply defaults for geofence configuration
103
- function normalizeGeofence(geofence) {
105
+ export function normalizeGeofence(geofence) {
104
106
  if (geofence.radius !== undefined && !geofence.displayRadius) {
105
107
  geofence.displayRadius = String(geofence.radius);
106
108
  }
@@ -111,7 +113,7 @@ function normalizeGeofence(geofence) {
111
113
  return geofence;
112
114
  }
113
115
  // Wrap a result as an MCP JSON text response
114
- function jsonResponse(result) {
116
+ export function jsonResponse(result) {
115
117
  return {
116
118
  content: [
117
119
  {
@@ -125,7 +127,7 @@ function jsonResponse(result) {
125
127
  const READ_ONLY_ANNOTATIONS = { readOnlyHint: true };
126
128
  const MUTATING_ANNOTATIONS = { readOnlyHint: false, destructiveHint: true };
127
129
  // Define available tools
128
- const TOOLS = [
130
+ export const TOOLS = [
129
131
  {
130
132
  name: 'vybit_list',
131
133
  description: 'List vybits with optional search and pagination. Returns a list of vybits owned by the authenticated user.',
@@ -137,22 +139,22 @@ const TOOLS = [
137
139
  },
138
140
  {
139
141
  name: 'vybit_get',
140
- description: 'Get detailed information about a specific vybit by ID',
142
+ description: 'Get detailed information about a specific vybit by ID (key)',
141
143
  inputSchema: {
142
144
  type: 'object',
143
145
  properties: {
144
- vybitId: {
146
+ key: {
145
147
  type: 'string',
146
- description: 'The unique identifier of the vybit',
148
+ description: 'The unique identifier (key) of the vybit',
147
149
  },
148
150
  },
149
- required: ['vybitId'],
151
+ required: ['key'],
150
152
  },
151
153
  annotations: READ_ONLY_ANNOTATIONS,
152
154
  },
153
155
  {
154
156
  name: 'vybit_create',
155
- description: 'Create a new vybit notification',
157
+ description: 'Create a new vybit',
156
158
  inputSchema: {
157
159
  type: 'object',
158
160
  properties: {
@@ -176,20 +178,20 @@ const TOOLS = [
176
178
  },
177
179
  description: {
178
180
  type: 'string',
179
- description: 'Detailed description of the vybit',
181
+ description: 'Detailed description of the vybit. Appears internally and on subscription cards',
180
182
  },
181
183
  access: {
182
184
  type: 'string',
183
- description: 'Vybit visibility (defaults to "private")',
185
+ description: 'Vybit subscription access (defaults to "private")',
184
186
  enum: ['public', 'private', 'unlisted'],
185
187
  },
186
188
  message: {
187
189
  type: 'string',
188
- description: 'Default message displayed with notifications',
190
+ description: 'Default message included when a notification is triggered',
189
191
  },
190
192
  imageUrl: {
191
193
  type: 'string',
192
- description: 'Default image URL for notifications (must be a direct link to a JPG, PNG, or GIF image)',
194
+ description: 'Default image URL included when a notification is triggered. Must be a direct link to a JPG, PNG, or GIF image and the filename in the url must end with .jpg, .jpeg, .png, or .gif',
193
195
  },
194
196
  linkUrl: {
195
197
  type: 'string',
@@ -208,9 +210,9 @@ const TOOLS = [
208
210
  inputSchema: {
209
211
  type: 'object',
210
212
  properties: {
211
- vybitId: {
213
+ key: {
212
214
  type: 'string',
213
- description: 'The unique identifier of the vybit to update',
215
+ description: 'The unique identifier (key) of the vybit to update',
214
216
  },
215
217
  name: {
216
218
  type: 'string',
@@ -236,17 +238,25 @@ const TOOLS = [
236
238
  },
237
239
  access: {
238
240
  type: 'string',
239
- description: 'Vybit visibility and access control',
241
+ description: 'Vybit subscription visibility and access control',
240
242
  enum: ['public', 'private', 'unlisted'],
241
243
  },
242
244
  message: {
243
245
  type: 'string',
244
- description: 'Default message displayed with notifications',
246
+ description: 'Default message included when a notification is triggered',
247
+ },
248
+ imageUrl: {
249
+ type: 'string',
250
+ description: 'Default image URL included when a notification is triggered. Must be a direct link to a JPG, PNG, or GIF image and the filename in the url must end with .jpg, .jpeg, .png, or .gif',
251
+ },
252
+ linkUrl: {
253
+ type: 'string',
254
+ description: 'Default URL to open when notification is tapped',
245
255
  },
246
256
  triggerSettings: TRIGGER_SETTINGS_SCHEMA,
247
257
  geofence: GEOFENCE_SCHEMA,
248
258
  },
249
- required: ['vybitId'],
259
+ required: ['key'],
250
260
  },
251
261
  annotations: MUTATING_ANNOTATIONS,
252
262
  },
@@ -256,12 +266,12 @@ const TOOLS = [
256
266
  inputSchema: {
257
267
  type: 'object',
258
268
  properties: {
259
- vybitId: {
269
+ key: {
260
270
  type: 'string',
261
- description: 'The unique identifier of the vybit to delete',
271
+ description: 'The unique identifier (key) of the vybit to delete',
262
272
  },
263
273
  },
264
- required: ['vybitId'],
274
+ required: ['key'],
265
275
  },
266
276
  annotations: MUTATING_ANNOTATIONS,
267
277
  },
@@ -271,9 +281,9 @@ const TOOLS = [
271
281
  inputSchema: {
272
282
  type: 'object',
273
283
  properties: {
274
- triggerKey: {
284
+ key: {
275
285
  type: 'string',
276
- description: 'The vybit key (not the trigger key)',
286
+ description: 'The unique identifier (key) of the vybit to trigger',
277
287
  },
278
288
  message: {
279
289
  type: 'string',
@@ -281,11 +291,11 @@ const TOOLS = [
281
291
  },
282
292
  imageUrl: {
283
293
  type: 'string',
284
- description: 'Optional image URL to attach to the notification (must be a direct link to a JPG, PNG, or GIF image)',
294
+ description: 'Optional image URL included when a notification is triggered. Must be a direct link to a JPG, PNG, or GIF image and the filename in the url must end with .jpg, .jpeg, .png, or .gif',
285
295
  },
286
296
  runOnce: {
287
297
  type: 'boolean',
288
- description: 'If true, the vybit is automatically disabled after this trigger fires',
298
+ description: 'If true, the vybit is automatically disabled after this trigger fires. Default is false.',
289
299
  },
290
300
  linkUrl: {
291
301
  type: 'string',
@@ -296,28 +306,28 @@ const TOOLS = [
296
306
  description: 'Optional log entry to append to the vybit log',
297
307
  },
298
308
  },
299
- required: ['triggerKey'],
309
+ required: ['key'],
300
310
  },
301
311
  annotations: MUTATING_ANNOTATIONS,
302
312
  },
303
313
  // Reminders
304
314
  {
305
315
  name: 'reminder_create',
306
- description: 'Create a reminder on a vybit (the vybit must have triggerType=reminders). Each reminder gets its own cron schedule.',
316
+ description: 'Create a reminder on a vybit (the vybit must have triggerType=reminders). Each reminder gets its own cron schedule. Reminders must be in the future and will not trigger if the scheduled time has already passed. ',
307
317
  inputSchema: {
308
318
  type: 'object',
309
319
  properties: {
310
- vybitKey: {
320
+ key: {
311
321
  type: 'string',
312
322
  description: 'The key of the vybit to add a reminder to',
313
323
  },
314
324
  cron: {
315
325
  type: 'string',
316
- description: 'Cron expression (5 fields): minute hour day month dayOfWeek. Example: "0 9 * * *" = every day at 9:00 AM',
326
+ description: 'Cron expression (5 fields): minute hour day month dayOfWeek. Uses 24-hour time. Examples: "0 7 * * *" = 7:00 AM, "0 19 * * *" = 7:00 PM, "30 14 25 12 *" = 2:30 PM on Dec 25',
317
327
  },
318
328
  timeZone: {
319
329
  type: 'string',
320
- description: 'IANA timezone identifier (defaults to UTC). Example: "America/Denver"',
330
+ description: 'IANA timezone identifier. Defaults to UTC if omitted — always set this to the user\'s local timezone. Examples: "America/New_York", "America/Denver", "America/Los_Angeles", "Europe/London"',
321
331
  },
322
332
  year: {
323
333
  type: 'number',
@@ -329,7 +339,7 @@ const TOOLS = [
329
339
  },
330
340
  imageUrl: {
331
341
  type: 'string',
332
- description: 'Image URL for the notification (must be a direct link to a JPG, PNG, or GIF image, max 512 characters)',
342
+ description: 'Image URL for the notification (must be a direct link to a JPG, PNG, or GIF image, max 512 characters, and the filename in the url must end with .jpg, .jpeg, .png, or .gif)',
333
343
  },
334
344
  linkUrl: {
335
345
  type: 'string',
@@ -337,10 +347,10 @@ const TOOLS = [
337
347
  },
338
348
  log: {
339
349
  type: 'string',
340
- description: 'Log content for the notification (max 1024 characters)',
350
+ description: 'Log content sent with the notification that will be appended to the notification log (max 1024 characters)',
341
351
  },
342
352
  },
343
- required: ['vybitKey', 'cron'],
353
+ required: ['key', 'cron'],
344
354
  },
345
355
  annotations: MUTATING_ANNOTATIONS,
346
356
  },
@@ -350,12 +360,12 @@ const TOOLS = [
350
360
  inputSchema: {
351
361
  type: 'object',
352
362
  properties: {
353
- vybitKey: {
363
+ key: {
354
364
  type: 'string',
355
365
  description: 'The key of the vybit',
356
366
  },
357
367
  },
358
- required: ['vybitKey'],
368
+ required: ['key'],
359
369
  },
360
370
  annotations: READ_ONLY_ANNOTATIONS,
361
371
  },
@@ -365,7 +375,7 @@ const TOOLS = [
365
375
  inputSchema: {
366
376
  type: 'object',
367
377
  properties: {
368
- vybitKey: {
378
+ key: {
369
379
  type: 'string',
370
380
  description: 'The key of the vybit',
371
381
  },
@@ -375,11 +385,11 @@ const TOOLS = [
375
385
  },
376
386
  cron: {
377
387
  type: 'string',
378
- description: 'Cron expression (5 fields): minute hour day month dayOfWeek. Example: "0 9 * * *" = every day at 9:00 AM',
388
+ description: 'Cron expression (5 fields): minute hour day month dayOfWeek. Uses 24-hour time. Examples: "0 7 * * *" = 7:00 AM, "0 19 * * *" = 7:00 PM, "30 14 25 12 *" = 2:30 PM on Dec 25',
379
389
  },
380
390
  timeZone: {
381
391
  type: 'string',
382
- description: 'IANA timezone identifier. Example: "America/Denver"',
392
+ description: 'IANA timezone identifier. Defaults to UTC if omitted — always set this to the user\'s local timezone. Examples: "America/New_York", "America/Denver", "America/Los_Angeles", "Europe/London"',
383
393
  },
384
394
  message: {
385
395
  type: 'string',
@@ -387,7 +397,7 @@ const TOOLS = [
387
397
  },
388
398
  imageUrl: {
389
399
  type: 'string',
390
- description: 'Image URL for the notification (must be a direct link to a JPG, PNG, or GIF image, max 512 characters)',
400
+ description: 'Image URL for the notification (must be a direct link to a JPG, PNG, or GIF image, max 512 characters, and the filename in the url must end with .jpg, .jpeg, .png, or .gif)',
391
401
  },
392
402
  linkUrl: {
393
403
  type: 'string',
@@ -398,7 +408,7 @@ const TOOLS = [
398
408
  description: 'Log content for the notification (max 1024 characters)',
399
409
  },
400
410
  },
401
- required: ['vybitKey', 'reminderId'],
411
+ required: ['key', 'reminderId'],
402
412
  },
403
413
  annotations: MUTATING_ANNOTATIONS,
404
414
  },
@@ -408,7 +418,7 @@ const TOOLS = [
408
418
  inputSchema: {
409
419
  type: 'object',
410
420
  properties: {
411
- vybitKey: {
421
+ key: {
412
422
  type: 'string',
413
423
  description: 'The key of the vybit',
414
424
  },
@@ -417,7 +427,7 @@ const TOOLS = [
417
427
  description: 'The unique identifier of the reminder to delete',
418
428
  },
419
429
  },
420
- required: ['vybitKey', 'reminderId'],
430
+ required: ['key', 'reminderId'],
421
431
  },
422
432
  annotations: MUTATING_ANNOTATIONS,
423
433
  },
@@ -545,7 +555,7 @@ const TOOLS = [
545
555
  },
546
556
  imageUrl: {
547
557
  type: 'string',
548
- description: 'Custom image URL (must be a direct link to a JPG, PNG, or GIF image, only if subscribers can send)',
558
+ description: 'Custom image URL (must be a direct link to a JPG, PNG, or GIF image and the filename in the url must end with .jpg, .jpeg, .png, or .gif, only if subscribers can send)',
549
559
  },
550
560
  linkUrl: {
551
561
  type: 'string',
@@ -602,13 +612,13 @@ const TOOLS = [
602
612
  inputSchema: {
603
613
  type: 'object',
604
614
  properties: {
605
- vybitKey: {
615
+ key: {
606
616
  type: 'string',
607
617
  description: 'The key of the vybit',
608
618
  },
609
619
  ...PAGINATION_SCHEMA,
610
620
  },
611
- required: ['vybitKey'],
621
+ required: ['key'],
612
622
  },
613
623
  annotations: READ_ONLY_ANNOTATIONS,
614
624
  },
@@ -631,7 +641,7 @@ const TOOLS = [
631
641
  // Peeps (Access Control)
632
642
  {
633
643
  name: 'peeps_list',
634
- description: 'List all peeps (people you have shared vybits with)',
644
+ description: 'List all peeps (people invited or subscribed to your vybits)',
635
645
  inputSchema: {
636
646
  type: 'object',
637
647
  properties: { ...PAGINATION_SCHEMA },
@@ -655,11 +665,11 @@ const TOOLS = [
655
665
  },
656
666
  {
657
667
  name: 'peep_create',
658
- description: 'Invite someone to a private vybit by email',
668
+ description: 'Invite someone to subscribe to your vybit',
659
669
  inputSchema: {
660
670
  type: 'object',
661
671
  properties: {
662
- vybitKey: {
672
+ key: {
663
673
  type: 'string',
664
674
  description: 'The key of the vybit to share',
665
675
  },
@@ -668,13 +678,13 @@ const TOOLS = [
668
678
  description: 'Email address of the person to invite',
669
679
  },
670
680
  },
671
- required: ['vybitKey', 'email'],
681
+ required: ['key', 'email'],
672
682
  },
673
683
  annotations: MUTATING_ANNOTATIONS,
674
684
  },
675
685
  {
676
686
  name: 'peep_delete',
677
- description: 'Remove a peep (revoke access)',
687
+ description: 'Remove a peep (revoke subscription access)',
678
688
  inputSchema: {
679
689
  type: 'object',
680
690
  properties: {
@@ -693,285 +703,294 @@ const TOOLS = [
693
703
  inputSchema: {
694
704
  type: 'object',
695
705
  properties: {
696
- vybitKey: {
706
+ key: {
697
707
  type: 'string',
698
708
  description: 'The key of the vybit',
699
709
  },
700
710
  ...PAGINATION_SCHEMA,
701
711
  },
702
- required: ['vybitKey'],
712
+ required: ['key'],
703
713
  },
704
714
  annotations: READ_ONLY_ANNOTATIONS,
705
715
  },
706
716
  ];
707
- // Vybit logo (64x64 PNG, base64-encoded)
708
- const VYBIT_ICON = 'data:image/png;base64,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';
709
- // Create MCP server
710
- const server = new Server({
711
- name: 'vybit-mcp-server',
712
- version: '1.2.5',
713
- icons: [
714
- {
715
- src: VYBIT_ICON,
716
- mimeType: 'image/png',
717
- sizes: ['64x64'],
718
- },
719
- ],
720
- websiteUrl: 'https://developer.vybit.net',
721
- }, {
722
- capabilities: {
723
- tools: {},
724
- },
725
- });
726
- // Handle list_tools request
727
- server.setRequestHandler(ListToolsRequestSchema, async () => {
728
- return {
729
- tools: TOOLS,
730
- };
731
- });
732
- // Handle call_tool request
733
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
734
- const { name, arguments: args } = request.params;
735
- if (!args) {
717
+ // --- Stdio server (only runs when credentials are available) ---
718
+ // When this module is imported for exports only (TOOLS, normalizeGeofence, jsonResponse),
719
+ // the code below is skipped because vybitClient will be null.
720
+ if (vybitClient) {
721
+ // Vybit logo (64x64 PNG, base64-encoded)
722
+ const VYBIT_ICON = 'data:image/png;base64,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';
723
+ // Create MCP server
724
+ const server = new Server({
725
+ name: 'vybit-mcp-server',
726
+ version: '1.5.0',
727
+ icons: [
728
+ {
729
+ src: VYBIT_ICON,
730
+ mimeType: 'image/png',
731
+ sizes: ['64x64'],
732
+ },
733
+ ],
734
+ websiteUrl: 'https://www.vybit.net',
735
+ }, {
736
+ capabilities: {
737
+ tools: {},
738
+ },
739
+ });
740
+ // Handle list_tools request
741
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
736
742
  return {
737
- content: [
738
- {
739
- type: 'text',
740
- text: 'Error: Missing arguments',
741
- },
742
- ],
743
- isError: true,
743
+ tools: TOOLS,
744
744
  };
745
- }
746
- try {
747
- switch (name) {
748
- case 'vybit_list':
749
- return jsonResponse(await vybitClient.listVybits({
750
- search: args.search,
751
- limit: args.limit,
752
- offset: args.offset,
753
- }));
754
- case 'vybit_get':
755
- return jsonResponse(await vybitClient.getVybit(args.vybitId));
756
- case 'vybit_create': {
757
- const createData = {
758
- name: args.name,
759
- };
760
- if (args.description)
761
- createData.description = args.description;
762
- if (args.soundKey)
763
- createData.soundKey = args.soundKey;
764
- if (args.status)
765
- createData.status = args.status;
766
- if (args.triggerType)
767
- createData.triggerType = args.triggerType;
768
- if (args.access)
769
- createData.access = args.access;
770
- if (args.message !== undefined)
771
- createData.message = args.message;
772
- if (args.imageUrl)
773
- createData.imageUrl = args.imageUrl;
774
- if (args.linkUrl)
775
- createData.linkUrl = args.linkUrl;
776
- if (args.triggerSettings)
777
- createData.triggerSettings = args.triggerSettings;
778
- if (args.geofence)
779
- createData.geofence = normalizeGeofence(args.geofence);
780
- return jsonResponse(await vybitClient.createVybit(createData));
781
- }
782
- case 'vybit_update': {
783
- const updateData = {};
784
- if (args.name)
785
- updateData.name = args.name;
786
- if (args.description)
787
- updateData.description = args.description;
788
- if (args.soundKey)
789
- updateData.soundKey = args.soundKey;
790
- if (args.status)
791
- updateData.status = args.status;
792
- if (args.triggerType)
793
- updateData.triggerType = args.triggerType;
794
- if (args.access)
795
- updateData.access = args.access;
796
- if (args.message !== undefined)
797
- updateData.message = args.message;
798
- if (args.triggerSettings)
799
- updateData.triggerSettings = args.triggerSettings;
800
- if (args.geofence)
801
- updateData.geofence = normalizeGeofence(args.geofence);
802
- return jsonResponse(await vybitClient.patchVybit(args.vybitId, updateData));
803
- }
804
- case 'vybit_delete':
805
- await vybitClient.deleteVybit(args.vybitId);
806
- return jsonResponse({ success: true, message: 'Vybit deleted successfully' });
807
- case 'vybit_trigger': {
808
- const options = {};
809
- if (args.message)
810
- options.message = args.message;
811
- if (args.imageUrl)
812
- options.imageUrl = args.imageUrl;
813
- if (args.linkUrl)
814
- options.linkUrl = args.linkUrl;
815
- if (args.log)
816
- options.log = args.log;
817
- if (args.runOnce !== undefined)
818
- options.runOnce = args.runOnce;
819
- return jsonResponse(await vybitClient.triggerVybit(args.triggerKey, Object.keys(options).length > 0 ? options : undefined));
820
- }
821
- // Reminders
822
- case 'reminder_create': {
823
- const params = {
824
- cron: args.cron,
825
- };
826
- if (args.timeZone)
827
- params.timeZone = args.timeZone;
828
- if (args.year !== undefined)
829
- params.year = args.year;
830
- if (args.message !== undefined)
831
- params.message = args.message;
832
- if (args.imageUrl)
833
- params.imageUrl = args.imageUrl;
834
- if (args.linkUrl)
835
- params.linkUrl = args.linkUrl;
836
- if (args.log)
837
- params.log = args.log;
838
- return jsonResponse(await vybitClient.createReminder(args.vybitKey, params));
839
- }
840
- case 'reminder_list':
841
- return jsonResponse(await vybitClient.listReminders(args.vybitKey));
842
- case 'reminder_update': {
843
- const params = {};
844
- if (args.cron)
845
- params.cron = args.cron;
846
- if (args.timeZone)
847
- params.timeZone = args.timeZone;
848
- if (args.message !== undefined)
849
- params.message = args.message;
850
- if (args.imageUrl !== undefined)
851
- params.imageUrl = args.imageUrl;
852
- if (args.linkUrl !== undefined)
853
- params.linkUrl = args.linkUrl;
854
- if (args.log !== undefined)
855
- params.log = args.log;
856
- return jsonResponse(await vybitClient.updateReminder(args.vybitKey, args.reminderId, params));
857
- }
858
- case 'reminder_delete':
859
- await vybitClient.deleteReminder(args.vybitKey, args.reminderId);
860
- return jsonResponse({ success: true, message: 'Reminder deleted successfully' });
861
- case 'sounds_list':
862
- return jsonResponse(await vybitClient.searchSounds({
863
- search: args.search,
864
- limit: args.limit,
865
- offset: args.offset,
866
- }));
867
- case 'sound_get':
868
- return jsonResponse(await vybitClient.getSound(args.soundKey));
869
- case 'meter_get':
870
- return jsonResponse(await vybitClient.getMeter());
871
- // Public Vybit Discovery
872
- case 'vybits_browse_public':
873
- return jsonResponse(await vybitClient.listPublicVybits({
874
- search: args.search,
875
- limit: args.limit,
876
- offset: args.offset,
877
- }));
878
- case 'vybit_get_public':
879
- return jsonResponse(await vybitClient.getPublicVybit(args.subscriptionKey));
880
- // Subscription Management
881
- case 'subscription_create':
882
- return jsonResponse(await vybitClient.createVybitFollow(args.subscriptionKey));
883
- case 'subscriptions_list':
884
- return jsonResponse(await vybitClient.listVybitFollows({
885
- search: args.search,
886
- limit: args.limit,
887
- offset: args.offset,
888
- }));
889
- case 'subscription_get':
890
- return jsonResponse(await vybitClient.getVybitFollow(args.followingKey));
891
- case 'subscription_update': {
892
- const updateData = {};
893
- if (args.status)
894
- updateData.status = args.status;
895
- if (args.accessStatus)
896
- updateData.accessStatus = args.accessStatus;
897
- if (args.message !== undefined)
898
- updateData.message = args.message;
899
- if (args.imageUrl)
900
- updateData.imageUrl = args.imageUrl;
901
- if (args.linkUrl)
902
- updateData.linkUrl = args.linkUrl;
903
- return jsonResponse(await vybitClient.updateVybitFollow(args.followingKey, updateData));
745
+ });
746
+ // Handle call_tool request
747
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
748
+ const { name, arguments: args } = request.params;
749
+ if (!args) {
750
+ return {
751
+ content: [
752
+ {
753
+ type: 'text',
754
+ text: 'Error: Missing arguments',
755
+ },
756
+ ],
757
+ isError: true,
758
+ };
759
+ }
760
+ try {
761
+ switch (name) {
762
+ case 'vybit_list':
763
+ return jsonResponse(await vybitClient.listVybits({
764
+ search: args.search,
765
+ limit: args.limit,
766
+ offset: args.offset,
767
+ }));
768
+ case 'vybit_get':
769
+ return jsonResponse(await vybitClient.getVybit(args.key));
770
+ case 'vybit_create': {
771
+ const createData = {
772
+ name: args.name,
773
+ };
774
+ if (args.description)
775
+ createData.description = args.description;
776
+ if (args.soundKey)
777
+ createData.soundKey = args.soundKey;
778
+ if (args.status)
779
+ createData.status = args.status;
780
+ if (args.triggerType)
781
+ createData.triggerType = args.triggerType;
782
+ if (args.access)
783
+ createData.access = args.access;
784
+ if (args.message !== undefined)
785
+ createData.message = args.message;
786
+ if (args.imageUrl)
787
+ createData.imageUrl = args.imageUrl;
788
+ if (args.linkUrl)
789
+ createData.linkUrl = args.linkUrl;
790
+ if (args.triggerSettings)
791
+ createData.triggerSettings = args.triggerSettings;
792
+ if (args.geofence)
793
+ createData.geofence = normalizeGeofence(args.geofence);
794
+ return jsonResponse(await vybitClient.createVybit(createData));
795
+ }
796
+ case 'vybit_update': {
797
+ const updateData = {};
798
+ if (args.name)
799
+ updateData.name = args.name;
800
+ if (args.description)
801
+ updateData.description = args.description;
802
+ if (args.soundKey)
803
+ updateData.soundKey = args.soundKey;
804
+ if (args.status)
805
+ updateData.status = args.status;
806
+ if (args.triggerType)
807
+ updateData.triggerType = args.triggerType;
808
+ if (args.access)
809
+ updateData.access = args.access;
810
+ if (args.message !== undefined)
811
+ updateData.message = args.message;
812
+ if (args.imageUrl)
813
+ updateData.imageUrl = args.imageUrl;
814
+ if (args.linkUrl)
815
+ updateData.linkUrl = args.linkUrl;
816
+ if (args.triggerSettings)
817
+ updateData.triggerSettings = args.triggerSettings;
818
+ if (args.geofence)
819
+ updateData.geofence = normalizeGeofence(args.geofence);
820
+ return jsonResponse(await vybitClient.patchVybit(args.key, updateData));
821
+ }
822
+ case 'vybit_delete':
823
+ await vybitClient.deleteVybit(args.key);
824
+ return jsonResponse({ success: true, message: 'Vybit deleted successfully' });
825
+ case 'vybit_trigger': {
826
+ const options = {};
827
+ if (args.message)
828
+ options.message = args.message;
829
+ if (args.imageUrl)
830
+ options.imageUrl = args.imageUrl;
831
+ if (args.linkUrl)
832
+ options.linkUrl = args.linkUrl;
833
+ if (args.log)
834
+ options.log = args.log;
835
+ if (args.runOnce !== undefined)
836
+ options.runOnce = args.runOnce;
837
+ return jsonResponse(await vybitClient.triggerVybit(args.key, Object.keys(options).length > 0 ? options : undefined));
838
+ }
839
+ // Reminders
840
+ case 'reminder_create': {
841
+ const params = {
842
+ cron: args.cron,
843
+ };
844
+ if (args.timeZone)
845
+ params.timeZone = args.timeZone;
846
+ if (args.year !== undefined)
847
+ params.year = args.year;
848
+ if (args.message !== undefined)
849
+ params.message = args.message;
850
+ if (args.imageUrl)
851
+ params.imageUrl = args.imageUrl;
852
+ if (args.linkUrl)
853
+ params.linkUrl = args.linkUrl;
854
+ if (args.log)
855
+ params.log = args.log;
856
+ return jsonResponse(await vybitClient.createReminder(args.key, params));
857
+ }
858
+ case 'reminder_list':
859
+ return jsonResponse(await vybitClient.listReminders(args.key));
860
+ case 'reminder_update': {
861
+ const params = {};
862
+ if (args.cron)
863
+ params.cron = args.cron;
864
+ if (args.timeZone)
865
+ params.timeZone = args.timeZone;
866
+ if (args.message !== undefined)
867
+ params.message = args.message;
868
+ if (args.imageUrl !== undefined)
869
+ params.imageUrl = args.imageUrl;
870
+ if (args.linkUrl !== undefined)
871
+ params.linkUrl = args.linkUrl;
872
+ if (args.log !== undefined)
873
+ params.log = args.log;
874
+ return jsonResponse(await vybitClient.updateReminder(args.key, args.reminderId, params));
875
+ }
876
+ case 'reminder_delete':
877
+ await vybitClient.deleteReminder(args.key, args.reminderId);
878
+ return jsonResponse({ success: true, message: 'Reminder deleted successfully' });
879
+ case 'sounds_list':
880
+ return jsonResponse(await vybitClient.searchSounds({
881
+ search: args.search,
882
+ limit: args.limit,
883
+ offset: args.offset,
884
+ }));
885
+ case 'sound_get':
886
+ return jsonResponse(await vybitClient.getSound(args.soundKey));
887
+ case 'meter_get':
888
+ return jsonResponse(await vybitClient.getMeter());
889
+ // Public Vybit Discovery
890
+ case 'vybits_browse_public':
891
+ return jsonResponse(await vybitClient.listPublicVybits({
892
+ search: args.search,
893
+ limit: args.limit,
894
+ offset: args.offset,
895
+ }));
896
+ case 'vybit_get_public':
897
+ return jsonResponse(await vybitClient.getPublicVybit(args.subscriptionKey));
898
+ // Subscription Management
899
+ case 'subscription_create':
900
+ return jsonResponse(await vybitClient.createVybitFollow(args.subscriptionKey));
901
+ case 'subscriptions_list':
902
+ return jsonResponse(await vybitClient.listVybitFollows({
903
+ search: args.search,
904
+ limit: args.limit,
905
+ offset: args.offset,
906
+ }));
907
+ case 'subscription_get':
908
+ return jsonResponse(await vybitClient.getVybitFollow(args.followingKey));
909
+ case 'subscription_update': {
910
+ const updateData = {};
911
+ if (args.status)
912
+ updateData.status = args.status;
913
+ if (args.accessStatus)
914
+ updateData.accessStatus = args.accessStatus;
915
+ if (args.message !== undefined)
916
+ updateData.message = args.message;
917
+ if (args.imageUrl)
918
+ updateData.imageUrl = args.imageUrl;
919
+ if (args.linkUrl)
920
+ updateData.linkUrl = args.linkUrl;
921
+ return jsonResponse(await vybitClient.updateVybitFollow(args.followingKey, updateData));
922
+ }
923
+ case 'subscription_delete':
924
+ await vybitClient.deleteVybitFollow(args.followingKey);
925
+ return jsonResponse({ success: true, message: 'Unsubscribed successfully' });
926
+ // Logs
927
+ case 'logs_list':
928
+ return jsonResponse(await vybitClient.listLogs({
929
+ search: args.search,
930
+ limit: args.limit,
931
+ offset: args.offset,
932
+ }));
933
+ case 'log_get':
934
+ return jsonResponse(await vybitClient.getLog(args.logKey));
935
+ case 'vybit_logs':
936
+ return jsonResponse(await vybitClient.listVybitLogs(args.key, {
937
+ search: args.search,
938
+ limit: args.limit,
939
+ offset: args.offset,
940
+ }));
941
+ case 'subscription_logs':
942
+ return jsonResponse(await vybitClient.listVybitFollowLogs(args.followingKey, {
943
+ search: args.search,
944
+ limit: args.limit,
945
+ offset: args.offset,
946
+ }));
947
+ // Peeps
948
+ case 'peeps_list':
949
+ return jsonResponse(await vybitClient.listPeeps({
950
+ search: args.search,
951
+ limit: args.limit,
952
+ offset: args.offset,
953
+ }));
954
+ case 'peep_get':
955
+ return jsonResponse(await vybitClient.getPeep(args.peepKey));
956
+ case 'peep_create':
957
+ return jsonResponse(await vybitClient.createPeep(args.key, args.email));
958
+ case 'peep_delete':
959
+ await vybitClient.deletePeep(args.peepKey);
960
+ return jsonResponse({ success: true, message: 'Peep removed successfully' });
961
+ case 'vybit_peeps_list':
962
+ return jsonResponse(await vybitClient.listVybitPeeps(args.key, {
963
+ search: args.search,
964
+ limit: args.limit,
965
+ offset: args.offset,
966
+ }));
967
+ default:
968
+ throw new Error(`Unknown tool: ${name}`);
904
969
  }
905
- case 'subscription_delete':
906
- await vybitClient.deleteVybitFollow(args.followingKey);
907
- return jsonResponse({ success: true, message: 'Unsubscribed successfully' });
908
- // Logs
909
- case 'logs_list':
910
- return jsonResponse(await vybitClient.listLogs({
911
- search: args.search,
912
- limit: args.limit,
913
- offset: args.offset,
914
- }));
915
- case 'log_get':
916
- return jsonResponse(await vybitClient.getLog(args.logKey));
917
- case 'vybit_logs':
918
- return jsonResponse(await vybitClient.listVybitLogs(args.vybitKey, {
919
- search: args.search,
920
- limit: args.limit,
921
- offset: args.offset,
922
- }));
923
- case 'subscription_logs':
924
- return jsonResponse(await vybitClient.listVybitFollowLogs(args.followingKey, {
925
- search: args.search,
926
- limit: args.limit,
927
- offset: args.offset,
928
- }));
929
- // Peeps
930
- case 'peeps_list':
931
- return jsonResponse(await vybitClient.listPeeps({
932
- search: args.search,
933
- limit: args.limit,
934
- offset: args.offset,
935
- }));
936
- case 'peep_get':
937
- return jsonResponse(await vybitClient.getPeep(args.peepKey));
938
- case 'peep_create':
939
- return jsonResponse(await vybitClient.createPeep(args.vybitKey, args.email));
940
- case 'peep_delete':
941
- await vybitClient.deletePeep(args.peepKey);
942
- return jsonResponse({ success: true, message: 'Peep removed successfully' });
943
- case 'vybit_peeps_list':
944
- return jsonResponse(await vybitClient.listVybitPeeps(args.vybitKey, {
945
- search: args.search,
946
- limit: args.limit,
947
- offset: args.offset,
948
- }));
949
- default:
950
- throw new Error(`Unknown tool: ${name}`);
951
970
  }
971
+ catch (error) {
972
+ const errorMessage = error.message || 'Unknown error';
973
+ const statusCode = error.statusCode ? ` (Status: ${error.statusCode})` : '';
974
+ return {
975
+ content: [
976
+ {
977
+ type: 'text',
978
+ text: `Error: ${errorMessage}${statusCode}`,
979
+ },
980
+ ],
981
+ isError: true,
982
+ };
983
+ }
984
+ });
985
+ // Start the server
986
+ async function main() {
987
+ const transport = new StdioServerTransport();
988
+ await server.connect(transport);
989
+ console.error('Vybit MCP server running on stdio');
952
990
  }
953
- catch (error) {
954
- const errorMessage = error.message || 'Unknown error';
955
- const statusCode = error.statusCode ? ` (Status: ${error.statusCode})` : '';
956
- return {
957
- content: [
958
- {
959
- type: 'text',
960
- text: `Error: ${errorMessage}${statusCode}`,
961
- },
962
- ],
963
- isError: true,
964
- };
965
- }
966
- });
967
- // Start the server
968
- async function main() {
969
- const transport = new StdioServerTransport();
970
- await server.connect(transport);
971
- console.error('Vybit MCP server running on stdio');
972
- }
973
- main().catch((error) => {
974
- console.error('Server error:', error);
975
- process.exit(1);
976
- });
991
+ main().catch((error) => {
992
+ console.error('Server error:', error);
993
+ process.exit(1);
994
+ });
995
+ } // end if (vybitClient)
977
996
  //# sourceMappingURL=index.js.map