11using Aspire . Hosting . ApplicationModel ;
2+ using Microsoft . Extensions . DependencyInjection ;
23
34namespace Aspire . Hosting ;
45
@@ -15,16 +16,39 @@ public static class McpInspectorResourceBuilderExtensions
1516 /// <param name="clientPort">The port for the client application. Defaults to 6274.</param>
1617 /// <param name="serverPort">The port for the server proxy application. Defaults to 6277.</param>
1718 /// <param name="inspectorVersion">The version of the Inspector app to use</param>
19+ [ Obsolete ( "Use the overload with McpInspectorOptions instead. This overload will be removed in the next version." ) ]
1820 public static IResourceBuilder < McpInspectorResource > AddMcpInspector ( this IDistributedApplicationBuilder builder , [ ResourceName ] string name , int clientPort = 6274 , int serverPort = 6277 , string inspectorVersion = McpInspectorResource . InspectorVersion )
1921 {
20- return builder . AddResource ( new McpInspectorResource ( name ) )
21- . WithArgs ( [ "-y" , $ "@modelcontextprotocol/inspector@{ inspectorVersion } "] )
22+ ArgumentNullException . ThrowIfNull ( builder ) ;
23+
24+ return AddMcpInspector ( builder , name , options =>
25+ {
26+ options . ClientPort = clientPort ;
27+ options . ServerPort = serverPort ;
28+ options . InspectorVersion = inspectorVersion ;
29+ } ) ;
30+ }
31+
32+ /// <summary>
33+ /// Adds a MCP Inspector container resource to the <see cref="IDistributedApplicationBuilder"/> using an options object.
34+ /// </summary>
35+ /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to which the MCP Inspector resource will be added.</param>
36+ /// <param name="name">The name of the MCP Inspector container resource.</param>
37+ /// <param name="options">The <see cref="McpInspectorOptions"/> to configure the MCP Inspector resource.</param>
38+ /// <returns>A reference to the <see cref="IResourceBuilder{McpInspectorResource}"/> for further configuration.</returns>
39+ public static IResourceBuilder < McpInspectorResource > AddMcpInspector ( this IDistributedApplicationBuilder builder , [ ResourceName ] string name , McpInspectorOptions options )
40+ {
41+ ArgumentNullException . ThrowIfNull ( builder ) ;
42+ ArgumentNullException . ThrowIfNull ( options ) ;
43+
44+ var proxyTokenParameter = options . ProxyToken ? . Resource ?? ParameterResourceBuilderExtensions . CreateDefaultPasswordParameter ( builder , $ "{ name } -proxyToken") ;
45+
46+ var resource = builder . AddResource ( new McpInspectorResource ( name ) )
47+ . WithArgs ( [ "-y" , $ "@modelcontextprotocol/inspector@{ options . InspectorVersion } "] )
2248 . ExcludeFromManifest ( )
23- . WithHttpEndpoint ( isProxied : false , port : clientPort , env : "CLIENT_PORT" , name : McpInspectorResource . ClientEndpointName )
24- . WithHttpEndpoint ( isProxied : false , port : serverPort , env : "SERVER_PORT" , name : McpInspectorResource . ServerProxyEndpointName )
25- . WithEnvironment ( "DANGEROUSLY_OMIT_AUTH" , "true" )
49+ . WithHttpEndpoint ( isProxied : false , port : options . ClientPort , env : "CLIENT_PORT" , name : McpInspectorResource . ClientEndpointName )
50+ . WithHttpEndpoint ( isProxied : false , port : options . ServerPort , env : "SERVER_PORT" , name : McpInspectorResource . ServerProxyEndpointName )
2651 . WithHttpHealthCheck ( "/" , endpointName : McpInspectorResource . ClientEndpointName )
27- . WithHttpHealthCheck ( "/config" , endpointName : McpInspectorResource . ServerProxyEndpointName )
2852 . WithEnvironment ( "MCP_AUTO_OPEN_ENABLED" , "false" )
2953 . WithUrlForEndpoint ( McpInspectorResource . ClientEndpointName , annotation =>
3054 {
@@ -35,6 +59,7 @@ public static IResourceBuilder<McpInspectorResource> AddMcpInspector(this IDistr
3559 {
3660 annotation . DisplayText = "Server Proxy" ;
3761 annotation . DisplayOrder = 1 ;
62+ annotation . DisplayLocation = UrlDisplayLocation . DetailsOnly ;
3863 } )
3964 . OnBeforeResourceStarted ( async ( inspectorResource , @event , ct ) =>
4065 {
@@ -78,8 +103,76 @@ public static IResourceBuilder<McpInspectorResource> AddMcpInspector(this IDistr
78103 ctx . EnvironmentVariables [ "MCP_PROXY_FULL_ADDRESS" ] = serverProxyEndpoint . Url ;
79104 ctx . EnvironmentVariables [ "CLIENT_PORT" ] = clientEndpoint . TargetPort ? . ToString ( ) ?? throw new InvalidOperationException ( "The MCP Inspector 'client' endpoint must have a target port defined." ) ;
80105 ctx . EnvironmentVariables [ "SERVER_PORT" ] = serverProxyEndpoint . TargetPort ? . ToString ( ) ?? throw new InvalidOperationException ( "The MCP Inspector 'server-proxy' endpoint must have a target port defined." ) ;
106+ ctx . EnvironmentVariables [ "MCP_PROXY_AUTH_TOKEN" ] = proxyTokenParameter ;
81107 } )
82- . WithDefaultArgs ( ) ;
108+ . WithDefaultArgs ( )
109+ . WithUrls ( async context =>
110+ {
111+ var token = await proxyTokenParameter . GetValueAsync ( CancellationToken . None ) ;
112+
113+ foreach ( var url in context . Urls )
114+ {
115+ if ( url . Endpoint is not null )
116+ {
117+ var uriBuilder = new UriBuilder ( url . Url )
118+ {
119+ Query = $ "MCP_PROXY_AUTH_TOKEN={ Uri . EscapeDataString ( token ! ) } "
120+ } ;
121+ url . Url = uriBuilder . ToString ( ) ;
122+ }
123+ }
124+ } ) ;
125+
126+ resource . Resource . ProxyTokenParameter = proxyTokenParameter ;
127+
128+ // Add authenticated health check for server proxy /config endpoint
129+ var healthCheckKey = $ "{ name } _proxy_config_check";
130+ builder . Services . AddHealthChecks ( ) . AddUrlGroup ( options =>
131+ {
132+ var serverProxyEndpoint = resource . GetEndpoint ( McpInspectorResource . ServerProxyEndpointName ) ;
133+ var uri = serverProxyEndpoint . Url ?? throw new DistributedApplicationException ( "The MCP Inspector 'server-proxy' endpoint URL is not set. Ensure that the resource has been allocated before the health check is executed." ) ;
134+ var healthCheckUri = new Uri ( new Uri ( uri ) , "/config" ) ;
135+ options . AddUri ( healthCheckUri , async setup =>
136+ {
137+ var token = await proxyTokenParameter . GetValueAsync ( CancellationToken . None ) ;
138+ setup . AddCustomHeader ( "X-MCP-Proxy-Auth" , $ "Bearer { token } ") ;
139+ } ) ;
140+ } , healthCheckKey ) ;
141+
142+ return resource . WithHealthCheck ( healthCheckKey ) ;
143+ }
144+
145+ /// <summary>
146+ /// Adds a MCP Inspector container resource to the <see cref="IDistributedApplicationBuilder"/> using a configuration delegate.
147+ /// </summary>
148+ /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to which the MCP Inspector resource will be added.</param>
149+ /// <param name="name">The name of the MCP Inspector container resource.</param>
150+ /// <param name="configureOptions">A delegate to configure the <see cref="McpInspectorOptions"/>.</param>
151+ /// <returns>A reference to the <see cref="IResourceBuilder{McpInspectorResource}"/> for further configuration.</returns>
152+ public static IResourceBuilder < McpInspectorResource > AddMcpInspector ( this IDistributedApplicationBuilder builder , [ ResourceName ] string name , Action < McpInspectorOptions > configureOptions )
153+ {
154+ ArgumentNullException . ThrowIfNull ( builder ) ;
155+ ArgumentNullException . ThrowIfNull ( configureOptions ) ;
156+
157+ var options = new McpInspectorOptions ( ) ;
158+ configureOptions ( options ) ;
159+
160+ return builder . AddMcpInspector ( name , options ) ;
161+ }
162+
163+ /// <summary>
164+ /// Adds a MCP Inspector container resource to the <see cref="IDistributedApplicationBuilder"/> using a configuration delegate.
165+ /// </summary>
166+ /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to which the MCP Inspector resource will be added.</param>
167+ /// <param name="name">The name of the MCP Inspector container resource.</param>
168+ /// <returns>A reference to the <see cref="IResourceBuilder{McpInspectorResource}"/> for further configuration.</returns>
169+ public static IResourceBuilder < McpInspectorResource > AddMcpInspector ( this IDistributedApplicationBuilder builder , [ ResourceName ] string name )
170+ {
171+ ArgumentNullException . ThrowIfNull ( builder ) ;
172+
173+ var options = new McpInspectorOptions ( ) ;
174+
175+ return builder . AddMcpInspector ( name , options ) ;
83176 }
84177
85178 /// <summary>
0 commit comments