@@ -14,6 +14,7 @@ export interface McpUserConfiguration {
1414 user_id : string ;
1515 user_args ?: Record < string , string > ;
1616 user_env ?: Record < string , string > ;
17+ user_headers ?: Record < string , string > ;
1718 created_at : Date ;
1819 updated_at : Date ;
1920 last_used_at ?: Date ;
@@ -29,18 +30,21 @@ export interface McpUserConfiguration {
2930 description : string ;
3031 user_args_schema ?: any [ ] ;
3132 user_env_schema ?: any [ ] ;
33+ user_headers_schema ?: any [ ] ;
3234 } ;
3335 } ;
3436}
3537
3638export interface CreateUserConfigRequest {
3739 user_args ?: Record < string , string > ;
3840 user_env ?: Record < string , string > ;
41+ user_headers ?: Record < string , string > ;
3942}
4043
4144export interface UpdateUserConfigRequest {
4245 user_args ?: Record < string , string > ;
4346 user_env ?: Record < string , string > ;
47+ user_headers ?: Record < string , string > ;
4448}
4549
4650export class McpUserConfigurationService {
@@ -106,6 +110,7 @@ export class McpUserConfigurationService {
106110 for ( const row of configurations ) {
107111 const userArgsSchema = this . parseJsonField ( row . server ?. user_args_schema , [ ] ) ;
108112 const userEnvSchema = this . parseJsonField ( row . server ?. user_env_schema , [ ] ) ;
113+ const userHeadersSchema = this . parseJsonField ( row . server ?. user_headers_schema , [ ] ) ;
109114
110115 const userArgs = row . config . user_args
111116 ? await McpArgsStorage . retrieveUserArgs (
@@ -125,10 +130,20 @@ export class McpUserConfigurationService {
125130 )
126131 : undefined ;
127132
133+ const userHeaders = row . config . user_headers
134+ ? await McpEnvStorage . retrieveUserEnv (
135+ row . config . user_headers ,
136+ userHeadersSchema ,
137+ { maskSecrets : true } ,
138+ this . logger
139+ )
140+ : undefined ;
141+
128142 processedConfigurations . push ( {
129143 ...row . config ,
130144 user_args : userArgs ,
131145 user_env : userEnv ,
146+ user_headers : userHeaders ,
132147 installation : row . installation ? {
133148 id : row . installation . id ,
134149 installation_name : row . installation . installation_name ,
@@ -139,7 +154,8 @@ export class McpUserConfigurationService {
139154 name : row . server . name ,
140155 description : row . server . description ,
141156 user_args_schema : userArgsSchema ,
142- user_env_schema : userEnvSchema
157+ user_env_schema : userEnvSchema ,
158+ user_headers_schema : userHeadersSchema
143159 } : undefined
144160 } : undefined
145161 } ) ;
@@ -192,6 +208,7 @@ export class McpUserConfigurationService {
192208
193209 const userArgsSchema = this . parseJsonField ( server ?. user_args_schema , [ ] ) ;
194210 const userEnvSchema = this . parseJsonField ( server ?. user_env_schema , [ ] ) ;
211+ const userHeadersSchema = this . parseJsonField ( server ?. user_headers_schema , [ ] ) ;
195212
196213 const userArgs = config . user_args
197214 ? await McpArgsStorage . retrieveUserArgs (
@@ -211,10 +228,20 @@ export class McpUserConfigurationService {
211228 )
212229 : undefined ;
213230
231+ const userHeaders = config . user_headers
232+ ? await McpEnvStorage . retrieveUserEnv (
233+ config . user_headers ,
234+ userHeadersSchema ,
235+ { maskSecrets : true } ,
236+ this . logger
237+ )
238+ : undefined ;
239+
214240 return {
215241 ...config ,
216242 user_args : userArgs ,
217243 user_env : userEnv ,
244+ user_headers : userHeaders ,
218245 installation : installation ? {
219246 id : installation . id ,
220247 installation_name : installation . installation_name ,
@@ -225,7 +252,8 @@ export class McpUserConfigurationService {
225252 name : server . name ,
226253 description : server . description ,
227254 user_args_schema : userArgsSchema ,
228- user_env_schema : userEnvSchema
255+ user_env_schema : userEnvSchema ,
256+ user_headers_schema : userHeadersSchema
229257 } : undefined
230258 } : undefined
231259 } ;
@@ -275,6 +303,9 @@ export class McpUserConfigurationService {
275303 if ( data . user_env ) {
276304 this . validateUserEnv ( data . user_env , this . parseJsonField ( serverInfo . user_env_schema , [ ] ) ) ;
277305 }
306+ if ( data . user_headers ) {
307+ this . validateUserHeaders ( data . user_headers , this . parseJsonField ( serverInfo . user_headers_schema , [ ] ) ) ;
308+ }
278309 }
279310
280311 const configId = nanoid ( ) ;
@@ -294,6 +325,11 @@ export class McpUserConfigurationService {
294325 this . parseJsonField ( serverInfo ?. user_env_schema , [ ] ) ,
295326 this . logger
296327 ) : null ,
328+ user_headers : data . user_headers ? await McpEnvStorage . storeUserEnv (
329+ data . user_headers ,
330+ this . parseJsonField ( serverInfo ?. user_headers_schema , [ ] ) ,
331+ this . logger
332+ ) : null ,
297333 created_at : now ,
298334 updated_at : now ,
299335 last_used_at : null
@@ -344,6 +380,9 @@ export class McpUserConfigurationService {
344380 if ( data . user_env !== undefined ) {
345381 this . validateUserEnv ( data . user_env , existing . installation . server . user_env_schema || [ ] ) ;
346382 }
383+ if ( data . user_headers !== undefined ) {
384+ this . validateUserHeaders ( data . user_headers , existing . installation . server . user_headers_schema || [ ] ) ;
385+ }
347386 }
348387
349388
@@ -368,6 +407,14 @@ export class McpUserConfigurationService {
368407 ) : null ;
369408 }
370409
410+ if ( data . user_headers !== undefined ) {
411+ updateData . user_headers = data . user_headers ? await McpEnvStorage . storeUserEnv (
412+ data . user_headers ,
413+ existing . installation ?. server ?. user_headers_schema || [ ] ,
414+ this . logger
415+ ) : null ;
416+ }
417+
371418 await this . db
372419 . update ( mcpUserConfigurations )
373420 . set ( updateData )
@@ -497,6 +544,24 @@ export class McpUserConfigurationService {
497544 }
498545 }
499546
547+ private validateUserHeaders ( userHeaders : Record < string , string > , schema : any [ ] ) : void {
548+ // Validate user headers against schema
549+ // Only validate the fields that are actually being sent, not all required fields
550+ for ( const [ headerName , headerValue ] of Object . entries ( userHeaders ) ) {
551+ const schemaEntry = schema . find ( ( header : any ) => header . name === headerName )
552+
553+ if ( schemaEntry ) {
554+ // If this field is required and the sent value is empty, throw error
555+ if ( schemaEntry . required && ( ! headerValue || headerValue . trim ( ) === '' ) ) {
556+ throw new Error ( `Required header '${ headerName } ' is missing or empty` )
557+ }
558+
559+ // Additional type validation can be added here in the future
560+ }
561+ // Note: We don't validate fields that aren't in the schema - allowing flexibility
562+ }
563+ }
564+
500565 private parseJsonField ( fieldValue : any , defaultValue : any ) : any {
501566 // Handle null, undefined, or empty values
502567 if ( fieldValue === null || fieldValue === undefined || fieldValue === '' ) {
0 commit comments