@shin1ohno/sage 0.3.0 → 0.5.3

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 (95) hide show
  1. package/dist/cli/http-server-with-config.d.ts +38 -0
  2. package/dist/cli/http-server-with-config.d.ts.map +1 -0
  3. package/dist/cli/http-server-with-config.js +458 -0
  4. package/dist/cli/http-server-with-config.js.map +1 -0
  5. package/dist/cli/http-server.d.ts +74 -0
  6. package/dist/cli/http-server.d.ts.map +1 -0
  7. package/dist/cli/http-server.js +407 -0
  8. package/dist/cli/http-server.js.map +1 -0
  9. package/dist/cli/jwt-middleware.d.ts +36 -0
  10. package/dist/cli/jwt-middleware.d.ts.map +1 -0
  11. package/dist/cli/jwt-middleware.js +99 -0
  12. package/dist/cli/jwt-middleware.js.map +1 -0
  13. package/dist/cli/main-entry.d.ts +41 -0
  14. package/dist/cli/main-entry.d.ts.map +1 -0
  15. package/dist/cli/main-entry.js +80 -0
  16. package/dist/cli/main-entry.js.map +1 -0
  17. package/dist/cli/mcp-handler.d.ts +56 -0
  18. package/dist/cli/mcp-handler.d.ts.map +1 -0
  19. package/dist/cli/mcp-handler.js +2189 -0
  20. package/dist/cli/mcp-handler.js.map +1 -0
  21. package/dist/cli/parser.d.ts +43 -0
  22. package/dist/cli/parser.d.ts.map +1 -0
  23. package/dist/cli/parser.js +162 -0
  24. package/dist/cli/parser.js.map +1 -0
  25. package/dist/cli/remote-config-loader.d.ts +85 -0
  26. package/dist/cli/remote-config-loader.d.ts.map +1 -0
  27. package/dist/cli/remote-config-loader.js +129 -0
  28. package/dist/cli/remote-config-loader.js.map +1 -0
  29. package/dist/cli/secret-auth.d.ts +47 -0
  30. package/dist/cli/secret-auth.d.ts.map +1 -0
  31. package/dist/cli/secret-auth.js +165 -0
  32. package/dist/cli/secret-auth.js.map +1 -0
  33. package/dist/cli/sse-stream-handler.d.ts +45 -0
  34. package/dist/cli/sse-stream-handler.d.ts.map +1 -0
  35. package/dist/cli/sse-stream-handler.js +125 -0
  36. package/dist/cli/sse-stream-handler.js.map +1 -0
  37. package/dist/index.js +885 -209
  38. package/dist/index.js.map +1 -1
  39. package/dist/integrations/calendar-event-creator.d.ts +152 -0
  40. package/dist/integrations/calendar-event-creator.d.ts.map +1 -0
  41. package/dist/integrations/calendar-event-creator.js +507 -0
  42. package/dist/integrations/calendar-event-creator.js.map +1 -0
  43. package/dist/integrations/calendar-event-deleter.d.ts +137 -0
  44. package/dist/integrations/calendar-event-deleter.d.ts.map +1 -0
  45. package/dist/integrations/calendar-event-deleter.js +378 -0
  46. package/dist/integrations/calendar-event-deleter.js.map +1 -0
  47. package/dist/integrations/calendar-event-response.d.ts +213 -0
  48. package/dist/integrations/calendar-event-response.d.ts.map +1 -0
  49. package/dist/integrations/calendar-event-response.js +560 -0
  50. package/dist/integrations/calendar-event-response.js.map +1 -0
  51. package/dist/integrations/calendar-service.d.ts +66 -1
  52. package/dist/integrations/calendar-service.d.ts.map +1 -1
  53. package/dist/integrations/calendar-service.js +223 -0
  54. package/dist/integrations/calendar-service.js.map +1 -1
  55. package/dist/oauth/client-store.d.ts +36 -0
  56. package/dist/oauth/client-store.d.ts.map +1 -0
  57. package/dist/oauth/client-store.js +104 -0
  58. package/dist/oauth/client-store.js.map +1 -0
  59. package/dist/oauth/code-store.d.ts +48 -0
  60. package/dist/oauth/code-store.d.ts.map +1 -0
  61. package/dist/oauth/code-store.js +89 -0
  62. package/dist/oauth/code-store.js.map +1 -0
  63. package/dist/oauth/index.d.ts +13 -0
  64. package/dist/oauth/index.d.ts.map +1 -0
  65. package/dist/oauth/index.js +21 -0
  66. package/dist/oauth/index.js.map +1 -0
  67. package/dist/oauth/oauth-handler.d.ts +101 -0
  68. package/dist/oauth/oauth-handler.d.ts.map +1 -0
  69. package/dist/oauth/oauth-handler.js +577 -0
  70. package/dist/oauth/oauth-handler.js.map +1 -0
  71. package/dist/oauth/oauth-server.d.ts +165 -0
  72. package/dist/oauth/oauth-server.d.ts.map +1 -0
  73. package/dist/oauth/oauth-server.js +489 -0
  74. package/dist/oauth/oauth-server.js.map +1 -0
  75. package/dist/oauth/pkce.d.ts +48 -0
  76. package/dist/oauth/pkce.d.ts.map +1 -0
  77. package/dist/oauth/pkce.js +106 -0
  78. package/dist/oauth/pkce.js.map +1 -0
  79. package/dist/oauth/refresh-token-store.d.ts +45 -0
  80. package/dist/oauth/refresh-token-store.d.ts.map +1 -0
  81. package/dist/oauth/refresh-token-store.js +98 -0
  82. package/dist/oauth/refresh-token-store.js.map +1 -0
  83. package/dist/oauth/token-service.d.ts +46 -0
  84. package/dist/oauth/token-service.d.ts.map +1 -0
  85. package/dist/oauth/token-service.js +199 -0
  86. package/dist/oauth/token-service.js.map +1 -0
  87. package/dist/oauth/types.d.ts +264 -0
  88. package/dist/oauth/types.d.ts.map +1 -0
  89. package/dist/oauth/types.js +37 -0
  90. package/dist/oauth/types.js.map +1 -0
  91. package/dist/version.d.ts +9 -0
  92. package/dist/version.d.ts.map +1 -0
  93. package/dist/version.js +11 -0
  94. package/dist/version.js.map +1 -0
  95. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,20 +5,21 @@
5
5
  * An MCP server for Claude Desktop and Claude Code that provides
6
6
  * task management, prioritization, and reminder integration.
7
7
  */
8
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
- import { z } from 'zod';
11
- import { ConfigLoader } from './config/loader.js';
12
- import { SetupWizard } from './setup/wizard.js';
13
- import { TaskAnalyzer } from './tools/analyze-tasks.js';
14
- import { ReminderManager } from './integrations/reminder-manager.js';
15
- import { CalendarService } from './integrations/calendar-service.js';
16
- import { NotionMCPService } from './integrations/notion-mcp.js';
17
- import { TodoListManager } from './integrations/todo-list-manager.js';
18
- import { TaskSynchronizer } from './integrations/task-synchronizer.js';
19
- // Server metadata
20
- const SERVER_NAME = 'sage';
21
- const SERVER_VERSION = '0.1.0';
8
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ import { z } from "zod";
11
+ import { ConfigLoader } from "./config/loader.js";
12
+ import { SetupWizard } from "./setup/wizard.js";
13
+ import { TaskAnalyzer } from "./tools/analyze-tasks.js";
14
+ import { ReminderManager } from "./integrations/reminder-manager.js";
15
+ import { CalendarService } from "./integrations/calendar-service.js";
16
+ import { NotionMCPService } from "./integrations/notion-mcp.js";
17
+ import { TodoListManager } from "./integrations/todo-list-manager.js";
18
+ import { TaskSynchronizer } from "./integrations/task-synchronizer.js";
19
+ import { CalendarEventResponseService } from "./integrations/calendar-event-response.js";
20
+ import { CalendarEventCreatorService } from "./integrations/calendar-event-creator.js";
21
+ import { CalendarEventDeleterService } from "./integrations/calendar-event-deleter.js";
22
+ import { VERSION, SERVER_NAME } from "./version.js";
22
23
  // Global state
23
24
  let config = null;
24
25
  let wizardSession = null;
@@ -27,55 +28,61 @@ let calendarService = null;
27
28
  let notionService = null;
28
29
  let todoListManager = null;
29
30
  let taskSynchronizer = null;
31
+ let calendarEventResponseService = null;
32
+ let calendarEventCreatorService = null;
33
+ let calendarEventDeleterService = null;
30
34
  /**
31
35
  * Validate config updates for a specific section
32
36
  */
