@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.
- package/README.md +250 -0
- package/build/calendar/calendar.d.ts +69 -0
- package/build/calendar/calendar.d.ts.map +1 -0
- package/build/calendar/calendar.js +455 -0
- package/build/calendar/calendar.js.map +1 -0
- package/build/calendar/index.d.ts +3 -0
- package/build/calendar/index.d.ts.map +1 -0
- package/build/calendar/index.js +3 -0
- package/build/calendar/index.js.map +1 -0
- package/build/calendar/loader.d.ts +32 -0
- package/build/calendar/loader.d.ts.map +1 -0
- package/build/calendar/loader.js +179 -0
- package/build/calendar/loader.js.map +1 -0
- package/build/index.d.ts +13 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +707 -0
- package/build/index.js.map +1 -0
- package/build/types/calendar.d.ts +176 -0
- package/build/types/calendar.d.ts.map +1 -0
- package/build/types/calendar.js +5 -0
- package/build/types/calendar.js.map +1 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -0
- package/package.json +62 -0
|
@@ -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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"}
|
package/build/index.d.ts
ADDED
|
@@ -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"}
|