はじめに
MCPサーバーの実装を細々と続けていて、stdioトランスポートも作ろうと思い調査を進めていたところ、ChatGPTさんが libuv 使うと良いのではというので調べてみました。
libuv とは?
クロスプラットフォームの非同期I/Oライブラリとのこと。
stdin、stdout の処理って、POSIX と Windows で微妙に差があり、どうしても #ifdef 的なものが必要になる。
これを使えばシンプルに同じ実装で実現できる。
早速作ってみた
今までのお試し実装から少し進化して、cmake のプロジェクトで作り直してみました。
そして、MCP Server から トランスポートの実装を分離。HTTPトランスポートとSTDIOトランポートという感じで実装を整理しました。
結果、MCPサーバーの実装は以下のような感じに。
using namespace Mcp;
int main()
{
McpServer server("MCP Test");
server.AddTool(
"get_current_time",
"Get the current time at the specified location.",
std::vector<McpServer::McpProperty> {
{ "location", McpServer::PROPERTY_STRING, "location", false }
},
std::vector<McpServer::McpProperty> {},
[](const std::map<std::string, std::string>& args) -> std::vector<McpServer::McpContent> {
std::vector<McpServer::McpContent> contents;
char datetime_str[20];
time_t now = time(NULL);
struct tm* tm_info = localtime(&now);
strftime(datetime_str, sizeof(datetime_str), "%Y/%m/%d %H:%M:%S", tm_info);
McpServer::McpContent content{
.property_type = McpServer::PROPERTY_TEXT,
.value = datetime_str,
};
contents.push_back(content);
return contents;
}
);
#ifdef USE_HTTP_TRANSPORT
// HTTPトランスポート
McpHttpServerTransport* transport = new McpHttpServerTransport();
// HTTPSにする場合
transport->SetTls(
"cert.pem",
"key.pem"
);
// OAuthで認証させる場合
transport->SetAuthorization(
"\"https://***tenant name***.us.auth0.com\"",
"\"***api permission***\""
);
transport->SetEntryPoint(
"localhost:8000/mcp",
10 * 60 * 1000
);
#else
// STDIOトランスポート
McpStdioServerTransport::Initialize();
McpStdioServerTransport* transport = McpStdioServerTransport::GetInstance();
#endif
server.Run(transport);
#ifdef USE_HTTP_TRANSPORT
delete transport;
#else
McpStdioServerTransport::Terminate();
#endif
return 0;
}
落とし穴
ubuntuでビルドした場合、stdioトランスポートで無事に動作しました。
が、しかし、windowsでビルドした場合は、まったく動作しません。
なんだかんだ調べた結果...
NOTE:
On windows only sockets can be polled with poll handles. On Unix any
file descriptor that would be accepted by poll(2) can be used.
えっ?Windowsではソケットだけです?
うん知ってた。
いやだからこそ、libuvなら動作するのかと思って使ってみたのですが、結局だめでした。
てか、ChatGTPに改めて聞いてみたら、そうだよ動作しないよとのこと。
いやいや、あなたがlibuv使えばって勧めてきたんだよ..._| ̄|○
最後に
折角動いたけれど、作り直しかな。
ちゃんちゃん。
ただ、ここまで作ってきて、これまで書いてきたことでLLMについてとか、MCPについてとか勘違いしていたことなど、分かってきた気がします。
もう少し時間を見つけて作っていきたいなと思います。