@1mcp/agent 0.10.3 → 0.12.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.
Files changed (147) hide show
  1. package/README.md +41 -17
  2. package/build/auth/authManager.d.ts +109 -0
  3. package/build/auth/authManager.d.ts.map +1 -0
  4. package/build/auth/authManager.js +173 -0
  5. package/build/auth/authManager.js.map +1 -0
  6. package/build/auth/authMiddleware.d.ts +16 -0
  7. package/build/auth/authMiddleware.d.ts.map +1 -0
  8. package/build/auth/authMiddleware.js +45 -0
  9. package/build/auth/authMiddleware.js.map +1 -0
  10. package/build/auth/sessionManager.d.ts +197 -0
  11. package/build/auth/sessionManager.d.ts.map +1 -0
  12. package/build/auth/sessionManager.js +408 -0
  13. package/build/auth/sessionManager.js.map +1 -0
  14. package/build/capabilities/capabilityManager.d.ts +1 -1
  15. package/build/capabilities/capabilityManager.d.ts.map +1 -1
  16. package/build/capabilities/capabilityManager.js +39 -6
  17. package/build/capabilities/capabilityManager.js.map +1 -1
  18. package/build/config/configManager.d.ts +7 -1
  19. package/build/config/configManager.d.ts.map +1 -1
  20. package/build/config/configManager.js +24 -2
  21. package/build/config/configManager.js.map +1 -1
  22. package/build/constants.d.ts +25 -1
  23. package/build/constants.d.ts.map +1 -1
  24. package/build/constants.js +31 -2
  25. package/build/constants.js.map +1 -1
  26. package/build/{client.d.ts → core/client/clientFactory.d.ts} +1 -1
  27. package/build/core/client/clientFactory.d.ts.map +1 -0
  28. package/build/{client.js → core/client/clientFactory.js} +2 -2
  29. package/build/core/client/clientFactory.js.map +1 -0
  30. package/build/{clients → core/client}/clientManager.d.ts +3 -2
  31. package/build/core/client/clientManager.d.ts.map +1 -0
  32. package/build/{clients → core/client}/clientManager.js +10 -6
  33. package/build/core/client/clientManager.js.map +1 -0
  34. package/build/core/server/serverConfig.d.ts +100 -0
  35. package/build/core/server/serverConfig.d.ts.map +1 -0
  36. package/build/core/server/serverConfig.js +117 -0
  37. package/build/core/server/serverConfig.js.map +1 -0
  38. package/build/{serverManager.d.ts → core/server/serverManager.d.ts} +7 -2
  39. package/build/core/server/serverManager.d.ts.map +1 -0
  40. package/build/core/server/serverManager.js +159 -0
  41. package/build/core/server/serverManager.js.map +1 -0
  42. package/build/core/types/client.d.ts +38 -0
  43. package/build/core/types/client.d.ts.map +1 -0
  44. package/build/core/types/client.js +13 -0
  45. package/build/core/types/client.js.map +1 -0
  46. package/build/core/types/index.d.ts +4 -0
  47. package/build/core/types/index.d.ts.map +1 -0
  48. package/build/core/types/index.js +5 -0
  49. package/build/core/types/index.js.map +1 -0
  50. package/build/core/types/server.d.ts +14 -0
  51. package/build/core/types/server.d.ts.map +1 -0
  52. package/build/core/types/server.js +2 -0
  53. package/build/core/types/server.js.map +1 -0
  54. package/build/{types.d.ts → core/types/transport.d.ts} +1 -48
  55. package/build/core/types/transport.d.ts.map +1 -0
  56. package/build/{types.js → core/types/transport.js} +1 -13
  57. package/build/core/types/transport.js.map +1 -0
  58. package/build/handlers/notificationHandlers.d.ts +1 -1
  59. package/build/handlers/notificationHandlers.d.ts.map +1 -1
  60. package/build/handlers/notificationHandlers.js +41 -15
  61. package/build/handlers/notificationHandlers.js.map +1 -1
  62. package/build/handlers/requestHandlers.d.ts +1 -1
  63. package/build/handlers/requestHandlers.d.ts.map +1 -1
  64. package/build/handlers/requestHandlers.js +65 -2
  65. package/build/handlers/requestHandlers.js.map +1 -1
  66. package/build/index.d.ts +1 -1
  67. package/build/index.d.ts.map +1 -1
  68. package/build/index.js +44 -5
  69. package/build/index.js.map +1 -1
  70. package/build/logger/logger.js +1 -1
  71. package/build/logger/logger.js.map +1 -1
  72. package/build/server.d.ts +1 -1
  73. package/build/server.d.ts.map +1 -1
  74. package/build/server.js +6 -3
  75. package/build/server.js.map +1 -1
  76. package/build/services/configReloadService.d.ts +15 -5
  77. package/build/services/configReloadService.d.ts.map +1 -1
  78. package/build/services/configReloadService.js +28 -11
  79. package/build/services/configReloadService.js.map +1 -1
  80. package/build/{config/transportConfig.d.ts → transport/config.d.ts} +2 -2
  81. package/build/transport/config.d.ts.map +1 -0
  82. package/build/{config/transportConfig.js → transport/config.js} +2 -2
  83. package/build/transport/config.js.map +1 -0
  84. package/build/transport/http/errorHandler.d.ts.map +1 -0
  85. package/build/{server → transport/http}/errorHandler.js +1 -1
  86. package/build/transport/http/errorHandler.js.map +1 -0
  87. package/build/transport/http/middleware/loggingMiddleware.d.ts.map +1 -0
  88. package/build/{middleware → transport/http/middleware}/loggingMiddleware.js +11 -7
  89. package/build/transport/http/middleware/loggingMiddleware.js.map +1 -0
  90. package/build/transport/http/routes/oauthRoutes.d.ts +14 -0
  91. package/build/transport/http/routes/oauthRoutes.d.ts.map +1 -0
  92. package/build/transport/http/routes/oauthRoutes.js +132 -0
  93. package/build/transport/http/routes/oauthRoutes.js.map +1 -0
  94. package/build/transport/http/routes/sseRoutes.d.ts +4 -0
  95. package/build/transport/http/routes/sseRoutes.d.ts.map +1 -0
  96. package/build/transport/http/routes/sseRoutes.js +64 -0
  97. package/build/transport/http/routes/sseRoutes.js.map +1 -0
  98. package/build/transport/http/routes/streamableHttpRoutes.d.ts +4 -0
  99. package/build/transport/http/routes/streamableHttpRoutes.d.ts.map +1 -0
  100. package/build/transport/http/routes/streamableHttpRoutes.js +121 -0
  101. package/build/transport/http/routes/streamableHttpRoutes.js.map +1 -0
  102. package/build/transport/http/server.d.ts +69 -0
  103. package/build/transport/http/server.d.ts.map +1 -0
  104. package/build/transport/http/server.js +115 -0
  105. package/build/transport/http/server.js.map +1 -0
  106. package/build/utils/clientFiltering.d.ts +1 -1
  107. package/build/utils/clientFiltering.d.ts.map +1 -1
  108. package/build/utils/errorHandling.d.ts +1 -0
  109. package/build/utils/errorHandling.d.ts.map +1 -1
  110. package/build/utils/errorHandling.js +29 -5
  111. package/build/utils/errorHandling.js.map +1 -1
  112. package/build/utils/errorTypes.d.ts +4 -1
  113. package/build/utils/errorTypes.d.ts.map +1 -1
  114. package/build/utils/errorTypes.js +12 -4
  115. package/build/utils/errorTypes.js.map +1 -1
  116. package/build/utils/pagination.d.ts +1 -1
  117. package/build/utils/pagination.d.ts.map +1 -1
  118. package/build/utils/pagination.js +84 -5
  119. package/build/utils/pagination.js.map +1 -1
  120. package/build/utils/tagsExtractor.d.ts.map +1 -0
  121. package/build/utils/tagsExtractor.js.map +1 -0
  122. package/package.json +14 -5
  123. package/build/client.d.ts.map +0 -1
  124. package/build/client.js.map +0 -1
  125. package/build/clients/clientManager.d.ts.map +0 -1
  126. package/build/clients/clientManager.js.map +0 -1
  127. package/build/config/transportConfig.d.ts.map +0 -1
  128. package/build/config/transportConfig.js.map +0 -1
  129. package/build/middleware/loggingMiddleware.d.ts.map +0 -1
  130. package/build/middleware/loggingMiddleware.js.map +0 -1
  131. package/build/server/errorHandler.d.ts.map +0 -1
  132. package/build/server/errorHandler.js.map +0 -1
  133. package/build/server/expressServer.d.ts +0 -11
  134. package/build/server/expressServer.d.ts.map +0 -1
  135. package/build/server/expressServer.js +0 -177
  136. package/build/server/expressServer.js.map +0 -1
  137. package/build/server/tagsExtractor.d.ts.map +0 -1
  138. package/build/server/tagsExtractor.js.map +0 -1
  139. package/build/serverManager.d.ts.map +0 -1
  140. package/build/serverManager.js +0 -87
  141. package/build/serverManager.js.map +0 -1
  142. package/build/types.d.ts.map +0 -1
  143. package/build/types.js.map +0 -1
  144. /package/build/{server → transport/http}/errorHandler.d.ts +0 -0
  145. /package/build/{middleware → transport/http/middleware}/loggingMiddleware.d.ts +0 -0
  146. /package/build/{server → utils}/tagsExtractor.d.ts +0 -0
  147. /package/build/{server → utils}/tagsExtractor.js +0 -0
