Skip to main content
Glama
andreasronge

ptc-fs-mcp

by andreasronge

ptc-fs-mcp

単一のルートディレクトリ配下でファイルの読み書きを行う、小さなファイルシステムMCPサーバーです。stdio 経由で動作します。

デモ用ソフトウェアです。 エージェント実行環境がチュートリアルやサンプル、統合テストで参照できる、実際に動作する決定的な外部ツールとして存在します。一度で読み切れる程度に意図的に小さく設計されており、自分のプロジェクトにコピーして使うことができます。本番用のファイルサービスとしてデプロイしないでください。

このサーバーは、ファイルシステム機能が実行時コードではなくホスト設定のみを通じて提供されるPtcRunnerエージェンティックフレームワークのために構築されました。サーバー内の何も PtcRunner 固有のものではありません。stdio 上で素の MCP を話すため、任意の MCP クライアントからインストールできます。

npx -y ptc-fs-mcp --root ./workspace --include '**'

ツール

ツール

効果

戻り値

list_directory

読み取り

相対プレフィックス配下のエントリをソート・ページングして返す

search_files

読み取り

リテラル部分文字列を含むパスをソート・ページングして返す

search_text

読み取り

パスと行の証跡付きでリテラル一致をページングして返す

read_text_file

読み取り

正確な UTF-8 バイトチャンクをページングして返す

write_text_file

書き込み

1 つの通常ファイルを置き換え、パスとバイト数を報告する

4 つの読み取りツールはオプションの cursor と limit を受け付け、正確に items、next_cursor、content_hash を返します。カーソルなしで開始し、next_cursor が null になるまで追跡します。read_text_file の場合、アイテムの text を連結するとファイルが正確に再構築されます。

Related MCP server: Files MCP Server

ライブバイト

読み取りは呼び出し時点のファイルシステムを反映するため、書き込みは次の読み取りに反映されます。それがこのサーバーの存在意義であり、発見するよりも明示すべき 2 つの結果があります。

カーソルは破れるのではなく失敗します。 カーソルは、その走査が依存する状態のダイジェストを保持します。その状態が変更された場合、次のページは the filesystem changed since this cursor was issued; start the traversal again で拒否されます。変更前の半分と変更後の半分からなる、静かに破れたページ——それがエラーを費やす価値のある唯一の結果です。

結果が実際に依存する状態のみがバインドされるため、カーソルは無関係な変更では無効になりません:

ツール

失敗する条件

影響を受けない条件

list_directory

リストされたエントリが変更された場合

リストされたサブディレクトリのより深い場所にファイルが現れた場合

search_files

一致するパス集合が変更された場合

一致したファイルの内容が編集された場合

search_text

スコープ内のファイルの内容または同一性が変更された場合

検索プレフィックス外の変更

read_text_file

その 1 つのファイルが変更された場合

他のファイルの変更

カーソルはプロセスごとのキーで署名され、ツールとその引数にバインドされ、発行されたとおりに提示される必要があります。別の走査、別のプロセス、または編集された文字列からのカーソルは拒否されます。

すべての結果は content_hash を保持します。 これは、呼び出しが返したバイトの SHA-256 ダイジェストです。引用は、他の瞬間にたまたま存在したツリーではなく、実際に読み取られたバイトを指し示します。write_text_file は書き込んだバイトに対して同じダイジェストを報告するため、書き込みとそれに続く読み取りを相互に検証できます。

ツリー全体のハッシュやインストールする snapshot_identity はありません。ダイジェストは境界のあるキャプチャのみをカバーでき、このサーバーはキャプチャを行いません。

実行

ptc-fs-mcp --root ./workspace --include 'lib/**' --include 'docs/**' --exclude '**/secrets/**'

オプション

意味

--root <dir>

制限するディレクトリ。必須。

--include <glob>

一致するパスを提供。必須、繰り返し可能。

--exclude <glob>

一致するパスを提供しない。繰り返し可能。狭めることのみ可能。

--max-file-bytes <n>

これより大きいファイルは提供しない。

--max-write-bytes <n>

最大の write_text_file ペイロード。デフォルト 65536。