33
37
  function validateConfigUpdate(section, updates) {
34
38
  const invalidFields = [];
35
39
  switch (section) {
36
- case 'user':
37
- if (updates.name !== undefined && typeof updates.name !== 'string') {
38
- invalidFields.push('name');
40
+ case "user":
41
+ if (updates.name !== undefined && typeof updates.name !== "string") {
42
+ invalidFields.push("name");
39
43
  }
40
- if (updates.timezone !== undefined && typeof updates.timezone !== 'string') {
41
- invalidFields.push('timezone');
44
+ if (updates.timezone !== undefined &&
45
+ typeof updates.timezone !== "string") {
46
+ invalidFields.push("timezone");
42
47
  }
43
48
  break;
44
- case 'calendar':
49
+ case "calendar":
45
50
  if (updates.workingHours !== undefined) {
46
51
  const wh = updates.workingHours;
47
52
  if (!wh.start || !wh.end) {
48
- invalidFields.push('workingHours');
53
+ invalidFields.push("workingHours");
49
54
  }
50
55
  }
51
- if (updates.deepWorkDays !== undefined && !Array.isArray(updates.deepWorkDays)) {
52
- invalidFields.push('deepWorkDays');
56
+ if (updates.deepWorkDays !== undefined &&
57
+ !Array.isArray(updates.deepWorkDays)) {
58
+ invalidFields.push("deepWorkDays");
53
59
  }
54
- if (updates.meetingHeavyDays !== undefined && !Array.isArray(updates.meetingHeavyDays)) {
55
- invalidFields.push('meetingHeavyDays');
60
+ if (updates.meetingHeavyDays !== undefined &&
61
+ !Array.isArray(updates.meetingHeavyDays)) {
62
+ invalidFields.push("meetingHeavyDays");
56
63
  }
57
64
  break;
58
- case 'integrations':
65
+ case "integrations":
59
66
  if (updates.notion !== undefined) {
60
67
  const notion = updates.notion;
61
68
  if (notion.enabled === true && !notion.databaseId) {
62
- invalidFields.push('notion.databaseId');
69
+ invalidFields.push("notion.databaseId");
63
70
  }
64
71
  }
65
72
  break;
66
- case 'team':
73
+ case "team":
67
74
  if (updates.members !== undefined && !Array.isArray(updates.members)) {
68
- invalidFields.push('members');
75
+ invalidFields.push("members");
69
76
  }
70
77
  if (updates.managers !== undefined && !Array.isArray(updates.managers)) {
71
- invalidFields.push('managers');
78
+ invalidFields.push("managers");
72
79
  }
73
80
  break;
74
81
  }
75
82
  if (invalidFields.length > 0) {
76
83
  return {
77
84
  valid: false,
78
- error: `無効なフィールド: ${invalidFields.join(', ')}`,
85
+ error: `無効なフィールド: ${invalidFields.join(", ")}`,
79
86
  invalidFields,
80
87
  };
81
88
  }
@@ -87,19 +94,22 @@ function validateConfigUpdate(section, updates) {
87
94
  function applyConfigUpdates(currentConfig, section, updates) {
88
95
  const newConfig = { ...currentConfig };
89
96
  switch (section) {
90
- case 'user':
97
+ case "user":
91
98
  newConfig.user = { ...newConfig.user, ...updates };
92
99
  break;
93
- case 'calendar':
94
- newConfig.calendar = { ...newConfig.calendar, ...updates };
100
+ case "calendar":
101
+ newConfig.calendar = {
102
+ ...newConfig.calendar,
103
+ ...updates,
104
+ };
95
105
  break;
96
- case 'priorityRules':
106
+ case "priorityRules":
97
107
  newConfig.priorityRules = {
98
108
  ...newConfig.priorityRules,
99
109
  ...updates,
100
110
  };
101
111
  break;
102
- case 'integrations':
112
+ case "integrations":
103
113
  // Deep merge for integrations
104
114
  if (updates.appleReminders) {
105
115
  newConfig.integrations.appleReminders = {
@@ -114,11 +124,14 @@ function applyConfigUpdates(currentConfig, section, updates) {
114
124
  };
115
125
  }
116
126
  break;
117
- case 'team':
127
+ case "team":
118
128
  newConfig.team = { ...newConfig.team, ...updates };
119
129
  break;
120
- case 'preferences':
121
- newConfig.preferences = { ...newConfig.preferences, ...updates };
130
+ case "preferences":
131
+ newConfig.preferences = {
132
+ ...newConfig.preferences,
133
+ ...updates,
134
+ };
122
135
  break;
123
136
  }
124
137
  return newConfig;
@@ -137,6 +150,9 @@ function initializeServices(userConfig) {
137
150
  notionService = new NotionMCPService();
138
151
  todoListManager = new TodoListManager();
139
152
  taskSynchronizer = new TaskSynchronizer();
153
+ calendarEventResponseService = new CalendarEventResponseService();
154
+ calendarEventCreatorService = new CalendarEventCreatorService();
155
+ calendarEventDeleterService = new CalendarEventDeleterService();
140
156
  }
141
157
  /**
142
158
  * Initialize the MCP server with all tools
@@ -144,7 +160,7 @@ function initializeServices(userConfig) {
144
160
  async function createServer() {
145
161
  const server = new McpServer({
146
162
  name: SERVER_NAME,
147
- version: SERVER_VERSION,
163
+ version: VERSION,
148
164
  });
149
165
  // Try to load existing config
150
166
  try {
@@ -163,19 +179,19 @@ async function createServer() {
163
179
  * check_setup_status - Check if initial setup is complete
164
180
  * Requirement: 1.1, 1.2
165
181
  */
166
- server.tool('check_setup_status', 'Check if sage has been configured. Returns setup status and guidance.', {}, async () => {
182
+ server.tool("check_setup_status", "Check if sage has been configured. Returns setup status and guidance.", {}, async () => {
167
183
  const exists = await ConfigLoader.exists();
168
184
  const isValid = config !== null;
169
185
  if (!exists) {
170
186
  return {
171
187
  content: [
172
188
  {
173
- type: 'text',
189
+ type: "text",
174
190
  text: JSON.stringify({
175
191
  setupComplete: false,
176
192
  configExists: false,
177
- message: 'sageの初期設定が必要です。start_setup_wizardを実行してセットアップを開始してください。',
178
- nextAction: 'start_setup_wizard',
193
+ message: "sageの初期設定が必要です。start_setup_wizardを実行してセットアップを開始してください。",
194
+ nextAction: "start_setup_wizard",
179
195
  }, null, 2),
180
196
  },
181
197
  ],
@@ -185,12 +201,12 @@ async function createServer() {
185
201
  return {
186
202
  content: [
187
203
  {
188
- type: 'text',
204
+ type: "text",
189
205
  text: JSON.stringify({
190
206
  setupComplete: false,
191
207
  configExists: true,
192
- message: '設定ファイルが見つかりましたが、読み込みに失敗しました。設定を再作成してください。',
193
- nextAction: 'start_setup_wizard',
208
+ message: "設定ファイルが見つかりましたが、読み込みに失敗しました。設定を再作成してください。",
209
+ nextAction: "start_setup_wizard",
194
210
  }, null, 2),
195
211
  },
196
212
  ],
@@ -199,18 +215,18 @@ async function createServer() {
199
215
  return {
200
216
  content: [
201
217
  {
202
- type: 'text',
218
+ type: "text",
203
219
  text: JSON.stringify({
204
220
  setupComplete: true,
205
221
  configExists: true,
206
222
  userName: config?.user.name,
207
- message: 'sageは設定済みです。タスク分析やリマインド設定を開始できます。',
223
+ message: "sageは設定済みです。タスク分析やリマインド設定を開始できます。",
208
224
  availableTools: [
209
- 'analyze_tasks',
210
- 'set_reminder',
211
- 'find_available_slots',
212
- 'sync_to_notion',
213
- 'update_config',
225
+ "analyze_tasks",
226
+ "set_reminder",
227
+ "find_available_slots",
228
+ "sync_to_notion",
229
+ "update_config",
214
230
  ],
215
231
  }, null, 2),
216
232
  },
@@ -221,18 +237,18 @@ async function createServer() {
221
237
  * start_setup_wizard - Begin the interactive setup process
222
238
  * Requirement: 1.3
223
239
  */
224
- server.tool('start_setup_wizard', 'Start the interactive setup wizard for sage. Returns the first question.', {
240
+ server.tool("start_setup_wizard", "Start the interactive setup wizard for sage. Returns the first question.", {
225
241
  mode: z
226
- .enum(['full', 'quick'])
242
+ .enum(["full", "quick"])
227
243
  .optional()
228
- .describe('Setup mode: full (all questions) or quick (essential only)'),
229
- }, async ({ mode = 'full' }) => {
244
+ .describe("Setup mode: full (all questions) or quick (essential only)"),
245
+ }, async ({ mode = "full" }) => {
230
246
  wizardSession = SetupWizard.createSession(mode);
231
247
  const question = SetupWizard.getCurrentQuestion(wizardSession);
232
248
  return {
233
249
  content: [
234
250
  {
235
- type: 'text',
251
+ type: "text",
236
252
  text: JSON.stringify({
237
253
  sessionId: wizardSession.sessionId,
238
254
  currentStep: wizardSession.currentStep,
@@ -246,7 +262,7 @@ async function createServer() {
246
262
  defaultValue: question.defaultValue,
247
263
  helpText: question.helpText,
248
264
  },
249
- message: 'セットアップを開始します。以下の質問に回答してください。',
265
+ message: "セットアップを開始します。以下の質問に回答してください。",
250
266
  }, null, 2),
251
267
  },
252
268
  ],
@@ -256,18 +272,20 @@ async function createServer() {
256
272
  * answer_wizard_question - Answer a setup wizard question
257
273
  * Requirement: 1.3, 1.4
258
274
  */
259
- server.tool('answer_wizard_question', 'Answer a question in the setup wizard and get the next question.', {
260
- questionId: z.string().describe('The ID of the question being answered'),
261
- answer: z.union([z.string(), z.array(z.string())]).describe('The answer to the question'),
275
+ server.tool("answer_wizard_question", "Answer a question in the setup wizard and get the next question.", {
276
+ questionId: z.string().describe("The ID of the question being answered"),
277
+ answer: z
278
+ .union([z.string(), z.array(z.string())])
279
+ .describe("The answer to the question"),
262
280
  }, async ({ questionId, answer }) => {
263
281
  if (!wizardSession) {
264
282
  return {
265
283
  content: [
266
284
  {
267
- type: 'text',
285
+ type: "text",
268
286
  text: JSON.stringify({
269
287
  error: true,
270
- message: 'セットアップセッションが見つかりません。start_setup_wizardを実行してください。',
288
+ message: "セットアップセッションが見つかりません。start_setup_wizardを実行してください。",
271
289
  }, null, 2),
272
290
  },
273
291
  ],
@@ -278,7 +296,7 @@ async function createServer() {
278
296
  return {
279
297
  content: [
280
298
  {
281
- type: 'text',
299
+ type: "text",
282
300
  text: JSON.stringify({
283
301
  error: true,
284
302
  message: result.error,
@@ -292,13 +310,13 @@ async function createServer() {
292
310
  return {
293
311
  content: [
294
312
  {
295
- type: 'text',
313
+ type: "text",
296
314
  text: JSON.stringify({
297
315
  isComplete: true,
298
316
  sessionId: wizardSession.sessionId,
299
317
  answers: wizardSession.answers,
300
- message: 'すべての質問に回答しました。save_configを実行して設定を保存してください。',
301
- nextAction: 'save_config',
318
+ message: "すべての質問に回答しました。save_configを実行して設定を保存してください。",
319
+ nextAction: "save_config",
302
320
  }, null, 2),
303
321
  },
304
322
  ],
@@ -308,7 +326,7 @@ async function createServer() {
308
326
  return {
309
327
  content: [
310
328
  {
311
- type: 'text',
329
+ type: "text",
312
330
  text: JSON.stringify({
313
331
  success: true,
314
332
  currentStep: wizardSession.currentStep,
@@ -331,17 +349,17 @@ async function createServer() {
331
349
  * save_config - Save the configuration from the setup wizard
332
350
  * Requirement: 1.4, 1.5, 1.6
333
351
  */
334
- server.tool('save_config', 'Save the configuration after completing the setup wizard.', {
335
- confirm: z.boolean().describe('Confirm saving the configuration'),
352
+ server.tool("save_config", "Save the configuration after completing the setup wizard.", {
353
+ confirm: z.boolean().describe("Confirm saving the configuration"),
336
354
  }, async ({ confirm }) => {
337
355
  if (!confirm) {
338
356
  return {
339
357
  content: [
340
358
  {
341
- type: 'text',
359
+ type: "text",
342
360
  text: JSON.stringify({
343
361
  saved: false,
344
- message: '設定の保存がキャンセルされました。',
362
+ message: "設定の保存がキャンセルされました。",
345
363
  }, null, 2),
346
364
  },
347
365
  ],
@@ -351,10 +369,10 @@ async function createServer() {
351
369
  return {
352
370
  content: [
353
371
  {
354
- type: 'text',
372
+ type: "text",
355
373
  text: JSON.stringify({
356
374
  error: true,
357
- message: 'セットアップセッションが見つかりません。start_setup_wizardを実行してください。',
375
+ message: "セットアップセッションが見つかりません。start_setup_wizardを実行してください。",
358
376
  }, null, 2),
359
377
  },
360
378
  ],
@@ -368,17 +386,17 @@ async function createServer() {
368
386
  return {
369
387
  content: [
370
388
  {
371
- type: 'text',
389
+ type: "text",
372
390
  text: JSON.stringify({
373
391
  saved: true,
374
392
  configPath: ConfigLoader.getConfigPath(),
375
393
  userName: newConfig.user.name,
376
394
  message: `設定を保存しました。${newConfig.user.name}さん、sageをご利用いただきありがとうございます!`,
377
395
  availableTools: [
378
- 'analyze_tasks',
379
- 'set_reminder',
380
- 'find_available_slots',
381
- 'sync_to_notion',
396
+ "analyze_tasks",
397
+ "set_reminder",
398
+ "find_available_slots",
399
+ "sync_to_notion",
382
400
  ],
383
401
  }, null, 2),
384
402
  },
@@ -389,10 +407,10 @@ async function createServer() {
389
407
  return {
390
408
  content: [
391
409
  {
392
- type: 'text',
410
+ type: "text",
393
411
  text: JSON.stringify({
394
412
  error: true,
395
- message: `設定の保存に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
413
+ message: `設定の保存に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
396
414
  }, null, 2),
397
415
  },
398
416
  ],
@@ -406,23 +424,26 @@ async function createServer() {
406
424
  * analyze_tasks - Analyze tasks and provide prioritization
407
425
  * Requirement: 2.1-2.6, 3.1-3.2, 4.1-4.5
408
426
  */
409
- server.tool('analyze_tasks', 'Analyze tasks to determine priority, estimate time, and identify stakeholders.', {
427
+ server.tool("analyze_tasks", "Analyze tasks to determine priority, estimate time, and identify stakeholders.", {
410
428
  tasks: z
411
429
  .array(z.object({
412
- title: z.string().describe('Task title'),
413
- description: z.string().optional().describe('Task description'),
414
- deadline: z.string().optional().describe('Task deadline (ISO 8601 format)'),
430
+ title: z.string().describe("Task title"),
431
+ description: z.string().optional().describe("Task description"),
432
+ deadline: z
433
+ .string()
434
+ .optional()
435
+ .describe("Task deadline (ISO 8601 format)"),
415
436
  }))
416
- .describe('List of tasks to analyze'),
437
+ .describe("List of tasks to analyze"),
417
438
  }, async ({ tasks }) => {
418
439
  if (!config) {
419
440
  return {
420
441
  content: [
421
442
  {
422
- type: 'text',
443
+ type: "text",
423
444
  text: JSON.stringify({
424
445
  error: true,
425
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
446
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
426
447
  }, null, 2),
427
448
  },
428
449
  ],
@@ -433,7 +454,7 @@ async function createServer() {
433
454
  return {
434
455
  content: [
435
456
  {
436
- type: 'text',
457
+ type: "text",
437
458
  text: JSON.stringify({
438
459
  success: true,
439
460
  summary: result.summary,
@@ -457,10 +478,10 @@ async function createServer() {
457
478
  return {
458
479
  content: [
459
480
  {
460
- type: 'text',
481
+ type: "text",
461
482
  text: JSON.stringify({
462
483
  error: true,
463
- message: `タスク分析に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
484
+ message: `タスク分析に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
464
485
  }, null, 2),
465
486
  },
466
487
  ],
@@ -471,25 +492,43 @@ async function createServer() {
471
492
  * set_reminder - Set a reminder for a task
472
493
  * Requirement: 5.1-5.6
473
494
  */
474
- server.tool('set_reminder', 'Set a reminder for a task in Apple Reminders or Notion.', {
475
- taskTitle: z.string().describe('Title of the task'),
476
- dueDate: z.string().optional().describe('Due date for the reminder (ISO 8601 format)'),
495
+ server.tool("set_reminder", "Set a reminder for a task in Apple Reminders or Notion.", {
496
+ taskTitle: z.string().describe("Title of the task"),
497
+ dueDate: z
498
+ .string()
499
+ .optional()
500
+ .describe("Due date for the reminder (ISO 8601 format)"),
477
501
  reminderType: z
478
- .enum(['1_hour_before', '3_hours_before', '1_day_before', '3_days_before', '1_week_before'])
502
+ .enum([
503
+ "1_hour_before",
504
+ "3_hours_before",
505
+ "1_day_before",
506
+ "3_days_before",
507
+ "1_week_before",
508
+ ])
509
+ .optional()
510
+ .describe("Type of reminder"),
511
+ list: z
512
+ .string()
479
513
  .optional()
480
- .describe('Type of reminder'),
481
- list: z.string().optional().describe('Reminder list name (for Apple Reminders)'),
482
- priority: z.enum(['P0', 'P1', 'P2', 'P3']).optional().describe('Task priority'),
483
- notes: z.string().optional().describe('Additional notes for the reminder'),
514
+ .describe("Reminder list name (for Apple Reminders)"),
515
+ priority: z
516
+ .enum(["P0", "P1", "P2", "P3"])
517
+ .optional()
518
+ .describe("Task priority"),
519
+ notes: z
520
+ .string()
521
+ .optional()
522
+ .describe("Additional notes for the reminder"),
484
523
  }, async ({ taskTitle, dueDate, reminderType, list, priority, notes }) => {
485
524
  if (!config) {
486
525
  return {
487
526
  content: [
488
527
  {
489
- type: 'text',
528
+ type: "text",
490
529
  text: JSON.stringify({
491
530
  error: true,
492
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
531
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
493
532
  }, null, 2),
494
533
  },
495
534
  ],
@@ -513,16 +552,16 @@ async function createServer() {
513
552
  return {
514
553
  content: [
515
554
  {
516
- type: 'text',
555
+ type: "text",
517
556
  text: JSON.stringify({
518
557
  success: true,
519
- destination: 'notion_mcp',
520
- method: 'delegate',
558
+ destination: "notion_mcp",
559
+ method: "delegate",
521
560
  delegateToNotion: true,
522
561
  notionRequest: result.notionRequest,
523
562
  message: `Notionへの追加はClaude Codeが直接notion-create-pagesツールを使用してください。`,
524
563
  instruction: `notion-create-pagesツールを以下のパラメータで呼び出してください:
525
- - parent: { "type": "data_source_id", "data_source_id": "${result.notionRequest.databaseId.replace(/-/g, '')}" }
564
+ - parent: { "type": "data_source_id", "data_source_id": "${result.notionRequest.databaseId.replace(/-/g, "")}" }
526
565
  - pages: [{ "properties": ${JSON.stringify(result.notionRequest.properties)} }]`,
527
566
  }, null, 2),
528
567
  },
@@ -532,14 +571,14 @@ async function createServer() {
532
571
  return {
533
572
  content: [
534
573
  {
535
- type: 'text',
574
+ type: "text",
536
575
  text: JSON.stringify({
537
576
  success: true,
538
577
  destination: result.destination,
539
578
  method: result.method,
540
579
  reminderId: result.reminderId,
541
580
  reminderUrl: result.reminderUrl ?? result.pageUrl,
542
- message: result.destination === 'apple_reminders'
581
+ message: result.destination === "apple_reminders"
543
582
  ? `Apple Remindersにリマインダーを作成しました: ${taskTitle}`
544
583
  : `Notionにタスクを作成しました: ${taskTitle}`,
545
584
  }, null, 2),
@@ -550,14 +589,14 @@ async function createServer() {
550
589
  return {
551
590
  content: [
552
591
  {
553
- type: 'text',
592
+ type: "text",
554
593
  text: JSON.stringify({
555
594
  success: false,
556
595
  destination: result.destination,
557
596
  error: result.error,
558
597
  fallbackText: result.fallbackText,
559
598
  message: result.fallbackText
560
- ? '自動作成に失敗しました。以下のテキストを手動でコピーしてください。'
599
+ ? "自動作成に失敗しました。以下のテキストを手動でコピーしてください。"
561
600
  : `リマインダー作成に失敗しました: ${result.error}`,
562
601
  }, null, 2),
563
602
  },
@@ -568,10 +607,10 @@ async function createServer() {
568
607
  return {
569
608
  content: [
570
609
  {
571
- type: 'text',
610
+ type: "text",
572
611
  text: JSON.stringify({
573
612
  error: true,
574
- message: `リマインダー設定に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
613
+ message: `リマインダー設定に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
575
614
  }, null, 2),
576
615
  },
577
616
  ],
@@ -582,20 +621,29 @@ async function createServer() {
582
621
  * find_available_slots - Find available time slots in calendar
583
622
  * Requirement: 3.3-3.6, 6.1-6.6
584
623
  */
585
- server.tool('find_available_slots', 'Find available time slots in the calendar for scheduling tasks.', {
586
- durationMinutes: z.number().describe('Required duration in minutes'),
587
- startDate: z.string().optional().describe('Start date for search (ISO 8601 format)'),
588
- endDate: z.string().optional().describe('End date for search (ISO 8601 format)'),
589
- preferDeepWork: z.boolean().optional().describe('Prefer deep work time slots'),
624
+ server.tool("find_available_slots", "Find available time slots in the calendar for scheduling tasks.", {
625
+ durationMinutes: z.number().describe("Required duration in minutes"),
626
+ startDate: z
627
+ .string()
628
+ .optional()
629
+ .describe("Start date for search (ISO 8601 format)"),
630
+ endDate: z
631
+ .string()
632
+ .optional()
633
+ .describe("End date for search (ISO 8601 format)"),
634
+ preferDeepWork: z
635
+ .boolean()
636
+ .optional()
637
+ .describe("Prefer deep work time slots"),
590
638
  }, async ({ durationMinutes, startDate, endDate, preferDeepWork }) => {
591
639
  if (!config) {
592
640
  return {
593
641
  content: [
594
642
  {
595
- type: 'text',
643
+ type: "text",
596
644
  text: JSON.stringify({
597
645
  error: true,
598
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
646
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
599
647
  }, null, 2),
600
648
  },
601
649
  ],
@@ -610,16 +658,19 @@ async function createServer() {
610
658
  const isAvailable = await calendarService.isAvailable();
611
659
  if (!isAvailable) {
612
660
  // Return manual input prompt for unsupported platforms
613
- const manualPrompt = calendarService.generateManualInputPrompt(startDate ?? new Date().toISOString().split('T')[0], endDate ?? new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]);
661
+ const manualPrompt = calendarService.generateManualInputPrompt(startDate ?? new Date().toISOString().split("T")[0], endDate ??
662
+ new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
663
+ .toISOString()
664
+ .split("T")[0]);
614
665
  return {
615
666
  content: [
616
667
  {
617
- type: 'text',
668
+ type: "text",
618
669
  text: JSON.stringify({
619
670
  success: false,
620
671
  platform: platformInfo.platform,
621
672
  method: platformInfo.recommendedMethod,
622
- message: 'カレンダー統合がこのプラットフォームで利用できません。手動で予定を入力してください。',
673
+ message: "カレンダー統合がこのプラットフォームで利用できません。手動で予定を入力してください。",
623
674
  manualPrompt,
624
675
  }, null, 2),
625
676
  },
@@ -627,8 +678,11 @@ async function createServer() {
627
678
  };
628
679
  }
629
680
  // Fetch events from calendar
630
- const searchStart = startDate ?? new Date().toISOString().split('T')[0];
631
- const searchEnd = endDate ?? new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
681
+ const searchStart = startDate ?? new Date().toISOString().split("T")[0];
682
+ const searchEnd = endDate ??
683
+ new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
684
+ .toISOString()
685
+ .split("T")[0];
632
686
  const events = await calendarService.fetchEvents(searchStart, searchEnd);
633
687
  // Find available slots
634
688
  const workingHours = {
@@ -644,7 +698,7 @@ async function createServer() {
644
698
  const scoredSlots = slots.map((slot) => calendarService.calculateSuitability(slot, suitabilityConfig));
645
699
  // Filter for deep work preference if requested
646
700
  const filteredSlots = preferDeepWork
647
- ? scoredSlots.filter((s) => s.dayType === 'deep-work')
701
+ ? scoredSlots.filter((s) => s.dayType === "deep-work")
648
702
  : scoredSlots;
649
703
  // Sort by suitability (excellent > good > acceptable)
650
704
  const suitabilityOrder = { excellent: 0, good: 1, acceptable: 2 };
@@ -652,7 +706,7 @@ async function createServer() {
652
706
  return {
653
707
  content: [
654
708
  {
655
- type: 'text',
709
+ type: "text",
656
710
  text: JSON.stringify({
657
711
  success: true,
658
712
  platform: platformInfo.platform,
@@ -669,7 +723,295 @@ async function createServer() {
669
723
  })),
670
724
  message: filteredSlots.length > 0
671
725
  ? `${filteredSlots.length}件の空き時間が見つかりました。`
672
- : '指定した条件に合う空き時間が見つかりませんでした。',
726
+ : "指定した条件に合う空き時間が見つかりませんでした。",
727
+ }, null, 2),
728
+ },
729
+ ],
730
+ };
731
+ }
732
+ catch (error) {
733
+ return {
734
+ content: [
735
+ {
736
+ type: "text",
737
+ text: JSON.stringify({
738
+ error: true,
739
+ message: `カレンダー検索に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
740
+ }, null, 2),
741
+ },
742
+ ],
743
+ };
744
+ }
745
+ });
746
+ /**
747
+ * list_calendar_events - List calendar events for a specified period
748
+ * Requirement: 16.1-16.12
749
+ */
750
+ server.tool("list_calendar_events", "List calendar events for a specified period. Returns events with details including calendar name and location.", {
751
+ startDate: z
752
+ .string()
753
+ .describe("Start date in ISO 8601 format (e.g., 2025-01-15)"),
754
+ endDate: z
755
+ .string()
756
+ .describe("End date in ISO 8601 format (e.g., 2025-01-20)"),
757
+ calendarName: z
758
+ .string()
759
+ .optional()
760
+ .describe("Optional: filter events by calendar name"),
761
+ }, async ({ startDate, endDate, calendarName }) => {
762
+ if (!config) {
763
+ return {
764
+ content: [
765
+ {
766
+ type: "text",
767
+ text: JSON.stringify({
768
+ error: true,
769
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
770
+ }, null, 2),
771
+ },
772
+ ],
773
+ };
774
+ }
775
+ if (!calendarService) {
776
+ initializeServices(config);
777
+ }
778
+ try {
779
+ // Check platform availability
780
+ const platformInfo = await calendarService.detectPlatform();
781
+ const isAvailable = await calendarService.isAvailable();
782
+ if (!isAvailable) {
783
+ return {
784
+ content: [
785
+ {
786
+ type: "text",
787
+ text: JSON.stringify({
788
+ success: false,
789
+ platform: platformInfo.platform,
790
+ method: platformInfo.recommendedMethod,
791
+ message: "カレンダー統合がこのプラットフォームで利用できません。macOSで実行してください。",
792
+ }, null, 2),
793
+ },
794
+ ],
795
+ };
796
+ }
797
+ // List events
798
+ const result = await calendarService.listEvents({
799
+ startDate,
800
+ endDate,
801
+ calendarName,
802
+ });
803
+ return {
804
+ content: [
805
+ {
806
+ type: "text",
807
+ text: JSON.stringify({
808
+ success: true,
809
+ platform: platformInfo.platform,
810
+ method: platformInfo.recommendedMethod,
811
+ events: result.events.map((event) => ({
812
+ id: event.id,
813
+ title: event.title,
814
+ start: event.start,
815
+ end: event.end,
816
+ isAllDay: event.isAllDay,
817
+ calendar: event.calendar,
818
+ location: event.location,
819
+ })),
820
+ period: result.period,
821
+ totalEvents: result.totalEvents,
822
+ message: result.totalEvents > 0
823
+ ? `${result.totalEvents}件のイベントが見つかりました。`
824
+ : "指定した期間にイベントが見つかりませんでした。",
825
+ }, null, 2),
826
+ },
827
+ ],
828
+ };
829
+ }
830
+ catch (error) {
831
+ return {
832
+ content: [
833
+ {
834
+ type: "text",
835
+ text: JSON.stringify({
836
+ error: true,
837
+ message: `カレンダーイベントの取得に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
838
+ }, null, 2),
839
+ },
840
+ ],
841
+ };
842
+ }
843
+ });
844
+ /**
845
+ * respond_to_calendar_event - Respond to a single calendar event
846
+ * Requirement: 17.1, 17.2, 17.5-17.11
847
+ */
848
+ server.tool("respond_to_calendar_event", "Respond to a calendar event with accept, decline, or tentative. Use this to RSVP to meeting invitations.", {
849
+ eventId: z.string().describe("The ID of the calendar event to respond to"),
850
+ response: z
851
+ .enum(["accept", "decline", "tentative"])
852
+ .describe("Response type: accept (承諾), decline (辞退), or tentative (仮承諾)"),
853
+ comment: z
854
+ .string()
855
+ .optional()
856
+ .describe("Optional comment to include with the response (e.g., '年末年始休暇のため')"),
857
+ }, async ({ eventId, response, comment }) => {
858
+ if (!config) {
859
+ return {
860
+ content: [
861
+ {
862
+ type: "text",
863
+ text: JSON.stringify({
864
+ error: true,
865
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
866
+ }, null, 2),
867
+ },
868
+ ],
869
+ };
870
+ }
871
+ if (!calendarEventResponseService) {
872
+ initializeServices(config);
873
+ }
874
+ try {
875
+ // Check platform availability
876
+ const isAvailable = await calendarEventResponseService.isEventKitAvailable();
877
+ if (!isAvailable) {
878
+ return {
879
+ content: [
880
+ {
881
+ type: "text",
882
+ text: JSON.stringify({
883
+ success: false,
884
+ message: "カレンダーイベント返信機能はmacOSでのみ利用可能です。",
885
+ }, null, 2),
886
+ },
887
+ ],
888
+ };
889
+ }
890
+ // Respond to the event
891
+ const result = await calendarEventResponseService.respondToEvent({
892
+ eventId,
893
+ response,
894
+ comment,
895
+ });
896
+ if (result.success) {
897
+ return {
898
+ content: [
899
+ {
900
+ type: "text",
901
+ text: JSON.stringify({
902
+ success: true,
903
+ eventId: result.eventId,
904
+ eventTitle: result.eventTitle,
905
+ newStatus: result.newStatus,
906
+ method: result.method,
907
+ instanceOnly: result.instanceOnly,
908
+ message: result.message,
909
+ }, null, 2),
910
+ },
911
+ ],
912
+ };
913
+ }
914
+ // Handle skipped or failed response
915
+ return {
916
+ content: [
917
+ {
918
+ type: "text",
919
+ text: JSON.stringify({
920
+ success: false,
921
+ eventId: result.eventId,
922
+ eventTitle: result.eventTitle,
923
+ skipped: result.skipped,
924
+ reason: result.reason,
925
+ error: result.error,
926
+ message: result.skipped
927
+ ? `イベントをスキップしました: ${result.reason}`
928
+ : `イベント返信に失敗しました: ${result.error}`,
929
+ }, null, 2),
930
+ },
931
+ ],
932
+ };
933
+ }
934
+ catch (error) {
935
+ return {
936
+ content: [
937
+ {
938
+ type: "text",
939
+ text: JSON.stringify({
940
+ error: true,
941
+ message: `カレンダーイベント返信に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
942
+ }, null, 2),
943
+ },
944
+ ],
945
+ };
946
+ }
947
+ });
948
+ /**
949
+ * respond_to_calendar_events_batch - Respond to multiple calendar events
950
+ * Requirement: 17.3, 17.4, 17.12
951
+ */
952
+ server.tool("respond_to_calendar_events_batch", "Respond to multiple calendar events at once. Useful for declining all events during vacation or leave periods.", {
953
+ eventIds: z
954
+ .array(z.string())
955
+ .describe("Array of event IDs to respond to"),
956
+ response: z
957
+ .enum(["accept", "decline", "tentative"])
958
+ .describe("Response type: accept (承諾), decline (辞退), or tentative (仮承諾)"),
959
+ comment: z
960
+ .string()
961
+ .optional()
962
+ .describe("Optional comment to include with all responses (e.g., '年末年始休暇のため')"),
963
+ }, async ({ eventIds, response, comment }) => {
964
+ if (!config) {
965
+ return {
966
+ content: [
967
+ {
968
+ type: "text",
969
+ text: JSON.stringify({
970
+ error: true,
971
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
972
+ }, null, 2),
973
+ },
974
+ ],
975
+ };
976
+ }
977
+ if (!calendarEventResponseService) {
978
+ initializeServices(config);
979
+ }
980
+ try {
981
+ // Check platform availability
982
+ const isAvailable = await calendarEventResponseService.isEventKitAvailable();
983
+ if (!isAvailable) {
984
+ return {
985
+ content: [
986
+ {
987
+ type: "text",
988
+ text: JSON.stringify({
989
+ success: false,
990
+ message: "カレンダーイベント返信機能はmacOSでのみ利用可能です。",
991
+ }, null, 2),
992
+ },
993
+ ],
994
+ };
995
+ }
996
+ // Respond to all events in batch
997
+ const result = await calendarEventResponseService.respondToEventsBatch({
998
+ eventIds,
999
+ response,
1000
+ comment,
1001
+ });
1002
+ return {
1003
+ content: [
1004
+ {
1005
+ type: "text",
1006
+ text: JSON.stringify({
1007
+ success: result.success,
1008
+ summary: result.summary,
1009
+ details: {
1010
+ succeeded: result.details.succeeded,
1011
+ skipped: result.details.skipped,
1012
+ failed: result.details.failed,
1013
+ },
1014
+ message: result.message,
673
1015
  }, null, 2),
674
1016
  },
675
1017
  ],
@@ -679,10 +1021,298 @@ async function createServer() {
679
1021
  return {
680
1022
  content: [
681
1023
  {
682
- type: 'text',
1024
+ type: "text",
683
1025
  text: JSON.stringify({
684
1026
  error: true,
685
- message: `カレンダー検索に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1027
+ message: `カレンダーイベント一括返信に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1028
+ }, null, 2),
1029
+ },
1030
+ ],
1031
+ };
1032
+ }
1033
+ });
1034
+ /**
1035
+ * create_calendar_event - Create a new calendar event
1036
+ * Requirement: 18.1-18.11
1037
+ */
1038
+ server.tool("create_calendar_event", "Create a new calendar event with optional location, notes, and alarms.", {
1039
+ title: z.string().describe("Event title"),
1040
+ startDate: z
1041
+ .string()
1042
+ .describe("Start date/time in ISO 8601 format (e.g., 2025-01-15T10:00:00+09:00)"),
1043
+ endDate: z
1044
+ .string()
1045
+ .describe("End date/time in ISO 8601 format (e.g., 2025-01-15T11:00:00+09:00)"),
1046
+ location: z.string().optional().describe("Event location"),
1047
+ notes: z.string().optional().describe("Event notes/description"),
1048
+ calendarName: z
1049
+ .string()
1050
+ .optional()
1051
+ .describe("Calendar name to create the event in (uses default if not specified)"),
1052
+ alarms: z
1053
+ .array(z.string())
1054
+ .optional()
1055
+ .describe("Optional: Override default alarms with custom settings (e.g., ['-15m', '-1h']). If omitted, calendar's default alarm settings apply."),
1056
+ }, async ({ title, startDate, endDate, location, notes, calendarName, alarms }) => {
1057
+ if (!config) {
1058
+ return {
1059
+ content: [
1060
+ {
1061
+ type: "text",
1062
+ text: JSON.stringify({
1063
+ error: true,
1064
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
1065
+ }, null, 2),
1066
+ },
1067
+ ],
1068
+ };
1069
+ }
1070
+ if (!calendarEventCreatorService) {
1071
+ initializeServices(config);
1072
+ }
1073
+ try {
1074
+ // Check platform availability
1075
+ const isAvailable = await calendarEventCreatorService.isEventKitAvailable();
1076
+ if (!isAvailable) {
1077
+ return {
1078
+ content: [
1079
+ {
1080
+ type: "text",
1081
+ text: JSON.stringify({
1082
+ success: false,
1083
+ message: "カレンダーイベント作成機能はmacOSでのみ利用可能です。",
1084
+ }, null, 2),
1085
+ },
1086
+ ],
1087
+ };
1088
+ }
1089
+ // Create the event
1090
+ const result = await calendarEventCreatorService.createEvent({
1091
+ title,
1092
+ startDate,
1093
+ endDate,
1094
+ location,
1095
+ notes,
1096
+ calendarName,
1097
+ alarms,
1098
+ });
1099
+ if (result.success) {
1100
+ return {
1101
+ content: [
1102
+ {
1103
+ type: "text",
1104
+ text: JSON.stringify({
1105
+ success: true,
1106
+ eventId: result.eventId,
1107
+ title: result.title,
1108
+ startDate: result.startDate,
1109
+ endDate: result.endDate,
1110
+ calendarName: result.calendarName,
1111
+ isAllDay: result.isAllDay,
1112
+ message: result.message,
1113
+ }, null, 2),
1114
+ },
1115
+ ],
1116
+ };
1117
+ }
1118
+ // Handle creation failure
1119
+ return {
1120
+ content: [
1121
+ {
1122
+ type: "text",
1123
+ text: JSON.stringify({
1124
+ success: false,
1125
+ error: result.error,
1126
+ message: result.message,
1127
+ }, null, 2),
1128
+ },
1129
+ ],
1130
+ };
1131
+ }
1132
+ catch (error) {
1133
+ return {
1134
+ content: [
1135
+ {
1136
+ type: "text",
1137
+ text: JSON.stringify({
1138
+ error: true,
1139
+ message: `カレンダーイベント作成に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1140
+ }, null, 2),
1141
+ },
1142
+ ],
1143
+ };
1144
+ }
1145
+ });
1146
+ /**
1147
+ * delete_calendar_event - Delete a calendar event
1148
+ * Requirement: 19.1-19.9
1149
+ */
1150
+ server.tool("delete_calendar_event", "Delete a calendar event by its ID.", {
1151
+ eventId: z.string().describe("Event ID (UUID or full ID from list_calendar_events)"),
1152
+ calendarName: z
1153
+ .string()
1154
+ .optional()
1155
+ .describe("Calendar name (searches all calendars if not specified)"),
1156
+ }, async ({ eventId, calendarName }) => {
1157
+ if (!config) {
1158
+ return {
1159
+ content: [
1160
+ {
1161
+ type: "text",
1162
+ text: JSON.stringify({
1163
+ error: true,
1164
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
1165
+ }, null, 2),
1166
+ },
1167
+ ],
1168
+ };
1169
+ }
1170
+ if (!calendarEventDeleterService) {
1171
+ initializeServices(config);
1172
+ }
1173
+ try {
1174
+ // Check platform availability
1175
+ const isAvailable = await calendarEventDeleterService.isEventKitAvailable();
1176
+ if (!isAvailable) {
1177
+ return {
1178
+ content: [
1179
+ {
1180
+ type: "text",
1181
+ text: JSON.stringify({
1182
+ error: true,
1183
+ message: "カレンダー統合がこのプラットフォームで利用できません。macOSで実行してください。",
1184
+ }, null, 2),
1185
+ },
1186
+ ],
1187
+ };
1188
+ }
1189
+ // Delete the event
1190
+ const result = await calendarEventDeleterService.deleteEvent({
1191
+ eventId,
1192
+ calendarName,
1193
+ });
1194
+ if (result.success) {
1195
+ return {
1196
+ content: [
1197
+ {
1198
+ type: "text",
1199
+ text: JSON.stringify({
1200
+ success: true,
1201
+ eventId: result.eventId,
1202
+ title: result.title,
1203
+ calendarName: result.calendarName,
1204
+ message: result.message,
1205
+ }, null, 2),
1206
+ },
1207
+ ],
1208
+ };
1209
+ }
1210
+ // Handle deletion failure
1211
+ return {
1212
+ content: [
1213
+ {
1214
+ type: "text",
1215
+ text: JSON.stringify({
1216
+ success: false,
1217
+ error: result.error,
1218
+ message: result.message,
1219
+ }, null, 2),
1220
+ },
1221
+ ],
1222
+ };
1223
+ }
1224
+ catch (error) {
1225
+ return {
1226
+ content: [
1227
+ {
1228
+ type: "text",
1229
+ text: JSON.stringify({
1230
+ error: true,
1231
+ message: `カレンダーイベント削除に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1232
+ }, null, 2),
1233
+ },
1234
+ ],
1235
+ };
1236
+ }
1237
+ });
1238
+ /**
1239
+ * delete_calendar_events_batch - Delete multiple calendar events
1240
+ * Requirement: 19.10-19.11
1241
+ */
1242
+ server.tool("delete_calendar_events_batch", "Delete multiple calendar events by their IDs.", {
1243
+ eventIds: z.array(z.string()).describe("Array of event IDs to delete"),
1244
+ calendarName: z
1245
+ .string()
1246
+ .optional()
1247
+ .describe("Calendar name (searches all calendars if not specified)"),
1248
+ }, async ({ eventIds, calendarName }) => {
1249
+ if (!config) {
1250
+ return {
1251
+ content: [
1252
+ {
1253
+ type: "text",
1254
+ text: JSON.stringify({
1255
+ error: true,
1256
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
1257
+ }, null, 2),
1258
+ },
1259
+ ],
1260
+ };
1261
+ }
1262
+ if (!calendarEventDeleterService) {
1263
+ initializeServices(config);
1264
+ }
1265
+ try {
1266
+ // Check platform availability
1267
+ const isAvailable = await calendarEventDeleterService.isEventKitAvailable();
1268
+ if (!isAvailable) {
1269
+ return {
1270
+ content: [
1271
+ {
1272
+ type: "text",
1273
+ text: JSON.stringify({
1274
+ error: true,
1275
+ message: "カレンダー統合がこのプラットフォームで利用できません。macOSで実行してください。",
1276
+ }, null, 2),
1277
+ },
1278
+ ],
1279
+ };
1280
+ }
1281
+ // Delete events in batch
1282
+ const result = await calendarEventDeleterService.deleteEventsBatch({
1283
+ eventIds,
1284
+ calendarName,
1285
+ });
1286
+ return {
1287
+ content: [
1288
+ {
1289
+ type: "text",
1290
+ text: JSON.stringify({
1291
+ success: result.success,
1292
+ totalCount: result.totalCount,
1293
+ successCount: result.successCount,
1294
+ failedCount: result.failedCount,
1295
+ results: result.results.map((r) => ({
1296
+ eventId: r.eventId,
1297
+ success: r.success,
1298
+ title: r.title,
1299
+ calendarName: r.calendarName,
1300
+ error: r.error,
1301
+ })),
1302
+ message: result.message,
1303
+ }, null, 2),
1304
+ },
1305
+ ],
1306
+ };
1307
+ }
1308
+ catch (error) {
1309
+ return {
1310
+ content: [
1311
+ {
1312
+ type: "text",
1313
+ text: JSON.stringify({
1314
+ error: true,
1315
+ message: `カレンダーイベント一括削除に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
686
1316
  }, null, 2),
687
1317
  },
688
1318
  ],
@@ -693,22 +1323,31 @@ async function createServer() {
693
1323
  * sync_to_notion - Sync a task to Notion
694
1324
  * Requirement: 8.1-8.5
695
1325
  */
696
- server.tool('sync_to_notion', 'Sync a task to Notion database for long-term tracking.', {
697
- taskTitle: z.string().describe('Title of the task'),
698
- description: z.string().optional().describe('Task description'),
699
- priority: z.enum(['P0', 'P1', 'P2', 'P3']).optional().describe('Task priority'),
700
- dueDate: z.string().optional().describe('Due date (ISO 8601 format)'),
701
- stakeholders: z.array(z.string()).optional().describe('List of stakeholders'),
702
- estimatedMinutes: z.number().optional().describe('Estimated duration in minutes'),
703
- }, async ({ taskTitle, description, priority, dueDate, stakeholders, estimatedMinutes }) => {
1326
+ server.tool("sync_to_notion", "Sync a task to Notion database for long-term tracking.", {
1327
+ taskTitle: z.string().describe("Title of the task"),
1328
+ description: z.string().optional().describe("Task description"),
1329
+ priority: z
1330
+ .enum(["P0", "P1", "P2", "P3"])
1331
+ .optional()
1332
+ .describe("Task priority"),
1333
+ dueDate: z.string().optional().describe("Due date (ISO 8601 format)"),
1334
+ stakeholders: z
1335
+ .array(z.string())
1336
+ .optional()
1337
+ .describe("List of stakeholders"),
1338
+ estimatedMinutes: z
1339
+ .number()
1340
+ .optional()
1341
+ .describe("Estimated duration in minutes"),
1342
+ }, async ({ taskTitle, description, priority, dueDate, stakeholders, estimatedMinutes, }) => {
704
1343
  if (!config) {
705
1344
  return {
706
1345
  content: [
707
1346
  {
708
- type: 'text',
1347
+ type: "text",
709
1348
  text: JSON.stringify({
710
1349
  error: true,
711
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
1350
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
712
1351
  }, null, 2),
713
1352
  },
714
1353
  ],
@@ -718,10 +1357,10 @@ async function createServer() {
718
1357
  return {
719
1358
  content: [
720
1359
  {
721
- type: 'text',
1360
+ type: "text",
722
1361
  text: JSON.stringify({
723
1362
  error: true,
724
- message: 'Notion統合が有効になっていません。update_configでNotion設定を更新してください。',
1363
+ message: "Notion統合が有効になっていません。update_configでNotion設定を更新してください。",
725
1364
  }, null, 2),
726
1365
  },
727
1366
  ],
@@ -755,15 +1394,15 @@ async function createServer() {
755
1394
  return {
756
1395
  content: [
757
1396
  {
758
- type: 'text',
1397
+ type: "text",
759
1398
  text: JSON.stringify({
760
1399
  success: false,
761
- method: 'fallback',
762
- message: 'Notion MCP統合が利用できません。以下のテンプレートを手動でNotionにコピーしてください。',
1400
+ method: "fallback",
1401
+ message: "Notion MCP統合が利用できません。以下のテンプレートを手動でNotionにコピーしてください。",
763
1402
  fallbackText,
764
1403
  task: {
765
1404
  taskTitle,
766
- priority: priority ?? 'P3',
1405
+ priority: priority ?? "P3",
767
1406
  dueDate,
768
1407
  stakeholders: stakeholders ?? [],
769
1408
  estimatedMinutes,
@@ -783,10 +1422,10 @@ async function createServer() {
783
1422
  return {
784
1423
  content: [
785
1424
  {
786
- type: 'text',
1425
+ type: "text",
787
1426
  text: JSON.stringify({
788
1427
  success: true,
789
- method: 'mcp',
1428
+ method: "mcp",
790
1429
  pageId: result.pageId,
791
1430
  pageUrl: result.pageUrl,
792
1431
  message: `Notionにタスクを同期しました: ${taskTitle}`,
@@ -807,12 +1446,12 @@ async function createServer() {
807
1446
  return {
808
1447
  content: [
809
1448
  {
810
- type: 'text',
1449
+ type: "text",
811
1450
  text: JSON.stringify({
812
1451
  success: false,
813
- method: 'fallback',
1452
+ method: "fallback",
814
1453
  error: result.error,
815
- message: 'Notion MCP呼び出しに失敗しました。以下のテンプレートを手動でコピーしてください。',
1454
+ message: "Notion MCP呼び出しに失敗しました。以下のテンプレートを手動でコピーしてください。",
816
1455
  fallbackText,
817
1456
  }, null, 2),
818
1457
  },
@@ -823,10 +1462,10 @@ async function createServer() {
823
1462
  return {
824
1463
  content: [
825
1464
  {
826
- type: 'text',
1465
+ type: "text",
827
1466
  text: JSON.stringify({
828
1467
  error: true,
829
- message: `Notion同期に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1468
+ message: `Notion同期に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
830
1469
  }, null, 2),
831
1470
  },
832
1471
  ],
@@ -837,20 +1476,27 @@ async function createServer() {
837
1476
  * update_config - Update configuration
838
1477
  * Requirement: 10.1-10.6
839
1478
  */
840
- server.tool('update_config', 'Update sage configuration settings.', {
1479
+ server.tool("update_config", "Update sage configuration settings.", {
841
1480
  section: z
842
- .enum(['user', 'calendar', 'priorityRules', 'integrations', 'team', 'preferences'])
843
- .describe('Configuration section to update'),
844
- updates: z.record(z.unknown()).describe('Key-value pairs to update'),
1481
+ .enum([
1482
+ "user",
1483
+ "calendar",
1484
+ "priorityRules",
1485
+ "integrations",
1486
+ "team",
1487
+ "preferences",
1488
+ ])
1489
+ .describe("Configuration section to update"),
1490
+ updates: z.record(z.unknown()).describe("Key-value pairs to update"),
845
1491
  }, async ({ section, updates }) => {
846
1492
  if (!config) {
847
1493
  return {
848
1494
  content: [
849
1495
  {
850
- type: 'text',
1496
+ type: "text",
851
1497
  text: JSON.stringify({
852
1498
  error: true,
853
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
1499
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
854
1500
  }, null, 2),
855
1501
  },
856
1502
  ],
@@ -863,7 +1509,7 @@ async function createServer() {
863
1509
  return {
864
1510
  content: [
865
1511
  {
866
- type: 'text',
1512
+ type: "text",
867
1513
  text: JSON.stringify({
868
1514
  error: true,
869
1515
  message: `設定の検証に失敗しました: ${validationResult.error}`,
@@ -879,13 +1525,13 @@ async function createServer() {
879
1525
  await ConfigLoader.save(updatedConfig);
880
1526
  config = updatedConfig;
881
1527
  // Re-initialize services if integrations changed
882
- if (section === 'integrations') {
1528
+ if (section === "integrations") {
883
1529
  initializeServices(config);
884
1530
  }
885
1531
  return {
886
1532
  content: [
887
1533
  {
888
- type: 'text',
1534
+ type: "text",
889
1535
  text: JSON.stringify({
890
1536
  success: true,
891
1537
  section,
@@ -900,10 +1546,10 @@ async function createServer() {
900
1546
  return {
901
1547
  content: [
902
1548
  {
903
- type: 'text',
1549
+ type: "text",
904
1550
  text: JSON.stringify({
905
1551
  error: true,
906
- message: `設定の更新に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1552
+ message: `設定の更新に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
907
1553
  }, null, 2),
908
1554
  },
909
1555
  ],
@@ -917,30 +1563,30 @@ async function createServer() {
917
1563
  * list_todos - List all TODO items with optional filtering
918
1564
  * Requirement: 12.1, 12.2, 12.3, 12.4, 12.7, 12.8
919
1565
  */
920
- server.tool('list_todos', 'List TODO items from Apple Reminders and Notion with optional filtering.', {
1566
+ server.tool("list_todos", "List TODO items from Apple Reminders and Notion with optional filtering.", {
921
1567
  priority: z
922
- .array(z.enum(['P0', 'P1', 'P2', 'P3']))
1568
+ .array(z.enum(["P0", "P1", "P2", "P3"]))
923
1569
  .optional()
924
- .describe('Filter by priority levels'),
1570
+ .describe("Filter by priority levels"),
925
1571
  status: z
926
- .array(z.enum(['not_started', 'in_progress', 'completed', 'cancelled']))
1572
+ .array(z.enum(["not_started", "in_progress", "completed", "cancelled"]))
927
1573
  .optional()
928
- .describe('Filter by status'),
1574
+ .describe("Filter by status"),
929
1575
  source: z
930
- .array(z.enum(['apple_reminders', 'notion', 'manual']))
1576
+ .array(z.enum(["apple_reminders", "notion", "manual"]))
931
1577
  .optional()
932
- .describe('Filter by source'),
933
- todayOnly: z.boolean().optional().describe('Show only tasks due today'),
934
- tags: z.array(z.string()).optional().describe('Filter by tags'),
1578
+ .describe("Filter by source"),
1579
+ todayOnly: z.boolean().optional().describe("Show only tasks due today"),
1580
+ tags: z.array(z.string()).optional().describe("Filter by tags"),
935
1581
  }, async ({ priority, status, source, todayOnly, tags }) => {
936
1582
  if (!config) {
937
1583
  return {
938
1584
  content: [
939
1585
  {
940
- type: 'text',
1586
+ type: "text",
941
1587
  text: JSON.stringify({
942
1588
  error: true,
943
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
1589
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
944
1590
  }, null, 2),
945
1591
  },
946
1592
  ],
@@ -977,14 +1623,14 @@ async function createServer() {
977
1623
  return {
978
1624
  content: [
979
1625
  {
980
- type: 'text',
1626
+ type: "text",
981
1627
  text: JSON.stringify({
982
1628
  success: true,
983
1629
  totalCount: todos.length,
984
1630
  todos: formattedTodos,
985
1631
  message: todos.length > 0
986
1632
  ? `${todos.length}件のタスクが見つかりました。`
987
- : 'タスクが見つかりませんでした。',
1633
+ : "タスクが見つかりませんでした。",
988
1634
  filters: {
989
1635
  priority,
990
1636
  status,
@@ -1001,10 +1647,10 @@ async function createServer() {
1001
1647
  return {
1002
1648
  content: [
1003
1649
  {
1004
- type: 'text',
1650
+ type: "text",
1005
1651
  text: JSON.stringify({
1006
1652
  error: true,
1007
- message: `TODOリストの取得に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1653
+ message: `TODOリストの取得に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1008
1654
  }, null, 2),
1009
1655
  },
1010
1656
  ],
@@ -1015,27 +1661,27 @@ async function createServer() {
1015
1661
  * update_task_status - Update the status of a task
1016
1662
  * Requirement: 12.5, 12.6
1017
1663
  */
1018
- server.tool('update_task_status', 'Update the status of a task in Apple Reminders or Notion.', {
1019
- taskId: z.string().describe('ID of the task to update'),
1664
+ server.tool("update_task_status", "Update the status of a task in Apple Reminders or Notion.", {
1665
+ taskId: z.string().describe("ID of the task to update"),
1020
1666
  status: z
1021
- .enum(['not_started', 'in_progress', 'completed', 'cancelled'])
1022
- .describe('New status for the task'),
1667
+ .enum(["not_started", "in_progress", "completed", "cancelled"])
1668
+ .describe("New status for the task"),
1023
1669
  source: z
1024
- .enum(['apple_reminders', 'notion', 'manual'])
1025
- .describe('Source of the task'),
1670
+ .enum(["apple_reminders", "notion", "manual"])
1671
+ .describe("Source of the task"),
1026
1672
  syncAcrossSources: z
1027
1673
  .boolean()
1028
1674
  .optional()
1029
- .describe('Whether to sync the status across all sources'),
1675
+ .describe("Whether to sync the status across all sources"),
1030
1676
  }, async ({ taskId, status, source, syncAcrossSources }) => {
1031
1677
  if (!config) {
1032
1678
  return {
1033
1679
  content: [
1034
1680
  {
1035
- type: 'text',
1681
+ type: "text",
1036
1682
  text: JSON.stringify({
1037
1683
  error: true,
1038
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
1684
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
1039
1685
  }, null, 2),
1040
1686
  },
1041
1687
  ],
@@ -1051,7 +1697,7 @@ async function createServer() {
1051
1697
  return {
1052
1698
  content: [
1053
1699
  {
1054
- type: 'text',
1700
+ type: "text",
1055
1701
  text: JSON.stringify({
1056
1702
  success: false,
1057
1703
  taskId,
@@ -1070,7 +1716,7 @@ async function createServer() {
1070
1716
  return {
1071
1717
  content: [
1072
1718
  {
1073
- type: 'text',
1719
+ type: "text",
1074
1720
  text: JSON.stringify({
1075
1721
  success: true,
1076
1722
  taskId,
@@ -1088,10 +1734,10 @@ async function createServer() {
1088
1734
  return {
1089
1735
  content: [
1090
1736
  {
1091
- type: 'text',
1737
+ type: "text",
1092
1738
  text: JSON.stringify({
1093
1739
  error: true,
1094
- message: `タスクステータスの更新に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1740
+ message: `タスクステータスの更新に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1095
1741
  }, null, 2),
1096
1742
  },
1097
1743
  ],
@@ -1102,15 +1748,15 @@ async function createServer() {
1102
1748
  * sync_tasks - Sync tasks across all sources
1103
1749
  * Requirement: 12.6
1104
1750
  */
1105
- server.tool('sync_tasks', 'Synchronize tasks between Apple Reminders and Notion, detecting and resolving conflicts.', {}, async () => {
1751
+ server.tool("sync_tasks", "Synchronize tasks between Apple Reminders and Notion, detecting and resolving conflicts.", {}, async () => {
1106
1752
  if (!config) {
1107
1753
  return {
1108
1754
  content: [
1109
1755
  {
1110
- type: 'text',
1756
+ type: "text",
1111
1757
  text: JSON.stringify({
1112
1758
  error: true,
1113
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
1759
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
1114
1760
  }, null, 2),
1115
1761
  },
1116
1762
  ],
@@ -1124,7 +1770,7 @@ async function createServer() {
1124
1770
  return {
1125
1771
  content: [
1126
1772
  {
1127
- type: 'text',
1773
+ type: "text",
1128
1774
  text: JSON.stringify({
1129
1775
  success: true,
1130
1776
  totalTasks: result.totalTasks,
@@ -1144,10 +1790,10 @@ async function createServer() {
1144
1790
  return {
1145
1791
  content: [
1146
1792
  {
1147
- type: 'text',
1793
+ type: "text",
1148
1794
  text: JSON.stringify({
1149
1795
  error: true,
1150
- message: `タスク同期に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1796
+ message: `タスク同期に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1151
1797
  }, null, 2),
1152
1798
  },
1153
1799
  ],
@@ -1158,20 +1804,20 @@ async function createServer() {
1158
1804
  * detect_duplicates - Detect duplicate tasks across sources
1159
1805
  * Requirement: 12.5
1160
1806
  */
1161
- server.tool('detect_duplicates', 'Detect duplicate tasks between Apple Reminders and Notion.', {
1807
+ server.tool("detect_duplicates", "Detect duplicate tasks between Apple Reminders and Notion.", {
1162
1808
  autoMerge: z
1163
1809
  .boolean()
1164
1810
  .optional()
1165
- .describe('Whether to automatically merge high-confidence duplicates'),
1811
+ .describe("Whether to automatically merge high-confidence duplicates"),
1166
1812
  }, async ({ autoMerge }) => {
1167
1813
  if (!config) {
1168
1814
  return {
1169
1815
  content: [
1170
1816
  {
1171
- type: 'text',
1817
+ type: "text",
1172
1818
  text: JSON.stringify({
1173
1819
  error: true,
1174
- message: 'sageが設定されていません。check_setup_statusを実行してください。',
1820
+ message: "sageが設定されていません。check_setup_statusを実行してください。",
1175
1821
  }, null, 2),
1176
1822
  },
1177
1823
  ],
@@ -1203,7 +1849,7 @@ async function createServer() {
1203
1849
  // Auto-merge high-confidence duplicates if requested
1204
1850
  let mergeResults;
1205
1851
  if (autoMerge) {
1206
- const highConfidenceDuplicates = duplicates.filter((d) => d.confidence === 'high');
1852
+ const highConfidenceDuplicates = duplicates.filter((d) => d.confidence === "high");
1207
1853
  if (highConfidenceDuplicates.length > 0) {
1208
1854
  mergeResults = await taskSynchronizer.mergeDuplicates(highConfidenceDuplicates);
1209
1855
  }
@@ -1211,7 +1857,7 @@ async function createServer() {
1211
1857
  return {
1212
1858
  content: [
1213
1859
  {
1214
- type: 'text',
1860
+ type: "text",
1215
1861
  text: JSON.stringify({
1216
1862
  success: true,
1217
1863
  duplicatesFound: duplicates.length,
@@ -1219,7 +1865,7 @@ async function createServer() {
1219
1865
  mergeResults: autoMerge ? mergeResults : undefined,
1220
1866
  message: duplicates.length > 0
1221
1867
  ? `${duplicates.length}件の重複タスクが検出されました。`
1222
- : '重複タスクは見つかりませんでした。',
1868
+ : "重複タスクは見つかりませんでした。",
1223
1869
  }, null, 2),
1224
1870
  },
1225
1871
  ],
@@ -1229,10 +1875,10 @@ async function createServer() {
1229
1875
  return {
1230
1876
  content: [
1231
1877
  {
1232
- type: 'text',
1878
+ type: "text",
1233
1879
  text: JSON.stringify({
1234
1880
  error: true,
1235
- message: `重複検出に失敗しました: ${error instanceof Error ? error.message : 'Unknown error'}`,
1881
+ message: `重複検出に失敗しました: ${error instanceof Error ? error.message : "Unknown error"}`,
1236
1882
  }, null, 2),
1237
1883
  },
1238
1884
  ],
@@ -1245,13 +1891,43 @@ async function createServer() {
1245
1891
  * Main entry point
1246
1892
  */
1247
1893
  async function main() {
1894
+ // Import CLI modules
1895
+ const { parseArgs } = await import("./cli/parser.js");
1896
+ const { startServer } = await import("./cli/main-entry.js");
1897
+ // Parse CLI arguments
1898
+ const options = parseArgs(process.argv.slice(2));
1899
+ // Handle help and version
1900
+ if (options.help || options.version) {
1901
+ const result = await startServer(options);
1902
+ console.log(result.message);
1903
+ process.exit(0);
1904
+ }
1905
+ // Start in HTTP mode if --remote flag is set
1906
+ if (options.remote) {
1907
+ const result = await startServer(options);
1908
+ if (!result.success) {
1909
+ console.error(`Failed to start HTTP server: ${result.error}`);
1910
+ process.exit(1);
1911
+ }
1912
+ console.error(`${SERVER_NAME} v${VERSION} started in HTTP mode on ${result.host}:${result.port}`);
1913
+ // Keep the process running
1914
+ process.on("SIGINT", async () => {
1915
+ console.error("\nShutting down...");
1916
+ if (result.stop) {
1917
+ await result.stop();
1918
+ }
1919
+ process.exit(0);
1920
+ });
1921
+ return;
1922
+ }
1923
+ // Start in Stdio mode (default for MCP)
1248
1924
  const server = await createServer();
1249
1925
  const transport = new StdioServerTransport();
1250
1926
  await server.connect(transport);
1251
- console.error(`${SERVER_NAME} v${SERVER_VERSION} started`);
1927
+ console.error(`${SERVER_NAME} v${VERSION} started in Stdio mode`);
1252
1928
  }
1253
1929
  main().catch((error) => {
1254
- console.error('Failed to start sage server:', error);
1930
+ console.error("Failed to start sage server:", error);
1255
1931
  process.exit(1);
1256
1932
  });
1257
1933
  //# sourceMappingURL=index.js.map