@@ -0,0 +1,132 @@
1
+ import bodyParser from 'body-parser';
2
+ import { randomUUID } from 'node:crypto';
3
+ import logger from '../../../logger/logger.js';
4
+ import { ServerConfigManager } from '../../../core/server/serverConfig.js';
5
+ import { AUTH_CONFIG, RATE_LIMIT_CONFIG } from '../../../constants.js';
6
+ import rateLimit from 'express-rate-limit';
7
+ /**
8
+ * Sets up OAuth 2.1 and related endpoints on the Express app.
9
+ *
10
+ * This function registers all OAuth 2.1 endpoints (authorization, token, metadata, registration)
11
+ * and MCP resource metadata endpoints on the provided Express application. It uses the provided
12
+ * AuthManager for all authentication and token operations.
13
+ *
14
+ * @param app - The Express application instance
15
+ * @param authManager - The AuthManager instance for OAuth/session logic
16
+ */
17
+ export function setupOAuthRoutes(app, authManager) {
18
+ const configManager = ServerConfigManager.getInstance();
19
+ const DEFAULT_REDIRECT_PATH = '/oauth/callback';
20
+ // Rate limiter: 10 requests per minute per IP for sensitive endpoints
21
+ const oauthLimiter = rateLimit({
22
+ windowMs: RATE_LIMIT_CONFIG.OAUTH.WINDOW_MS,
23
+ max: RATE_LIMIT_CONFIG.OAUTH.MAX,
24
+ standardHeaders: true,
25
+ legacyHeaders: false,
26
+ message: RATE_LIMIT_CONFIG.OAUTH.MESSAGE,
27
+ });
28
+ /**
29
+ * Helper to build the OAuth issuer URL from the incoming request.
30
+ * Uses protocol and host headers for correct environment support.
31
+ */
32
+ function getIssuer(req) {
33
+ // X-Forwarded-Proto/Host for proxies, fallback to req.protocol/host
34
+ const proto = req.headers['x-forwarded-proto'] || req.protocol;
35
+ const host = req.headers['x-forwarded-host'] || req.get('host');
36
+ return `${proto}://${host}`;
37
+ }
38
+ // /authorize endpoint (auto-approve)
39
+ app.get('/authorize', oauthLimiter, (req, res) => {
40
+ logger.info('[OAuth] /authorize request', { query: req.query, headers: req.headers });
41
+ const { response_type, client_id, redirect_uri, state, resource, code_challenge: _code_challenge, code_challenge_method: _code_challenge_method, } = req.query;
42
+ if (response_type !== 'code' || !client_id) {
43
+ logger.warn('[OAuth] /authorize invalid request', { response_type, client_id });
44
+ res.status(400).json({ error: 'invalid_request' });
45
+ return;
46
+ }
47
+ // Accept S256 or plain for code_challenge_method (not enforced for local dev)
48
+ // Use default redirect URI if not provided
49
+ const issuer = getIssuer(req);
50
+ const defaultRedirect = `${issuer}${DEFAULT_REDIRECT_PATH}`;
51
+ const redirect = typeof redirect_uri === 'string' ? redirect_uri : defaultRedirect;
52
+ const code = authManager.createAuthCode(client_id, redirect, typeof resource === 'string' ? resource : '');
53
+ // Build redirect URL
54
+ const url = new URL(redirect);
55
+ url.searchParams.set('code', code);
56
+ if (state)
57
+ url.searchParams.set('state', state);
58
+ logger.info('[OAuth] /authorize success', { client_id, code, redirect: url.toString() });
59
+ res.redirect(url.toString());
60
+ });
61
+ // /token endpoint
62
+ app.post('/token', oauthLimiter, bodyParser.urlencoded({ extended: false }), (req, res) => {
63
+ logger.info('[OAuth] /token request', { body: req.body, headers: req.headers });
64
+ const { grant_type, code, client_id, redirect_uri, resource } = req.body;
65
+ if (grant_type !== 'authorization_code' || !code || !client_id) {
66
+ logger.warn('[OAuth] /token invalid request', { grant_type, code: !!code, client_id });
67
+ res.status(400).json({ error: 'invalid_request' });
68
+ return;
69
+ }
70
+ const accessToken = authManager.exchangeCodeForToken(code, client_id, redirect_uri, resource);
71
+ if (!accessToken) {
72
+ logger.warn('[OAuth] /token invalid grant', { code, client_id });
73
+ res.status(400).json({ error: 'invalid_grant' });
74
+ return;
75
+ }
76
+ const ttlMs = configManager.getOAuthTokenTtlMs();
77
+ logger.info('[OAuth] /token success', { client_id, accessToken });
78
+ res.json({
79
+ access_token: accessToken,
80
+ token_type: 'Bearer',
81
+ expires_in: ttlMs / 1000,
82
+ scope: '',
83
+ });
84
+ });
85
+ // OAuth 2.0 Authorization Server Metadata (RFC8414)
86
+ app.get('/.well-known/oauth-authorization-server', (req, res) => {
87
+ logger.info('[OAuth] metadata request', { url: req.url });
88
+ const issuer = getIssuer(req);
89
+ res.json({
90
+ issuer,
91
+ authorization_endpoint: `${issuer}/authorize`,
92
+ token_endpoint: `${issuer}/token`,
93
+ registration_endpoint: `${issuer}/register`,
94
+ response_types_supported: ['code'],
95
+ grant_types_supported: ['authorization_code'],
96
+ code_challenge_methods_supported: ['S256', 'plain'],
97
+ token_endpoint_auth_methods_supported: ['none'],
98
+ });
99
+ });
100
+ // MCP Resource Metadata (RFC9728)
101
+ app.get('/mcp-resource-metadata', (req, res) => {
102
+ logger.info('[OAuth] resource metadata request', { url: req.url });
103
+ const issuer = getIssuer(req);
104
+ res.json({
105
+ authorization_servers: [`${issuer}/.well-known/oauth-authorization-server`],
106
+ resource: issuer,
107
+ });
108
+ });
109
+ // OAuth 2.0 Protected Resource Metadata (RFC9728) well-known endpoint
110
+ app.get('/.well-known/oauth-protected-resource', (req, res) => {
111
+ logger.info('[OAuth] protected resource metadata request', { url: req.url });
112
+ const issuer = getIssuer(req);
113
+ res.json({
114
+ authorization_servers: [`${issuer}/.well-known/oauth-authorization-server`],
115
+ resource: issuer,
116
+ });
117
+ });
118
+ // OAuth 2.0 Dynamic Client Registration (RFC7591)
119
+ app.post('/register', oauthLimiter, bodyParser.json(), (req, res) => {
120
+ logger.info('[OAuth] client registration request', { body: req.body });
121
+ // Accept any registration, auto-approve
122
+ const clientId = AUTH_CONFIG.PREFIXES.CLIENT_ID + randomUUID();
123
+ logger.info('[OAuth] client registration success', { clientId });
124
+ res.status(201).json({
125
+ client_id: clientId,
126
+ client_id_issued_at: Math.floor(Date.now() / 1000),
127
+ token_endpoint_auth_method: 'none',
128
+ ...req.body,
129
+ });
130
+ });
131
+ }
132
+ //# sourceMappingURL=oauthRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauthRoutes.js","sourceRoot":"","sources":["../../../../src/transport/http/routes/oauthRoutes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import express from 'express';
2
+ import { ServerManager } from '../../../core/server/serverManager.js';
3
+ export declare function setupSseRoutes(app: express.Application, serverManager: ServerManager, authMiddleware: express.RequestHandler): void;
4
+ //# sourceMappingURL=sseRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sseRoutes.d.ts","sourceRoot":"","sources":["../../../../src/transport/http/routes/sseRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAGtE,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,CAAC,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,OAAO,CAAC,cAAc,GACrC,IAAI,CA8DN"}
@@ -0,0 +1,64 @@
1
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
2
+ import { ErrorCode } from '@modelcontextprotocol/sdk/types.js';
3
+ import logger from '../../../logger/logger.js';
4
+ import { SSE_ENDPOINT, MESSAGES_ENDPOINT } from '../../../constants.js';
5
+ import tagsExtractor from '../../../utils/tagsExtractor.js';
6
+ export function setupSseRoutes(app, serverManager, authMiddleware) {
7
+ app.get(SSE_ENDPOINT, authMiddleware, tagsExtractor, async (req, res) => {
8
+ try {
9
+ logger.info('[GET] sse', { query: req.query, headers: req.headers });
10
+ const transport = new SSEServerTransport(MESSAGES_ENDPOINT, res);
11
+ // Use tags from middleware
12
+ const tags = res.locals.tags;
13
+ // Connect the transport using the server manager
14
+ await serverManager.connectTransport(transport, transport.sessionId, {
15
+ tags,
16
+ enablePagination: req.query.pagination === 'true',
17
+ });
18
+ transport.onclose = () => {
19
+ serverManager.disconnectTransport(transport.sessionId);
20
+ // Note: ServerManager already logs the disconnection
21
+ };
22
+ }
23
+ catch (error) {
24
+ logger.error('SSE connection error:', error);
25
+ res.status(500).end();
26
+ }
27
+ });
28
+ app.post(MESSAGES_ENDPOINT, authMiddleware, async (req, res) => {
29
+ try {
30
+ const sessionId = req.query.sessionId;
31
+ if (!sessionId) {
32
+ res.status(400).json({
33
+ error: {
34
+ code: ErrorCode.InvalidParams,
35
+ message: 'Invalid params: sessionId is required',
36
+ },
37
+ });
38
+ return;
39
+ }
40
+ logger.info('message', { body: req.body, sessionId });
41
+ const transport = serverManager.getTransport(sessionId);
42
+ if (transport instanceof SSEServerTransport) {
43
+ await transport.handlePostMessage(req, res, req.body);
44
+ return;
45
+ }
46
+ res.status(404).json({
47
+ error: {
48
+ code: ErrorCode.InvalidParams,
49
+ message: 'Transport not found',
50
+ },
51
+ });
52
+ }
53
+ catch (error) {
54
+ logger.error('Message handling error:', error);
55
+ res.status(500).json({
56
+ error: {
57
+ code: ErrorCode.InternalError,
58
+ message: 'Internal server error',
59
+ },
60
+ });
61
+ }
62
+ });
63
+ }
64
+ //# sourceMappingURL=sseRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sseRoutes.js","sourceRoot":"","sources":["../../../../src/transport/http/routes/sseRoutes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import express from 'express';
2
+ import { ServerManager } from '../../../core/server/serverManager.js';
3
+ export declare function setupStreamableHttpRoutes(app: express.Application, serverManager: ServerManager, authMiddleware: express.RequestHandler): void;
4
+ //# sourceMappingURL=streamableHttpRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamableHttpRoutes.d.ts","sourceRoot":"","sources":["../../../../src/transport/http/routes/streamableHttpRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAGtE,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,CAAC,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,OAAO,CAAC,cAAc,GACrC,IAAI,CA6HN"}
@@ -0,0 +1,121 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
+ import { ErrorCode } from '@modelcontextprotocol/sdk/types.js';
4
+ import logger from '../../../logger/logger.js';
5
+ import { STREAMABLE_HTTP_ENDPOINT } from '../../../constants.js';
6
+ import tagsExtractor from '../../../utils/tagsExtractor.js';
7
+ export function setupStreamableHttpRoutes(app, serverManager, authMiddleware) {
8
+ app.post(STREAMABLE_HTTP_ENDPOINT, authMiddleware, tagsExtractor, async (req, res) => {
9
+ try {
10
+ logger.info('[POST] streamable-http', { query: req.query, body: req.body, headers: req.headers });
11
+ let transport;
12
+ const sessionId = req.headers['mcp-session-id'];
13
+ if (!sessionId) {
14
+ const id = randomUUID();
15
+ transport = new StreamableHTTPServerTransport({
16
+ sessionIdGenerator: () => id,
17
+ });
18
+ // Use tags from middleware
19
+ const tags = res.locals.tags;
20
+ await serverManager.connectTransport(transport, id, {
21
+ tags,
22
+ enablePagination: req.query.pagination === 'true',
23
+ });
24
+ transport.onclose = () => {
25
+ serverManager.disconnectTransport(id);
26
+ // Note: ServerManager already logs the disconnection
27
+ };
28
+ }
29
+ else {
30
+ const existingTransport = serverManager.getTransport(sessionId);
31
+ if (!existingTransport) {
32
+ res.status(404).json({
33
+ error: {
34
+ code: ErrorCode.InvalidParams,
35
+ message: 'No active streamable HTTP session found for the provided sessionId',
36
+ },
37
+ });
38
+ return;
39
+ }
40
+ if (existingTransport instanceof StreamableHTTPServerTransport) {
41
+ transport = existingTransport;
42
+ }
43
+ else {
44
+ res.status(400).json({
45
+ error: {
46
+ code: ErrorCode.InvalidParams,
47
+ message: 'Session already exists but uses a different transport protocol',
48
+ },
49
+ });
50
+ return;
51
+ }
52
+ }
53
+ await transport.handleRequest(req, res, req.body);
54
+ }
55
+ catch (error) {
56
+ logger.error('Streamable HTTP error:', error);
57
+ res.status(500).end();
58
+ }
59
+ });
60
+ app.get(STREAMABLE_HTTP_ENDPOINT, authMiddleware, async (req, res) => {
61
+ try {
62
+ logger.info('[GET] streamable-http', { query: req.query, headers: req.headers });
63
+ const sessionId = req.headers['mcp-session-id'];
64
+ if (!sessionId) {
65
+ res.status(400).json({
66
+ error: {
67
+ code: ErrorCode.InvalidParams,
68
+ message: 'Invalid params: sessionId is required',
69
+ },
70
+ });
71
+ return;
72
+ }
73
+ const transport = serverManager.getTransport(sessionId);
74
+ if (!transport) {
75
+ res.status(404).json({
76
+ error: {
77
+ code: ErrorCode.InvalidParams,
78
+ message: 'No active streamable HTTP session found for the provided sessionId',
79
+ },
80
+ });
81
+ return;
82
+ }
83
+ await transport.handleRequest(req, res, req.body);
84
+ }
85
+ catch (error) {
86
+ logger.error('Streamable HTTP error:', error);
87
+ res.status(500).end();
88
+ }
89
+ });
90
+ app.delete(STREAMABLE_HTTP_ENDPOINT, authMiddleware, async (req, res) => {
91
+ try {
92
+ logger.info('[DELETE] streamable-http', { query: req.query, headers: req.headers });
93
+ const sessionId = req.headers['mcp-session-id'];
94
+ if (!sessionId) {
95
+ res.status(400).json({
96
+ error: {
97
+ code: ErrorCode.InvalidParams,
98
+ message: 'Invalid params: sessionId is required',
99
+ },
100
+ });
101
+ return;
102
+ }
103
+ const transport = serverManager.getTransport(sessionId);
104
+ if (!transport) {
105
+ res.status(404).json({
106
+ error: {
107
+ code: ErrorCode.InvalidParams,
108
+ message: 'No active streamable HTTP session found for the provided sessionId',
109
+ },
110
+ });
111
+ return;
112
+ }
113
+ await transport.handleRequest(req, res);
114
+ }
115
+ catch (error) {
116
+ logger.error('Streamable HTTP error:', error);
117
+ res.status(500).end();
118
+ }
119
+ });
120
+ }
121
+ //# sourceMappingURL=streamableHttpRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamableHttpRoutes.js","sourceRoot":"","sources":["../../../../src/transport/http/routes/streamableHttpRoutes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { ServerManager } from '../../core/server/serverManager.js';
2
+ /**
3
+ * ExpressServer orchestrates the HTTP/SSE transport layer for the MCP server.
4
+ *
5
+ * This class manages the Express application, authentication, and route setup.
6
+ * It provides both HTTP and SSE transport options with optional OAuth 2.1 authentication.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const serverManager = await setupServer();
11
+ * const expressServer = new ExpressServer(serverManager);
12
+ * expressServer.start(3050, 'localhost');
13
+ * ```
14
+ */
15
+ export declare class ExpressServer {
16
+ private app;
17
+ private serverManager;
18
+ private authManager;
19
+ private configManager;
20
+ /**
21
+ * Creates a new ExpressServer instance.
22
+ *
23
+ * Initializes the Express application, sets up middleware, authentication,
24
+ * and configures all routes for MCP transport and OAuth endpoints.
25
+ *
26
+ * @param serverManager - The server manager instance for handling MCP operations
27
+ */
28
+ constructor(serverManager: ServerManager);
29
+ /**
30
+ * Sets up Express middleware including CORS, body parsing, and error handling.
31
+ *
32
+ * Configures the basic middleware stack required for the MCP server:
33
+ * - CORS for cross-origin requests
34
+ * - JSON body parsing
35
+ * - Global error handling
36
+ */
37
+ private setupMiddleware;
38
+ /**
39
+ * Sets up all application routes including OAuth and MCP transport endpoints.
40
+ *
41
+ * Configures the following route groups:
42
+ * - OAuth 2.1 endpoints (always available, auth can be disabled)
43
+ * - Streamable HTTP transport routes with authentication middleware
44
+ * - SSE transport routes with authentication middleware
45
+ *
46
+ * Logs the authentication status for debugging purposes.
47
+ */
48
+ private setupRoutes;
49
+ /**
50
+ * Starts the Express server on the specified port and host.
51
+ *
52
+ * Binds the Express application to the network interface and logs
53
+ * the server status including authentication configuration.
54
+ *
55
+ * @param port - The port number to listen on
56
+ * @param host - The host address to bind to
57
+ */
58
+ start(port: number, host: string): void;
59
+ /**
60
+ * Performs graceful shutdown of the Express server.
61
+ *
62
+ * Cleans up resources including:
63
+ * - Authentication manager shutdown
64
+ * - Session cleanup
65
+ * - Timer cleanup
66
+ */
67
+ shutdown(): void;
68
+ }
69
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/transport/http/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAUnE;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAAsB;IAE3C;;;;;;;OAOG;gBACS,aAAa,EAAE,aAAa;IAaxC;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;;;;;;OASG;IACH,OAAO,CAAC,WAAW;IAmBnB;;;;;;;;OAQG;IACI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAO9C;;;;;;;OAOG;IACI,QAAQ,IAAI,IAAI;CAGxB"}
@@ -0,0 +1,115 @@
1
+ import express from 'express';
2
+ import bodyParser from 'body-parser';
3
+ import cors from 'cors';
4
+ import logger from '../../logger/logger.js';
5
+ import errorHandler from './errorHandler.js';
6
+ import { AuthManager } from '../../auth/authManager.js';
7
+ import { createAuthMiddleware } from '../../auth/authMiddleware.js';
8
+ import { setupOAuthRoutes } from './routes/oauthRoutes.js';
9
+ import { setupStreamableHttpRoutes } from './routes/streamableHttpRoutes.js';
10
+ import { setupSseRoutes } from './routes/sseRoutes.js';
11
+ import { ServerConfigManager } from '../../core/server/serverConfig.js';
12
+ /**
13
+ * ExpressServer orchestrates the HTTP/SSE transport layer for the MCP server.
14
+ *
15
+ * This class manages the Express application, authentication, and route setup.
16
+ * It provides both HTTP and SSE transport options with optional OAuth 2.1 authentication.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const serverManager = await setupServer();
21
+ * const expressServer = new ExpressServer(serverManager);
22
+ * expressServer.start(3050, 'localhost');
23
+ * ```
24
+ */
25
+ export class ExpressServer {
26
+ app;
27
+ serverManager;
28
+ authManager;
29
+ configManager;
30
+ /**
31
+ * Creates a new ExpressServer instance.
32
+ *
33
+ * Initializes the Express application, sets up middleware, authentication,
34
+ * and configures all routes for MCP transport and OAuth endpoints.
35
+ *
36
+ * @param serverManager - The server manager instance for handling MCP operations
37
+ */
38
+ constructor(serverManager) {
39
+ this.app = express();
40
+ this.serverManager = serverManager;
41
+ this.configManager = ServerConfigManager.getInstance();
42
+ // Initialize auth manager with custom session storage path if configured
43
+ const sessionStoragePath = this.configManager.getSessionStoragePath();
44
+ this.authManager = new AuthManager(sessionStoragePath);
45
+ this.setupMiddleware();
46
+ this.setupRoutes();
47
+ }
48
+ /**
49
+ * Sets up Express middleware including CORS, body parsing, and error handling.
50
+ *
51
+ * Configures the basic middleware stack required for the MCP server:
52
+ * - CORS for cross-origin requests
53
+ * - JSON body parsing
54
+ * - Global error handling
55
+ */
56
+ setupMiddleware() {
57
+ this.app.use(cors()); // Allow all origins for local dev
58
+ this.app.use(bodyParser.json());
59
+ // Add error handling middleware
60
+ this.app.use(errorHandler);
61
+ }
62
+ /**
63
+ * Sets up all application routes including OAuth and MCP transport endpoints.
64
+ *
65
+ * Configures the following route groups:
66
+ * - OAuth 2.1 endpoints (always available, auth can be disabled)
67
+ * - Streamable HTTP transport routes with authentication middleware
68
+ * - SSE transport routes with authentication middleware
69
+ *
70
+ * Logs the authentication status for debugging purposes.
71
+ */
72
+ setupRoutes() {
73
+ // Create auth middleware
74
+ const authMiddleware = createAuthMiddleware(this.authManager);
75
+ // Setup OAuth routes (always available, but auth can be disabled)
76
+ setupOAuthRoutes(this.app, this.authManager);
77
+ // Setup MCP transport routes with auth middleware
78
+ setupStreamableHttpRoutes(this.app, this.serverManager, authMiddleware);
79
+ setupSseRoutes(this.app, this.serverManager, authMiddleware);
80
+ // Log authentication status
81
+ if (this.authManager.isAuthEnabled()) {
82
+ logger.info('Authentication enabled - OAuth 2.1 endpoints available');
83
+ }
84
+ else {
85
+ logger.info('Authentication disabled - all endpoints accessible without auth');
86
+ }
87
+ }
88
+ /**
89
+ * Starts the Express server on the specified port and host.
90
+ *
91
+ * Binds the Express application to the network interface and logs
92
+ * the server status including authentication configuration.
93
+ *
94
+ * @param port - The port number to listen on
95
+ * @param host - The host address to bind to
96
+ */
97
+ start(port, host) {
98
+ this.app.listen(port, host, () => {
99
+ const authStatus = this.authManager.isAuthEnabled() ? 'with authentication' : 'without authentication';
100
+ logger.info(`Server is running on port ${port} with HTTP/SSE and Streamable HTTP transport ${authStatus}`);
101
+ });
102
+ }
103
+ /**
104
+ * Performs graceful shutdown of the Express server.
105
+ *
106
+ * Cleans up resources including:
107
+ * - Authentication manager shutdown
108
+ * - Session cleanup
109
+ * - Timer cleanup
110
+ */
111
+ shutdown() {
112
+ this.authManager.shutdown();
113
+ }
114
+ }
115
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/transport/http/server.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
2
- import { Clients } from '../types.js';
2
+ import { Clients } from '../core/types/index.js';
3
3
  /**
4
4
  * Filters clients by tags
5
5
  * @param clients Record of client instances
@@ -1 +1 @@
1
- {"version":3,"file":"clientFiltering.d.ts","sourceRoot":"","sources":["../../src/utils/clientFiltering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAwBvG;AAED,KAAK,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,CAItE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,GAAG,YAAY,CAYrF;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,CAYpD"}
1
+ {"version":3,"file":"clientFiltering.d.ts","sourceRoot":"","sources":["../../src/utils/clientFiltering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAwBvG;AAED,KAAK,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,CAItE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,GAAG,YAAY,CAYrF;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,CAYpD"}
@@ -50,6 +50,7 @@ export declare function formatErrorResponse(error: any): {
50
50
  };
51
51
  /**
52
52
  * Extracts client name and resource name from a URI
53
+ * Uses robust parsing to handle edge cases where separator might appear in resource names.
53
54
  * @param uri The URI to parse
54
55
  * @param separator The separator used in the URI
55
56
  * @returns An object with clientName and resourceName
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandling.d.ts","sourceRoot":"","sources":["../../src/utils/errorHandling.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAC;AAE9E;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,GAAG,EAAE,EACrD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACjC,YAAY,EAAE,MAAM,GACnB,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAkB/B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,CAUjF;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAE/G;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKnD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAA;CAAE,CAa7F;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAWrG"}
1
+ {"version":3,"file":"errorHandling.d.ts","sourceRoot":"","sources":["../../src/utils/errorHandling.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAC;AAE9E;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,GAAG,EAAE,EACrD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACjC,YAAY,EAAE,MAAM,GACnB,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAkB/B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,CAUjF;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAE/G;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKnD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAA;CAAE,CAa7F;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAyCrG"}
@@ -102,19 +102,43 @@ export function formatErrorResponse(error) {
102
102
  }
103
103
  /**
104
104
  * Extracts client name and resource name from a URI
105
+ * Uses robust parsing to handle edge cases where separator might appear in resource names.
105
106
  * @param uri The URI to parse
106
107
  * @param separator The separator used in the URI
107
108
  * @returns An object with clientName and resourceName
108
109
  * @throws InvalidRequestError if the URI is invalid
109
110
  */
