@1mcp/agent 0.10.1 → 0.11.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.
- package/README.md +14 -0
- package/build/clients/clientManager.d.ts +3 -2
- package/build/clients/clientManager.d.ts.map +1 -1
- package/build/clients/clientManager.js +10 -2
- package/build/clients/clientManager.js.map +1 -1
- package/build/constants.d.ts +25 -1
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +31 -2
- package/build/constants.js.map +1 -1
- package/build/handlers/notificationHandlers.d.ts.map +1 -1
- package/build/handlers/notificationHandlers.js +41 -14
- package/build/handlers/notificationHandlers.js.map +1 -1
- package/build/handlers/requestHandlers.d.ts.map +1 -1
- package/build/handlers/requestHandlers.js +43 -1
- package/build/handlers/requestHandlers.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +43 -4
- package/build/index.js.map +1 -1
- package/build/middleware/loggingMiddleware.d.ts.map +1 -1
- package/build/middleware/loggingMiddleware.js +10 -6
- package/build/middleware/loggingMiddleware.js.map +1 -1
- package/build/server/auth/authManager.d.ts +109 -0
- package/build/server/auth/authManager.d.ts.map +1 -0
- package/build/server/auth/authManager.js +173 -0
- package/build/server/auth/authManager.js.map +1 -0
- package/build/server/auth/authMiddleware.d.ts +16 -0
- package/build/server/auth/authMiddleware.d.ts.map +1 -0
- package/build/server/auth/authMiddleware.js +45 -0
- package/build/server/auth/authMiddleware.js.map +1 -0
- package/build/server/auth/sessionManager.d.ts +196 -0
- package/build/server/auth/sessionManager.d.ts.map +1 -0
- package/build/server/auth/sessionManager.js +376 -0
- package/build/server/auth/sessionManager.js.map +1 -0
- package/build/server/config/serverConfig.d.ts +100 -0
- package/build/server/config/serverConfig.d.ts.map +1 -0
- package/build/server/config/serverConfig.js +117 -0
- package/build/server/config/serverConfig.js.map +1 -0
- package/build/server/expressServer.d.ts +60 -2
- package/build/server/expressServer.d.ts.map +1 -1
- package/build/server/expressServer.js +91 -153
- package/build/server/expressServer.js.map +1 -1
- package/build/server/routes/oauthRoutes.d.ts +14 -0
- package/build/server/routes/oauthRoutes.d.ts.map +1 -0
- package/build/server/routes/oauthRoutes.js +132 -0
- package/build/server/routes/oauthRoutes.js.map +1 -0
- package/build/server/routes/sseRoutes.d.ts +4 -0
- package/build/server/routes/sseRoutes.d.ts.map +1 -0
- package/build/server/routes/sseRoutes.js +64 -0
- package/build/server/routes/sseRoutes.js.map +1 -0
- package/build/server/routes/streamableHttpRoutes.d.ts +4 -0
- package/build/server/routes/streamableHttpRoutes.d.ts.map +1 -0
- package/build/server/routes/streamableHttpRoutes.js +94 -0
- package/build/server/routes/streamableHttpRoutes.js.map +1 -0
- package/build/server.js +1 -1
- package/build/server.js.map +1 -1
- package/build/serverManager.d.ts +3 -1
- package/build/serverManager.d.ts.map +1 -1
- package/build/serverManager.js +8 -1
- package/build/serverManager.js.map +1 -1
- package/build/services/configReloadService.d.ts.map +1 -1
- package/build/services/configReloadService.js +4 -0
- package/build/services/configReloadService.js.map +1 -1
- package/build/types.d.ts +2 -1
- package/build/types.d.ts.map +1 -1
- package/build/utils/errorTypes.d.ts +4 -1
- package/build/utils/errorTypes.d.ts.map +1 -1
- package/build/utils/errorTypes.js +9 -1
- package/build/utils/errorTypes.js.map +1 -1
- package/package.json +9 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expressServer.d.ts","sourceRoot":"","sources":["../../src/server/expressServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"expressServer.d.ts","sourceRoot":"","sources":["../../src/server/expressServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAUpD;;;;;;;;;;;;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"}
|
|
@@ -1,177 +1,115 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import express from 'express';
|
|
3
2
|
import bodyParser from 'body-parser';
|
|
4
|
-
import
|
|
5
|
-
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
6
|
-
import { ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import cors from 'cors';
|
|
7
4
|
import logger from '../logger/logger.js';
|
|
8
|
-
import { SSE_ENDPOINT, MESSAGES_ENDPOINT, STREAMABLE_HTTP_ENDPOINT } from '../constants.js';
|
|
9
|
-
import tagsExtractor from './tagsExtractor.js';
|
|
10
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 './config/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
|
+
*/
|
|
11
25
|
export class ExpressServer {
|
|
12
26
|
app;
|
|
13
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
|
+
*/
|
|
14
38
|
constructor(serverManager) {
|
|
15
39
|
this.app = express();
|
|
16
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);
|
|
17
45
|
this.setupMiddleware();
|
|
18
|
-
this.
|
|
19
|
-
this.setupSseRoutes();
|
|
46
|
+
this.setupRoutes();
|
|
20
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
|
+
*/
|
|
21
56
|
setupMiddleware() {
|
|
57
|
+
this.app.use(cors()); // Allow all origins for local dev
|
|
22
58
|
this.app.use(bodyParser.json());
|
|
23
59
|
// Add error handling middleware
|
|
24
60
|
this.app.use(errorHandler);
|
|
25
61
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
transport = existingTransport;
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
res.status(400).json({
|
|
55
|
-
error: {
|
|
56
|
-
code: ErrorCode.InvalidParams,
|
|
57
|
-
message: 'Session already exists but uses a different transport protocol',
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
await transport.handleRequest(req, res, req.body);
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
logger.error('Streamable HTTP error:', error);
|
|
67
|
-
res.status(500).end();
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
this.app.get(STREAMABLE_HTTP_ENDPOINT, async (req, res) => {
|
|
71
|
-
try {
|
|
72
|
-
logger.info('[GET] streamable-http', { query: req.query, headers: req.headers });
|
|
73
|
-
const sessionId = req.headers['mcp-session-id'];
|
|
74
|
-
if (!sessionId) {
|
|
75
|
-
res.status(400).json({
|
|
76
|
-
error: {
|
|
77
|
-
code: ErrorCode.InvalidParams,
|
|
78
|
-
message: 'Invalid params: sessionId is required',
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const transport = this.serverManager.getTransport(sessionId);
|
|
84
|
-
await transport.handleRequest(req, res, req.body);
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
logger.error('Streamable HTTP error:', error);
|
|
88
|
-
res.status(500).end();
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
this.app.delete(STREAMABLE_HTTP_ENDPOINT, async (req, res) => {
|
|
92
|
-
try {
|
|
93
|
-
logger.info('[DELETE] streamable-http', { query: req.query, headers: req.headers });
|
|
94
|
-
const sessionId = req.headers['mcp-session-id'];
|
|
95
|
-
if (!sessionId) {
|
|
96
|
-
res.status(400).json({
|
|
97
|
-
error: {
|
|
98
|
-
code: ErrorCode.InvalidParams,
|
|
99
|
-
message: 'Invalid params: sessionId is required',
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const transport = this.serverManager.getTransport(sessionId);
|
|
105
|
-
await transport.handleRequest(req, res);
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
logger.error('Streamable HTTP error:', error);
|
|
109
|
-
res.status(500).end();
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
setupSseRoutes() {
|
|
114
|
-
this.app.get(SSE_ENDPOINT, tagsExtractor, async (req, res) => {
|
|
115
|
-
try {
|
|
116
|
-
logger.info('[GET] sse', { query: req.query, headers: req.headers });
|
|
117
|
-
const transport = new SSEServerTransport(MESSAGES_ENDPOINT, res);
|
|
118
|
-
// Use tags from middleware
|
|
119
|
-
const tags = res.locals.tags;
|
|
120
|
-
// Connect the transport using the server manager
|
|
121
|
-
await this.serverManager.connectTransport(transport, transport.sessionId, {
|
|
122
|
-
tags,
|
|
123
|
-
enablePagination: req.query.pagination === 'true',
|
|
124
|
-
});
|
|
125
|
-
transport.onclose = () => {
|
|
126
|
-
this.serverManager.disconnectTransport(transport.sessionId);
|
|
127
|
-
logger.info('transport closed', transport.sessionId);
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
catch (error) {
|
|
131
|
-
logger.error('SSE connection error:', error);
|
|
132
|
-
res.status(500).end();
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
this.app.post(MESSAGES_ENDPOINT, async (req, res) => {
|
|
136
|
-
try {
|
|
137
|
-
const sessionId = req.query.sessionId;
|
|
138
|
-
if (!sessionId) {
|
|
139
|
-
res.status(400).json({
|
|
140
|
-
error: {
|
|
141
|
-
code: ErrorCode.InvalidParams,
|
|
142
|
-
message: 'Invalid params: sessionId is required',
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
logger.info('message', { body: req.body, sessionId });
|
|
148
|
-
const transport = this.serverManager.getTransport(sessionId);
|
|
149
|
-
if (transport instanceof SSEServerTransport) {
|
|
150
|
-
await transport.handlePostMessage(req, res, req.body);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
res.status(404).json({
|
|
154
|
-
error: {
|
|
155
|
-
code: ErrorCode.InvalidParams,
|
|
156
|
-
message: 'Transport not found',
|
|
157
|
-
},
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
logger.error('Message handling error:', error);
|
|
162
|
-
res.status(500).json({
|
|
163
|
-
error: {
|
|
164
|
-
code: ErrorCode.InternalError,
|
|
165
|
-
message: 'Internal server error',
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
});
|
|
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
|
+
}
|
|
170
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
|
+
*/
|
|
171
97
|
start(port, host) {
|
|
172
98
|
this.app.listen(port, host, () => {
|
|
173
|
-
|
|
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}`);
|
|
174
101
|
});
|
|
175
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
|
+
}
|
|
176
114
|
}
|
|
177
115
|
//# sourceMappingURL=expressServer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expressServer.js","sourceRoot":"","sources":["../../src/server/expressServer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"expressServer.js","sourceRoot":"","sources":["../../src/server/expressServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { AuthManager } from '../auth/authManager.js';
|
|
3
|
+
/**
|
|
4
|
+
* Sets up OAuth 2.1 and related endpoints on the Express app.
|
|
5
|
+
*
|
|
6
|
+
* This function registers all OAuth 2.1 endpoints (authorization, token, metadata, registration)
|
|
7
|
+
* and MCP resource metadata endpoints on the provided Express application. It uses the provided
|
|
8
|
+
* AuthManager for all authentication and token operations.
|
|
9
|
+
*
|
|
10
|
+
* @param app - The Express application instance
|
|
11
|
+
* @param authManager - The AuthManager instance for OAuth/session logic
|
|
12
|
+
*/
|
|
13
|
+
export declare function setupOAuthRoutes(app: express.Application, authManager: AuthManager): void;
|
|
14
|
+
//# sourceMappingURL=oauthRoutes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthRoutes.d.ts","sourceRoot":"","sources":["../../../src/server/routes/oauthRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAI9B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAKrD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAsJzF"}
|
|
@@ -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 '../config/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/server/routes/oauthRoutes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { ServerManager } from '../../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/server/routes/sseRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,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 '../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
|
+
logger.info('transport closed', transport.sessionId);
|
|
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/server/routes/sseRoutes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { ServerManager } from '../../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/server/routes/streamableHttpRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,CAAC,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,OAAO,CAAC,cAAc,GACrC,IAAI,CAkGN"}
|