--include は必須であり、デフォルトはファイルなしです。したがって、それを指定せずに起動したサーバーは何も公開しません。除外されたパスは、stat や open の前にスキップされるため、インベントリされることはありません。グロブはセグメント内の * とセグメントをまたぐ ** に一致します。lib/** は lib/a.ts と lib/deep/a.ts の両方を選択します。

書き込みはルートに置かれるため、include ルールがルートに到達する必要があります。 write_text_file はディレクトリではなく 1 つのベース名を指定するため、すべての書き込みは直接ルートに入ります。サブディレクトリにのみ到達する include セット — --include 'lib/**' — は、それらのファイルを読み取り用に提供しますが、書き込みは一切受け付けず、各試行は no --include pattern of this root matches a file in the root itself で拒否されます。これは読み取り専用インストールの正当な構成であるため、サーバーはとにかく起動し、stderr にその旨を出力します:

ptc-fs-mcp: no --include pattern matches a file in the root itself, so
write_text_file will refuse every call.

書き込みツールがマッピングされている場合は、--include '**' を使用するか、ディレクトリパターンに加えて --include '*.md' などのルートレベルのパターンを追加します。

ホストドキュメントからバージョンを固定してインストールします:

"transport": {
  "type": "stdio",
  "command": "npx",
  "args": ["-y", "ptc-fs-mcp@0.1.0", "--root", "workspace", "--include", "**"],
  "inherit_environment": true
}

継承された環境なしでの起動

その形式では PATH が 2 回必要です。npx は PATH 上で見つかり、インストールされたバイナリは #!/usr/bin/env node で始まり、インタプリタも PATH 上で解決されます。スクラブされた環境で起動するホスト — PtcRunner の inherit_environment: false(独自のエンドツーエンドテストで使用)— はサーバーをまったく起動できず、失敗は PATH を指定するものではなく、provider_unavailable のような取得エラーとして届きます。バージョンマネージャはこれをより鋭く、より柔らかくします。nvm インタプリタは ~/.nvm/versions/node/v20.19.0/bin/node のようなパスに存在し、他のどこにも存在しません。

2 つの構成は相互に排他的です。密閉的に起動するには、パッケージを事前にインストールし、インタプリタとスクリプトを絶対パスで指定して、npx とシェバングの両方をバイパスします:

npm install ptc-fs-mcp@0.1.0
node -p process.execPath
node -p "require.resolve('ptc-fs-mcp/package.json').replace(/package\.json$/, 'dist/cli.js')"
"transport": {
  "type": "stdio",
  "command": "/absolute/path/to/bin/node",
  "args": [
    "/absolute/path/to/node_modules/ptc-fs-mcp/dist/cli.js",
    "--root",
    "/absolute/path/to/workspace",
    "--include",
    "**"
  ],
  "inherit_environment": false,
  "env": {}
}

サーバー自体は環境から何も必要としません。プロセスを生成せず、ネットワーク接続を開かず、独自の変数を読み取りません。--root は作業ディレクトリに対して解決されるため、ホストが制御する cwd を設定しない限り、絶対パスにしてください。examples/ptc-host.json の hermetic_workspace はこの形式です。

サーバーを分割せずに権限を分割する

MCP ホストは、どのアップストリームツールが機能になるかを選択するため、このパッケージの 1 つのインストールは read_text_file のみをマッピングでき、別のルートを指す 2 番目のインストールは write_text_file のみをマッピングできます。生成されたリーダープログラムは、書き込みツールをまったく解決できません。examples/ptc-host.json を参照してください。

Node からの使用

パッケージはライブラリでもあります。openRoot は構成を検証してルートを固定します。createServer はバイナリが提供するのと同じ McpServer を構築し、任意のトランスポートを指定できます。

import { createServer, openRoot } from 'ptc-fs-mcp'

const root = openRoot({ root: './workspace', include: ['**'], exclude: ['*.secret'] })
const server = createServer(root)

await server.connect(myTransport)

examples/embed.mjs は、ファイルを書き込み、読み戻し、検索する実行可能なバージョンです — すべて SDK のインメモリトランスポートを介して 1 つのプロセスで実行します:

npm run build && node examples/embed.mjs

openRoot は使用できない構成で ConfigError をスローし、ツールは ToolError を発生させます。どちらもエクスポートされており、normalizeRelative、compileGlob、createSelector、DEFAULT_LIMITS とともに、ホストがパス契約を再実装せずに再利用できます。TypeScript 宣言はパッケージに同梱されています。

プロトコル

2026-07-28 のみ。initialize フォールバック、ダウングレードネゴシエーション、互換性ブランチはありません。2025 年時代のオープニングは、このサーバーが実装するプロファイルを指定するサポートされていないプロトコルバージョンエラーで拒否されます。tools 機能のみがアドバタイズされます — Roots、Sampling、Logging、Tasks はありません。

制限

  • 相対パスのみ。絶対パス、./.. セグメント、NUL バイト、Windows セパレータは解決ではなく拒否されます。

  • シンボリックリンクはスキップされ、決して追跡されないため、ルート内のリンクがルート外のバイトに到達することはできません。最終的な open は O_NOFOLLOW を使用するため、チェック後にリンクが交換されても失敗します。

  • ディレクトリは、提供される何かを保持している場合にのみリストに表示されるため、提供されていないディレクトリの名前が漏れることはありません。

  • write_text_file は 1 つの小文字のベース名を受け入れます — ディレクトリなし、トラバーサルなし — ペイロードを制限し、シンボリックリンクが追い越す可能性のある別の stat ではなく、書き込む記述子を介して宛先が通常ファイルであることを確認します。--include の外の宛先は拒否されます。読み戻せない書き込みは罠であり、機能ではないからです。書き込みはルートに置かれるため、サブディレクトリにのみ到達する include ルールはすべての書き込みを拒否します。実行 を参照してください。

  • パスリストはコンテンツに依存しません。コンテンツツールはデコードできないものを拒否します。read_text_file は有効な UTF-8 でないファイルで失敗し、search_text はバイトがデコードされない行をスキップするため、行は全体として報告されるか、まったく報告されません。

  • 結果は完全にデコードされた MCP 結果に適合され、テキスト検索にはスキャンバイト予算もあります。空の検索ページは、スパースファイルがより多くのスキャンを必要とする場合に、進行状況カーソルを運ぶことができます。

  • エラーは短い実用的なテキストです — スタックトレース、ホストパスはありません。

  • 何も生成されず、ネットワークは使用されず、stdout はプロトコルメッセージのみを運びます。診断は stderr に送られます。

防御しないもの

ルートは、特権のあるアクターがあなたと競争していないように、信頼でき、静止している必要があります。ポータブルな Node パス API は、すべての祖先ディレクトリを記述子で制限することはできないため、呼び出し中に親ディレクトリを交換できるアクターはスコープ外です。サーバーは観測されたシンボリックリンクを拒否し、フォローなしの最終オープンを使用します。積極的に敵対的なソースルートを防御するとは主張していません。

カーソルの陳腐化は、サイズ、mtime、ctime、inode 番号から検出されます。粗いタイムスタンプ粒度のファイルシステムでは、同じタイムスタンプティック内でまったく同じ長さのインプレース書き換えは検出されません。これが実行されるすべての主流ファイルシステムはナノ秒時間を記録し、ctime はユーザースペースから設定できません。

開発

npm install
npm run build        # tsc to dist/, with declarations and source maps
npm test             # builds, then runs the suite against the built binary
npm run verify       # format check, typecheck, and tests

スイートは、ビルドされた dist/cli.js を実際の子プロセスとして実際の stdio を介して駆動するため、出荷されるものがテストされるものです。ルートはコミットではなくテストごとに生成されます。このサーバーは読み取りだけでなく書き込みも行うためです。

ライセンス

MIT。LICENSE を参照してください。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A lightweight, stdio-based MCP server enabling AI assistants to perform local file system operations like reading, writing, searching, and executing commands.
    3,012 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Stdio MCP server for sandboxed file access — read files, search content, safely edit with checksums, and manage file structure.
    13 npm
    ISC
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that gives AI agents file system access: read, write, search, hash, directory trees — 12 tools, zero dependencies, pure Python stdlib.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A sandboxed file-access MCP server for Claude Desktop, enabling safe read/write access to selected directories with atomic verified writes, undo, and read-only git operations.
    1
    MIT