2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自家製 MCP サーバーで個人開発の Web ツール集を Claude から直接呼べるようにした完全レシピ

2
Posted at

本記事は lit-forge.com/blog/mcp-server-launch のクロスポストです。

やったこと(要約)

lit-forge.com の開発者向けユーティリティ 10 種を MCP(Model Context Protocol)サーバー化し、Claude Desktop / Claude Code / Cursor から直接呼び出せるようにしました。npm にも、公式 MCP Registry にも、awesome-mcp-servers にも公開済み。

以下、ツール選定の基準・実装・公開で踏んだ落とし穴を全部公開します。これから自分の Web ツール集を MCP 化する人の参考になれば。

なぜ MCP 化したか(集客戦略の話)

lit-forge.com は 38 個の Web ツールを抱える個人開発サイトで、収益源は AdSense + アフィリエイト。問題は「人を呼ぶ手段」です。Google 検索流入は SEO の積み上げに数ヶ月かかるし、SNS は 1 投稿の射程が短い。

そこで「Google 検索以外の発見経路」を開きたくて選んだのが MCP 化です。狙いは 3 つ:

  1. awesome-mcp-servers / 公式 MCP Registry に掲載される。数万スターのリストの読者・MCP クライアントの推奨候補に乗る
  2. Claude / Cursor のユーザーが普段使いするうちに lit-forge ブランドに触れる
  3. AI クライアント上で実際にツールを使ったユーザーが、「Web 版もある」と知って lit-forge.com を訪問する

Web ツールという土俵で「もう 39 個目のサイト」を作るより、AI クライアントという別土俵に同じ機能で出る方が、少ない労力でニッチ独占できる可能性が高いと踏みました。

ツール選定: 「Claude が苦手な領域」を狙う

lit-forge.com の 38 ツールから、MCP 化して意味があるものだけを選びました。判定基準は 「Claude が単体でやろうとすると不正確になる処理か?」

優先度 ツール 理由
★★★ 必須 generate_hash Claude はハッシュ計算できない。架空の hex 文字列を返してしまう
★★★ 必須 generate_uuid v4 はそれっぽく書けるが乱数性なし。v7 は時刻部の精度が出ない
★★★ 必須 describe_cron 「次回実行時刻」の計算でしばしば誤る。タイムゾーン込みなら確実
★★ 有利 test_regex 脳内シミュで誤ることがある。実 RegExp 実行で安心
★★ 有利 decode_jwt exp の今時刻判定が不正確。Date.now() で確実
★★ 有利 convert_timestamp タイムゾーン誤りが頻発する
★★ 有利 convert_yaml_json 単純なら可、エッジケースで誤る
★ 互角 format_json 小規模なら自力 OK、巨大 JSON では省略・改変リスク
★ 互角 convert_url 単純な文字列なら正確
★ 互角 convert_base64 ASCII OK、UTF-8 で誤りやすい

10 中 3 つだけが「絶対 MCP 必須」、残りは「有利」「互角」。機能的差別化だけ見たら 30% しか勝ち目がないけど、それでも 10 個セットにしたのはブランド露出が本来の目的だから。登録時に「ツール 10 個」と言える方がリスト掲載で目立つ。

逆に MVP から外したのは:

  • BMI 計算機・割り勘・年齢計算 → Claude が暗算できる
  • テキスト読み上げ・画像リサイズ → ブラウザ API 必須で stdio MCP では実装困難
  • QR コード生成・PDF 生成 → バイナリ返却が面倒(後の v0.2.0 候補)
  • 診断系(エンジニアタイプ等)→ 対話 UI が本質

実装: 200 行規模の TypeScript で完結

MCP TypeScript SDK は v1.29.0 を採用(v2 は alpha のため見送り)。stdio transport を使い、McpServerregisterTool でツールを登録するだけ。

// 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 するだけ。

「lit-forge.com の既存 app/lib/ を再利用すればよかった」と思いたいところですが、ブラウザ依存(btoa/atob/unescape/Web Crypto の一部)があるので結局 Node native(Buffer/node:crypto)で書き直し。同じロジックを 2 箇所に持つのは美しくないけど、サーバー側の純粋性を優先しました。

