Skip to content

Commit 77873c0

Browse files
authored
Merge pull request #4 from abeckDev/feature/basic-mcp-scaffold
Feature/basic mcp scaffold
2 parents f8209a6 + dd64407 commit 77873c0

15 files changed

Lines changed: 527 additions & 8 deletions

.devcontainer/devcontainer.json

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,37 @@
55
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
66
"image": "mcr.microsoft.com/devcontainers/dotnet:1-9.0-bookworm",
77
"features": {
8-
"ghcr.io/devcontainers/features/azure-cli:1": {}
8+
"ghcr.io/devcontainers/features/azure-cli:1": {},
9+
"ghcr.io/devcontainers/features/node:1": {
10+
"version": "lts"
11+
}
912
},
1013

1114
// Features to add to the dev container. More info: https://containers.dev/features.
1215
// "features": {},
1316

1417
// Use 'forwardPorts' to make a list of ports inside the container available locally.
15-
// "forwardPorts": [5000, 5001],
16-
// "portsAttributes": {
17-
// "5001": {
18-
// "protocol": "https"
19-
// }
20-
// }
18+
"forwardPorts": [6274, 6277, 3001],
19+
"portsAttributes": {
20+
"6274": {
21+
"protocol": "http",
22+
"label": "MCP-Inspector",
23+
"onAutoForward": "notify"
24+
},
25+
"6277": {
26+
"protocol": "http",
27+
"label": "MCP-Inspector-Proxy",
28+
"onAutoForward": "notify"
29+
},
30+
"3001":{
31+
"label": "MCP-Server",
32+
"onAutoForward": "notify",
33+
"protocol": "http"
34+
}
35+
},
2136

2237
// Use 'postCreateCommand' to run commands after the container is created.
23-
// "postCreateCommand": "dotnet restore",
38+
"postCreateCommand": "npm install -g @modelcontextprotocol/inspector",
2439

2540
// Configure tool-specific properties.
2641
"customizations": {

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
*.userosscache
1111
*.sln.docstates
1212
*.env
13+
AbeckDev.DbTimetable.Mcp/appsettings.Development.json
14+
1315

1416
# User-specific files (MonoDevelop/Xamarin Studio)
1517
*.userprefs

.vscode/launch.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Debug MCP Server with Inspector (HTTP)",
6+
"type": "node",
7+
"request": "launch",
8+
"runtimeExecutable": "npx",
9+
"runtimeArgs": [
10+
"@modelcontextprotocol/inspector",
11+
"--transport",
12+
"http",
13+
"--server-url",
14+
"http://localhost:3001/mcp"
15+
],
16+
"env": {
17+
"HOST": "0.0.0.0"
18+
},
19+
"console": "integratedTerminal",
20+
"internalConsoleOptions": "neverOpen",
21+
"preLaunchTask": "build-and-run-server",
22+
"serverReadyAction": {
23+
"pattern": "MCP Inspector is up and running at:\\s+(http://[^\\s]+)",
24+
"uriFormat": "%s",
25+
"action": "openExternally"
26+
}
27+
}
28+
]
29+
}

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"dotnet.defaultSolution": "AbeckDev.DbTimetable.sln"
3+
}

