Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ See `docs/dev/mcp-server-architecture.md` for full architecture details.
| `MCP_AUTH_SECRET` | If auth | `openssl rand -hex 32` |
| `MCP_AUTH_ISSUER` | If auth | public HTTPS URL of this server |
| `MCP_AUTH_STATE_DIR` | No | Directory for persisted OAuth state (default `/app/state`) |
| `MCP_LOCALE` | No | BCP 47 locale tag for `localTime` in `get_local_time` (e.g. `sv-SE`); defaults to system locale |
| `LOG_LEVEL` | No | `trace`/`debug`/`info`/`warn`/`error`/`fatal` |

## Tests
Expand Down
5 changes: 5 additions & 0 deletions mcp-server/src/auth/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ function loadJson<T>(filePath: string): T | null {
} catch (err: unknown) {
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
logger.warn({ file: filePath, err }, '[state] Failed to load state file — starting fresh');
try {
unlinkSync(filePath);
} catch {
/* ignore */
}
}
return null;
}
Expand Down
5 changes: 5 additions & 0 deletions mcp-server/src/tools/apps/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ function icalNow(): string {
function toICalDateTime(dateStr: string): string {
// Already in iCal format
if (/^\d{8}(T\d{6}Z?)?$/.test(dateStr)) {
if (dateStr.length === 8) {
// Parse as local-midnight date, then convert to UTC for CalDAV time-range
const d = new Date(+dateStr.slice(0, 4), +dateStr.slice(4, 6) - 1, +dateStr.slice(6, 8));
return d.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
}
return dateStr;
}
// ISO format -> iCal UTC
Expand Down
42 changes: 41 additions & 1 deletion mcp-server/src/tools/system/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,47 @@ export const setupChecksTool = {
},
};

/**
* Get the current local time and timezone of the MCP server
*/
export const getLocalTimeTool = {
name: 'get_local_time',
description:
'Get the current local time and timezone of the MCP server. ' +
'Call this to establish a time reference before creating or listing calendar events, ' +
'or to resolve scheduling ambiguities with the user.',
inputSchema: z.object({}),
handler: async () => {
const now = new Date();
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
const offsetMin = now.getTimezoneOffset(); // positive = behind UTC, negative = ahead
const sign = offsetMin <= 0 ? '+' : '-';
const abs = Math.abs(offsetMin);
const h = String(Math.floor(abs / 60)).padStart(2, '0');
const m = String(abs % 60).padStart(2, '0');
const utcOffset = `${sign}${h}:${m}`;

return {
content: [
{
type: 'text' as const,
text: JSON.stringify(
{
localTime: now.toLocaleString(process.env.MCP_LOCALE, { timeZone: tz }),
utcTime: now.toISOString(),
timezone: tz, // e.g. "Europe/Berlin"
utcOffset, // e.g. "+01:00"
},
null,
2
),
},
],
};
},
};

/**
* Export all System Status tools
*/
export const statusTools = [systemStatusTool, setupChecksTool];
export const statusTools = [systemStatusTool, setupChecksTool, getLocalTimeTool];
Loading