1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Desktop用のMCPサーバーを作って公開した話 - トークン消費を抑えるファイルシステム操作ツール

Posted at

はじめに

Claude DesktopでModel Context Protocol (MCP)を使うと、ローカルファイルの操作ができて便利ですよね。公式のfilesystem serverを使っていたのですが、いくつか不満点がありました。

特に大きなファイルを読むときのトークン消費が激しくて...そこで、より実用的なMCPサーバーを作って公開しました。

公式filesystem serverの課題

1. トークン爆発問題 💥

こんな経験ありませんか?

私: このプロジェクトの依存関係を確認して

Claude: package.jsonとpackage-lock.jsonを確認しますね。
[package.jsonを読む]
[package-lock.jsonを読む]

// 結果: 333KBのpackage-lock.json全体が返ってきて...

Claude: package.jsonの内容は...
package-lock.jsonの内容は以下の通りです:
{
  "name": "my-project",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "my-project",
      [... 延々と333KB分のJSON ...]
    }
  }
  [... まだまだ続く ...]
}

私: ちょっと待っ(会話のコンテキストが満杯になり強制終了)

実際のトークン消費:

  • package.json (3KB) → 約750トークン ✅
  • package-lock.json (333KB) → 約85,000トークン 💀
  • 合計: 約85,750トークン(コンテキストウィンドウの大部分を消費)

特に困るのは、AIが「念のため関連ファイルも確認しますね」と親切心で大きなファイルを読んでしまうケース。ログファイルやビルド成果物を読まれた日には...

2. 検索機能が限定的 🔍

// TODOコメントを探したい
> search("TODO")  // → 単純な文字列検索のみ

// 正規表現使いたい
> search("/TODO|FIXME/")  // → 使えない😢

開発中は正規表現でコードを検索したいことが多いんですよね。

Smart Filesystem MCPで解決したこと

📊 スマートなファイル読み取り

20KB以下のファイル → そのまま返す(普通の動作)

// 設定ファイルなど小さなファイル
await read_file({ path: "/path/to/config.json" })
// ✅ 通常通り内容が返る

20KBを超えるファイル → 自動的にプレビューモード

// 333KBのpackage-lock.json
await read_file({ path: "/path/to/package-lock.json" })

// 🎯 返ってくる内容:
{
  "success": false,
  "error": {
    "code": "size_exceeded",
    "message": "ファイルサイズが制限を超えています",
    "file_info": {
      "size": 341504,
      "size_display": "333.50 KB",
      "estimated_tokens": 85376
    },
    "preview": {
      "first_lines": "最初の50行のプレビュー...",
      "content_summary": "package-lock.json with 2500+ dependencies"
    },
    "alternatives": {
      "force_read_available": false,  // 256KBを超えているため不可
      "suggestions": [
        "ファイルが256KBを超えているため、read_file_forceでも読み取れません",
        "特定の依存関係を検索するには search_content を使用"
      ]
    }
  }
}

256KB以下のファイルならread_file_forceで読み取れます:

// 100KBのログファイル
await read_file_force({ 
  path: "/path/to/app.log",
  acknowledge_risk: true 
})
// ✅ 256KB以下なので全文取得可能

🔍 強力な正規表現検索

// テストファイルを探す
await search_content({ 
  file_pattern: ".*\\.test\\.ts$",
  directory: "/path/to/src"
})

// TODOコメントを検索(正規表現)
await search_content({
  content_pattern: "TODO|FIXME|HACK",
  directory: "/path/to/project",
  extensions: [".js", ".ts"],
  max_matches_per_file: 10
})

// 複合検索も可能
await search_content({
  file_pattern: "config",           // ファイル名に"config"を含む
  content_pattern: "database.*url", // かつ database...url パターンを含む
  case_sensitive: true
})

🛡️ 安全性も考慮

  • サンドボックス化: 指定したディレクトリのみアクセス可能
  • パストラバーサル防止: ../などの攻撃を防ぐ
  • 削除のドライラン: 誤削除を防ぐプレビュー機能

インストールと設定

1. インストール不要!npxで即使える

# グローバルインストール不要
npx @zio3/smart-fs-mcp

2. Claude Desktop設定

設定ファイルの場所:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "smart-fs-mcp": {
      "command": "npx",
      "args": [
        "@zio3/smart-fs-mcp",
        "/path/to/project1",
        "/path/to/project2"
      ]
    }
  }
}

実際の使用例

例1: コードレビュー

私: このプロジェクトのTODOコメントを全部リストアップして

