0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

libuvの落とし穴

Last updated at Posted at 2025-09-10

はじめに

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についてとか勘違いしていたことなど、分かってきた気がします。
もう少し時間を見つけて作っていきたいなと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?