1313 */
1414
1515import { BearerAuthMiddlewareOptions , requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js" ;
16- import { getOAuthProtectedResourceMetadataUrl , mcpAuthMetadataRouter } from "@modelcontextprotocol/sdk/server/auth/router.js" ;
16+ import { getOAuthProtectedResourceMetadataUrl } from "@modelcontextprotocol/sdk/server/auth/router.js" ;
1717import cors from "cors" ;
1818import rateLimit from "express-rate-limit" ;
1919import express from "express" ;
@@ -135,13 +135,19 @@ app.use(baseSecurityHeaders);
135135// Enable CORS pre-flight requests
136136app . options ( '*' , cors ( corsOptions ) ) ;
137137
138- // Rate limiting for custom endpoints
138+ // Rate limiting for endpoints
139139const staticFileRateLimit = rateLimit ( {
140140 windowMs : 10 * 60 * 1000 , // 10 minutes
141141 limit : 25 , // 25 requests per 10 minutes for static files
142142 message : { error : 'too_many_requests' , error_description : 'Static file rate limit exceeded' }
143143} ) ;
144144
145+ const mcpRateLimit = rateLimit ( {
146+ windowMs : 15 * 60 * 1000 , // 15 minutes
147+ limit : 100 , // 100 requests per 15 minutes per IP
148+ message : { error : 'too_many_requests' , error_description : 'MCP rate limit exceeded' }
149+ } ) ;
150+
145151// MCP server using external auth server
146152logger . info ( 'Starting MCP server' , {
147153 baseUri : BASE_URI ,
@@ -150,7 +156,7 @@ logger.info('Starting MCP server', {
150156} ) ;
151157
152158// Auth server state - will be populated asynchronously
153- let authMetadata : any ;
159+ let authMetadata : Record < string , unknown > | undefined ;
154160let authServerAvailable = false ;
155161
156162// OAuth metadata endpoint - responds based on current auth server status
@@ -197,13 +203,13 @@ const bearerAuth: express.RequestHandler = (req, res, next) => {
197203} ;
198204
199205// MCP routes (legacy SSE transport)
200- app . get ( "/sse" , cors ( corsOptions ) , bearerAuth , sseHeaders , handleSSEConnection ) ;
201- app . post ( "/message" , cors ( corsOptions ) , bearerAuth , sensitiveDataHeaders , handleMessage ) ;
206+ app . get ( "/sse" , cors ( corsOptions ) , mcpRateLimit , bearerAuth , sseHeaders , handleSSEConnection ) ;
207+ app . post ( "/message" , cors ( corsOptions ) , mcpRateLimit , bearerAuth , sensitiveDataHeaders , handleMessage ) ;
202208
203209// MCP routes (new streamable HTTP transport)
204- app . get ( "/mcp" , cors ( corsOptions ) , bearerAuth , handleStreamableHTTP ) ;
205- app . post ( "/mcp" , cors ( corsOptions ) , bearerAuth , handleStreamableHTTP ) ;
206- app . delete ( "/mcp" , cors ( corsOptions ) , bearerAuth , handleStreamableHTTP ) ;
210+ app . get ( "/mcp" , cors ( corsOptions ) , mcpRateLimit , bearerAuth , handleStreamableHTTP ) ;
211+ app . post ( "/mcp" , cors ( corsOptions ) , mcpRateLimit , bearerAuth , handleStreamableHTTP ) ;
212+ app . delete ( "/mcp" , cors ( corsOptions ) , mcpRateLimit , bearerAuth , handleStreamableHTTP ) ;
207213
208214// Health check endpoint
209215app . get ( "/health" , ( req , res ) => {
@@ -291,9 +297,9 @@ async function connectToAuthServer() {
291297 authMetadata = await authMetadataResponse . json ( ) ;
292298 authServerAvailable = true ;
293299 logger . info ( 'Successfully connected to auth server' , {
294- issuer : authMetadata . issuer ,
295- authorizationEndpoint : authMetadata . authorization_endpoint ,
296- tokenEndpoint : authMetadata . token_endpoint
300+ issuer : authMetadata ? .issuer ,
301+ authorizationEndpoint : authMetadata ? .authorization_endpoint ,
302+ tokenEndpoint : authMetadata ? .token_endpoint
297303 } ) ;
298304 break ; // Success, exit retry loop
299305
0 commit comments