mcp-csharp-create について
公式 SDK と .NET テンプレートを使って C# MCP サーバーを作成するスキルです。プロジェクトの準備、トランスポートの選択、ツールやプロンプト、リソースの実装を案内します。
主な機能
- 01C# MCP サーバープロジェクトの作成
- 02stdio または HTTP の選択
- 03ツール、プロンプト、リソースの実装
- 04ASP.NET Core ホスティングの設定
- 05ビルドと起動の確認
活用シーン
- 01新しい MCP サーバーの開始
- 02既存サーバーへの機能追加
- 03API の MCP ツール化
MCP 対応
stdio または HTTP 経由で MCP クライアントにツール、プロンプト、リソースを提供する MCP サーバーの作成を案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dotnet/ skills --skill mcp-csharp-createインストール後、Claude Code で/mcp-csharp-createを入力して読み込まれたか確認します。
同梱ファイルreferences/api-patterns.mdreferences/transport-config.md
詳細
C# MCP サーバーの作成
公式 C# SDK(ModelContextProtocol NuGet パッケージ)と dotnet new mcpserver プロジェクトテンプレートを使って、Model Context Protocol サーバーを作成します。サーバーは、LLM が検出し、MCP プロトコル経由で呼び出せるツール、プロンプト、リソースを公開します。
使用する場面
- 新しい MCP サーバープロジェクトを一から始める
- 既存の MCP サーバーにツール、プロンプト、リソースを追加する
- stdio(
--transport local)と HTTP(--transport remote)のトランスポートを選択する - HTTP MCP サーバー向けに ASP.NET Core ホスティングを設定する
- 外部 API またはサービスを MCP ツールとしてラップする
中止の判断基準
- テストや評価が必要ですか? →
mcp-csharp-testを使用します - 公開する準備ができていますか? →
mcp-csharp-publishを使用します - サーバーではなく MCP クライアントを構築しますか? → このスキルはサーバー側専用です
入力
| 入力 | 必須 | 説明 |
|---|---|---|
| トランスポートの種類 | はい | stdio(ローカル/CLI)または http(リモート/ウェブ)。指定されていない場合はユーザーに確認します。既定値は stdio です |
| プロジェクト名 | はい | プロジェクトの PascalCase 名(例:WeatherMcpServer) |
| .NET SDK のバージョン | 推奨 | .NET 10.0 以降が必要です。dotnet --version で確認します |
| ラップするサービス/API | 推奨 | ツールが連携する外部 API またはサービス |
ワークフロー
コミット戦略: 各ステップの完了後にコミットし、足場の作成と実装を個別にレビューできるようにします。
ステップ 1:前提条件を確認する
-
.NET 10 以降の SDK を確認します:
dotnet --version(10.0 未満の場合は https://dotnet.microsoft.com からインストールします) -
MCP サーバーテンプレートがすでにインストールされているか確認します:
dotnet new list mcpserver「No templates found」と表示された場合は、
dotnet new install Microsoft.McpServer.ProjectTemplatesでインストールします
ステップ 2:トランスポートを選択する
| stdio を選ぶ場合… | HTTP を選ぶ場合… |
|---|---|
| ローカルの CLI ツールまたは IDE プラグイン | クラウド/ウェブサービスとしてのデプロイ |
| 一度に 1 人のユーザーが利用 | 複数のクライアントが同時に利用 |
| サブプロセスとして実行(VS Code、GitHub Copilot) | ネットワークをまたいだアクセスが必要 |
| 設定が簡単で、ネットワーク設定が不要 | コンテナー化したデプロイ(Docker/Azure) |
既定値: stdio。設定が簡単で、ほとんどのローカル開発に適しています。HTTP は後から追加できます。
ステップ 3:プロジェクトを作成する
stdio サーバー:
dotnet new mcpserver -n <ProjectName>
テンプレートがタイムアウトする、または利用できない場合は、dotnet new console -n <ProjectName> を使って dotnet add package ModelContextProtocol を追加します。
HTTP サーバー:
dotnet new web -n <ProjectName>
cd <ProjectName>
dotnet add package ModelContextProtocol.AspNetCore
この方法が推奨されます。テンプレートより高速で信頼性が高いためです。テンプレートでも dotnet new mcpserver -n <ProjectName> --transport remote によって HTTP を利用できますが、dotnet new web のほうがプロジェクト構造を細かく制御できます。
テンプレートのフラグ一覧: --transport local(stdio、既定値)、--transport remote(ASP.NET Core HTTP)、--aot、--self-contained。
ステップ 4:ツールを実装する
ツールは、MCP サーバーが機能を公開する主な方法です。[McpServerToolType] を指定したクラスと、[McpServerTool] を指定したメソッドを追加します:
using ModelContextProtocol.Server;
using System.ComponentModel;
[McpServerToolType]
public static class MyTools
{
[McpServerTool, Description("Brief description of what the tool does.")]
public static async Task<string> DoSomething(
[Description("What this parameter controls")] string input,
CancellationToken cancellationToken = default)
{
// Implementation
return $"Result: {input}";
}
}
重要なルール:
- すべてのツールメソッドに
[Description]属性を必ず付けます。LLM はこの情報を使ってツールを呼び出すタイミングを判断します - すべてのパラメーターに
[Description]属性を必ず付けます - すべての非同期ツールで
CancellationTokenを受け取ります - 既定のメソッド名が分かりにくい場合に限り、
[McpServerTool(Name = "custom_name")]を使用します
DI の注入パターン — SDK は次の 2 つのスタイルをサポートしています。
-
メソッドパラメーターへの注入(静的クラス): DI サービスをメソッドパラメーターとして指定します。SDK が自動的に解決するため、ツールスキーマには表示されません。
-
コンストラクターへの注入(非静的クラス): ツールで共有状態や複数のサービスが必要な場合に使用します:
[McpServerToolType]
public class ApiTools(HttpClient httpClient, ILogger<ApiTools> logger)
{
[McpServerTool, Description("Fetch a resource by ID.")]
public async Task<string> FetchResource(
[Description("Resource identifier")] string id,
CancellationToken cancellationToken = default)
{
logger.LogInformation("Fetching {Id}", id);
return await httpClient.GetStringAsync($"/api/{id}", cancellationToken);
}
}
Program.cs でサービスを登録します:
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(options =>
options.LogToStandardErrorThreshold = LogLevel.Trace);
builder.Services.AddHttpClient(); // registers IHttpClientFactory + HttpClient
// ILogger<T> is registered by default — no extra setup needed.
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly(); // discovers non-static [McpServerToolType] classes
await builder.Build().RunAsync();
属性、戻り値の型、DI の注入、ビルダー API のパターンに関する完全なリファレンスは、references/api-patterns.md を参照してください。
ステップ 5:プロンプトとリソースを追加する(任意)
プロンプト — 再利用可能な LLM 対話テンプレート:
[McpServerPromptType]
public static class MyPrompts
{
[McpServerPrompt, Description("Summarize content into one sentence.")]
public static ChatMessage Summarize(
[Description("Content to summarize")] string content) =>
new(ChatRole.User, $"Summarize this into one sentence: {content}");
}
リソース — LLM が読み取れるデータ:
[McpServerResourceType]
public static class MyResources
{
[McpServerResource(UriTemplate = "config://app", Name = "App Config",
MimeType = "application/json"), Description("Application configuration")]
public static string GetConfig() => JsonSerializer.Serialize(AppConfig.Current);
}
ステップ 6:Program.cs を設定する
stdio トランスポート:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(options =>
options.LogToStandardErrorThreshold = LogLevel.Trace); // CRITICAL: stderr only
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly();
await builder.Build().RunAsync();
HTTP トランスポート:
using ModelContextProtocol.Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly();
// Register services your tools need via DI
// builder.Services.AddHttpClient();
// builder.Services.AddSingleton<IMyService, MyService>();
var app = builder.Build();
app.MapMcp(); // exposes MCP endpoint at /mcp (Streamable HTTP)
app.MapGet("/health", () => "ok"); // health check for container orchestrators
app.Run();
HTTP の主な詳細: MapMcp() のデフォルトのパスは /mcp です。コンテナーの場合は、ASPNETCORE_URLS=http://+:8080 を設定し、EXPOSE 8080 を指定します。MCP HTTP プロトコルでは Streamable HTTP を使用するため、URL 以外に特別なクライアント設定は必要ありません。
トランスポート設定の詳細(ステートレスモード、認証、パスプレフィックス、HttpContextAccessor)については、references/transport-config.md を参照してください。
ステップ 7:サーバーの起動を確認する
cd <ProjectName>
dotnet build
dotnet run
stdio の場合:プロセスが起動し、stdin で JSON-RPC 入力を待ちます。 HTTP の場合:サーバーは設定されたポートで待ち受けます。
検証
- プロジェクトがエラーなしでビルドされる(
dotnet build) - すべてのツールクラスに
[McpServerToolType]属性がある - すべてのツールメソッドに
[McpServerTool]属性と[Description]属性がある - すべてのパラメーターに
[Description]属性がある - stdio:ログが stdout ではなく stderr に出力される
- HTTP:Program.cs で
app.MapMcp()が呼び出されている -
dotnet runでサーバーが正常に起動する
よくある落とし穴
| 落とし穴 | 解決策 |
|---|---|
| stdio サーバーが文字化けしたデータを出力する、または応答しなくなる | stdout へのログ出力は JSON-RPC プロトコルを破損させます。LogToStandardErrorThreshold = LogLevel.Trace を設定してください |
| LLM クライアントがツールを検出できない | クラスに [McpServerToolType] がない、またはメソッドに [McpServerTool] がありません。Program.cs に .WithToolsFromAssembly() があることを確認してください |
| LLM がツールを使うタイミングを理解できない | メソッドとすべてのパラメーターの両方に、明確な [Description] 属性を追加してください |
AOT で WithToolsFromAssembly() が失敗する | リフレクションベースの検出は Native AOT と互換性がありません。代わりに .WithTools<MyTools>() を使用してください |
| パラメーターがツールスキーマに表示されない | CancellationToken、IMcpServer、DI サービスは自動的に注入されるため、スキーマには表示されません。[Description] があるパラメーターのみが公開されます |
| HTTP サーバーが 404 を返す | app.MapMcp() を呼び出す必要があります。リクエストパスが設定済みのルートと一致していることを確認してください |
関連スキル
mcp-csharp-test— 単体テスト、統合テスト、評価mcp-csharp-publish— NuGet、Docker、Azure へのデプロイ
リファレンスファイル
- references/api-patterns.md — 属性、戻り値の型、DI 注入、ビルダー API、動的ツール、実験的 API の完全なリファレンス。読み込む場面: 上記の基本パターンを超えて、ツール、プロンプト、リソースを実装する場合。
- references/transport-config.md — トランスポート設定の詳細:ステートレス HTTP モード、OAuth/認証、カスタムパスプレフィックス、
HttpContextAccessor、OpenTelemetry による可観測性。読み込む場面: 高度なトランスポートオプションや認証を設定する場合。
詳細情報
- C# MCP SDK — 公式 SDK リポジトリ
- MCP サーバーを構築する(.NET) — Microsoft のクイックスタート
- MCP 仕様 — プロトコル仕様