Skip to content

Commit 94b40b3

Browse files
authored
Loading the config file to MCP inspector so you can inspect right away (#816)
1 parent caa55b2 commit 94b40b3

File tree

5 files changed

+63
-9
lines changed

5 files changed

+63
-9
lines changed

examples/mcp-inspector/CommunityToolkit.Aspire.Hosting.McpInspector.McpServer/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
var app = builder.Build();
1212

13-
app.MapMcp();
13+
app.MapMcp("/mcp");
1414

1515
app.Run();
1616

src/CommunityToolkit.Aspire.Hosting.McpInspector/McpInspectorResource.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public class McpInspectorResource(string name) : ExecutableResource(name, "npx",
3737
/// <summary>
3838
/// Gets the version of the MCP Inspector.
3939
/// </summary>
40-
public const string InspectorVersion = "0.16.2";
40+
public const string InspectorVersion = "0.16.5";
4141

4242
private readonly List<McpServerMetadata> _mcpServers = [];
4343

@@ -58,7 +58,7 @@ public class McpInspectorResource(string name) : ExecutableResource(name, "npx",
5858
/// </summary>
5959
public ParameterResource ProxyTokenParameter { get; set; } = default!;
6060

61-
internal void AddMcpServer(IResourceWithEndpoints mcpServer, bool isDefault, McpTransportType transportType)
61+
internal void AddMcpServer(IResourceWithEndpoints mcpServer, bool isDefault, McpTransportType transportType, string path)
6262
{
6363
if (_mcpServers.Any(s => s.Name == mcpServer.Name))
6464
{
@@ -68,7 +68,8 @@ internal void AddMcpServer(IResourceWithEndpoints mcpServer, bool isDefault, Mcp
6868
McpServerMetadata item = new(
6969
mcpServer.Name,
7070
mcpServer.GetEndpoint("http") ?? throw new InvalidOperationException($"The MCP server {mcpServer.Name} must have a 'http' endpoint defined."),
71-
transportType);
71+
transportType,
72+
path);
7273

7374
_mcpServers.Add(item);
7475

src/CommunityToolkit.Aspire.Hosting.McpInspector/McpInspectorResourceBuilderExtensions.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@ public static IResourceBuilder<McpInspectorResource> AddMcpInspector(this IDistr
7070

7171
var servers = inspectorResource.McpServers.ToDictionary(s => s.Name, s => new
7272
{
73-
transport = s.TransportType switch
73+
type = s.TransportType switch
7474
{
7575
McpTransportType.StreamableHttp => "streamable-http",
7676
#pragma warning disable CS0618
7777
McpTransportType.Sse => "sse",
7878
#pragma warning restore CS0618
7979
_ => throw new NotSupportedException($"The transport type {s.TransportType} is not supported.")
8080
},
81-
endpoint = s.Endpoint.Url
81+
url = Combine(s.Endpoint.Url, s.Path),
8282
});
8383

8484
var config = new { mcpServers = servers };
@@ -183,18 +183,20 @@ public static IResourceBuilder<McpInspectorResource> AddMcpInspector(this IDistr
183183
/// <param name="mcpServer">The <see cref="IResourceBuilder{T}"/> for the MCP server resource.</param>
184184
/// <param name="isDefault">Indicates whether this MCP server should be considered the default server for the MCP Inspector.</param>
185185
/// <param name="transportType">The transport type to use for the MCP server. Defaults to <see cref="McpTransportType.StreamableHttp"/>.</param>
186+
/// <param name="path">The path to use for MCP communication. Defaults to "/mcp".</param>
186187
/// <returns>A reference to the <see cref="IResourceBuilder{McpInspectorResource}"/> for further configuration.</returns>
187188
public static IResourceBuilder<McpInspectorResource> WithMcpServer<TResource>(
188189
this IResourceBuilder<McpInspectorResource> builder,
189190
IResourceBuilder<TResource> mcpServer,
190191
bool isDefault = true,
191-
McpTransportType transportType = McpTransportType.StreamableHttp)
192+
McpTransportType transportType = McpTransportType.StreamableHttp,
193+
string path = "/mcp")
192194
where TResource : IResourceWithEndpoints
193195
{
194196
ArgumentNullException.ThrowIfNull(mcpServer);
195197
ArgumentNullException.ThrowIfNull(builder);
196198

197-
builder.Resource.AddMcpServer(mcpServer.Resource, isDefault, transportType);
199+
builder.Resource.AddMcpServer(mcpServer.Resource, isDefault, transportType, path);
198200
return builder;
199201
}
200202

@@ -222,4 +224,27 @@ private static IResourceBuilder<McpInspectorResource> WithDefaultArgs(this IReso
222224
ctx.Args.Add(defaultMcpServer?.Name ?? throw new InvalidOperationException("The MCP Inspector resource must have a default MCP server defined."));
223225
});
224226
}
227+
228+
internal static Uri Combine(string baseUrl, params string[] segments)
229+
{
230+
if (string.IsNullOrEmpty(baseUrl))
231+
throw new ArgumentException("baseUrl required", nameof(baseUrl));
232+
233+
if (segments == null || segments.Length == 0)
234+
return new Uri(baseUrl, UriKind.RelativeOrAbsolute);
235+
236+
var baseUri = new Uri(baseUrl, UriKind.Absolute);
237+
238+
// If first segment is absolute URI, return it
239+
if (Uri.IsWellFormedUriString(segments[0], UriKind.Absolute))
240+
return new Uri(segments[0], UriKind.Absolute);
241+
242+
var escaped = segments
243+
.Where(s => !string.IsNullOrEmpty(s))
244+
.Select(s => Uri.EscapeDataString(s.Trim('/')));
245+
246+
var relative = string.Join("/", escaped);
247+
248+
return new Uri(baseUri, relative);
249+
}
225250
}

src/CommunityToolkit.Aspire.Hosting.McpInspector/McpServerMetadata.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ namespace Aspire.Hosting.ApplicationModel;
66
/// <param name="Name">The name of the server resource.</param>
77
/// <param name="Endpoint">The endpoint reference for the server resource.</param>
88
/// <param name="TransportType">The transport type used by the server resource.</param>
9-
public record McpServerMetadata(string Name, EndpointReference Endpoint, McpTransportType TransportType);
9+
/// <param name="Path">The path used for MCP communication.</param>
10+
public record McpServerMetadata(string Name, EndpointReference Endpoint, McpTransportType TransportType, string Path);

tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/McpInspectorResourceBuilderExtensionsTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,33 @@ public void WithMcpServerSpecificTransportTypeAddsServerToResource(McpTransportT
6363
Assert.Equal(transportType, inspectorResource.DefaultMcpServer.TransportType);
6464
}
6565

66+
[Fact]
67+
public void WithMcpServerCustomPathAddsServerWithCustomPath()
68+
{
69+
// Arrange
70+
var appBuilder = DistributedApplication.CreateBuilder();
71+
72+
// Create a mock MCP server resource
73+
var mockServer = appBuilder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_McpInspector_McpServer>("mcpServer");
74+
75+
// Act
76+
var inspector = appBuilder.AddMcpInspector("inspector")
77+
.WithMcpServer(mockServer, isDefault: true, path: "/custom/mcp/path");
78+
79+
using var app = appBuilder.Build();
80+
81+
// Assert
82+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
83+
84+
var inspectorResource = Assert.Single(appModel.Resources.OfType<McpInspectorResource>());
85+
Assert.Equal("inspector", inspectorResource.Name);
86+
87+
Assert.Single(inspectorResource.McpServers);
88+
Assert.NotNull(inspectorResource.DefaultMcpServer);
89+
Assert.Equal("mcpServer", inspectorResource.DefaultMcpServer.Name);
90+
Assert.Equal("/custom/mcp/path", inspectorResource.DefaultMcpServer.Path);
91+
}
92+
6693
[Fact]
6794
public void WithMultipleMcpServersAddsAllServersToResource()
6895
{

0 commit comments

Comments
 (0)