@oneentry/mcp-platform-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -0
- package/data/catalog.json +1 -0
- package/data/knowledge.json +1 -0
- package/dist/api/audit.d.ts +32 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +35 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/auth.d.ts +53 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +126 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/catalog.d.ts +39 -0
- package/dist/api/catalog.d.ts.map +1 -0
- package/dist/api/catalog.js +108 -0
- package/dist/api/catalog.js.map +1 -0
- package/dist/api/client.d.ts +60 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +196 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/policy.d.ts +52 -0
- package/dist/api/policy.d.ts.map +1 -0
- package/dist/api/policy.js +0 -0
- package/dist/api/policy.js.map +1 -0
- package/dist/api/shape.d.ts +19 -0
- package/dist/api/shape.d.ts.map +1 -0
- package/dist/api/shape.js +151 -0
- package/dist/api/shape.js.map +1 -0
- package/dist/api/types.d.ts +85 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +48 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/config/config.d.ts +108 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +167 -0
- package/dist/config/config.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/chunk.d.ts +35 -0
- package/dist/knowledge/chunk.d.ts.map +1 -0
- package/dist/knowledge/chunk.js +87 -0
- package/dist/knowledge/chunk.js.map +1 -0
- package/dist/knowledge/loader.d.ts +27 -0
- package/dist/knowledge/loader.d.ts.map +1 -0
- package/dist/knowledge/loader.js +125 -0
- package/dist/knowledge/loader.js.map +1 -0
- package/dist/knowledge/search.d.ts +34 -0
- package/dist/knowledge/search.d.ts.map +1 -0
- package/dist/knowledge/search.js +95 -0
- package/dist/knowledge/search.js.map +1 -0
- package/dist/knowledge/types.d.ts +47 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +2 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +48 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +43 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +75 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/api-call.d.ts +5 -0
- package/dist/tools/api-call.d.ts.map +1 -0
- package/dist/tools/api-call.js +169 -0
- package/dist/tools/api-call.js.map +1 -0
- package/dist/tools/api-discovery.d.ts +5 -0
- package/dist/tools/api-discovery.d.ts.map +1 -0
- package/dist/tools/api-discovery.js +80 -0
- package/dist/tools/api-discovery.js.map +1 -0
- package/dist/tools/docs.d.ts +5 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +113 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/guide.d.ts +11 -0
- package/dist/tools/guide.d.ts.map +1 -0
- package/dist/tools/guide.js +67 -0
- package/dist/tools/guide.js.map +1 -0
- package/dist/tools/result.d.ts +19 -0
- package/dist/tools/result.d.ts.map +1 -0
- package/dist/tools/result.js +19 -0
- package/dist/tools/result.js.map +1 -0
- package/dist/tools/whoami.d.ts +5 -0
- package/dist/tools/whoami.d.ts.map +1 -0
- package/dist/tools/whoami.js +42 -0
- package/dist/tools/whoami.js.map +1 -0
- package/dist/transports/http.d.ts +10 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +126 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +8 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +15 -0
- package/dist/transports/stdio.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/knowledge/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAiB3C,MAAM,YAAY,GAA0B;IAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE;IACjE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,YAAY,EAAE;IACnE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,YAAY,EAAE;IACnE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,YAAY,EAAE;IACnE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE;CACpF,CAAC;AAEF,MAAM,aAAa,GAA0B;IAC3C,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE;IACnE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE;IACrE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE;CACtE,CAAC;AAEF,4DAA4D;AAC5D,MAAM,YAAY,GAAG,CAAC,IAAY,EAAY,EAAE;IAC9C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,GAAW,EAAQ,EAAE;QAClC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,CAAC;YACd,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAW,EAAE;IACvC,IAAI,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CACpB,QAAgB,EAChB,IAAgB,EACoC,EAAE;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAChE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU;YACzB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAClE,MAAM,MAAM,GAAG,aAAa,CAAC;YAC3B,KAAK;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YACnD,QAAQ,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;SACrC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE,CAC1C,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;AAE3E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,OAAO,GAAG,GAAW,EAAE,CAClC,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAKzB,EAAiB,EAAE;IAClB,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAqB,EAAE,CAAC;IAEpC,MAAM,GAAG,GAAG,aAAa,CAAC,eAAe,EAAE,EAAE;QAC3C,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,GAAG;QACZ,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAE3B,MAAM,GAAG,GAAG,CAAC,IAAwB,EAAE,KAA4B,EAAQ,EAAE;QAC3E,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC;IACF,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACnC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAErC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACtF,CAAC,CAAC;AAEF,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAkB,EAAE;IAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,CAAC;IACvE,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAGhC,EAAiB,EAAE;IAClB,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;YACf,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,YAAY,EAAE,CAAC;AACxB,CAAC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { KnowledgeChunk, KnowledgeDoc, KnowledgePack } from './types.js';
|
|
2
|
+
/** Найденный раздел с оценкой и вырезкой вокруг совпадения. */
|
|
3
|
+
export interface KnowledgeHit {
|
|
4
|
+
id: string;
|
|
5
|
+
docId: string;
|
|
6
|
+
anchor: string;
|
|
7
|
+
title: string;
|
|
8
|
+
docTitle: string;
|
|
9
|
+
repo: KnowledgeChunk['repo'];
|
|
10
|
+
score: number;
|
|
11
|
+
snippet: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Поисковый индекс по разделам документации.
|
|
15
|
+
* Хранит только идентификаторы в индексе, а тексты — в отдельной карте:
|
|
16
|
+
* так `cms_docs_search` отдаёт вырезки, не поднимая в память дубли корпуса.
|
|
17
|
+
*/
|
|
18
|
+
export declare class KnowledgeIndex {
|
|
19
|
+
private readonly mini;
|
|
20
|
+
private readonly byId;
|
|
21
|
+
private readonly byDocId;
|
|
22
|
+
readonly pack: KnowledgePack;
|
|
23
|
+
constructor(pack: KnowledgePack);
|
|
24
|
+
/** Разделы документа в порядке следования — для листания в cms_docs_read. */
|
|
25
|
+
doc(docId: string): KnowledgeDoc | undefined;
|
|
26
|
+
chunk(id: string): KnowledgeChunk | undefined;
|
|
27
|
+
docs(): readonly KnowledgeDoc[];
|
|
28
|
+
/**
|
|
29
|
+
* Ищет разделы по запросу. Оценка minisearch домножается на веса источника и вида
|
|
30
|
+
* документа, поэтому правила эксплуатации всегда всплывают выше истории фиксов.
|
|
31
|
+
*/
|
|
32
|
+
search(query: string, limit?: number): KnowledgeHit[];
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/knowledge/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9E,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAiCD;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8B;IACnD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;gBAEjB,IAAI,EAAE,aAAa;IAkB/B,6EAA6E;IAC7E,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI5C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI7C,IAAI,IAAI,SAAS,YAAY,EAAE;IAI/B;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,EAAE;CAwBjD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import MiniSearch from 'minisearch';
|
|
2
|
+
/**
|
|
3
|
+
* Веса источников. `mcp` — собственные правила эксплуатации, они всегда должны
|
|
4
|
+
* побеждать первичную документацию; `fixes` — история багов, полезна, но шумна,
|
|
5
|
+
* поэтому опускается вниз, чтобы не вытеснять описание модуля.
|
|
6
|
+
*/
|
|
7
|
+
const REPO_WEIGHT = { mcp: 1.6, back: 1, front: 0.9 };
|
|
8
|
+
const KIND_WEIGHT = { docs: 1.15, tests: 1, rules: 1, fixes: 0.6 };
|
|
9
|
+
const kindOf = (docId) => docId.split('/')[1] ?? 'docs';
|
|
10
|
+
const SNIPPET_RADIUS = 180;
|
|
11
|
+
/** Вырезка вокруг первого совпавшего терма; при отсутствии — начало раздела. */
|
|
12
|
+
const makeSnippet = (text, terms) => {
|
|
13
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
14
|
+
const lower = flat.toLowerCase();
|
|
15
|
+
let at = -1;
|
|
16
|
+
for (const term of terms) {
|
|
17
|
+
const found = lower.indexOf(term.toLowerCase());
|
|
18
|
+
if (found !== -1 && (at === -1 || found < at)) {
|
|
19
|
+
at = found;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (at === -1) {
|
|
23
|
+
return flat.slice(0, SNIPPET_RADIUS * 2) + (flat.length > SNIPPET_RADIUS * 2 ? '…' : '');
|
|
24
|
+
}
|
|
25
|
+
const start = Math.max(0, at - SNIPPET_RADIUS);
|
|
26
|
+
const end = Math.min(flat.length, at + SNIPPET_RADIUS);
|
|
27
|
+
return `${start > 0 ? '…' : ''}${flat.slice(start, end)}${end < flat.length ? '…' : ''}`;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Поисковый индекс по разделам документации.
|
|
31
|
+
* Хранит только идентификаторы в индексе, а тексты — в отдельной карте:
|
|
32
|
+
* так `cms_docs_search` отдаёт вырезки, не поднимая в память дубли корпуса.
|
|
33
|
+
*/
|
|
34
|
+
export class KnowledgeIndex {
|
|
35
|
+
mini;
|
|
36
|
+
byId;
|
|
37
|
+
byDocId;
|
|
38
|
+
pack;
|
|
39
|
+
constructor(pack) {
|
|
40
|
+
this.pack = pack;
|
|
41
|
+
this.byId = new Map(pack.chunks.map((c) => [c.id, c]));
|
|
42
|
+
this.byDocId = new Map(pack.docs.map((d) => [d.docId, d]));
|
|
43
|
+
this.mini = new MiniSearch({
|
|
44
|
+
idField: 'id',
|
|
45
|
+
fields: ['title', 'docTitle', 'docId', 'text'],
|
|
46
|
+
storeFields: ['id'],
|
|
47
|
+
searchOptions: {
|
|
48
|
+
prefix: true,
|
|
49
|
+
fuzzy: 0.2,
|
|
50
|
+
boost: { title: 4, docTitle: 2, docId: 3, text: 1 },
|
|
51
|
+
combineWith: 'OR',
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
this.mini.addAll(pack.chunks);
|
|
55
|
+
}
|
|
56
|
+
/** Разделы документа в порядке следования — для листания в cms_docs_read. */
|
|
57
|
+
doc(docId) {
|
|
58
|
+
return this.byDocId.get(docId);
|
|
59
|
+
}
|
|
60
|
+
chunk(id) {
|
|
61
|
+
return this.byId.get(id);
|
|
62
|
+
}
|
|
63
|
+
docs() {
|
|
64
|
+
return this.pack.docs;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Ищет разделы по запросу. Оценка minisearch домножается на веса источника и вида
|
|
68
|
+
* документа, поэтому правила эксплуатации всегда всплывают выше истории фиксов.
|
|
69
|
+
*/
|
|
70
|
+
search(query, limit = 8) {
|
|
71
|
+
const terms = query.split(/\s+/).filter((t) => t.length > 1);
|
|
72
|
+
const raw = this.mini.search(query);
|
|
73
|
+
const hits = [];
|
|
74
|
+
for (const result of raw) {
|
|
75
|
+
const chunk = this.byId.get(String(result.id));
|
|
76
|
+
if (!chunk || chunk.text.trim() === '') {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const weight = (REPO_WEIGHT[chunk.repo] ?? 1) * (KIND_WEIGHT[kindOf(chunk.docId)] ?? 1);
|
|
80
|
+
hits.push({
|
|
81
|
+
id: chunk.id,
|
|
82
|
+
docId: chunk.docId,
|
|
83
|
+
anchor: chunk.anchor,
|
|
84
|
+
title: chunk.title,
|
|
85
|
+
docTitle: chunk.docTitle,
|
|
86
|
+
repo: chunk.repo,
|
|
87
|
+
score: Number((result.score * weight).toFixed(3)),
|
|
88
|
+
snippet: makeSnippet(chunk.text, terms),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
hits.sort((a, b) => b.score - a.score);
|
|
92
|
+
return hits.slice(0, limit);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/knowledge/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Один раздел документации — единица поиска и чтения.
|
|
3
|
+
* Резать документы на разделы обязательно: отдельные файлы доходят до 56 КБ,
|
|
4
|
+
* а модели нужен ровно тот раздел, который отвечает на её вопрос.
|
|
5
|
+
*/
|
|
6
|
+
export interface KnowledgeChunk {
|
|
7
|
+
/** Стабильный идентификатор `<docId>#<anchor>`. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Идентификатор документа, например `back/docs/menus-module`. */
|
|
10
|
+
docId: string;
|
|
11
|
+
/** Репозиторий-источник. */
|
|
12
|
+
repo: 'back' | 'front' | 'mcp';
|
|
13
|
+
/** Путь файла относительно корня репозитория-источника. */
|
|
14
|
+
path: string;
|
|
15
|
+
/** Слаг заголовка раздела; пустая строка — преамбула документа. */
|
|
16
|
+
anchor: string;
|
|
17
|
+
/** Текст заголовка раздела. */
|
|
18
|
+
title: string;
|
|
19
|
+
/** Заголовок документа (первый `#`), нужен для ранжирования и вывода. */
|
|
20
|
+
docTitle: string;
|
|
21
|
+
/** Тело раздела без заголовка. */
|
|
22
|
+
text: string;
|
|
23
|
+
}
|
|
24
|
+
/** Документ целиком: список его разделов, чтобы агент мог листать соседние. */
|
|
25
|
+
export interface KnowledgeDoc {
|
|
26
|
+
docId: string;
|
|
27
|
+
repo: 'back' | 'front' | 'mcp';
|
|
28
|
+
path: string;
|
|
29
|
+
title: string;
|
|
30
|
+
anchors: Array<{
|
|
31
|
+
anchor: string;
|
|
32
|
+
title: string;
|
|
33
|
+
bytes: number;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
/** Собранный пакет знаний: то, что build-knowledge.ts пишет в data/knowledge.json. */
|
|
37
|
+
export interface KnowledgePack {
|
|
38
|
+
/** Версия формата — чтобы рантайм не пытался читать несовместимый снапшот. */
|
|
39
|
+
version: 1;
|
|
40
|
+
/** Когда собран (ISO). Показывается в cms_whoami. */
|
|
41
|
+
builtAt: string;
|
|
42
|
+
/** Из какого источника собран: снапшот или живой чекаут. */
|
|
43
|
+
source: 'snapshot' | 'live';
|
|
44
|
+
docs: KnowledgeDoc[];
|
|
45
|
+
chunks: KnowledgeChunk[];
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/knowledge/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC/B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,OAAO,EAAE,CAAC,CAAC;IACX,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;IAC5B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/knowledge/types.ts"],"names":[],"mappings":""}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { Config } from './config/config.js';
|
|
3
|
+
import { Session, type SharedDeps } from './session.js';
|
|
4
|
+
/**
|
|
5
|
+
* Собирает разделяемые зависимости: каталог операций, индекс знаний, журнал.
|
|
6
|
+
* Вынесено отдельно, чтобы remote-режим строил их один раз на процесс,
|
|
7
|
+
* а не на каждую сессию.
|
|
8
|
+
*/
|
|
9
|
+
export declare const createSharedDeps: (config: Config) => SharedDeps;
|
|
10
|
+
/**
|
|
11
|
+
* Создаёт MCP-сервер с полным набором инструментов.
|
|
12
|
+
* Сессия передаётся геттером: в stdio-режиме она одна на процесс,
|
|
13
|
+
* в HTTP-режиме — своя на каждое подключение, и код инструментов от этого не зависит.
|
|
14
|
+
*/
|
|
15
|
+
export declare const createServer: (deps: SharedDeps, getSession: () => Session) => McpServer;
|
|
16
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAUxD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,UAahD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,UAAU,EAAE,YAAY,MAAM,OAAO,KAAG,SAkB1E,CAAC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { AuditLog } from './api/audit.js';
|
|
3
|
+
import { OperationCatalog } from './api/catalog.js';
|
|
4
|
+
import { resolveKnowledge } from './knowledge/loader.js';
|
|
5
|
+
import { KnowledgeIndex } from './knowledge/search.js';
|
|
6
|
+
import { registerApiCall } from './tools/api-call.js';
|
|
7
|
+
import { registerApiDiscovery } from './tools/api-discovery.js';
|
|
8
|
+
import { registerDocs } from './tools/docs.js';
|
|
9
|
+
import { registerGuide } from './tools/guide.js';
|
|
10
|
+
import { registerWhoami } from './tools/whoami.js';
|
|
11
|
+
/** Версия пакета, сообщаемая клиенту при handshake. */
|
|
12
|
+
const SERVER_VERSION = '0.1.0';
|
|
13
|
+
/**
|
|
14
|
+
* Собирает разделяемые зависимости: каталог операций, индекс знаний, журнал.
|
|
15
|
+
* Вынесено отдельно, чтобы remote-режим строил их один раз на процесс,
|
|
16
|
+
* а не на каждую сессию.
|
|
17
|
+
*/
|
|
18
|
+
export const createSharedDeps = (config) => ({
|
|
19
|
+
config,
|
|
20
|
+
catalog: OperationCatalog.load(),
|
|
21
|
+
knowledge: new KnowledgeIndex(resolveKnowledge({
|
|
22
|
+
...(config.backPath ? { backPath: config.backPath } : {}),
|
|
23
|
+
...(config.frontPath ? { frontPath: config.frontPath } : {}),
|
|
24
|
+
})),
|
|
25
|
+
audit: new AuditLog({
|
|
26
|
+
...(config.auditPath ? { path: config.auditPath } : {}),
|
|
27
|
+
mode: config.mode,
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Создаёт MCP-сервер с полным набором инструментов.
|
|
32
|
+
* Сессия передаётся геттером: в stdio-режиме она одна на процесс,
|
|
33
|
+
* в HTTP-режиме — своя на каждое подключение, и код инструментов от этого не зависит.
|
|
34
|
+
*/
|
|
35
|
+
export const createServer = (deps, getSession) => {
|
|
36
|
+
const server = new McpServer({ name: 'oneentry-mcp-platform', version: SERVER_VERSION }, {
|
|
37
|
+
instructions: 'OneEntry CMS Admin API. Call cms_guide first, then cms_docs_read on "mcp/operating-rules" before any write. ' +
|
|
38
|
+
'Discover endpoints with cms_api_search, get payload shapes with cms_api_describe, execute with cms_api_call. ' +
|
|
39
|
+
'Never construct paths or operation ids by hand.',
|
|
40
|
+
});
|
|
41
|
+
registerGuide(server, deps);
|
|
42
|
+
registerWhoami(server, getSession);
|
|
43
|
+
registerDocs(server, deps);
|
|
44
|
+
registerApiDiscovery(server, deps);
|
|
45
|
+
registerApiCall(server, getSession);
|
|
46
|
+
return server;
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,uDAAuD;AACvD,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAc,EAAE,CAAC,CAAC;IAC/D,MAAM;IACN,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE;IAChC,SAAS,EAAE,IAAI,cAAc,CAC3B,gBAAgB,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7D,CAAC,CACH;IACD,KAAK,EAAE,IAAI,QAAQ,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAC;CACH,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAgB,EAAE,UAAyB,EAAa,EAAE;IACrF,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,cAAc,EAAE,EAC1D;QACE,YAAY,EACV,8GAA8G;YAC9G,+GAA+G;YAC/G,iDAAiD;KACpD,CACF,CAAC;IAEF,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5B,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3B,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnC,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEpC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AuditLog } from './api/audit.js';
|
|
2
|
+
import { type AdminIdentity, type Credentials } from './api/auth.js';
|
|
3
|
+
import { OperationCatalog } from './api/catalog.js';
|
|
4
|
+
import { AdminApiClient, type CallArgs } from './api/client.js';
|
|
5
|
+
import { ConfirmStore } from './api/policy.js';
|
|
6
|
+
import type { Config } from './config/config.js';
|
|
7
|
+
import { KnowledgeIndex } from './knowledge/search.js';
|
|
8
|
+
import type { Operation } from './api/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Разделяемые между сессиями зависимости.
|
|
11
|
+
* Каталог и индекс знаний строятся один раз на процесс — они неизменяемы,
|
|
12
|
+
* и в remote-режиме держать их копию на сессию было бы чистой растратой.
|
|
13
|
+
*/
|
|
14
|
+
export interface SharedDeps {
|
|
15
|
+
config: Config;
|
|
16
|
+
catalog: OperationCatalog;
|
|
17
|
+
knowledge: KnowledgeIndex;
|
|
18
|
+
audit: AuditLog;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Состояние одной MCP-сессии: свои учётные данные, свои токены,
|
|
22
|
+
* свои токены подтверждения. Именно эта изоляция делает remote-режим безопасным.
|
|
23
|
+
*/
|
|
24
|
+
export declare class Session {
|
|
25
|
+
readonly shared: SharedDeps;
|
|
26
|
+
readonly confirms: ConfirmStore;
|
|
27
|
+
private readonly tokens;
|
|
28
|
+
readonly client: AdminApiClient;
|
|
29
|
+
private identityCache;
|
|
30
|
+
constructor(shared: SharedDeps, credentials?: Credentials);
|
|
31
|
+
get isConfigured(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Кто мы. Кэшируется: набор прав нужен почти каждому изменяющему вызову,
|
|
34
|
+
* а меняется он редко.
|
|
35
|
+
*/
|
|
36
|
+
identity(): Promise<AdminIdentity | undefined>;
|
|
37
|
+
/**
|
|
38
|
+
* Пытается показать, что именно будет изменено: ищет GET по тому же пути
|
|
39
|
+
* и читает объект. Без этого «подтверждение удаления» — подпись под пустым листом.
|
|
40
|
+
*/
|
|
41
|
+
describeTarget(operation: Operation, args: CallArgs): Promise<unknown>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAA2C,KAAK,aAAa,EAAE,KAAK,WAAW,EAAc,MAAM,eAAe,CAAC;AAC1H,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAY,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED;;;GAGG;AACH,qBAAa,OAAO;IAClB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,QAAQ,eAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,OAAO,CAAC,aAAa,CAA4B;gBAErC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,WAAW;IAczD,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAkBpD;;;OAGG;IACG,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;CAiB7E"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { adminIdFromToken, credentialsFromConfig, TokenStore } from './api/auth.js';
|
|
2
|
+
import { AdminApiClient, buildUrl } from './api/client.js';
|
|
3
|
+
import { ConfirmStore } from './api/policy.js';
|
|
4
|
+
/**
|
|
5
|
+
* Состояние одной MCP-сессии: свои учётные данные, свои токены,
|
|
6
|
+
* свои токены подтверждения. Именно эта изоляция делает remote-режим безопасным.
|
|
7
|
+
*/
|
|
8
|
+
export class Session {
|
|
9
|
+
shared;
|
|
10
|
+
confirms = new ConfirmStore();
|
|
11
|
+
tokens;
|
|
12
|
+
client;
|
|
13
|
+
identityCache;
|
|
14
|
+
constructor(shared, credentials) {
|
|
15
|
+
this.shared = shared;
|
|
16
|
+
this.tokens = new TokenStore({
|
|
17
|
+
baseUrl: shared.config.baseUrl,
|
|
18
|
+
timeoutMs: shared.config.requestTimeoutMs,
|
|
19
|
+
credentials: credentials ?? credentialsFromConfig(shared.config),
|
|
20
|
+
});
|
|
21
|
+
this.client = new AdminApiClient({
|
|
22
|
+
baseUrl: shared.config.baseUrl,
|
|
23
|
+
tokens: this.tokens,
|
|
24
|
+
timeoutMs: shared.config.requestTimeoutMs,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
get isConfigured() {
|
|
28
|
+
return this.tokens.isConfigured;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Кто мы. Кэшируется: набор прав нужен почти каждому изменяющему вызову,
|
|
32
|
+
* а меняется он редко.
|
|
33
|
+
*/
|
|
34
|
+
async identity() {
|
|
35
|
+
if (this.identityCache) {
|
|
36
|
+
return this.identityCache;
|
|
37
|
+
}
|
|
38
|
+
if (!this.tokens.isConfigured) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const token = await this.tokens.accessToken();
|
|
43
|
+
const id = adminIdFromToken(token);
|
|
44
|
+
const permissions = await this.client.fetchPermissions(id);
|
|
45
|
+
this.identityCache = { id, permissions };
|
|
46
|
+
return this.identityCache;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Пытается показать, что именно будет изменено: ищет GET по тому же пути
|
|
54
|
+
* и читает объект. Без этого «подтверждение удаления» — подпись под пустым листом.
|
|
55
|
+
*/
|
|
56
|
+
async describeTarget(operation, args) {
|
|
57
|
+
const sibling = this.shared.catalog
|
|
58
|
+
.operations()
|
|
59
|
+
.find((candidate) => candidate.method === 'get' && candidate.path === operation.path);
|
|
60
|
+
if (!sibling) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
buildUrl(this.shared.config.baseUrl, sibling, { ...(args.path ? { path: args.path } : {}) });
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const result = await this.client.call(sibling, {
|
|
70
|
+
...(args.path ? { path: args.path } : {}),
|
|
71
|
+
});
|
|
72
|
+
return result.ok ? result.body : undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { Session } from '../session.js';
|
|
3
|
+
/** Регистрирует `cms_api_call`. */
|
|
4
|
+
export declare const registerApiCall: (server: McpServer, getSession: () => Session) => void;
|
|
5
|
+
//# sourceMappingURL=api-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-call.d.ts","sourceRoot":"","sources":["../../src/tools/api-call.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAM7C,mCAAmC;AACnC,eAAO,MAAM,eAAe,GAAI,QAAQ,SAAS,EAAE,YAAY,MAAM,OAAO,KAAG,IAsL9E,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { AuditLog } from '../api/audit.js';
|
|
3
|
+
import { buildUrl, normalizeBody, RequestBuildError } from '../api/client.js';
|
|
4
|
+
import { checkLevel, decide } from '../api/policy.js';
|
|
5
|
+
import { shapeResponse, summarizeTarget } from '../api/shape.js';
|
|
6
|
+
import { errorResult, jsonResult } from './result.js';
|
|
7
|
+
/** Ограничение на показ тела в плане dry-run. */
|
|
8
|
+
const PLAN_BODY_LIMIT = 2_000;
|
|
9
|
+
/** Регистрирует `cms_api_call`. */
|
|
10
|
+
export const registerApiCall = (server, getSession) => {
|
|
11
|
+
server.registerTool('cms_api_call', {
|
|
12
|
+
title: 'Call an Admin API operation',
|
|
13
|
+
description: 'Execute one Admin API operation by its id. Reads run immediately. Mutations require the server to run with --allow=write (or --allow=destructive for DELETE), and deletes plus permanently gated paths require a confirm token obtained from a dryRun. Always dryRun first when mutating.',
|
|
14
|
+
inputSchema: {
|
|
15
|
+
opId: z.string().min(1).describe('Operation id from cms_api_search.'),
|
|
16
|
+
path: z
|
|
17
|
+
.record(z.union([z.string(), z.number()]))
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Path parameters, e.g. { id: 42 }.'),
|
|
20
|
+
query: z
|
|
21
|
+
.record(z.union([z.string(), z.number(), z.boolean()]))
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('Query parameters, e.g. { limit: 30, offset: 0 }.'),
|
|
24
|
+
body: z.unknown().optional().describe('Request body; copy the shape from cms_api_describe.'),
|
|
25
|
+
dryRun: z
|
|
26
|
+
.boolean()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Do not send: return the resolved request, the policy decision, the current target, and a confirm token when one is needed.'),
|
|
29
|
+
confirm: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Confirm token returned by a dryRun of this exact call. Single-use, valid 5 minutes.'),
|
|
33
|
+
},
|
|
34
|
+
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
|
|
35
|
+
}, async ({ opId, path, query, body, dryRun, confirm }) => {
|
|
36
|
+
const session = getSession();
|
|
37
|
+
const { config, catalog, audit } = session.shared;
|
|
38
|
+
const operation = catalog.get(opId);
|
|
39
|
+
if (!operation) {
|
|
40
|
+
return errorResult(`Unknown opId "${opId}". No request was sent.`, {
|
|
41
|
+
didYouMean: catalog.suggest(opId),
|
|
42
|
+
hint: 'Operation ids come from cms_api_search — do not construct them by hand.',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Тело нормализуется до всего остального: и хэш аудита, и токен подтверждения
|
|
47
|
+
* привязываются именно к отправляемым аргументам, иначе подтверждение,
|
|
48
|
+
* выданное на dry-run, не совпало бы с реальным вызовом.
|
|
49
|
+
*/
|
|
50
|
+
const normalizedBody = normalizeBody(body);
|
|
51
|
+
const args = {
|
|
52
|
+
...(path ? { path } : {}),
|
|
53
|
+
...(query ? { query } : {}),
|
|
54
|
+
...(normalizedBody !== undefined ? { body: normalizedBody } : {}),
|
|
55
|
+
};
|
|
56
|
+
const argsHash = AuditLog.hashArgs(args);
|
|
57
|
+
const auditBase = {
|
|
58
|
+
opId,
|
|
59
|
+
method: operation.method.toUpperCase(),
|
|
60
|
+
path: operation.path,
|
|
61
|
+
argsHash,
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Уровень доступа проверяется до аутентификации: иначе отказ read-only режима
|
|
65
|
+
* всё равно сходил бы в сеть за токеном, и обещание «no request was sent» было бы ложью.
|
|
66
|
+
*/
|
|
67
|
+
const levelDenial = checkLevel(operation, config.allow);
|
|
68
|
+
if (levelDenial) {
|
|
69
|
+
audit.record({ ...auditBase, outcome: 'denied' });
|
|
70
|
+
return errorResult(levelDenial.reason, { opId, policy: config.allow, risk: operation.risk });
|
|
71
|
+
}
|
|
72
|
+
/** Личность нужна только там, где операция объявляет требуемое право. */
|
|
73
|
+
const identity = operation.permission ? await session.identity() : undefined;
|
|
74
|
+
if (identity) {
|
|
75
|
+
Object.assign(auditBase, { adminId: identity.id });
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Негодный токен — отдельная ошибка, а не «просто нет подтверждения»:
|
|
79
|
+
* иначе агент получал бы в ответ новый токен и не понимал, что предыдущий не подошёл.
|
|
80
|
+
*/
|
|
81
|
+
const confirmValid = confirm !== undefined && session.confirms.verify(confirm, opId, args);
|
|
82
|
+
if (confirm !== undefined && !confirmValid) {
|
|
83
|
+
return errorResult('Confirm token is expired, already used, or does not match these arguments. Re-run with dryRun: true to get a fresh one.', { opId });
|
|
84
|
+
}
|
|
85
|
+
const decision = decide({
|
|
86
|
+
operation,
|
|
87
|
+
allow: config.allow,
|
|
88
|
+
...(identity ? { identity } : {}),
|
|
89
|
+
confirmValid,
|
|
90
|
+
});
|
|
91
|
+
if (decision.kind === 'deny') {
|
|
92
|
+
if (operation.risk !== 'read') {
|
|
93
|
+
audit.record({ ...auditBase, outcome: 'denied' });
|
|
94
|
+
}
|
|
95
|
+
return errorResult(decision.reason, { opId, policy: config.allow, risk: operation.risk });
|
|
96
|
+
}
|
|
97
|
+
/** Разрешение по уровню и правам получено — можно строить сам запрос. */
|
|
98
|
+
let url;
|
|
99
|
+
try {
|
|
100
|
+
url = buildUrl(config.baseUrl, operation, args);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (error instanceof RequestBuildError) {
|
|
104
|
+
return errorResult(error.message, { opId, params: operation.params });
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
if (decision.kind === 'needsConfirm') {
|
|
109
|
+
const token = session.confirms.issue(opId, args);
|
|
110
|
+
const target = await session.describeTarget(operation, args);
|
|
111
|
+
audit.record({ ...auditBase, outcome: 'needs-confirm' });
|
|
112
|
+
return jsonResult({
|
|
113
|
+
needsConfirm: true,
|
|
114
|
+
reason: decision.reason,
|
|
115
|
+
request: { method: operation.method.toUpperCase(), url },
|
|
116
|
+
target: summarizeTarget(target),
|
|
117
|
+
confirm: token,
|
|
118
|
+
expiresInSeconds: 300,
|
|
119
|
+
next: 'Show the target to the human. Then repeat this exact call with the confirm token added.',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (dryRun === true) {
|
|
123
|
+
const target = await session.describeTarget(operation, args);
|
|
124
|
+
return jsonResult({
|
|
125
|
+
dryRun: true,
|
|
126
|
+
request: {
|
|
127
|
+
method: operation.method.toUpperCase(),
|
|
128
|
+
url,
|
|
129
|
+
...(args.body !== undefined
|
|
130
|
+
? { body: JSON.stringify(args.body).slice(0, PLAN_BODY_LIMIT) }
|
|
131
|
+
: {}),
|
|
132
|
+
},
|
|
133
|
+
policy: { allow: config.allow, risk: operation.risk, decision: 'would be sent' },
|
|
134
|
+
target: summarizeTarget(target),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Токен гасится только здесь, перед самой отправкой: если бы он расходовался
|
|
139
|
+
* при проверке политики, отказ по другой причине заставлял бы подтверждать заново.
|
|
140
|
+
*/
|
|
141
|
+
if (confirm !== undefined && !session.confirms.consume(confirm, opId, args)) {
|
|
142
|
+
return errorResult('Confirm token was consumed concurrently. Re-run with dryRun: true to get a fresh one.', { opId });
|
|
143
|
+
}
|
|
144
|
+
const result = await session.client.call(operation, args);
|
|
145
|
+
if (operation.risk !== 'read') {
|
|
146
|
+
audit.record({
|
|
147
|
+
...auditBase,
|
|
148
|
+
outcome: 'sent',
|
|
149
|
+
status: result.ok ? result.status : result.error.status,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (!result.ok) {
|
|
153
|
+
return errorResult(result.error.message, {
|
|
154
|
+
opId,
|
|
155
|
+
status: result.error.status,
|
|
156
|
+
...(result.error.hint ? { hint: result.error.hint } : {}),
|
|
157
|
+
docs: operation.docLinks,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
const shaped = shapeResponse(result.body, config.maxResponseBytes);
|
|
161
|
+
return jsonResult({
|
|
162
|
+
opId,
|
|
163
|
+
status: result.status,
|
|
164
|
+
truncated: shaped.truncated,
|
|
165
|
+
body: shaped.body,
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=api-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-call.js","sourceRoot":"","sources":["../../src/tools/api-call.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SharedDeps } from '../session.js';
|
|
3
|
+
/** Регистрирует `cms_api_search` и `cms_api_describe`. */
|
|
4
|
+
export declare const registerApiDiscovery: (server: McpServer, deps: SharedDeps) => void;
|
|
5
|
+
//# sourceMappingURL=api-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-discovery.d.ts","sourceRoot":"","sources":["../../src/tools/api-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS,EAAE,MAAM,UAAU,KAAG,IA0F1E,CAAC"}
|