npm 公開でハマった: 2FA + OTP の罠

npm publish --access public 1 発で終わると思ったら、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: 新規 npm アカウントは即 2FA 強制

npm は新規アカウントの publish に対して2FA を実質強制します。2FA 未設定なら EOTP (One-Time Password) エラーで弾かれる。認証アプリ(Google Authenticator 等)で TOTP を設定し、毎回 publish 時に:

npm publish --access public --otp=847291

30 秒で OTP が変わるので、認証アプリの数字を確認したら即実行。

段差 3: スコープ取得は意外と難しい

ブランド名で scope を取りたかったけど、@nob-labs は既にユーザーが取得済み、@nobs も既存。3 文字の短い scope はほぼ全滅。結局 unscoped で lit-forge-mcp として公開

npm の package 名と user/scope 名は別 namespace ですが、人気の単語はほぼ取られているので、初めて公開する時は 「scope なしで動詞 + 機能名」 が一番スッと取れて分かりやすいです。

ブランド統一でやらかした: GitHub username rename と Contributors 永続キャッシュ

ここから本当の地獄。npm のユーザー名を実名要素含む形で取ってしまったので、途中で 「ブランド統一のため別アカウントに移管したい」 と判断。ところが GitHub と npm では rename の仕様が真逆でした。

npm: rename 不可、新規作成 + 所有権移管 + 旧アカ削除

# 旧アカで(OTP 必要)
npm owner add nob-labs lit-forge-mcp --otp=...
# 新アカで(招待を承認、OTP 必要)
npm owner rm 旧アカ lit-forge-mcp --otp=...
# Web UI から旧アカウント完全削除

所有権移管には新アカ側で招待を承認するステップが必要(npm owner ls ですぐ反映されない)。30 日後に旧 username が他人取得可能になるので、squat リスクは残ります。

GitHub: rename は公式サポート、ただし profile URL は redirect されない

GitHub は Settings → Account → Change username で 1 クリック改名。既存のリポジトリ・PR・Issue・Contribution graph が全部新名前に追従して redirect も効きます。ただし profile URL(github.com/旧名)は 404 になるので、profile への直リンクは生き残らない。これは privacy 観点ではむしろ好都合でした(旧 profile 経由で過去活動を辿られない)。

Contributors widget の永続キャッシュ問題

ここが一番ハマった。GitHub のリポジトリ右サイドに出る「Contributors」ウィジェットは、force-push で commit author を rewrite しても古いキャッシュを数日〜数週間返し続ける

git filter-branch で全 commit の author を新名前に書き換え、force-push しても、Contributors widget には旧名前のままが表示される。GitHub API の /contributors エンドポイントも同じ。stats endpoint は {} を返してきて再集計中であることを示すが、widget は更新されない。

解決策は リポジトリを一度削除して同じ名前で作り直す。これで完全にゼロから集計され、新 author だけが表示される。既に PR や issue が付いていなければダメージなし(私の場合は公開直後だったので 0 件)。

# delete_repo スコープが必要
gh auth refresh -h github.com -s delete_repo
gh repo delete noblabs/lit-forge-mcp --yes
gh repo create noblabs/lit-forge-mcp --public --description "..."
git push -u origin main

公開済みの awesome-mcp-servers PR や npm の repository.url は同じ URL なので無傷。リポジトリ削除は怖いですが、commit 履歴が数件しかない初期段階なら最速の解決でした。

公式 MCP Registry の罠: 公開ドメインの選び方

公式 MCP Registrymcp-publisher CLI で publish します。package.jsonmcpName を追加し、server.json をリポジトリ直下に置いて、CLI で GitHub device flow 認証 → publish。

ハマったのは namespace 仕様。GitHub auth で publish する場合、mcpNameio.github.<owner>/<name> 形式必須で、ownerOAuth 認証したユーザー本人 or 公開メンバーである org でなければ 403 が返ります。

個人 namespace(io.github.nob-owner/...)で publish するのが一番楽ですが、ブランド統一を考えると org(io.github.noblabs/...)を使いたい。すると条件として org member visibility が Public でなければならない。私は最初 privacy 目的で Private にしていたので、401 / 403 でハマりました。

