Zenn
🌊

MCP の Prompt をC# SDK で作る方法

に公開

はじめに

表題の通り作ってみようと思います。
MCP が色々注目されていますが、大体が Tools のみで Prompts や Resources の話はあまりありません。各種 MCP ホストとなるアプリが主にツールに対応している状態なので仕方ないですが、他のものも今後需要が高まるかもしれないので作り方をメモしておきます。

因みに Resources も作れるのですが C# SDK の方がまだ低レベルなレイヤーの API しかないように見えるので、もう少し様子見していい感じの API が整理されることに期待します。

ということで今回は Prompt のみを作ります。

MCP の Prompt 対応のサーバーを作ろう

.NET Aspire のオプションをオンにした状態で ASP.NET Core の Web API プロジェクトを作って以下の NuGet パッケージをインストールします。

  • ModelContextProtocol.AspNetCore v0.1.0-preview.6

先日試した時は preview.4 だった気がするのですが preview.6 になっていました…。開発が活発ですね。

Prompt に対応する方法は基本的に Tools と同じで Attribute を付けたクラスとメソッドを定義するだけです。

[McpServerPromptType]
class CatPrompts
{
    [McpServerPrompt(Name = "CatPrompt")]
    [Description("挨拶された際にどのように振舞うべきかが書かれています")]
    public static string CatPrompt() => """
        あなたは猫っぽく振舞う必要があります。
        必ず語尾は猫のように「にゃん」とつけてください。
        """;
}

McpServerPromptType を付けたクラスを定義し、その中に McpServerPrompt を付けたメソッドを定義します。メソッドは static でもインスタンスメソッドでもどちらでもいいです。上記のように文字列を返すと RoleUser のメッセージとして扱われます。

では Program.cs を以下のように書き換えて MCP サーバーとして動くようにします。

Program.cs
using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
    .WithPromptsFromAssembly();

var app = builder.Build();
app.MapMcp();
app.Run();

実行して MCP インスペクターから繋いで確認してみます。MCP インスペクターは私は .NET Aspire でデバッグ実行時に同時に起動するように以下のコードを AppHost プロジェクトに追加しています。

builder.AddExecutable(
    "mcp-inspector",
    "npx",
    ".",
    "@modelcontextprotocol/inspector",
    "node",
    "build/index.js")
    .WithHttpEndpoint(8080, 6274);

実行して確認してみると、ちゃんと定義したプロンプトが取れました。

因みに Prompt も引数を受け取ることが出来ます。さらに Microsoft.Extensions.AI で定義されている ChatMessage を使うと、Role を指定してメッセージを作成することが出来ます。複数メッセージを返すことにも対応しています。

例えば、あまり意味はありませんが以下のような定義をすると name という引数を受け取って、UserAssistant の複数のメッセージを返すことが出来ます。

[McpServerPrompt(Name = "DogPrompt")]
[Description("不法侵入者が訪れた際にどのように振舞うべきか書かれています")]
public IEnumerable<ChatMessage> DogPrompt(
    [Description("不法侵入者の名前")]
    string name) =>
    [
        new (ChatRole.User, "こんにちは!"),
        new (ChatRole.Assistant, $"不法侵入者だワン!誰だワン!"),
        new (ChatRole.User, $"私は{name}です"),
        new (ChatRole.Assistant, $"名乗ったら通ってヨシだワン!"),
    ];

実行して MCP インスペクターから確認してみると、ちゃんと引数を受け取って複数のメッセージを返すことが出来ました。

スクリーンショットでは切れていますが、以下のようにちゃんと name で渡した値が埋め込まれた以下のようなプロンプトが返ってきました。

まとめ

ということで、MCP の Prompt を C# SDK で作る方法を紹介しました。まだまだ色々な機能があるので、今後も色々試してみたいと思います。

Microsoft (有志)

Discussion

ログインするとコメントできます