Skip to content

Commit 923e19c

Browse files
authored
Merge pull request #118 from microsoft/bruno-add-whatsnew
Add 'What's new section' and include MCP samples
2 parents 3d5fde2 + a96f651 commit 923e19c

File tree

82 files changed

+61154
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+61154
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.35906.104
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSample.ServiceDefaults", "src\McpSample.ServiceDefaults\McpSample.ServiceDefaults.csproj", "{63E130E2-B108-D8A0-C6C6-0C05493F0690}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSample.AspNetCoreSseServer", "src\McpSample.AspNetCoreSseServer\McpSample.AspNetCoreSseServer.csproj", "{C9D8E344-77A7-C7C8-4F2B-D9521B6A441B}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSample.BlazorChat", "src\McpSample.Chat\McpSample.BlazorChat.csproj", "{6CC10BEE-2C2D-1BE7-4111-17587C4F7CC6}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSample.AppHost", "src\McpSample.AppHost\McpSample.AppHost.csproj", "{F73B9265-83CA-6ACB-BBE0-71D5856E1CB9}"
13+
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1 Aspire", "1 Aspire", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
15+
EndProject
16+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2 MCP Server", "2 MCP Server", "{9FE8D6F9-2B76-4BF7-9E29-884286C721C1}"
17+
EndProject
18+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3 Client", "3 Client", "{09DEE05B-519A-442E-A5E6-E1AE1E977F20}"
19+
EndProject
20+
Global
21+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
22+
Debug|Any CPU = Debug|Any CPU
23+
Release|Any CPU = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
26+
{63E130E2-B108-D8A0-C6C6-0C05493F0690}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{63E130E2-B108-D8A0-C6C6-0C05493F0690}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{63E130E2-B108-D8A0-C6C6-0C05493F0690}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{63E130E2-B108-D8A0-C6C6-0C05493F0690}.Release|Any CPU.Build.0 = Release|Any CPU
30+
{C9D8E344-77A7-C7C8-4F2B-D9521B6A441B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31+
{C9D8E344-77A7-C7C8-4F2B-D9521B6A441B}.Debug|Any CPU.Build.0 = Debug|Any CPU
32+
{C9D8E344-77A7-C7C8-4F2B-D9521B6A441B}.Release|Any CPU.ActiveCfg = Release|Any CPU
33+
{C9D8E344-77A7-C7C8-4F2B-D9521B6A441B}.Release|Any CPU.Build.0 = Release|Any CPU
34+
{6CC10BEE-2C2D-1BE7-4111-17587C4F7CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35+
{6CC10BEE-2C2D-1BE7-4111-17587C4F7CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
36+
{6CC10BEE-2C2D-1BE7-4111-17587C4F7CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
37+
{6CC10BEE-2C2D-1BE7-4111-17587C4F7CC6}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{F73B9265-83CA-6ACB-BBE0-71D5856E1CB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{F73B9265-83CA-6ACB-BBE0-71D5856E1CB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{F73B9265-83CA-6ACB-BBE0-71D5856E1CB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{F73B9265-83CA-6ACB-BBE0-71D5856E1CB9}.Release|Any CPU.Build.0 = Release|Any CPU
42+
EndGlobalSection
43+
GlobalSection(SolutionProperties) = preSolution
44+
HideSolutionNode = FALSE
45+
EndGlobalSection
46+
GlobalSection(NestedProjects) = preSolution
47+
{63E130E2-B108-D8A0-C6C6-0C05493F0690} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
48+
{C9D8E344-77A7-C7C8-4F2B-D9521B6A441B} = {9FE8D6F9-2B76-4BF7-9E29-884286C721C1}
49+
{6CC10BEE-2C2D-1BE7-4111-17587C4F7CC6} = {09DEE05B-519A-442E-A5E6-E1AE1E977F20}
50+
{F73B9265-83CA-6ACB-BBE0-71D5856E1CB9} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
51+
EndGlobalSection
52+
GlobalSection(ExtensibilityGlobals) = postSolution
53+
SolutionGuid = {7E7647F4-F1FE-4A6B-86AD-FAB7C91CA608}
54+
EndGlobalSection
55+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.azure
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />
4+
5+
<PropertyGroup>
6+
<OutputType>Exe</OutputType>
7+
<TargetFramework>net9.0</TargetFramework>
8+
<ImplicitUsings>enable</ImplicitUsings>
9+
<Nullable>enable</Nullable>
10+
<IsAspireHost>true</IsAspireHost>
11+
<UserSecretsId>4820c1bd-6164-4b01-914c-5c294cda9636</UserSecretsId>
12+
</PropertyGroup>
13+
14+
15+
<ItemGroup>
16+
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.1.0" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<ProjectReference Include="..\McpSample.AspNetCoreSseServer\McpSample.AspNetCoreSseServer.csproj" />
21+
<ProjectReference Include="..\McpSample.Chat\McpSample.BlazorChat.csproj" />
22+
</ItemGroup>
23+
24+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var builder = DistributedApplication.CreateBuilder(args);
2+
3+
var aspnetsseserver = builder
4+
.AddProject<Projects.McpSample_AspNetCoreSseServer>("aspnetsseserver")
5+
.WithExternalHttpEndpoints();
6+
var blazorchat = builder
7+
.AddProject<Projects.McpSample_BlazorChat>("blazorchat")
8+
.WithReference(aspnetsseserver)
9+
.WithExternalHttpEndpoints();
10+
11+
builder.Build().Run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"https": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": true,
8+
"applicationUrl": "https://localhost:17045;http://localhost:15247",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development",
11+
"DOTNET_ENVIRONMENT": "Development",
12+
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21184",
13+
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22202"
14+
}
15+
},
16+
"http": {
17+
"commandName": "Project",
18+
"dotnetRunMessages": true,
19+
"launchBrowser": true,
20+
"applicationUrl": "http://localhost:15247",
21+
"environmentVariables": {
22+
"ASPNETCORE_ENVIRONMENT": "Development",
23+
"DOTNET_ENVIRONMENT": "Development",
24+
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19020",
25+
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20263"
26+
}
27+
}
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning",
6+
"Aspire.Hosting.Dcp": "Warning"
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using ModelContextProtocol.Protocol.Messages;
2+
using ModelContextProtocol.Server;
3+
using ModelContextProtocol.Utils.Json;
4+
using Microsoft.Extensions.Options;
5+
using ModelContextProtocol.Protocol.Transport;
6+
7+
public static class McpEndpointRouteBuilderExtensions
8+
{
9+
public static IEndpointConventionBuilder MapMcpSse(this IEndpointRouteBuilder endpoints)
10+
{
11+
SseResponseStreamTransport? transport = null;
12+
var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
13+
var mcpServerOptions = endpoints.ServiceProvider.GetRequiredService<IOptions<McpServerOptions>>();
14+
15+
var routeGroup = endpoints.MapGroup("");
16+
17+
routeGroup.MapGet("/sse", async (HttpResponse response, CancellationToken requestAborted) =>
18+
{
19+
response.Headers.ContentType = "text/event-stream";
20+
response.Headers.CacheControl = "no-cache";
21+
22+
await using var localTransport = transport = new SseResponseStreamTransport(response.Body);
23+
await using var server = McpServerFactory.Create(transport, mcpServerOptions.Value, loggerFactory, endpoints.ServiceProvider);
24+
25+
try
26+
{
27+
var transportTask = transport.RunAsync(cancellationToken: requestAborted);
28+
await server.StartAsync(cancellationToken: requestAborted);
29+
await transportTask;
30+
}
31+
catch (OperationCanceledException) when (requestAborted.IsCancellationRequested)
32+
{
33+
// RequestAborted always triggers when the client disconnects before a complete response body is written,
34+
// but this is how SSE connections are typically closed.
35+
}
36+
});
37+
38+
routeGroup.MapPost("/message", async context =>
39+
{
40+
if (transport is null)
41+
{
42+
await Results.BadRequest("Connect to the /sse endpoint before sending messages.").ExecuteAsync(context);
43+
return;
44+
}
45+
46+
var message = await context.Request.ReadFromJsonAsync<IJsonRpcMessage>(McpJsonUtilities.DefaultOptions, context.RequestAborted);
47+
if (message is null)
48+
{
49+
await Results.BadRequest("No message in request body.").ExecuteAsync(context);
50+
return;
51+
}
52+
53+
await transport.OnMessageReceivedAsync(message, context.RequestAborted);
54+
context.Response.StatusCode = StatusCodes.Status202Accepted;
55+
await context.Response.WriteAsync("Accepted");
56+
});
57+
58+
return routeGroup;
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<UserSecretsId>be7e169c-f253-407a-bd06-458c056a42d1</UserSecretsId>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="ModelContextProtocol" Version="0.1.0-preview.2" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\McpSample.ServiceDefaults\McpSample.ServiceDefaults.csproj" />
16+
</ItemGroup>
17+
18+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using ModelContextProtocol;
2+
3+
var builder = WebApplication.CreateBuilder(args);
4+
5+
// Add default services
6+
builder.AddServiceDefaults();
7+
builder.Services.AddProblemDetails();
8+
9+
// add MCP server
10+
//builder.Services.AddMcpServer().WithTools();
11+
builder.Services.AddMcpServer().WithToolsFromAssembly();
12+
var app = builder.Build();
13+
14+
// Initialize default endpoints
15+
app.MapDefaultEndpoints();
16+
app.UseHttpsRedirection();
17+
18+
// map endpoints
19+
app.MapGet("/", () => $"Hello World! {DateTime.Now}");
20+
app.MapMcpSse();
21+
22+
app.Run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"http": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": true,
8+
"applicationUrl": "http://localhost:3001",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development"
11+
}
12+
},
13+
"https": {
14+
"commandName": "Project",
15+
"dotnetRunMessages": true,
16+
"launchBrowser": true,
17+
"applicationUrl": "https://localhost:7133;http://localhost:3001",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using ModelContextProtocol.Server;
2+
using System.ComponentModel;
3+
4+
namespace McpSample.AspNetCoreSseServer;
5+
6+
[McpServerToolType]
7+
public static class Jokes
8+
{
9+
[McpServerTool, Description("Returns a joke about a specific topic")]
10+
public static string GetJoke(string topic)
11+
{
12+
Console.WriteLine("==========================");
13+
Console.WriteLine($"Function get joke with topic: {topic}");
14+
var message = $"I don't do jokes about {topic}.";
15+
Console.WriteLine("Function report: " + message);
16+
Console.WriteLine($"Function End get joke with topic: {topic}");
17+
Console.WriteLine("==========================");
18+
return message;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using ModelContextProtocol.Server;
2+
using System.ComponentModel;
3+
4+
namespace McpSample.AspNetCoreSseServer;
5+
6+
[McpServerToolType]
7+
public static class WeatherTool
8+
{
9+
[McpServerTool, Description("Returns the current weather for a specific city")]
10+
public static string GetWeatherForCity(string cityName)
11+
{
12+
Console.WriteLine("==========================");
13+
Console.WriteLine($"Function Start WeatherTool: GetWeatherForCity called with cityName: {cityName}");
14+
15+
// generate a random weather report and return the result
16+
var random = new Random();
17+
var temperature = random.Next(-20, 40);
18+
var condition = random.Next(0, 2) == 0 ? "Sunny" : "Rainy";
19+
var humidity = random.Next(0, 100);
20+
var windSpeed = random.Next(0, 20);
21+
var report = $"Weather in {cityName}: {temperature}°C, {condition}, Humidity: {humidity}%, Wind Speed: {windSpeed} km/h";
22+
23+
Console.WriteLine("Function report: " + report);
24+
Console.WriteLine($"Function End WeatherTool: GetWeatherForCity called with cityName: {cityName}");
25+
Console.WriteLine("==========================");
26+
27+
return report;
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*"
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<base href="/" />
8+
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
9+
<link rel="stylesheet" href="@Assets["app.css"]" />
10+
<link rel="stylesheet" href="@Assets["McpSample.BlazorChat.styles.css"]" />
11+
<ImportMap />
12+
<link rel="icon" type="image/png" href="favicon.png" />
13+
<HeadOutlet />
14+
</head>
15+
16+
<body>
17+
<Routes />
18+
<script src="_framework/blazor.web.js"></script>
19+
</body>
20+
21+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@inherits LayoutComponentBase
2+
3+
<div class="page">
4+
<div class="sidebar">
5+
<NavMenu />
6+
</div>
7+
8+
<main>
9+
<div class="top-row px-4">
10+
<a href="https://aka.ms/aspiremcp/repo" target="_blank">Aspire and MCP</a>
11+
</div>
12+
13+
<article class="content px-4">
14+
@Body
15+
</article>
16+
</main>
17+
</div>
18+
19+
<div id="blazor-error-ui" data-nosnippet>
20+
An unhandled error has occurred.
21+
<a href="." class="reload">Reload</a>
22+
<span class="dismiss">🗙</span>
23+
</div>

0 commit comments

Comments
 (0)