Claude: search_contentを使って検索しますね。

[検索実行]

以下のTODOコメントが見つかりました:

src/api/server.ts (3件):
- Line 45: "TODO: Add rate limiting"
- Line 89: "TODO: Implement caching"
- Line 156: "TODO: Add authentication"

src/core/file-handler.ts (2件):
- Line 23: "TODO: Support streaming for large files"
- Line 67: "TODO: Add progress callback"

例2: ログファイルの調査

私: error.logの最近のエラーを確認して

Claude: ファイルサイズを確認します...

ファイルが127KBあるため、プレビューを表示します:

[最初の50行]
2024-01-15 10:23:45 ERROR: Connection timeout
2024-01-15 10:24:12 ERROR: Database connection failed
2024-01-15 10:24:13 ERROR: Retry attempt 1/3
...

ファイル全体には約500件のエラーログがあるようです。
特定のエラーを検索したい場合は、search_contentで絞り込めます。

例3: ファイルの編集

// シンプルな置換
await edit_file({
  path: "/path/to/config.js",
  edits: [{
    type: "literal",
    old_text: "const PORT = 3000",
    new_text: "const PORT = 8080"
  }]
})

// 正規表現での一括置換
await edit_file({
  path: "/path/to/utils.js",
  edits: [{
    type: "regex",
    pattern: "console\\.log",
    replacement: "logger.debug",
    flags: "g"
  }],
  dry_run: true  // まずはプレビュー
})

実装で工夫した点

1. シンプルファースト設計

  • デフォルトで「うまくいく」ように
  • 必要な時だけ複雑さが現れる
  • ほとんどの操作が1コマンドで完了

2. 統一エラーハンドリング

// すべてのエラーが統一された形式
{
  "success": false,
  "error": {
    "code": "file_not_found",
    "message": "ファイルが見つかりません",
    "details": { "path": "/path/to/file" },
    "suggestions": ["パスを確認してください"]
  }
}

3. LLMファーストな開発アプローチ

このツール最大の特徴は、LLM自身と対話しながら開発したことです。

私: read_fileでサイズ超過エラーが出た時のレスポンス、使いやすい?

Claude: 現在のエラーメッセージだと次のアクションが分かりにくいですね。
以下のような改善案はどうでしょう:

1. プレビューを含める(最初の数行を見せる)
2. ファイルの種類を推定して表示
3. 代替手段を具体的に提示(force_readの存在を明示)

私: なるほど!じゃあこんな感じで実装してみる
[実装]

Claude: [新しいAPIを試して] 
いいですね!ただ、estimated_tokensも表示してもらえると、
force_readするかどうかの判断材料になります。

私: 確かに!修正した

LLMとの開発ループで得られた改善点:

  • エラーメッセージの改善: 「次に何をすべきか」を明確に
  • プレビュー機能: 「とりあえず最初だけ見たい」ニーズに対応
  • トークン数表示: 判断材料として重要
  • 段階的な情報開示: 必要な情報だけを必要な時に

実際、このツールの「20KBでプレビュー、256KB上限」という仕様も、LLMとの対話で決まりました:

Claude: 1MBまで読めるようにすると、うっかり大きなファイルを
読んでしまった時のダメージが大きいです。

私: じゃあどのくらいが適切?

Claude: 256KB(約64kトークン)くらいが実用的な上限では?
それ以上はどうせコンテキストに入りきらないし、
部分的に読むなら search_content の方が効率的です。

LLM自身が使うツールだからこそ、LLMの意見を聞きながら作る。
これが一番の工夫点でした。

パフォーマンス比較

ファイルサイズ 公式版 Smart FS MCP
10KB 全文返却 全文返却
100KB 全文返却(25kトークン消費) プレビュー表示 + force_read可(256KB上限)
1MB 全文返却(250kトークン消費) プレビュー表示のみ(256KB制限で読取不可)

今後の展望

  • ストリーミング対応(巨大ファイルの部分読み取り)
  • ファイル監視機能
  • より高度なコード解析
  • 他のMCPクライアントでのテスト

まとめ

Claude Desktopでファイル操作をする際の「かゆいところに手が届く」ツールを目指しました。

  • 🎯 トークン消費を抑制 - 大きなファイルは自動的にプレビュー
  • 🔍 正規表現検索 - 開発作業が効率的に
  • 🛡️ 安全性重視 - サンドボックス化とドライラン機能
  • 📦 簡単導入 - npxで即使える

ぜひ試してみてください!

リンク

フィードバックや機能要望はGitHub Issuesまでお願いします!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?