ptc-fs-mcp
ptc-fs-mcp
Небольшой файловый MCP-сервер: чтение и запись файлов в пределах одного изолированного корневого каталога, через stdio.
Демонстрационное программное обеспечение. Оно существует для того, чтобы у агентных сред выполнения был реальный, детерминированный внешний инструмент, на который можно ссылаться в руководствах, примерах и интеграционных тестах. Он намеренно достаточно мал, чтобы его можно было прочитать за один присест и скопировать в свой проект. Не разворачивайте его как продакшн-сервис файлов.
Он был создан для агентного фреймворка PtcRunner, где возможность работы с файловой системой появляется целиком через конфигурацию хоста, а не через код времени выполнения. В самом сервере нет ничего специфичного для PtcRunner — он говорит на обычном MCP через stdio, так что любой 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 восстанавливает файл.
Живые байты
Чтение отражает файловую систему на момент вызова, поэтому запись видна следующему чтению. В этом и заключается смысл сервера, и у этого есть два следствия, которые лучше проговорить сразу, чем обнаружить позже.
Курсоры скорее ломаются, чем рвутся. Курсор несёт в себе дайджест состояния, от которого зависит обход. Если состояние изменилось, следующая страница отклоняется с ошибкой traversal state changed; start the traversal again. Только состояние, от которого реально зависит результат, влияет на курсор, поэтому несвязанное изменение не инвалидирует обход:
Инструмент | Не работает, когда | Работает, когда |
| Изменяется набор записей в пределах охвата | Изменение происходит глубже в уже перечисленном поддереве |
| Изменяется набор путей в пределах охвата | Изменяется содержимое файла, путь которого уже возвращён |
| Изменяется содержимое любого файла в пределах охвата | Изменение происходит за пределами охваченного пути |
| Изменяется содержимое файла | Изменяется любой другой файл |
Каждый вызов возвращает content_hash. Это HMAC-SHA-256 от байтов, которые возвращает инструмент, ключом служит производный от корня процесса секрет. Поэтому инструмент доказывает, что прочитал именно те байты, которые вернул. write_text_file возвращает и длину, и хэш, поэтому запись и последующее чтение можно сверить друг с другом.
Нет хэша всего дерева и нет snapshot_identity для установки. Дайджест может покрывать только ограниченный снимок, и этот сервер не делает снимков.
Запуск
ptc-fs-mcp --root ./workspace --include 'lib/**' --include 'docs/**' --exclude '**/secrets/**'Параметр | Назначение |
| Каталог, к которому ограничивается доступ. Обязательный. |
| Обслуживать только пути, соответствующие шаблону. Обязательный, повторяемый. |
| Никогда не обслуживать пути, соответствующие шаблону. Повторяемый; может сужать |
| Не обслуживать файлы больше этого размера. |
| Максимальный размер полезной нагрузки |
--include обязателен, и по умолчанию файлы не обслуживаются — сервер, запущенный без него, ничего не отдаёт. Исключённые пути пропускаются до любого stat или open, поэтому они не могут просочиться в результаты и не создают условий гонки. Инструменты чтения применяют одинаковые glob-выражения, и search_text дополнительно требует, чтобы совпадающий путь был текстовым.
Запись доверяет дескриптору, а не пути. write_text_file принимает только одно простое имя файла — без каталогов, без обхода, без точек — и открывает его с O_CREAT|O_EXCL, поэтому он никогда не перезаписывает существующий файл. Затем он записывает и вызывает fsync, и все это через тот же дескриптор. Символьные ссылки запрещены, а не разыменовываются. Файл за пределами --include отклоняется до открытия.
Протокол
Только 2026-07-28. Нет запасного initialize, нет согласования понижения версии, нет ветки совместимости: открытие протокола 2025 года отклоняется ошибкой неподдерживаемой версии протокола с указанием реализуемого профиля. Рекламируется только capability tools — никаких Roots, Sampling, Logging или Tasks.
Ограничения
Только относительные пути. Абсолютные пути, сегменты
./.., NUL-байты и разделители Windows отклоняются, а не разрешаются.Символические ссылки пропускаются и никогда не разыменовываются, поэтому ссылка внутри корня не может достать байты за его пределами. Финальный
openиспользуетO_NOFOLLOW, так что ссылка, подменённая после проверки, всё равно не сработает.Каталог появляется в списке только потому, что в нём есть обслуживаемое содержимое, поэтому имя каталога, не входящего в охват, не утекает.
write_text_fileпринимает одно имя в нижнем регистре — без каталогов, без обходов — ограничивает полезную нагрузку и подтверждает, что целевой файл является обычным файлом, через дескриптор, в который будет производиться запись, а не через отдельныйstat, который могла бы обойти символическая ссылка. Запись за пределами--includeотклоняется, потому что запись, которую нельзя прочитать обратно, — это не функция, а баг. Включения, доходящие только до подкаталогов, не разрешают запись на верхнем уровне; см. Запуск.Списки путей не зависят от содержимого; инструменты работы с содержимым отказываются от того, что не могут декодировать.
read_text_fileзавершается ошибкой на файле, не являющемся корректным UTF-8, аsearch_textпропускает строку, байты которой не декодируются. Строка либо есть целиком, либо её нет.Результаты подгоняются под полный декодированный результат MCP, а текстовый поиск также имеет ограничение на объем сканирования. Пустая страница поиска может нести курсор, если разреженный файл требует большего сканирования.
Ничего не порождается, сеть не открывается, переменные окружения не читаются. Ошибки — это короткий практичный текст, а не трассировки стека.
Что сервер не защищает
Корень должен быть доверенным и достаточно стабильным, чтобы противник не мог гоняться за вами. Переносимые Node-пути не могут защитить каждый родительский каталог, поэтому корень, который могут подменить во время вызова, выходит за рамки. Сервер отклоняет абсолютные пути и .., но не защищает от корня, который может быть переименован или подменён во время работы. Не размещайте его поверх недоверенного корня.
Временные окна: каталог перечисляется по содержимому, а файл проверяется на регулярность при открытии. Недоверенный корень может переключать записи между этими двумя проверками. Сервер закрывает окно с помощью O_NOFOLLOW и проверки fstat на том же дескрипторе, но не может предотвратить подмену родительского каталога. Для доверенного корня этого достаточно.
Running
ptc-fs-mcp --root ./workspace --include 'lib/**' --include 'docs/**' --exclude '**/secrets/**'Параметр | Назначение |
| Корневой каталог, в пределах которого всё ограничено. Обязательно. |
| Обслуживать пути, соответствующие glob. Повторяемый. Обязательно. |
| Никогда не обслуживать пути, соответствующие glob. Повторяемый. |
| Не обслуживать файлы больше этого размера. |
| Наибольший полезный размер записи. По умолчанию 65536. |
--include обязателен, и по умолчанию никакие файлы не обслуживаются — сервер, запущенный без него, не отдаёт ничего. Исключённые пути пропускаются до любого stat или open, поэтому даже имена файлов, соответствующих --exclude, никогда не наблюдаются вне корня.
Порядок применения: сначала --exclude, затем --include. Каталог обслуживается только тогда, когда он содержит обслуживаемый файл, поэтому пустые каталоги не видны.
Протокол
2026-07-28 только. Нет запасного initialize, нет согласования понижения версии, нет ветки совместимости: открытие эпохи 2025 года отклоняется ошибкой неподдерживаемой версии протокола с именем реализуемого этим сервером профиля. Рекламируется только возможность tools — никаких Roots, Sampling, Logging или Tasks.
Ограничения
Только относительные пути. Абсолютные пути, сегменты
./.., NUL-байты и разделители Windows отклоняются, а не разрешаются.Символические ссылки пропускаются, а не разыменовываются, поэтому ссылка внутри корня не может дотянуться до байтов вне его. Финальный
openиспользуетO_NOFOLLOW, поэтому ссылка, подставленная после проверки, всё равно не сработает.Каталог появляется в списке только потому, что содержит что-то обслуживаемое, поэтому имя каталога ничего не утекает.
write_text_fileпринимает одно имя файла в нижнем регистре — без каталогов, без обхода — ограничивает полезную нагрузку и подтверждает, что целевой файл является обычным, через дескриптор, в который будет производиться запись, а не через отдельныйstat, который ссылка могла бы обойти. Запись за пределами--includeотклоняется, потому что запись, которую нельзя прочитать обратно, — это скорее ловушка, чем функция. Поскольку запись попадает в корень, правила включения, которые не покрывают записанное имя, отклоняют её: включайте все пути, куда вы разрешаете писать.Перечисление путей не зависит от содержимого; инструменты работы с содержимым отказывают в том, что не могут прочитать.
read_text_fileзавершается ошибкой на недопустимом UTF-8. Поиск строки пропускает строки, которые не декодируются как UTF-8, чтобы не смещать номера строк.Результаты ограничены максимальным размером и квотами на количество элементов; исчерпание квоты возвращает частичные результаты с
cursorsиhasMore: true. Пустой результат по-прежнему является допустимым ответом.
GXP3, GXP4, GXP5, GXP6, GXP7, GXP8, GXP9 отсутствуют в оригинале.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Artifact store for AI agents. Hosted OAuth at mcp.artifacta.io/mcp; local stdio via npm/PyPI.
Project management MCP for AI agents with safe task reads and writes.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/andreasronge/ptc-fs-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server