@mcp-monorepo/ics 1.1.0 → 1.3.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.
Files changed (71) hide show
  1. package/dist/ics-parser/errors.d.ts +16 -0
  2. package/dist/ics-parser/errors.d.ts.map +1 -0
  3. package/dist/ics-parser/errors.js +31 -0
  4. package/dist/ics-parser/errors.js.map +1 -0
  5. package/dist/ics-parser/event-expander.d.ts +71 -0
  6. package/dist/ics-parser/event-expander.d.ts.map +1 -0
  7. package/dist/ics-parser/event-expander.js +328 -0
  8. package/dist/ics-parser/event-expander.js.map +1 -0
  9. package/dist/ics-parser/index.d.ts +67 -0
  10. package/dist/ics-parser/index.d.ts.map +1 -0
  11. package/dist/ics-parser/index.js +91 -0
  12. package/dist/ics-parser/index.js.map +1 -0
  13. package/dist/ics-parser/parser.d.ts +26 -0
  14. package/dist/ics-parser/parser.d.ts.map +1 -0
  15. package/dist/ics-parser/parser.js +99 -0
  16. package/dist/ics-parser/parser.js.map +1 -0
  17. package/dist/ics-parser/property-parsers.d.ts +66 -0
  18. package/dist/ics-parser/property-parsers.d.ts.map +1 -0
  19. package/dist/ics-parser/property-parsers.js +226 -0
  20. package/dist/ics-parser/property-parsers.js.map +1 -0
  21. package/dist/ics-parser/rrule-expander.d.ts +10 -0
  22. package/dist/ics-parser/rrule-expander.d.ts.map +1 -0
  23. package/dist/ics-parser/rrule-expander.js +305 -0
  24. package/dist/ics-parser/rrule-expander.js.map +1 -0
  25. package/dist/ics-parser/timezone-processor.d.ts +40 -0
  26. package/dist/ics-parser/timezone-processor.d.ts.map +1 -0
  27. package/dist/ics-parser/timezone-processor.js +219 -0
  28. package/dist/ics-parser/timezone-processor.js.map +1 -0
  29. package/dist/ics-parser/types.d.ts +119 -0
  30. package/dist/ics-parser/types.d.ts.map +1 -0
  31. package/dist/ics-parser/types.js +2 -0
  32. package/dist/ics-parser/types.js.map +1 -0
  33. package/dist/ics-parser/utils.d.ts +16 -0
  34. package/dist/ics-parser/utils.d.ts.map +1 -0
  35. package/dist/ics-parser/utils.js +19 -0
  36. package/dist/ics-parser/utils.js.map +1 -0
  37. package/dist/index.js +9 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/lib/config.d.ts +10 -0
  40. package/dist/lib/config.d.ts.map +1 -0
  41. package/dist/lib/config.js +39 -0
  42. package/dist/lib/config.js.map +1 -0
  43. package/dist/lib/event-store-2.d.ts +11 -0
  44. package/dist/lib/event-store-2.d.ts.map +1 -0
  45. package/dist/lib/event-store-2.js +90 -0
  46. package/dist/lib/event-store-2.js.map +1 -0
  47. package/dist/lib/format-date.d.ts +7 -1
  48. package/dist/lib/format-date.d.ts.map +1 -1
  49. package/dist/lib/format-date.js +9 -2
  50. package/dist/lib/format-date.js.map +1 -1
  51. package/dist/lib/types.d.ts +0 -34
  52. package/dist/lib/types.d.ts.map +1 -1
  53. package/dist/tools/fetch-events.d.ts.map +1 -1
  54. package/dist/tools/fetch-events.js +31 -26
  55. package/dist/tools/fetch-events.js.map +1 -1
  56. package/dist/tools/search-events.d.ts.map +1 -1
  57. package/dist/tools/search-events.js +50 -17
  58. package/dist/tools/search-events.js.map +1 -1
  59. package/package.json +10 -6
  60. package/dist/lib/event-store.d.ts +0 -9
  61. package/dist/lib/event-store.d.ts.map +0 -1
  62. package/dist/lib/event-store.js +0 -88
  63. package/dist/lib/event-store.js.map +0 -1
  64. package/dist/lib/filter-events.d.ts +0 -3
  65. package/dist/lib/filter-events.d.ts.map +0 -1
  66. package/dist/lib/filter-events.js +0 -10
  67. package/dist/lib/filter-events.js.map +0 -1
  68. package/dist/lib/recurrrence.d.ts +0 -3
  69. package/dist/lib/recurrrence.d.ts.map +0 -1
  70. package/dist/lib/recurrrence.js +0 -49
  71. package/dist/lib/recurrrence.js.map +0 -1
