2e6f1c3de5
Два структурных слепых пятна: (1) сервер грузит СКОМПИЛИРОВАННЫЙ
packages/mcp/build/index.js, а серверные guard-тесты читают src/tool-specs.ts —
правка src без пересборки оставляет тесты зелёными, но рантайм расходится со
спеками; (2) спеки добавляют в packages/mcp, а parity-тесты живут в jest-сьюте
apps/server — PR, трогающий только пакет, проходит зелёным, сломанная in-app-
проводка всплывает уже на develop (кейс f46d89ea).
- REGISTRY_STAMP: codegen (scripts/gen-registry-stamp.mjs) считает sha256 от
нормализованного (CRLF→LF, один хвостовой \n снят) сырого текста
src/tool-specs.ts, пишет src/registry-stamp.generated.ts (gitignored),
index.ts реэкспортит → попадает в build/. Вшит в build/pretest/watch ДО tsc.
- Loader (dev/test): computeSrcRegistryStamp пересчитывает стамп из src рядом с
build/index.js (dev-vs-prod по existsSync, любая ошибка → null), сверяет с
build-стампом → при рассинхроне бросает «build is stale — rebuild». В prod
(src нет) и на pre-#447 билдах (нет REGISTRY_STAMP) — чистый no-op.
- CI: job mcp-server-parity собирает shared-deps+mcp (регенерит стамп) и гоняет
ОБА сьюта вместе (mcp node:test + server guard-спеки) — именованный гейт, его
нельзя случайно расщепить.
- AGENTS.md: правка спеков требует ребилда @docmost/mcp.
Тесты (20): mcp-сайд (детерминизм, нормализация, desync-гард стамп-vs-билд) +
server-сайд (null при отсутствии src = prod no-op; mismatch → throw точного
сообщения; pre-#447 no-op). Кросс-импл equality-гард: один фиксированный вход →
один хэш на ОБЕИХ сторонах, ловит рассинхрон двух нормализаций. Внутреннее
ревью: APPROVE WITH SUGGESTIONS (обе — покрытие guard'а — закрыты этим тестом).
Мутационно: любой из двух normalize-имплов расходится → equality-тест краснеет.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.1 KiB
JSON
69 lines
2.1 KiB
JSON
{
|
|
"name": "@docmost/mcp",
|
|
"version": "1.0.0",
|
|
"description": "A Model Context Protocol (MCP) server for Docmost, allowing AI agents to manage documentation spaces and pages.",
|
|
"private": true,
|
|
"type": "module",
|
|
"main": "./build/index.js",
|
|
"exports": {
|
|
".": "./build/index.js",
|
|
"./http": "./build/http.js"
|
|
},
|
|
"bin": {
|
|
"docmost-mcp": "./build/stdio.js"
|
|
},
|
|
"scripts": {
|
|
"gen:stamp": "node scripts/gen-registry-stamp.mjs",
|
|
"build": "node scripts/gen-registry-stamp.mjs && tsc",
|
|
"start": "node build/stdio.js",
|
|
"watch": "node scripts/gen-registry-stamp.mjs && tsc --watch",
|
|
"pretest": "node scripts/gen-registry-stamp.mjs && tsc",
|
|
"test": "node --test \"test/unit/*.test.mjs\" \"test/mock/*.test.mjs\"",
|
|
"test:unit": "node --test \"test/unit/*.test.mjs\"",
|
|
"test:mock": "node --test \"test/mock/*.test.mjs\"",
|
|
"test:e2e": "node test-e2e.mjs"
|
|
},
|
|
"keywords": [
|
|
"mcp",
|
|
"docmost",
|
|
"documentation",
|
|
"ai",
|
|
"agent"
|
|
],
|
|
"author": "Moritz Krause",
|
|
"license": "MIT",
|
|
"dependencies": {
|
|
"@docmost/prosemirror-markdown": "workspace:*",
|
|
"@fellow/prosemirror-recreate-transform": "^1.2.3",
|
|
"@hocuspocus/provider": "^3.4.4",
|
|
"@hocuspocus/transformer": "^3.4.4",
|
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
"@tiptap/core": "3.20.4",
|
|
"@tiptap/extension-highlight": "3.20.4",
|
|
"@tiptap/extension-image": "3.20.4",
|
|
"@tiptap/extension-link": "3.20.4",
|
|
"@tiptap/extension-subscript": "3.20.4",
|
|
"@tiptap/extension-superscript": "3.20.4",
|
|
"@tiptap/extension-task-item": "3.20.4",
|
|
"@tiptap/extension-task-list": "3.20.4",
|
|
"@tiptap/html": "3.20.4",
|
|
"@tiptap/starter-kit": "3.20.4",
|
|
"@types/jsdom": "^27.0.0",
|
|
"axios": "^1.6.0",
|
|
"form-data": "^4.0.0",
|
|
"jsdom": "^27.4.0",
|
|
"marked": "^17.0.1",
|
|
"pako": "^2.0.3",
|
|
"re2": "^1.21.0",
|
|
"ws": "^8.19.0",
|
|
"y-prosemirror": "1.3.7",
|
|
"yjs": "^13.6.29",
|
|
"zod": "^3.22.0"
|
|
},
|
|
"devDependencies": {
|
|
"@types/form-data": "^2.5.0",
|
|
"@types/node": "^20.0.0",
|
|
"typescript": "^5.0.0"
|
|
}
|
|
}
|