paygate-mcp 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ /**
2
+ * SessionManager — MCP session tracking for Streamable HTTP transport.
3
+ *
4
+ * Manages:
5
+ * - Session creation and lifecycle (Mcp-Session-Id)
6
+ * - SSE connection tracking per session
7
+ * - Server-to-client notification routing
8
+ * - Session cleanup on DELETE or timeout
9
+ *
10
+ * Per MCP spec (2025-03-26):
11
+ * - POST /mcp may return SSE or JSON
12
+ * - GET /mcp opens SSE stream for server notifications
13
+ * - DELETE /mcp terminates a session
14
+ * - Mcp-Session-Id correlates all requests in a session
15
+ */
16
+ import { ServerResponse } from 'http';
17
+ import { JsonRpcResponse } from './types';
18
+ export interface McpSession {
19
+ id: string;
20
+ createdAt: number;
21
+ lastActivityAt: number;
22
+ /** SSE connections for server-to-client notifications */
23
+ sseConnections: Set<ServerResponse>;
24
+ /** API key associated with this session (null if unauthenticated) */
25
+ apiKey: string | null;
26
+ }
27
+ export interface SessionManagerConfig {
28
+ /** Session timeout in ms. Default: 30 minutes. */
29
+ sessionTimeoutMs: number;
30
+ /** Max concurrent sessions. Default: 1000. */
31
+ maxSessions: number;
32
+ /** Max SSE connections per session. Default: 3. */
33
+ maxSsePerSession: number;
34
+ }
35
+ /**
36
+ * Write SSE headers to a response.
37
+ * Extra headers (e.g., Mcp-Session-Id) can be merged in.
38
+ */
39
+ export declare function writeSseHeaders(res: ServerResponse, extraHeaders?: Record<string, string>): void;
40
+ /**
41
+ * Write a JSON-RPC response as an SSE event.
42
+ */
43
+ export declare function writeSseEvent(res: ServerResponse, data: JsonRpcResponse | object, eventType?: string): void;
44
+ /**
45
+ * Write a keepalive comment to an SSE stream (prevents connection timeout).
46
+ */
47
+ export declare function writeSseKeepAlive(res: ServerResponse): void;
48
+ export declare class SessionManager {
49
+ private sessions;
50
+ private readonly config;
51
+ private cleanupInterval;
52
+ constructor(config?: Partial<SessionManagerConfig>);
53
+ /**
54
+ * Create a new session. Returns the session ID.
55
+ */
56
+ createSession(apiKey: string | null): string;
57
+ /**
58
+ * Get a session by ID. Returns null if not found or expired.
59
+ */
60
+ getSession(sessionId: string): McpSession | null;
61
+ /**
62
+ * Register an SSE connection for a session.
63
+ * Returns false if the session is at its SSE limit.
64
+ */
65
+ addSseConnection(sessionId: string, res: ServerResponse): boolean;
66
+ /**
67
+ * Send a server-initiated notification to all SSE connections in a session.
68
+ */
69
+ sendNotification(sessionId: string, notification: JsonRpcResponse | object): void;
70
+ /**
71
+ * Destroy a session, closing all SSE connections.
72
+ */
73
+ destroySession(sessionId: string): boolean;
74
+ /**
75
+ * Get active session count.
76
+ */
77
+ get sessionCount(): number;
78
+ /**
79
+ * Cleanup expired sessions.
80
+ */
81
+ private cleanup;
82
+ /**
83
+ * Evict the oldest session to make room for a new one.
84
+ */
85
+ private evictOldest;
86
+ /**
87
+ * Stop the session manager, clean up all sessions.
88
+ */
89
+ destroy(): void;
90
+ }
91
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI1C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,cAAc,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACpC,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAUD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAUhG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAK3G;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAE3D;AAID,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,eAAe,CAAiC;gBAE5C,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAMlD;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAmB5C;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAchD;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO;IAkBjE;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI;IAcjF;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAkB1C;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB"}
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ /**
3
+ * SessionManager — MCP session tracking for Streamable HTTP transport.
4
+ *
5
+ * Manages:
6
+ * - Session creation and lifecycle (Mcp-Session-Id)
7
+ * - SSE connection tracking per session
8
+ * - Server-to-client notification routing
9
+ * - Session cleanup on DELETE or timeout
10
+ *
11
+ * Per MCP spec (2025-03-26):
12
+ * - POST /mcp may return SSE or JSON
13
+ * - GET /mcp opens SSE stream for server notifications
14
+ * - DELETE /mcp terminates a session
15
+ * - Mcp-Session-Id correlates all requests in a session
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.SessionManager = void 0;
19
+ exports.writeSseHeaders = writeSseHeaders;
20
+ exports.writeSseEvent = writeSseEvent;
21
+ exports.writeSseKeepAlive = writeSseKeepAlive;
22
+ const crypto_1 = require("crypto");
23
+ const DEFAULT_SESSION_CONFIG = {
24
+ sessionTimeoutMs: 30 * 60 * 1000, // 30 minutes
25
+ maxSessions: 1000,
26
+ maxSsePerSession: 3,
27
+ };
28
+ // ─── SSE Helpers ─────────────────────────────────────────────────────────────
29
+ /**
30
+ * Write SSE headers to a response.
31
+ * Extra headers (e.g., Mcp-Session-Id) can be merged in.
32
+ */
33
+ function writeSseHeaders(res, extraHeaders) {
34
+ res.writeHead(200, {
35
+ 'Content-Type': 'text/event-stream',
36
+ 'Cache-Control': 'no-cache, no-transform',
37
+ 'Connection': 'keep-alive',
38
+ 'X-Accel-Buffering': 'no', // Disable Nginx buffering
39
+ 'Access-Control-Allow-Origin': '*',
40
+ 'Access-Control-Expose-Headers': 'Mcp-Session-Id',
41
+ ...extraHeaders,
42
+ });
43
+ }
44
+ /**
45
+ * Write a JSON-RPC response as an SSE event.
46
+ */
47
+ function writeSseEvent(res, data, eventType) {
48
+ if (eventType) {
49
+ res.write(`event: ${eventType}\n`);
50
+ }
51
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
52
+ }
53
+ /**
54
+ * Write a keepalive comment to an SSE stream (prevents connection timeout).
55
+ */
56
+ function writeSseKeepAlive(res) {
57
+ res.write(': keepalive\n\n');
58
+ }
59
+ // ─── SessionManager ──────────────────────────────────────────────────────────
60
+ class SessionManager {
61
+ sessions = new Map();
62
+ config;
63
+ cleanupInterval;
64
+ constructor(config) {
65
+ this.config = { ...DEFAULT_SESSION_CONFIG, ...config };
66
+ // Cleanup expired sessions every 60 seconds
67
+ this.cleanupInterval = setInterval(() => this.cleanup(), 60_000);
68
+ }
69
+ /**
70
+ * Create a new session. Returns the session ID.
71
+ */
72
+ createSession(apiKey) {
73
+ // Enforce max sessions
74
+ if (this.sessions.size >= this.config.maxSessions) {
75
+ this.evictOldest();
76
+ }
77
+ const id = `mcp_sess_${(0, crypto_1.randomBytes)(16).toString('hex')}`;
78
+ const session = {
79
+ id,
80
+ createdAt: Date.now(),
81
+ lastActivityAt: Date.now(),
82
+ sseConnections: new Set(),
83
+ apiKey,
84
+ };
85
+ this.sessions.set(id, session);
86
+ return id;
87
+ }
88
+ /**
89
+ * Get a session by ID. Returns null if not found or expired.
90
+ */
91
+ getSession(sessionId) {
92
+ const session = this.sessions.get(sessionId);
93
+ if (!session)
94
+ return null;
95
+ // Check timeout
96
+ if (Date.now() - session.lastActivityAt > this.config.sessionTimeoutMs) {
97
+ this.destroySession(sessionId);
98
+ return null;
99
+ }
100
+ session.lastActivityAt = Date.now();
101
+ return session;
102
+ }
103
+ /**
104
+ * Register an SSE connection for a session.
105
+ * Returns false if the session is at its SSE limit.
106
+ */
107
+ addSseConnection(sessionId, res) {
108
+ const session = this.getSession(sessionId);
109
+ if (!session)
110
+ return false;
111
+ if (session.sseConnections.size >= this.config.maxSsePerSession) {
112
+ return false;
113
+ }
114
+ session.sseConnections.add(res);
115
+ // Clean up when the connection closes
116
+ res.on('close', () => {
117
+ session.sseConnections.delete(res);
118
+ });
119
+ return true;
120
+ }
121
+ /**
122
+ * Send a server-initiated notification to all SSE connections in a session.
123
+ */
124
+ sendNotification(sessionId, notification) {
125
+ const session = this.sessions.get(sessionId);
126
+ if (!session)
127
+ return;
128
+ for (const res of session.sseConnections) {
129
+ try {
130
+ writeSseEvent(res, notification, 'message');
131
+ }
132
+ catch {
133
+ // Connection already closed
134
+ session.sseConnections.delete(res);
135
+ }
136
+ }
137
+ }
138
+ /**
139
+ * Destroy a session, closing all SSE connections.
140
+ */
141
+ destroySession(sessionId) {
142
+ const session = this.sessions.get(sessionId);
143
+ if (!session)
144
+ return false;
145
+ // Close all SSE connections
146
+ for (const res of session.sseConnections) {
147
+ try {
148
+ res.end();
149
+ }
150
+ catch {
151
+ // Already closed
152
+ }
153
+ }
154
+ session.sseConnections.clear();
155
+ this.sessions.delete(sessionId);
156
+ return true;
157
+ }
158
+ /**
159
+ * Get active session count.
160
+ */
161
+ get sessionCount() {
162
+ return this.sessions.size;
163
+ }
164
+ /**
165
+ * Cleanup expired sessions.
166
+ */
167
+ cleanup() {
168
+ const now = Date.now();
169
+ for (const [id, session] of this.sessions) {
170
+ if (now - session.lastActivityAt > this.config.sessionTimeoutMs) {
171
+ this.destroySession(id);
172
+ }
173
+ }
174
+ }
175
+ /**
176
+ * Evict the oldest session to make room for a new one.
177
+ */
178
+ evictOldest() {
179
+ let oldestId = null;
180
+ let oldestTime = Infinity;
181
+ for (const [id, session] of this.sessions) {
182
+ if (session.lastActivityAt < oldestTime) {
183
+ oldestTime = session.lastActivityAt;
184
+ oldestId = id;
185
+ }
186
+ }
187
+ if (oldestId) {
188
+ this.destroySession(oldestId);
189
+ }
190
+ }
191
+ /**
192
+ * Stop the session manager, clean up all sessions.
193
+ */
194
+ destroy() {
195
+ clearInterval(this.cleanupInterval);
196
+ for (const id of this.sessions.keys()) {
197
+ this.destroySession(id);
198
+ }
199
+ }
200
+ }
201
+ exports.SessionManager = SessionManager;
202
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paygate-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Pay-per-tool-call gating proxy for MCP servers. Wrap any MCP server with API key auth, per-tool pricing, rate limiting, and usage metering.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",