@@ -1,12 +1,13 @@
1
1
  import { registerTool } from '@mcp-monorepo/shared';
2
2
  import { performKeywordSearch } from '@mcp-monorepo/shared';
3
3
  import { z } from 'zod';
4
- import { rawEvents } from '../lib/event-store.js';
4
+ import { getUnexpandedEvents } from '../ics-parser/index.js';
5
+ import { getPreparedIcs } from '../lib/event-store-2.js';
5
6
  import { formatDate } from '../lib/format-date.js';
6
7
  export const registerSearchEventsTool = (server) => registerTool(server, {
7
8
  name: 'search-events',
8
9
  title: 'Search Calendar Events',
9
- description: 'Search through all calendar events using keywords. Searches in title and description, sorts by number of matching words.',
10
+ description: 'Search through all calendar events using keywords. Searches in title, description, location, attendees, and categories. Sorts by number of matching words.',
10
11
  inputSchema: {
11
12
  query: z
12
13
  .string()
@@ -24,6 +25,13 @@ export const registerSearchEventsTool = (server) => registerTool(server, {
24
25
  source: z.string(),
25
26
  matchCount: z.number(),
26
27
  matchedWords: z.array(z.string()),
28
+ organizer: z.any().optional(),
29
+ attendees: z.array(z.any()).optional(),
30
+ categories: z.array(z.string()).optional(),
31
+ url: z.string().optional(),
32
+ rrule: z.any().optional(),
33
+ rdates: z.array(z.string()).optional(),
34
+ exdates: z.array(z.string()).optional(),
27
35
  })),
28
36
  errors: z.array(z.string()),
29
37
  total: z.number(),
@@ -34,34 +42,59 @@ export const registerSearchEventsTool = (server) => registerTool(server, {
34
42
  if (!query.trim()) {
35
43
  throw new Error('Search query cannot be empty');
36
44
  }
37
- const events = await rawEvents;
38
- const results = performKeywordSearch(query, events.events, (event) => [event.summary, event.description, event.location, event.source], (a, b) => new Date(a.dtstart).getTime() - new Date(b.dtstart).getTime());
39
- // Limit results based on the specified `limit`
45
+ const { prepared, errors } = await getPreparedIcs();
46
+ const unexpandedEvents = getUnexpandedEvents(prepared);
47
+ const results = performKeywordSearch(query, unexpandedEvents, (event) => {
48
+ const source = event.customProperties?.['X-MCP-SOURCE']?.value ?? 'Unknown';
49
+ const customPropValues = event.customProperties
50
+ ? Object.values(event.customProperties).map((p) => p.value)
51
+ : [];
52
+ const attendeeNames = event.attendees
53
+ ? event.attendees.flatMap((a) => [a.email, a.commonName]).filter((x) => x !== undefined)
54
+ : [];
55
+ return [
56
+ event.summary,
57
+ event.description,
58
+ event.location,
59
+ source,
60
+ ...(event.categories || []),
61
+ event.organizer?.commonName,
62
+ ...attendeeNames,
63
+ event.url,
64
+ ...customPropValues,
65
+ ].filter((v) => !!v);
66
+ }, (a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());
40
67
  const limitedResults = results.slice(0, limit);
41
68
  return {
42
69
  results: limitedResults,
43
70
  total: results.length,
44
71
  searchQuery: query,
45
- errors: events.errors,
72
+ errors: errors,
46
73
  };
47
74
  },
48
75
  formatter({ results, total, searchQuery, errors }) {
49
76
  const formattedEvents = results.map((result) => {
50
- const { description, dtend, dtstart, location, source, summary, uid } = result.match;
77
+ const event = result.match;
78
+ const source = event.customProperties?.['X-MCP-SOURCE']?.value ?? 'Unknown';
51
79
  return {
52
- summary: summary,
53
- start: formatDate(dtstart, true),
54
- ...(dtend ? { end: formatDate(dtend, true) } : {}),
55
- description: description
56
- ? description.length > 400
57
- ? description.substring(0, 400) + '...'
58
- : description
59
- : undefined,
60
- location: location,
61
- uid: uid,
80
+ summary: event.summary,
81
+ start: formatDate(new Date(event.start), event.allDay),
82
+ ...(event.end ? { end: formatDate(new Date(event.end), event.allDay) } : {}),
83
+ description: event.description && event.description.length > 400
84
+ ? event.description.substring(0, 400) + '...'
85
+ : event.description,
86
+ location: event.location,
87
+ uid: event.uid,
62
88
  source: source,
63
89
  matchCount: result.matchCount,
64
90
  matchedWords: result.matchedWords,
91
+ organizer: event.organizer,
92
+ attendees: event.attendees,
93
+ categories: event.categories,
94
+ url: event.url,
95
+ rrule: event.rrule,
96
+ rdates: event.rdates,
97
+ exdates: event.exdates,
65
98
  };
66
99
  });
67
100
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"search-events.js","sourceRoot":"","sources":["../../src/tools/search-events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-events.js","sourceRoot":"","sources":["../../src/tools/search-events.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-monorepo/ics",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "description": "MCP server for calendar tools using ICS/ical feeds",
6
6
  "main": "dist/index.js",
@@ -18,6 +18,7 @@
18
18
  "build": "tsc -b",
19
19
  "dev": "tsc --watch",
20
20
  "start": "node dist/index.js",
21
+ "demo": "node --inspect dist/demo.js",
21
22
  "test": "vitest run --passWithNoTests",
22
23
  "test:watch": "vitest",
23
24
  "test:coverage": "vitest run --coverage",
@@ -25,16 +26,19 @@
25
26
  "clean": "rimraf dist tsconfig.tsbuildinfo"
26
27
  },
27
28
  "dependencies": {
29
+ "@mcp-monorepo/shared": "*",
28
30
  "@modelcontextprotocol/sdk": "^1.23.1",
29
- "zod": "^3.25.76",
30
31
  "date-fns-tz": "^3.2.0",
31
- "node-ical": "^0.20.1",
32
- "@mcp-monorepo/shared": "*"
32
+ "luxon": "^3.7.2",
33
+ "node-ical": "^0.22.1",
34
+ "rrule": "^2.8.1",
35
+ "zod": "^3.25.76"
33
36
  },
34
37
  "devDependencies": {
38
+ "@types/luxon": "^3.7.1",
35
39
  "@types/node": "^22.14.1",
40
+ "rimraf": "^6.0.1",
36
41
  "typescript": "^5.8.3",
37
- "vitest": "^3.2.4",
38
- "rimraf": "^6.0.1"
42
+ "vitest": "^3.2.4"
39
43
  }
40
44
  }
@@ -1,9 +0,0 @@
1
- import { RefreshablePromise } from '@mcp-monorepo/shared';
2
- import { type CalendarSource, type RawIcalEvent } from './types.js';
3
- export declare const getIcsUrls: () => CalendarSource[];
4
- export declare const parseIcsContent: (icsContent: string, source: string) => Promise<RawIcalEvent[]>;
5
- export declare const rawEvents: RefreshablePromise<{
6
- events: RawIcalEvent[];
7
- errors: string[];
8
- }>;
9
- //# sourceMappingURL=event-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../../src/lib/event-store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAI1E,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAkB,MAAM,YAAY,CAAA;AAEnF,eAAO,MAAM,UAAU,QAAO,cAAc,EAsB3C,CAAA;AAED,eAAO,MAAM,eAAe,GAAU,YAAY,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,YAAY,EAAE,CAkBhG,CAAA;AAuDD,eAAO,MAAM,SAAS;YApDZ,YAAY,EAAE;YACd,MAAM,EAAE;EAmD4C,CAAA"}
@@ -1,88 +0,0 @@
1
- import { mkdir, readFile, writeFile } from 'fs/promises';
2
- import { dirname, join } from 'path';
3
- import { findProjectRoot, RefreshablePromise } from '@mcp-monorepo/shared';
4
- import { logger } from '@mcp-monorepo/shared';
5
- import ical from 'node-ical';
6
- export const getIcsUrls = () => {
7
- const envVars = process.env;
8
- const calendarSources = [];
9
- Object.keys(envVars).forEach((key) => {
10
- const ENV_PREFIX = 'CALENDAR_';
11
- if (key.startsWith(ENV_PREFIX)) {
12
- const url = envVars[key];
13
- if (url && (url.startsWith('http://') || url.startsWith('https://'))) {
14
- const name = key.substring(ENV_PREFIX.length);
15
- calendarSources.push({ name, url });
16
- }
17
- else {
18
- throw new Error(`Invalid URL for environment variable ${key}: ${url}`);
19
- }
20
- }
21
- });
22
- if (calendarSources.length === 0) {
23
- throw new Error('No valid ICS URLs provided in environment variables.');
24
- }
25
- return calendarSources;
26
- };
27
- export const parseIcsContent = async (icsContent, source) => {
28
- const entries = Object.values(await ical.async.parseICS(icsContent));
29
- return entries
30
- .filter((e) => e.type === 'VEVENT')
31
- .map((event) => {
32
- return {
33
- uid: event.uid,
34
- summary: event.summary,
35
- description: event.description,
36
- location: event.location,
37
- dtstart: event.start,
38
- dtend: event.end,
39
- allDay: event.datetype === 'date',
40
- source,
41
- rrule: event.rrule,
42
- rruleOptions: event.rrule ? event.rrule.origOptions : undefined,
43
- };
44
- });
45
- };
46
- async function refreshEvents() {
47
- const sources = getIcsUrls();
48
- logger.info('Refreshing events from: ', sources);
49
- const events = [];
50
- const errors = [];
51
- for (const source of sources) {
52
- const dataFile = join(await findProjectRoot(import.meta.dirname), 'data', 'ics', source.url.replace(/[^a-zA-Z0-9]/g, '_') + '.json');
53
- try {
54
- logger.info(`[${source.name}] Attempting to fetch fresh data...`);
55
- const icsContent = await fetch(source.url);
56
- if (!icsContent.ok) {
57
- throw new Error(`Fetch failed with status ${icsContent.status}`);
58
- }
59
- const text = await icsContent.text();
60
- const parsed = await parseIcsContent(text, source.name);
61
- events.push(...parsed);
62
- await mkdir(dirname(dataFile), { recursive: true });
63
- await writeFile(dataFile, JSON.stringify(parsed));
64
- logger.info(`[${source.name}] Successfully fetched and cached new data.`);
65
- }
66
- catch (e) {
67
- logger.warn(`[${source.name}] Fetch failed: ${e.message}. Attempting to use cache.`);
68
- try {
69
- const data = await readFile(dataFile, 'utf-8');
70
- const parsed = JSON.parse(data);
71
- events.push(...parsed);
72
- logger.info(`[${source.name}] Successfully loaded data from cache.`);
73
- }
74
- catch {
75
- const finalErrorMsg = `[${source.name}] Fetch failed and cache is unavailable or corrupt.`;
76
- logger.error(finalErrorMsg);
77
- errors.push(finalErrorMsg);
78
- }
79
- }
80
- }
81
- errors.forEach((e) => logger.error(e));
82
- return {
83
- events,
84
- errors,
85
- };
86
- }
87
- export const rawEvents = new RefreshablePromise(refreshEvents);
88
- //# sourceMappingURL=event-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-store.js","sourceRoot":"","sources":["../../src/lib/event-store.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { type CalendarEvent } from './types.js';
2
- export declare function filterEvents(events: CalendarEvent[], start: Date, end: Date): CalendarEvent[];
3
- //# sourceMappingURL=filter-events.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-events.d.ts","sourceRoot":"","sources":["../../src/lib/filter-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,mBAQ3E"}
@@ -1,10 +0,0 @@
1
- export function filterEvents(events, start, end) {
2
- return events
3
- .filter((evt) => {
4
- const st = evt.dtstart;
5
- const en = evt.dtend || evt.dtstart;
6
- return st <= end && en >= start;
7
- })
8
- .sort((a, b) => a.dtstart.getTime() - b.dtstart.getTime());
9
- }
10
- //# sourceMappingURL=filter-events.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-events.js","sourceRoot":"","sources":["../../src/lib/filter-events.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,MAAuB,EAAE,KAAW,EAAE,GAAS;IAC1E,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAA;QACtB,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAA;QACnC,OAAO,EAAE,IAAI,GAAG,IAAI,EAAE,IAAI,KAAK,CAAA;IACjC,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;AAC9D,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { CalendarEvent, RawIcalEvent } from './types.js';
2
- export declare function resolveRecurrence(events: RawIcalEvent[], startDate: Date, endDate: Date): CalendarEvent[];
3
- //# sourceMappingURL=recurrrence.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"recurrrence.d.ts","sourceRoot":"","sources":["../../src/lib/recurrrence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAqB7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,aAAa,EAAE,CA0CzG"}
@@ -1,49 +0,0 @@
1
- function getAdjustedRecurrenceDate(rruleOrigOptions, eventStart, recurrence) {
2
- if (rruleOrigOptions && rruleOrigOptions.tzid) {
3
- try {
4
- const utc = recurrence.getTime() + eventStart.getTimezoneOffset() * 60000;
5
- return new Date(utc);
6
- }
7
- catch {
8
- return recurrence;
9
- }
10
- }
11
- const origOffset = eventStart.getTimezoneOffset();
12
- const recOffset = recurrence.getTimezoneOffset();
13
- const offsetDiff = origOffset - recOffset;
14
- return new Date(recurrence.getTime() + offsetDiff * 60000);
15
- }
16
- export function resolveRecurrence(events, startDate, endDate) {
17
- const createCalendarEvent = (event, dtstart, dtend, uidSuffix) => ({
18
- uid: uidSuffix ? `${event.uid}_${uidSuffix}` : event.uid,
19
- summary: event.summary,
20
- description: event.description,
21
- location: event.location,
22
- dtstart: dtstart ?? event.dtstart,
23
- dtend: dtend ?? event.dtend,
24
- allDay: event.allDay,
25
- source: event.source,
26
- });
27
- const expandSingleEvent = (event) => {
28
- if (!event.rrule) {
29
- return [createCalendarEvent(event)];
30
- }
31
- try {
32
- const recurrences = event.rrule.between(startDate, endDate);
33
- if (recurrences.length === 0) {
34
- return event.dtstart >= startDate && event.dtstart <= endDate ? [createCalendarEvent(event)] : [];
35
- }
36
- const duration = event.dtend && event.dtstart ? event.dtend.getTime() - event.dtstart.getTime() : 0;
37
- return recurrences.map((recurrenceDate) => {
38
- const adjustedStart = getAdjustedRecurrenceDate(event.rruleOptions, event.dtstart, recurrenceDate);
39
- const adjustedEnd = duration ? new Date(adjustedStart.getTime() + duration) : undefined;
40
- return createCalendarEvent(event, adjustedStart, adjustedEnd, adjustedStart.getTime().toString());
41
- });
42
- }
43
- catch {
44
- return [createCalendarEvent(event)];
45
- }
46
- };
47
- return events.flatMap(expandSingleEvent);
48
- }
49
- //# sourceMappingURL=recurrrence.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"recurrrence.js","sourceRoot":"","sources":["../../src/lib/recurrrence.ts"],"names":[],"mappings":"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"}