110
111
  export function parseUri(uri, separator) {
111
- const parts = uri.split(separator);
112
- if (parts.length !== 2) {
113
- throw new InvalidRequestError(`Invalid URI format: ${uri}`);
112
+ // Validate inputs
113
+ if (!uri || typeof uri !== 'string') {
114
+ throw new InvalidRequestError('URI must be a non-empty string');
115
+ }
116
+ if (!separator || typeof separator !== 'string') {
117
+ throw new InvalidRequestError('Separator must be a non-empty string');
118
+ }
119
+ // Find the first occurrence of the separator
120
+ const separatorIndex = uri.indexOf(separator);
121
+ if (separatorIndex === -1) {
122
+ throw new InvalidRequestError(`Invalid URI format: missing separator '${separator}' in '${uri}'`);
123
+ }
124
+ if (separatorIndex === 0) {
125
+ throw new InvalidRequestError(`Invalid URI format: URI cannot start with separator '${separator}'`);
126
+ }
127
+ if (separatorIndex === uri.length - separator.length) {
128
+ throw new InvalidRequestError(`Invalid URI format: URI cannot end with separator '${separator}'`);
129
+ }
130
+ const clientName = uri.substring(0, separatorIndex);
131
+ const resourceName = uri.substring(separatorIndex + separator.length);
132
+ // Validate extracted parts
133
+ if (!clientName.trim()) {
134
+ throw new InvalidRequestError('Client name cannot be empty');
135
+ }
136
+ if (!resourceName.trim()) {
137
+ throw new InvalidRequestError('Resource name cannot be empty');
114
138
  }
115
139
  return {
116
- clientName: parts[0],
117
- resourceName: parts[1],
140
+ clientName,
141
+ resourceName,
118
142
  };
119
143
  }
120
144
  //# sourceMappingURL=errorHandling.js.map