結論: org publish したいなら member visibility は Public 必須。privacy と公開ブランドのトレードオフがここに発生します。私は noblabs の Public 化を選びました(ハンドル nob-owner 自体に実名要素がないので exposure コストは限定的)。

露出経路: 4 リストへの登録

MCP サーバーを「見つけてもらう」ための主要露出先と、各々の特徴:

リスト スター 投稿方法 結果
punkpeye/awesome-mcp-servers 85k PR (README 1 行追加) 提出済み・レビュー待ち
公式 MCP Registry 公式 mcp-publisher publish 即時 active
mcpservers.org 独立サイト フォーム送信 送信済み・レビュー待ち
tolkonepiu/best-of-mcp-servers 小規模 Issue テンプレ Issue 提出済み
appcypher/awesome-mcp-servers 5.5k PR/Issue 共に無効 投稿不可(メンテ停止)

punkpeye の awesome-mcp-servers は ジャンル「Developer Tools」だけで既に類似ユーティリティ系 MCP が 4 つ 登録されていて、差別化が苦しい。自分の lit-forge-mcp の場合は「lit-forge.com の Web UI 版と並走」を差別化文言に据えました。Web UI ↔ MCP の選択肢があるのは他社にない強みです。

lit-forge.com 内の導線整備

外部から流入してきたユーザーが「lit-forge.com 本体も Web 版あるんだ」と気づく導線が必要。3 段構えで配置しました:

  • TOPページのヒーロー直下にバナー: 紫グラデの 1 行カード「🤖 AI 連携 - lit-forge MCP サーバー」。全訪問者が必ず通る位置
  • MCP 対応 10 ツールのフッターに案内: JSON 整形や UUID 生成等の MCP 化済みツールには usePathname() でパス判定して「Claude から直接呼ぶには」のリンクを自動表示
  • 専用ページ /mcp: Claude Desktop / Code / Cursor のインストール手順、10 ツール一覧、自然言語での使い方例、公式 Registry へのリンクを集約

逆に「lit-forge.com の Web ツールを使ってた人が AI でも使う」流れも狙えます。双方向の導線で、ユーザーがどの土俵で接触してきても lit-forge ブランドに繋ぎ留める設計。

結果と学び

数字(公開直後の状態)

  • npm: lit-forge-mcp v0.1.2 公開、ダウンロード数は集計中
  • 公式 MCP Registry: 即時 active
  • awesome-mcp-servers PR: 提出 1 日目、レビュー待ち
  • lit-forge.com /mcp ページ: 公開済み、流入計測はこれから

学び 5 つ

  1. MCP 化は機能差別化より露出が本命。10 ツール中 3 つしか「絶対 MCP じゃないとできない」処理はなかった。それでもやる価値があるのは、awesome リスト・公式 Registry・AI クライアント経由のブランド接触が増えるから
  2. ブランド名取得は最初に全部やる。npm / GitHub / Vercel / X / ドメインで同じ名前を全部押さえてから始めるべき。途中で rename すると Contributors キャッシュ問題のような副作用が出る
  3. privacy と publish 権限のトレードオフ。公式 Registry に org namespace で publish したいなら member visibility は Public 必須。privacy 重視なら個人 namespace で妥協する
  4. WSL2 開発者は wslview + sleep infinity パイプ を覚えると CLI ベースの Web 認証フロー全般で詰まらなくなる
  5. 類似 MCP が既にあっても出す価値はある。Web UI と並走、Japanese-first ドキュメント、無料・no-telemetry など独自性で勝負できる

試してみる

一番楽な試し方は Claude Code 経由:

claude mcp add lit-forge -- npx -y lit-forge-mcp

セッションを開き直して /mcp でリストに lit-forge が出れば成功。あとは「この JWT デコードして」「UUID v7 を 5 個」「0 9 * * 1-5 を Asia/Tokyo で次の3回」のように自然言語で頼むだけで Claude が自動的にツールを呼びます。

Claude Desktop / Cursor の設定方法は /mcp ページ に集約してあります。バグ報告・機能要望は GitHub Issues までどうぞ。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?