4141using Microsoft . Extensions . Logging ;
4242using Microsoft . Identity . Client ;
4343
44- using ModelContextProtocol . AspNetCore ;
4544using StackExchange . Redis ;
4645
4746namespace GeneXus . Application
@@ -74,7 +73,6 @@ public static void Main(string[] args)
7473
7574 }
7675
77-
7876 if ( port == DEFAULT_PORT )
7977 {
8078 BuildWebHost ( null ) . Run ( ) ;
@@ -88,7 +86,7 @@ public static void Main(string[] args)
8886 {
8987 Console . Error . WriteLine ( "ERROR:" ) ;
9088 Console . Error . WriteLine ( "Web Host terminated unexpectedly: {0}" , e . Message ) ;
91- }
89+ }
9290 }
9391
9492 public static IWebHost BuildWebHost ( string [ ] args ) =>
@@ -287,43 +285,7 @@ public void ConfigureServices(IServiceCollection services)
287285 }
288286 if ( Startup . IsMcp )
289287 {
290- var mcp = services . AddMcpServer ( options =>
291- {
292- options . ServerInfo = new ModelContextProtocol . Protocol . Implementation
293- {
294- Name = "GxMcpServer" ,
295- Version = Assembly . GetExecutingAssembly ( )
296- . GetCustomAttribute < AssemblyInformationalVersionAttribute > ( ) ? . InformationalVersion ?? "1.0.0"
297- } ;
298- } )
299- . WithHttpTransport ( transportOptions =>
300- {
301- // SSE endpoints (/sse, /message) require STATEFUL sessions to support server-to-client push
302- transportOptions . Stateless = false ;
303- transportOptions . IdleTimeout = TimeSpan . FromSeconds ( 30 ) ;
304- GXLogging . Debug ( log , "MCP HTTP Transport configured: Stateless=false (SSE enabled), IdleTimeout=10min" ) ;
305- } ) ;
306-
307- try
308- {
309- var mcpAssemblies = FileTools . MCPFileTools ( Startup . LocalPath ) . ToList ( ) ;
310- foreach ( var assembly in mcpAssemblies )
311- {
312- try
313- {
314- mcp . WithToolsFromAssembly ( assembly ) ;
315- GXLogging . Debug ( log , $ "Successfully loaded MCP tools from assembly: { assembly . FullName } ") ;
316- }
317- catch ( Exception assemblyEx )
318- {
319- GXLogging . Error ( log , $ "Failed to load MCP tools from assembly: { assembly . FullName } ", assemblyEx ) ;
320- }
321- }
322- }
323- catch ( Exception ex )
324- {
325- GXLogging . Error ( log , "Error discovering MCP tool assemblies" , ex ) ;
326- }
288+ StartupMcp . AddService ( services ) ;
327289 }
328290
329291 services . AddDirectoryBrowser ( ) ;
@@ -332,20 +294,20 @@ public void ConfigureServices(IServiceCollection services)
332294 services . AddResponseCompression ( options =>
333295 {
334296 options . MimeTypes = new [ ]
335- {
336- // Default
337- "text/plain" ,
338- "text/css" ,
339- "application/javascript" ,
340- "text/html" ,
341- "application/xml" ,
342- "text/xml" ,
343- "application/json" ,
344- "text/json" ,
345- // Custom
346- "application/json" ,
347- "application/pdf"
348- } ;
297+ {
298+ // Default
299+ "text/plain" ,
300+ "text/css" ,
301+ "application/javascript" ,
302+ "text/html" ,
303+ "application/xml" ,
304+ "text/xml" ,
305+ "application/json" ,
306+ "text/json" ,
307+ // Custom
308+ "application/json" ,
309+ "application/pdf"
310+ } ;
349311 options . EnableForHttps = true ;
350312 } ) ;
351313 }
@@ -423,9 +385,9 @@ private void RegisterRestServices(IMvcBuilder mvcBuilder)
423385 try
424386 {
425387 string [ ] controllerAssemblyQualifiedName = new string ( File . ReadLines ( svcFile ) . First ( ) . SkipWhile ( c => c != '"' )
426- . Skip ( 1 )
427- . TakeWhile ( c => c != '"' )
428- . ToArray ( ) ) . Trim ( ) . Split ( ',' ) ;
388+ . Skip ( 1 )
389+ . TakeWhile ( c => c != '"' )
390+ . ToArray ( ) ) . Trim ( ) . Split ( ',' ) ;
429391 string controllerAssemblyName = controllerAssemblyQualifiedName . Last ( ) ;
430392 if ( ! serviceAssemblies . Contains ( controllerAssemblyName ) )
431393 {
@@ -486,17 +448,17 @@ private void DefineCorsPolicy(IServiceCollection services)
486448 services . AddCors ( options =>
487449 {
488450 options . AddPolicy ( name : CORS_POLICY_NAME ,
489- policy =>
490- {
491- policy . WithOrigins ( origins ) ;
492- if ( ! corsAllowedOrigins . Contains ( CORS_ANY_ORIGIN ) )
493- {
494- policy . AllowCredentials ( ) ;
495- }
496- policy . AllowAnyHeader ( ) ;
497- policy . AllowAnyMethod ( ) ;
498- policy . SetPreflightMaxAge ( TimeSpan . FromSeconds ( CORS_MAX_AGE_SECONDS ) ) ;
499- } ) ;
451+ policy =>
452+ {
453+ policy . WithOrigins ( origins ) ;
454+ if ( ! corsAllowedOrigins . Contains ( CORS_ANY_ORIGIN ) )
455+ {
456+ policy . AllowCredentials ( ) ;
457+ }
458+ policy . AllowAnyHeader ( ) ;
459+ policy . AllowAnyMethod ( ) ;
460+ policy . SetPreflightMaxAge ( TimeSpan . FromSeconds ( CORS_MAX_AGE_SECONDS ) ) ;
461+ } ) ;
500462 } ) ;
501463 }
502464 }
@@ -550,7 +512,6 @@ private void ConfigureSessionService(IServiceCollection services, ISessionServic
550512 }
551513 else
552514 {
553-
554515 services . AddDistributedSqlServerCache ( options =>
555516 {
556517 GXLogging . Info ( log , $ "Using SQLServer for Distributed session, ConnectionString:{ sessionService . ConnectionString } , SchemaName: { sessionService . Schema } , TableName: { sessionService . TableName } ") ;
@@ -640,11 +601,11 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos
640601 Predicate = check => check . Tags . Contains ( "ready" )
641602 } ) ;
642603 if ( Startup . IsMcp )
643- {
644- // Register MCP endpoints at root, exposing /sse and /message
645- endpoints . MapMcp ( ) ;
604+ {
605+ StartupMcp . MapEndpoints ( endpoints ) ;
646606 }
647607 } ) ;
608+
648609 if ( log . IsCriticalEnabled && env . IsDevelopment ( ) )
649610 {
650611 try
@@ -696,7 +657,7 @@ public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHos
696657 } ,
697658 ContentTypeProvider = provider
698659 } ) ;
699-
660+
700661 app . UseExceptionHandler ( new ExceptionHandlerOptions
701662 {
702663 ExceptionHandler = new CustomExceptionHandlerMiddleware ( ) . Invoke ,
0 commit comments