@jnss95/ical-mcp 1.0.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.
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Calendar loader - handles loading iCal data from various sources
3
+ */
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import { Calendar } from './calendar.js';
7
+ /**
8
+ * Load a calendar from a file path
9
+ */
10
+ export async function loadFromFile(filePath) {
11
+ const absolutePath = path.resolve(filePath);
12
+ // Check if file exists
13
+ try {
14
+ await fs.access(absolutePath, fs.constants.R_OK);
15
+ }
16
+ catch {
17
+ throw new Error(`Cannot access file: ${absolutePath}`);
18
+ }
19
+ const source = {
20
+ type: 'file',
21
+ source: absolutePath,
22
+ writable: await isFileWritable(absolutePath),
23
+ };
24
+ const calendar = new Calendar(source);
25
+ const content = await fs.readFile(absolutePath, 'utf-8');
26
+ calendar.loadFromString(content);
27
+ return calendar;
28
+ }
29
+ /**
30
+ * Load a calendar from an HTTP/HTTPS URL
31
+ */
32
+ export async function loadFromUrl(url) {
33
+ // Validate URL
34
+ let parsedUrl;
35
+ try {
36
+ parsedUrl = new URL(url);
37
+ }
38
+ catch {
39
+ throw new Error(`Invalid URL: ${url}`);
40
+ }
41
+ if (!['http:', 'https:'].includes(parsedUrl.protocol)) {
42
+ throw new Error(`Unsupported protocol: ${parsedUrl.protocol}. Only http and https are supported.`);
43
+ }
44
+ const source = {
45
+ type: 'http',
46
+ source: url,
47
+ writable: false, // HTTP sources are always read-only
48
+ };
49
+ const calendar = new Calendar(source);
50
+ const response = await fetch(url, {
51
+ headers: {
52
+ 'Accept': 'text/calendar, application/calendar+xml, */*',
53
+ 'User-Agent': 'iCal-MCP-Server/1.0',
54
+ },
55
+ });
56
+ if (!response.ok) {
57
+ throw new Error(`Failed to fetch calendar: ${response.status} ${response.statusText}`);
58
+ }
59
+ const content = await response.text();
60
+ if (!content.includes('BEGIN:VCALENDAR')) {
61
+ throw new Error('Invalid iCal data: missing VCALENDAR component');
62
+ }
63
+ calendar.loadFromString(content);
64
+ return calendar;
65
+ }
66
+ /**
67
+ * Load a calendar from a raw iCal string
68
+ */
69
+ export function loadFromString(icalString, writable = true) {
70
+ if (!icalString.includes('BEGIN:VCALENDAR')) {
71
+ throw new Error('Invalid iCal data: missing VCALENDAR component');
72
+ }
73
+ const source = {
74
+ type: 'string',
75
+ source: 'memory',
76
+ writable,
77
+ };
78
+ const calendar = new Calendar(source);
79
+ calendar.loadFromString(icalString);
80
+ return calendar;
81
+ }
82
+ /**
83
+ * Load a calendar from either a file path or URL
84
+ */
85
+ export async function loadCalendar(pathOrUrl) {
86
+ // Check if it's a URL
87
+ if (pathOrUrl.startsWith('http://') || pathOrUrl.startsWith('https://')) {
88
+ return loadFromUrl(pathOrUrl);
89
+ }
90
+ // Check if it's a file URL
91
+ if (pathOrUrl.startsWith('file://')) {
92
+ const filePath = pathOrUrl.replace(/^file:\/\//, '');
93
+ return loadFromFile(filePath);
94
+ }
95
+ // Assume it's a file path
96
+ return loadFromFile(pathOrUrl);
97
+ }
98
+ /**
99
+ * Save a calendar back to its source
100
+ */
101
+ export async function saveCalendar(calendar) {
102
+ const source = calendar.getSource();
103
+ if (!source.writable) {
104
+ throw new Error('Calendar source is read-only');
105
+ }
106
+ if (source.type === 'file') {
107
+ const content = calendar.toString();
108
+ await fs.writeFile(source.source, content, 'utf-8');
109
+ }
110
+ else if (source.type === 'http') {
111
+ throw new Error('Cannot save to HTTP source');
112
+ }
113
+ else if (source.type === 'string') {
114
+ // In-memory calendar, nothing to persist
115
+ throw new Error('Cannot save in-memory calendar');
116
+ }
117
+ }
118
+ /**
119
+ * Create a new empty calendar file
120
+ */
121
+ export async function createCalendarFile(filePath, options) {
122
+ const absolutePath = path.resolve(filePath);
123
+ // Check if file already exists
124
+ try {
125
+ await fs.access(absolutePath);
126
+ throw new Error(`File already exists: ${absolutePath}`);
127
+ }
128
+ catch (error) {
129
+ // File doesn't exist, which is what we want
130
+ if (error.code !== 'ENOENT') {
131
+ throw error;
132
+ }
133
+ }
134
+ const source = {
135
+ type: 'file',
136
+ source: absolutePath,
137
+ writable: true,
138
+ };
139
+ const calendar = new Calendar(source);
140
+ // Set optional properties
141
+ const icalString = buildEmptyCalendar(options?.name, options?.timezone);
142
+ calendar.loadFromString(icalString);
143
+ // Save to file
144
+ await fs.writeFile(absolutePath, calendar.toString(), 'utf-8');
145
+ return calendar;
146
+ }
147
+ /**
148
+ * Check if a file is writable
149
+ */
150
+ async function isFileWritable(filePath) {
151
+ try {
152
+ await fs.access(filePath, fs.constants.W_OK);
153
+ return true;
154
+ }
155
+ catch {
156
+ return false;
157
+ }
158
+ }
159
+ /**
160
+ * Build an empty iCal calendar string
161
+ */
162
+ function buildEmptyCalendar(name, timezone) {
163
+ const lines = [
164
+ 'BEGIN:VCALENDAR',
165
+ 'VERSION:2.0',
166
+ 'PRODID:-//iCal MCP Server//EN',
167
+ 'CALSCALE:GREGORIAN',
168
+ 'METHOD:PUBLISH',
169
+ ];
170
+ if (name) {
171
+ lines.push(`X-WR-CALNAME:${name}`);
172
+ }
173
+ if (timezone) {
174
+ lines.push(`X-WR-TIMEZONE:${timezone}`);
175
+ }
176
+ lines.push('END:VCALENDAR');
177
+ return lines.join('\r\n');
178
+ }
179
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/calendar/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * iCal MCP Server - Main entry point
4
+ */
5
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ import { Calendar } from './calendar/index.js';
7
+ declare const calendars: Map<string, Calendar>;
8
+ /**
9
+ * Create and configure the MCP server
10
+ */
11
+ export declare function createServer(): McpServer;
12
+ export { calendars };
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,EAAE,QAAQ,EAAkD,MAAM,qBAAqB,CAAC;AAI/F,QAAA,MAAM,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAa,CAAC;AAEnD;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAUxC;AA6yBD,OAAO,EAAE,SAAS,EAAE,CAAC"}