ClaudeにUUIDを生成させると、それっぽい文字列は返ってくるが乱数性がない。ハッシュ計算を頼めば架空のhex文字列が出てくる。これはLLMの構造上の限界で、今後も変わらない。
この問題を解決するアプローチとして注目されているのがMCPサーバーの自作だ。個人開発者のnob193氏がQiitaで公開した実践レポートが、その具体的な手順と落とし穴を余さず記録している。
この記事でわかること:
- どのWebツールをMCP化すべきかの判断基準
- TypeScript 200行規模での実装方法
- npm公開で躓く3つのポイント
- 公式MCPレジストリへの登録手順
- MCP化で集客・ブランド露出を狙う考え方
Claudeが苦手な処理を狙う
nob193氏が運営するlit-forge.comには38個の開発者向けWebツールがある。そのうちMCP化したのは10個だ。選定基準はシンプルで、「Claude単体でやろうとすると不正確になる処理か」で判断した。
優先度ごとに整理すると以下のようになる。
必須(★★★)
– generate_hash ── Claudeはハッシュ計算ができず架空のhex文字列を返す
– generate_uuid ── v4はそれっぽく書けるが乱数性なし。v7は時刻部の精度が出ない
– describe_cron ── 次回実行時刻の計算でしばしば誤る。タイムゾーン込みなら確実
有利(★★)
– test_regex ── 脳内シミュレーションで誤ることがある
– decode_jwt ── exp の今時刻判定が不正確
– convert_timestamp ── タイムゾーン誤りが頻発する
– convert_yaml_json ── 単純なら可。エッジケースで誤る
互角(★)
– format_json / convert_url / convert_base64
10ツール中「絶対必須」は3つだけで、機能面だけ見れば勝ち目は30%しかない。それでも10個セットで公開したのは、ブランド露出が本来の目的だからだ。リスト掲載時に「ツール10個」と言える方が目立つ。
逆にMVPから外したのは、BMI計算機や割り勘のように「Claudeが暗算できる」もの、テキスト読み上げのように「ブラウザAPI必須でstdio MCPでは実装困難」なもの、QRコード生成のように「バイナリ返却が面倒」なものだ。
実装はTypeScript 200行で完結
MCP TypeScript SDKはv1.29.0を採用した(v2はalphaのため見送り)。stdio transportを使い、McpServerにregisterToolで各ツールを登録するだけの構造だ。
// src/index.ts(簡略版)
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { tools } from "./tools/index.js";
const server = new McpServer({ name: "lit-forge", version: "0.1.2" });
for (const tool of tools) {
server.registerTool(tool.name, {
title: tool.title,
description: tool.description,
inputSchema: tool.inputSchema, // zod schema
}, tool.handler);
}
const transport = new StdioServerTransport();
await server.connect(transport);
各ツールはsrc/tools/<name>.tsにzodスキーマとhandler関数を一緒に書き、tools/index.tsで集約する。新ツールの追加は1ファイル足して1行importするだけで済む。
注意点として、Webサイト側の既存ロジック(app/lib/)を再利用しようとすると、btoa/atobなどブラウザ依存APIが含まれていて使えないケースが出てくる。Node native(Buffer/node:crypto)で書き直す前提で設計した方がスムーズだ。
npm公開で躓く3つの段差
npm publish --access public一発で終わると思いきや、3つの段差がある。
段差1: WSL2ではnpm loginのブラウザフローが落ちる
WSL2はOS標準ブラウザがないため、npm loginがweb認証URLを出した直後にstdinのUsernameプロンプトに落ちてEOFで死ぬ。回避策は以下だ。
sleep infinity | npm login --auth-type=web </dev/null
sleep infinityでstdinを活かしつつWeb認証のpollingを待つ。URLをwslviewでWindows側ブラウザに渡せばdevice flowが完走する。
段差2: 新規アカウントは2FA強制
npmは新規アカウントのpublishに対して2FAを実質強制する。2FA未設定ならEOTPエラーで弾かれる。認証アプリでTOTPを設定した上で、毎回publishのたびにOTPを付与する必要がある。
npm publish --access public --otp=847291
OTPは30秒で変わるため、認証アプリの数字を確認したら即実行することが肝心だ。
段差3: スコープ取得は想像より難しい
ブランド名でscopeを取ろうとすると、短い文字列はほぼ取得済みで空きがない。今回は@nob-labsも@nobsも既存ユーザーに取られていたため、unscopedでlit-forge-mcpとして公開した。初めて公開する場合は「動詞+機能名」の形が取れやすく分かりやすい。
公式MCPレジストリへの登録
公式MCP Registryへの掲載はmcp-publisher CLIで行う。package.jsonにmcpNameを追加し、server.jsonをリポジトリ直下に置いた上でCLIからpublishする。
namespaceの仕様として、GitHub認証でpublishする場合mcpNameはio.github.<owner>/<name>形式が必須だ。ownerはOAuth認証したユーザー本人か、公開メンバーであるorgでなければ403が返る。
orgを使いたい場合、orgのmember visibilityがPublicでないと401/403で弾かれる。プライバシー目的でPrivateにしていると詰まるポイントだ。
発見されるための4つのリスト
MCPサーバーを「見つけてもらう」主要な露出先は以下の4つだ。
| リスト | 規模 | 投稿方法 |
|---|---|---|
| punkpeye/awesome-mcp-servers | 85kスター | PR(README1行追加) |
| 公式MCP Registry | 公式 | mcp-publisher publish |
| mcpservers.org | 独立サイト | フォーム送信 |
| tolkonepiu/best-of-mcp-servers | 小規模 | Issueテンプレ |
punkpeyeのawesome-mcp-serversはDeveloper Toolsジャンルだけで類似のMCPが既に複数存在する。差別化ポイントを明確にした上で登録するとレビューが通りやすい。
なお、lit-forge-mcp自体はその後v0.2.0でツール構成をNISA/iDeCoなどの個人資産形成プランニングに全面刷新している。開発ユーティリティ10種から金融計算4種へのピボットだ。MCPサーバーを作った後に用途を変えることも十分できる、という意味での参考事例になっている。
Claudeに補完させるより正確に処理する
MCPサーバーの自作は「Claudeができないことをツールで補う」という発想の具体化だ。ハッシュ・UUID・cron計算など、LLMの確率的な動作では信頼できない処理は、正確な実装をMCPツールとして渡すことで解決できる。実装規模は200行程度で、公開まで含めても週末の作業量に収まる。
自分のWebツール集がある開発者なら、「Claudeが苦手な処理かどうか」を軸に選び直すだけで、すぐ試せる規模感の取り組みだ。