@@ -2,7 +2,9 @@ import { randomUUID } from 'node:crypto'
22import type { IncomingMessage , ServerResponse } from 'node:http'
33import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
44import type { SevLogger } from '@transloadit/sev-logger'
5+ import { isBasicAuthorized , normalizePath , parsePathname } from './http-helpers.ts'
56import { createMcpRequestHandler } from './http-request-handler.ts'
7+ import { getMetrics , getMetricsContentType } from './metrics.ts'
68import type { TransloaditMcpServerOptions } from './server.ts'
79import { createTransloaditMcpServer } from './server.ts'
810
@@ -12,6 +14,8 @@ export type TransloaditMcpHttpOptions = TransloaditMcpServerOptions & {
1214 enableDnsRebindingProtection ?: boolean
1315 mcpToken ?: string
1416 path ?: string
17+ metricsPath ?: string | false
18+ metricsAuth ?: { username : string ; password : string }
1519 sessionIdGenerator ?: ( ( ) => string ) | undefined
1620 logger ?: SevLogger
1721}
@@ -38,12 +42,47 @@ export const createTransloaditMcpHttpHandler = async (
3842
3943 await server . connect ( transport )
4044
41- const handler = createMcpRequestHandler ( transport , {
45+ const expectedPath = options . path ?? defaultPath
46+ const metricsPath =
47+ options . metricsPath === false ? undefined : normalizePath ( options . metricsPath ?? '/metrics' )
48+ const metricsAuth = options . metricsAuth
49+
50+ const mcpHandler = createMcpRequestHandler ( transport , {
4251 allowedOrigins : options . allowedOrigins ,
4352 mcpToken : options . mcpToken ,
44- path : { expectedPath : options . path ?? defaultPath } ,
53+ path : { expectedPath } ,
4554 logger : options . logger ,
4655 redactSecrets : [ options . mcpToken , options . authKey , options . authSecret ] ,
56+ } )
57+
58+ const handler = ( async ( req , res ) => {
59+ if ( metricsPath ) {
60+ const pathname = normalizePath ( parsePathname ( req . url , expectedPath ) )
61+ if ( pathname === metricsPath ) {
62+ if ( metricsAuth && ! isBasicAuthorized ( req , metricsAuth ) ) {
63+ res . statusCode = 401
64+ res . setHeader ( 'WWW-Authenticate' , 'Basic realm="metrics"' )
65+ res . end ( 'Unauthorized' )
66+ return
67+ }
68+ if ( req . method !== 'GET' && req . method !== 'HEAD' ) {
69+ res . statusCode = 405
70+ res . end ( 'Method Not Allowed' )
71+ return
72+ }
73+
74+ res . statusCode = 200
75+ res . setHeader ( 'Content-Type' , getMetricsContentType ( ) )
76+ if ( req . method === 'HEAD' ) {
77+ res . end ( )
78+ return
79+ }
80+ res . end ( await getMetrics ( ) )
81+ return
82+ }
83+ }
84+
85+ await mcpHandler ( req , res )
4786 } ) as TransloaditMcpHttpHandler
4887
4988 handler . close = async ( ) => {
0 commit comments