ptc-fs-mcp
ptc-fs-mcp
하나의 제한된 루트 아래에서 파일을 읽고 쓰는, stdio를 통해 동작하는 소형 파일시스템 MCP 서버입니다.
데모 소프트웨어입니다. 에이전트 런타임이 튜토리얼, 예제, 통합 테스트에서 가리킬 실제적이고 결정적인 외부 도구를 갖도록 존재합니다. 한 번에 읽고 자신의 프로젝트에 복사할 수 있을 만큼 의도적으로 작게 설계되었습니다. 프로덕션 파일 서비스로 배포하지 마십시오.
파일시스템 기능이 런타임 코드가 아닌 전적으로 호스트 구성으로 제공되는 PtcRunner 에이전트 프레임워크를 위해 만들어졌습니다. 서버에는 PtcRunner 특유의 것은 없습니다. — stdio를 통해 일반 MCP를 사용하므로 어떤 MCP 클라이언트든 설치할 수 있습니다.
npx -y ptc-fs-mcp --root ./workspace --include '**'도구
도구 | 효과 | 반환값 |
| 읽기 | 상대 접두어 아래의 정렬되고 페이지화된 항목 |
| 읽기 | 리터럴 부분 문자열을 포함하는 정렬되고 페이지화된 경로 |
| 읽기 | 경로와 줄 증거가 포함된 페이지화된 리터럴 일치 항목 |
| 읽기 | 페이지화된 정확한 UTF-8 바이트 청크 |
| 쓰기 | 일반 파일 하나를 교체하고 경로와 바이트 수를 보고 |
네 개의 읽기 도구는 선택적 cursor와 limit를 받아 정확히 items, next_cursor, content_hash를 반환합니다. 커서 없이 시작하여 next_cursor가 null이 될 때까지 따라갑니다. read_text_file의 경우 항목 text를 연결하면 파일이 정확히 재구성됩니다.
Related MCP server: Files MCP Server
실시간 바이트
읽기는 호출 시점의 파일시스템을 반영하므로 쓰기는 다음 읽기에 즉시 보입니다. 이것이 이 서버의 존재 이유이며, 발견이 아니라 명시적으로 밝힐 가치가 있는 두 가지 결과가 있습니다.
커서는 찢어지기보다 실패합니다. 커서는 자신의 순회가 의존하는 상태의 다이제스트를 담고 있습니다. 그 상태가 변경되면 다음 페이지는 이 커서가 발급된 이후 파일시스템이 변경되었습니다. 순회를 다시 시작하십시오라는 오류로 거부됩니다. 변경 전 절반과 변경 후 절반이 섞인 조용히 찢어진 페이지 — 그것이 오류 하나를 쓸 가치가 있는 유일한 결과입니다.
결과가 실제로 의존하는 상태만 바인딩되므로, 커서는 무관한 변경으로 무효화되지 않습니다:
도구 | 실패 조건 | 유지 조건 |
| 나열된 항목이 변경됨 | 나열된 하위 디렉터리 더 깊은 곳에 파일이 나타남 |
| 일치하는 경로 집합이 변경됨 | 일치하는 파일의 내용이 편집됨 |
| 범위 내 파일의 내용이나 정체성이 변경됨 | 검색된 접두어 밖의 변경 |
| 해당 파일 하나가 변경됨 | 다른 파일의 변경 |
커서는 프로세스별 키로 서명되고, 도구와 그 인자에 바인딩되며, 발급된 그대로 제시되어야 합니다. 다른 순회, 다른 프로세스, 또는 편집된 문자열의 커서는 거부됩니다.
모든 결과는 content_hash를 담고 있습니다. 이는 해당 호출이 반환한 바이트의 SHA-256 다이제스트입니다. 인용은 그때그때 우연히 존재했던 트리가 아니라 실제로 읽은 바이트를 지칭합니다. write_text_file은 자신이 쓴 바이트에 대해 동일한 다이제스트를 보고하므로, 쓰기와 그 뒤의 읽기를 서로 대조할 수 있습니다.
전체 트리 해시도, 설치할 snapshot_identity도 없습니다. 다이제스트는 경계가 있는 캡처만을 다룰 수 있으며, 이 서버는 캡처를 수행하지 않습니다.
실행
ptc-fs-mcp --root ./workspace --include 'lib/**' --include 'docs/**' --exclude '**/secrets/**'옵션 | 의미 |
| 제한할 디렉터리. 필수. |
| 일치하는 경로를 제공. 필수, 반복 가능. |
| 일치하는 경로를 절대 제공하지 않음. 반복 가능; 좁히기만 가능. |
| 이보다 큰 파일은 제공하지 않음. |
|
|
--include는 필수이며 기본값은 파일 없음이므로, 이 옵션 없이 시작된 서버는 아무것도 노출하지 않습니다. 제외된 경로는 stat이나 open 이전에 건너뛰므로 목록에 포함되지 않습니다. Glob은 세그먼트 내에서 *, 세그먼트를 가로질러 **와 일치합니다. lib/**는 lib/a.ts와 lib/deep/a.ts를 모두 선택합니다.
쓰기는 루트에 도달하므로 include 규칙이 루트에 닿아야 합니다. write_text_file은 디렉터리가 아닌 하나의 기본 이름만 지정하므로 모든 쓰기는 루트로 직접 들어갑니다. 하위 디렉터리에만 닿는 include 집합 — --include 'lib/**' — 은 해당 파일들을 읽기용으로 제공하지만 쓰기는 전혀 받아들일 수 없으며, 각 시도는 이 루트의 --include 패턴 중 루트 자체의 파일과 일치하는 것이 없습니다로 거부됩니다. 이는 읽기 전용 설치의 합법적인 구성이므로 서버는 어쨌든 시작하고 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가 두 번 필요합니다. npx는 PATH에서 찾아지고, 설치된 바이너리는 #!/usr/bin/env node로 시작하므로 인터프리터도 PATH에서 해석됩니다. 정리된 환경으로 실행하는 호스트 — PtcRunner의 inherit_environment: false, 자체 엔드투엔드 테스트에서 사용 — 는 서버를 전혀 시작할 수 없으며, 실패는 PATH를 언급하는 것이 아니라 provider_unavailable 같은 획득 오류로 도착합니다. 버전 관리자는 이를 더 선명하게 만들 뿐 부드럽게 만들지 않습니다. nvm 인터프리터는 ~/.nvm/versions/node/v20.19.0/bin/node 같은 경로에 있으며 다른 곳에는 존재하지 않습니다.
두 구성은 상호 배타적입니다. 밀폐형으로 실행하려면 패키지를 미리 설치하고 인터프리터와 스크립트를 절대 경로로 지정하여 npx와 shebang을 모두 우회하십시오:
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 호스트는 어떤 업스트림 도구가 기능이 될지 선택하므로, 이 패키지의 한 설치본은 read_text_file만 매핑할 수 있고 다른 루트를 가리키는 두 번째 설치본은 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의 인메모리 전송을 통해 단일 프로세스에서 수행됩니다:
npm run build && node examples/embed.mjsopenRoot는 사용할 수 없는 구성에서 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은 소문자 기본 이름 하나만 받습니다 — 디렉터리 없음, 순회 없음 — 페이로드를 제한하고, 심볼릭 링크가 앞지를 수 있는 별도의stat이 아니라 자신이 쓸 디스크립터를 통해 대상이 일반 파일인지 확인합니다.--include밖의 대상은 거부됩니다. 다시 읽을 수 없는 쓰기는 기능이 아니라 함정이기 때문입니다. 쓰기는 루트에 도달하므로 하위 디렉터리에만 닿는 include 규칙은 모든 쓰기를 거부합니다. 실행을 참조하십시오.경로 목록은 내용을 보지 않습니다. 내용 도구는 디코딩할 수 없는 것을 거부합니다.
read_text_file은 유효한 UTF-8이 아닌 파일에서 실패하고,search_text는 바이트가 디코딩되지 않는 줄을 건너뛰므로 줄은 전체로 보고되거나 전혀 보고되지 않습니다.결과는 전체 디코딩된 MCP 결과에 맞춰지며, 텍스트 검색에는 스캔 바이트 예산도 있습니다. 따라서 희소 파일이 더 많은 스캔을 필요로 할 때 빈 검색 페이지가 진행 커서를 담을 수 있습니다.
오류는 짧고 실행 가능한 텍스트입니다 — 스택트레이스 없음, 호스트 경로 없음.
아무것도 생성되지 않고, 네트워크가 사용되지 않으며, stdout은 프로토콜 메시지만 전달합니다. 진단은 stderr로 갑니다.
방어하지 않는 것
루트는 권한 있는 행위자가 당신과 경쟁하지 않을 만큼 신뢰할 수 있고 안정적이어야 합니다. 이식 가능한 Node 경로 API는 모든 상위 디렉터리를 디스크립터로 제한할 수 없으므로, 호출 중에 상위 디렉터리를 교체할 수 있는 행위자는 범위 밖입니다. 서버는 관찰된 심볼릭 링크를 거부하고 no-follow 최종 open을 사용합니다. 적극적으로 적대적인 소스 루트를 방어한다고 주장하지 않습니다.
커서 오래됨은 크기, 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를 참조하십시오.
This server cannot be deployed
Maintenance
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
- flockfsOAuthcom.flockfs
A real-time, multiplayer filesystem for agents and humans: shared files, live edits, history.
MCP server for Superserve sandboxes: create, exec, and manage Firecracker microVMs
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA lightweight, stdio-based MCP server enabling AI assistants to perform local file system operations like reading, writing, searching, and executing commands.3,012 npmMIT
- AlicenseNot gradedqualityDmaintenanceStdio MCP server for sandboxed file access — read files, search content, safely edit with checksums, and manage file structure.13 npmISC
- AlicenseNot gradedqualityCmaintenanceAn MCP server that gives AI agents file system access: read, write, search, hash, directory trees — 12 tools, zero dependencies, pure Python stdlib.MIT
- AlicenseNot gradedqualityBmaintenanceA 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.1MIT