@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
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Secret Authentication for Remote MCP Server
3
+ * Requirements: 15.4, 15.5, 15.6
4
+ *
5
+ * Provides JWT-based authentication using a shared secret.
6
+ */
7
+ import { createHmac, randomBytes } from 'crypto';
8
+ /**
9
+ * Authentication error
10
+ */
11
+ export class AuthError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = 'AuthError';
15
+ }
16
+ }
17
+ /**
18
+ * Minimum secret length
19
+ */
20
+ const MIN_SECRET_LENGTH = 32;
21
+ /**
22
+ * Parse expiresIn string to seconds
23
+ */
24
+ function parseExpiresIn(expiresIn) {
25
+ const match = expiresIn.match(/^(\d+)([smhdw])$/);
26
+ if (!match) {
27
+ return 86400; // Default to 24h
28
+ }
29
+ const value = parseInt(match[1], 10);
30
+ const unit = match[2];
31
+ switch (unit) {
32
+ case 's':
33
+ return value;
34
+ case 'm':
35
+ return value * 60;
36
+ case 'h':
37
+ return value * 3600;
38
+ case 'd':
39
+ return value * 86400;
40
+ case 'w':
41
+ return value * 604800;
42
+ default:
43
+ return 86400;
44
+ }
45
+ }
46
+ /**
47
+ * Base64url encode
48
+ */
49
+ function base64urlEncode(data) {
50
+ const buffer = typeof data === 'string' ? Buffer.from(data) : data;
51
+ return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
52
+ }
53
+ /**
54
+ * Base64url decode
55
+ */
56
+ function base64urlDecode(data) {
57
+ const base64 = data.replace(/-/g, '+').replace(/_/g, '/');
58
+ const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);
59
+ return Buffer.from(padded, 'base64').toString('utf8');
60
+ }
61
+ /**
62
+ * Create JWT header
63
+ */
64
+ function createHeader() {
65
+ return base64urlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));
66
+ }
67
+ /**
68
+ * Create JWT payload
69
+ */
70
+ function createPayload(expiresInSeconds) {
71
+ const now = Math.floor(Date.now() / 1000);
72
+ const jti = randomBytes(16).toString('hex');
73
+ return base64urlEncode(JSON.stringify({
74
+ iat: now,
75
+ exp: now + expiresInSeconds,
76
+ jti,
77
+ }));
78
+ }
79
+ /**
80
+ * Create HMAC signature
81
+ */
82
+ function createSignature(data, secret) {
83
+ const hmac = createHmac('sha256', secret);
84
+ hmac.update(data);
85
+ return base64urlEncode(hmac.digest());
86
+ }
87
+ /**
88
+ * Verify HMAC signature
89
+ */
90
+ function verifySignature(data, signature, secret) {
91
+ const expectedSignature = createSignature(data, secret);
92
+ return signature === expectedSignature;
93
+ }
94
+ /**
95
+ * Create a secret authenticator
96
+ */
97
+ export function createSecretAuthenticator(config) {
98
+ if (!config.secret || config.secret.length < MIN_SECRET_LENGTH) {
99
+ throw new AuthError('Secret must be at least 32 characters');
100
+ }
101
+ const expiresInSeconds = parseExpiresIn(config.expiresIn);
102
+ return {
103
+ async authenticate(providedSecret) {
104
+ // Validate provided secret
105
+ if (!providedSecret || providedSecret !== config.secret) {
106
+ return {
107
+ success: false,
108
+ error: 'Invalid secret',
109
+ };
110
+ }
111
+ // Generate JWT
112
+ const header = createHeader();
113
+ const payload = createPayload(expiresInSeconds);
114
+ const signature = createSignature(`${header}.${payload}`, config.secret);
115
+ const token = `${header}.${payload}.${signature}`;
116
+ return {
117
+ success: true,
118
+ token,
119
+ expiresIn: expiresInSeconds,
120
+ };
121
+ },
122
+ async verifyToken(token) {
123
+ if (!token || !token.includes('.')) {
124
+ return {
125
+ valid: false,
126
+ error: 'Invalid token format',
127
+ };
128
+ }
129
+ const parts = token.split('.');
130
+ if (parts.length !== 3) {
131
+ return {
132
+ valid: false,
133
+ error: 'Invalid token format',
134
+ };
135
+ }
136
+ const [header, payload, signature] = parts;
137
+ // Verify signature
138
+ if (!verifySignature(`${header}.${payload}`, signature, config.secret)) {
139
+ return {
140
+ valid: false,
141
+ error: 'Token signature invalid',
142
+ };
143
+ }
144
+ // Parse and verify payload
145
+ try {
146
+ const payloadData = JSON.parse(base64urlDecode(payload));
147
+ const now = Math.floor(Date.now() / 1000);
148
+ if (payloadData.exp && payloadData.exp < now) {
149
+ return {
150
+ valid: false,
151
+ error: 'Token expired',
152
+ };
153
+ }
154
+ return { valid: true };
155
+ }
156
+ catch {
157
+ return {
158
+ valid: false,
159
+ error: 'Invalid token payload',
160
+ };
161
+ }
162
+ },
163
+ };
164
+ }
165
+ //# sourceMappingURL=secret-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-auth.js","sourceRoot":"","sources":["../../src/cli/secret-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * SSE Stream Handler for Streamable HTTP Transport
3
+ * Requirements: 20.1, 20.2, 20.3, 20.4, 20.5, 20.6, 20.7, 20.8, 20.9, 20.10
4
+ *
5
+ * Implements Server-Sent Events (SSE) streaming for the MCP Streamable HTTP protocol.
6
+ * Handles GET /mcp requests by establishing SSE streams with keepalive support.
7
+ */
8
+ import { IncomingMessage, ServerResponse } from 'http';
9
+ /**
10
+ * Options for SSE stream handler
11
+ */
12
+ export interface SSEStreamHandlerOptions {
13
+ /** Keepalive interval in milliseconds (default: 30000) */
14
+ keepaliveInterval?: number;
15
+ }
16
+ /**
17
+ * SSE Stream Handler interface
18
+ */
19
+ export interface SSEStreamHandler {
20
+ /**
21
+ * Handle SSE request (GET /mcp)
22
+ */
23
+ handleSSERequest(req: IncomingMessage, res: ServerResponse): Promise<void>;
24
+ /**
25
+ * Send event to a specific session
26
+ */
27
+ sendEvent(eventType: string, data: unknown, sessionId?: string): void;
28
+ /**
29
+ * Broadcast event to all connected clients
30
+ */
31
+ broadcast(data: unknown): void;
32
+ /**
33
+ * Get number of active connections
34
+ */
35
+ getActiveConnections(): number;
36
+ /**
37
+ * Cleanup all connections
38
+ */
39
+ cleanup(): void;
40
+ }
41
+ /**
42
+ * Create SSE stream handler
43
+ */
44
+ export declare function createSSEStreamHandler(options?: SSEStreamHandlerOptions): SSEStreamHandler;
45
+ //# sourceMappingURL=sse-stream-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-stream-handler.d.ts","sourceRoot":"","sources":["../../src/cli/sse-stream-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAGvD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAWD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtE;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,oBAAoB,IAAI,MAAM,CAAC;IAE/B;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAqID;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CAElB"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * SSE Stream Handler for Streamable HTTP Transport
3
+ * Requirements: 20.1, 20.2, 20.3, 20.4, 20.5, 20.6, 20.7, 20.8, 20.9, 20.10
4
+ *
5
+ * Implements Server-Sent Events (SSE) streaming for the MCP Streamable HTTP protocol.
6
+ * Handles GET /mcp requests by establishing SSE streams with keepalive support.
7
+ */
8
+ import { randomUUID } from 'crypto';
9
+ /**
10
+ * Default keepalive interval (30 seconds)
11
+ */
12
+ const DEFAULT_KEEPALIVE_INTERVAL = 30000;
13
+ /**
14
+ * SSE Stream Handler Implementation
15
+ */
16
+ class SSEStreamHandlerImpl {
17
+ connections = new Map();
18
+ keepaliveInterval;
19
+ constructor(options = {}) {
20
+ this.keepaliveInterval = options.keepaliveInterval ?? DEFAULT_KEEPALIVE_INTERVAL;
21
+ }
22
+ async handleSSERequest(_req, res) {
23
+ const sessionId = randomUUID();
24
+ // Set SSE headers
25
+ // Requirement 20.2: Content-Type text/event-stream
26
+ // Requirement 20.5: Cache-Control no-cache
27
+ // Requirement 20.6: Connection keep-alive
28
+ res.writeHead(200, {
29
+ 'Content-Type': 'text/event-stream',
30
+ 'Cache-Control': 'no-cache',
31
+ 'Connection': 'keep-alive',
32
+ 'X-Accel-Buffering': 'no',
33
+ // Requirement 20.4: CORS headers
34
+ 'Access-Control-Allow-Origin': '*',
35
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
36
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
37
+ });
38
+ // Create connection record
39
+ const connection = {
40
+ sessionId,
41
+ response: res,
42
+ keepaliveTimer: null,
43
+ };
44
+ this.connections.set(sessionId, connection);
45
+ // Requirement 20.1: Send endpoint event on connection
46
+ this.sendEndpointEvent(connection);
47
+ // Requirement 20.3: Start keepalive timer
48
+ this.startKeepalive(connection);
49
+ // Requirement 20.7: Handle client disconnect
50
+ res.on('close', () => {
51
+ this.removeConnection(sessionId);
52
+ });
53
+ res.on('error', () => {
54
+ this.removeConnection(sessionId);
55
+ });
56
+ }
57
+ sendEvent(eventType, data, sessionId) {
58
+ const payload = this.formatSSEEvent(eventType, data);
59
+ if (sessionId) {
60
+ const connection = this.connections.get(sessionId);
61
+ if (connection) {
62
+ connection.response.write(payload);
63
+ }
64
+ }
65
+ else {
66
+ // Send to all connections
67
+ for (const connection of this.connections.values()) {
68
+ connection.response.write(payload);
69
+ }
70
+ }
71
+ }
72
+ broadcast(data) {
73
+ const payload = this.formatSSEEvent('message', data);
74
+ for (const connection of this.connections.values()) {
75
+ connection.response.write(payload);
76
+ }
77
+ }
78
+ getActiveConnections() {
79
+ return this.connections.size;
80
+ }
81
+ cleanup() {
82
+ for (const [sessionId, connection] of this.connections.entries()) {
83
+ if (connection.keepaliveTimer) {
84
+ clearInterval(connection.keepaliveTimer);
85
+ }
86
+ this.connections.delete(sessionId);
87
+ }
88
+ }
89
+ sendEndpointEvent(connection) {
90
+ const data = {
91
+ type: 'endpoint',
92
+ url: '/mcp',
93
+ sessionId: connection.sessionId,
94
+ };
95
+ const payload = this.formatSSEEvent('endpoint', data);
96
+ connection.response.write(payload);
97
+ }
98
+ startKeepalive(connection) {
99
+ connection.keepaliveTimer = setInterval(() => {
100
+ // Requirement 20.3: Send keepalive comment every 30 seconds
101
+ // SSE comment format: ": comment\n\n"
102
+ connection.response.write(': keepalive\n\n');
103
+ }, this.keepaliveInterval);
104
+ }
105
+ removeConnection(sessionId) {
106
+ const connection = this.connections.get(sessionId);
107
+ if (connection) {
108
+ if (connection.keepaliveTimer) {
109
+ clearInterval(connection.keepaliveTimer);
110
+ }
111
+ this.connections.delete(sessionId);
112
+ }
113
+ }
114
+ formatSSEEvent(eventType, data) {
115
+ const jsonData = JSON.stringify(data);
116
+ return `event: ${eventType}\ndata: ${jsonData}\n\n`;
117
+ }
118
+ }
119
+ /**
120
+ * Create SSE stream handler
121
+ */
122
+ export function createSSEStreamHandler(options = {}) {
123
+ return new SSEStreamHandlerImpl(options);
124
+ }
125
+ //# sourceMappingURL=sse-stream-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-stream-handler.js","sourceRoot":"","sources":["../../src/cli/sse-stream-handler.ts"],"names":[],"mappings":"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"}