.vscode/tasks.json

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "restore-solution",
6+
"command": "dotnet",
7+
"type": "process",
8+
"args": [
9+
"restore",
10+
"${workspaceFolder}/AbeckDev.DbTimetable.sln"
11+
],
12+
"problemMatcher": "$msCompile",
13+
"presentation": {
14+
"reveal": "silent",
15+
"panel": "shared"
16+
}
17+
},
18+
{
19+
"label": "build-solution",
20+
"command": "dotnet",
21+
"type": "process",
22+
"args": [
23+
"build",
24+
"${workspaceFolder}/AbeckDev.DbTimetable.sln",
25+
"--no-restore"
26+
],
27+
"problemMatcher": "$msCompile",
28+
"group": {
29+
"kind": "build",
30+
"isDefault": true
31+
},
32+
"dependsOn": [
33+
"restore-solution"
34+
],
35+
"presentation": {
36+
"reveal": "always",
37+
"panel": "shared"
38+
}
39+
},
40+
{
41+
"label": "install-mcp-inspector",
42+
"type": "shell",
43+
"command": "npx",
44+
"args": [
45+
"-y",
46+
"@modelcontextprotocol/inspector"
47+
],
48+
"problemMatcher": [],
49+
"presentation": {
50+
"reveal": "silent",
51+
"panel": "shared"
52+
}
53+
},
54+
{
55+
"label": "run-mcp-server",
56+
"command": "dotnet",
57+
"type": "process",
58+
"args": [
59+
"run",
60+
"--project",
61+
"${workspaceFolder}/AbeckDev.DbTimetable.Mcp/AbeckDev.DbTimetable.Mcp.csproj"
62+
],
63+
"isBackground": true,
64+
"problemMatcher": {
65+
"pattern": {
66+
"regexp": "^$",
67+
"file": 1,
68+
"location": 2,
69+
"message": 3
70+
},
71+
"background": {
72+
"activeOnStart": true,
73+
"beginsPattern": "^.*Building.*$",
74+
"endsPattern": "^.*Now listening on.*$|^.*Application started.*$"
75+
}
76+
},
77+
"presentation": {
78+
"reveal": "always",
79+
"panel": "dedicated"
80+
}
81+
},
82+
{
83+
"label": "build-and-run-server",
84+
"dependsOn": [
85+
"build-solution",
86+
"run-mcp-server"
87+
],
88+
"dependsOrder": "sequence",
89+
"problemMatcher": []
90+
}
91+
]
92+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.5" />
11+
<PackageReference Include="ModelContextProtocol" Version="0.4.0-preview.3" />
12+
<PackageReference Include="ModelContextProtocol.AspNetCore" Version="0.4.0-preview.3" />
13+
</ItemGroup>
14+
15+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace AbeckDev.DbTimetable.Mcp.Models;
4+
5+
public class Configuration
6+
{
7+
public const string SectionName = "DeutscheBahnApi";
8+
public string BaseUrl { get; set; } = "https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/";
9+
public string ClientId { get; set; } = string.Empty;
10+
public string ApiKey { get; set; } = string.Empty;
11+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//Minimal API approach
2+
using AbeckDev.DbTimetable.Mcp.Models;
3+
using AbeckDev.DbTimetable.Mcp.Services;
4+
using ModelContextProtocol.Protocol;
5+
6+
var builder = WebApplication.CreateBuilder(args);
7+
8+
//Setup Config provider
9+
builder.Configuration
10+
.SetBasePath(Directory.GetCurrentDirectory())
11+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
12+
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
13+
.AddEnvironmentVariables();
14+
15+
builder.Services.Configure<Configuration>(
16+
builder.Configuration.GetSection(Configuration.SectionName));
17+
18+
var dbConfig = builder.Configuration
19+
.GetSection(Configuration.SectionName)
20+
.Get<Configuration>() ?? new Configuration();
21+
22+
builder.Services.AddHttpClient<TimeTableService>(client =>
23+
{
24+
client.BaseAddress = new Uri(dbConfig.BaseUrl);
25+
client.DefaultRequestHeaders.Accept.Add(
26+
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));
27+
client.Timeout = TimeSpan.FromSeconds(30);
28+
});
29+
30+
// Add services to the container.
31+
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
32+
builder.Services.AddMcpServer(options =>
33+
{
34+
options.ServerInfo = new Implementation { Name = "Deutsche Bahn - Timetable API", Version = "1.0.0" };
35+
})
36+
.WithHttpTransport()
37+
.WithToolsFromAssembly()
38+
.WithPromptsFromAssembly();
39+
40+
41+
var app = builder.Build();
42+
43+
app.MapMcp("/mcp");
44+
45+
app.Run("http://0.0.0.0:3001");
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.ComponentModel;
3+
using Microsoft.Extensions.AI;
4+
using ModelContextProtocol.Server;
5+
6+
namespace AbeckDev.DbTimetable.Mcp;
7+
8+
[McpServerPromptType]
9+
public static class Prompts
10+
{
11+
[McpServerPrompt, Description("Creates a prompt to summarize the provided message.")]
12+
public static ChatMessage Summarize([Description("The content to summarize")] string content) =>
13+
new(ChatRole.User, $"Please summarize this content into a single sentence: {content}");
14+
}
Lines changed: 23 additions & 0 deletions
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": false,
8+
"applicationUrl": "http://localhost:5252",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development"
11+
}
12+
},
13+
"https": {
14+
"commandName": "Project",
15+
"dotnetRunMessages": true,
16+
"launchBrowser": false,
17+
"applicationUrl": "https://localhost:7041;http://localhost:5252",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)