@taiga-ai/mcp-server 0.25.0-dev.465 → 0.25.0-dev.466
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/dist/index.js
CHANGED
|
@@ -670,6 +670,29 @@ const POLICY_TYPE_BY_CONTROL_PREFIX = {
|
|
|
670
670
|
SCS: "policy_supply_chain",
|
|
671
671
|
CLD: "policy_cloud_governance"
|
|
672
672
|
};
|
|
673
|
+
/** The policy document a control id belongs to, or undefined for an unknown prefix. */
|
|
674
|
+
function policyTypeForControl(controlId) {
|
|
675
|
+
return POLICY_TYPE_BY_CONTROL_PREFIX[controlId.split("-")[0] ?? ""];
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* The policy a control id points a reader to (PRO-2809): its rightmost base
|
|
679
|
+
* prefix. An overlay family names its host policy last: TEL-TIC-1.1 is a
|
|
680
|
+
* telecom control in policy_tic, HC-FI-DATA-1.1 a Finnish healthcare control in
|
|
681
|
+
* policy_data, ARC-AWS-5 an AWS preset in policy_architecture. A regulatory
|
|
682
|
+
* family with no base prefix (GDPR, NIS2, AIACT) spans several policies and
|
|
683
|
+
* names none.
|
|
684
|
+
*
|
|
685
|
+
* For saying where to read a control, not for deciding who holds it:
|
|
686
|
+
* {@link policyTypeForControl} keeps an overlay control with the document it is
|
|
687
|
+
* written in, whatever its id says.
|
|
688
|
+
*/
|
|
689
|
+
function policyNamedByControl(controlId) {
|
|
690
|
+
const prefixes = controlId.split("-").filter((part) => /^[A-Z]/.test(part));
|
|
691
|
+
for (let at = prefixes.length - 1; at >= 0; at -= 1) {
|
|
692
|
+
const owner = POLICY_TYPE_BY_CONTROL_PREFIX[prefixes[at]];
|
|
693
|
+
if (owner) return owner;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
673
696
|
/**
|
|
674
697
|
* The shape of a control id in a policy's control table: `SEC-3.4`, and the
|
|
675
698
|
* overlay families too (`TEL-TIC-1.1`, `HC-FI-DATA-1.1`, `GDPR-1.1`). One
|
|
@@ -2663,17 +2686,6 @@ const sectionsInput = z.array(z.string().min(1).max(200)).max(50).optional().des
|
|
|
2663
2686
|
/** The sections input of a company document, where a policy control id also names the sections that state it. */
|
|
2664
2687
|
const policySectionsInput = sectionsInput.describe("Only these sections, by id, or a policy control id (SEC-5.1) for the sections that state it; [] for the outline (under outline: every section id and its size, no text); omit for the whole document");
|
|
2665
2688
|
/**
|
|
2666
|
-
* The policy that states a control: the rightmost policy prefix in its id, so an overlay family's
|
|
2667
|
-
* TEL-TIC-1.1 is policy_tic and HC-FI-DATA-1.1 policy_data, as the overlays file them.
|
|
2668
|
-
*/
|
|
2669
|
-
function policyOfControl(id) {
|
|
2670
|
-
const prefixes = id.split("-").filter((part) => /^[A-Z]/.test(part));
|
|
2671
|
-
for (const prefix of prefixes.reverse()) {
|
|
2672
|
-
const policy = POLICY_TYPE_BY_CONTROL_PREFIX[prefix];
|
|
2673
|
-
if (policy) return policy;
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
/**
|
|
2677
2689
|
* The sections that state each control id asked for (PRO-2800): policy
|
|
2678
2690
|
* standing cites SEC-5.1, and the section holding it has an id of its own
|
|
2679
2691
|
* (secretsManagement) an agent could only guess. A control id is found in
|
|
@@ -2699,7 +2711,7 @@ function withControls(outline, sections, policyType) {
|
|
|
2699
2711
|
return outline.map((entry) => {
|
|
2700
2712
|
const text = sectionContent(sections, entry.id) ?? "";
|
|
2701
2713
|
const ids = [...new Set([...text.matchAll(pattern)].filter((match) => !/^_?Reserved_?/i.test(match[2] ?? "")).map((match) => match[1]).filter((id) => {
|
|
2702
|
-
const owner =
|
|
2714
|
+
const owner = policyTypeForControl(id);
|
|
2703
2715
|
return owner === void 0 || owner === policyType;
|
|
2704
2716
|
}))];
|
|
2705
2717
|
return ids.length > 0 ? {
|
|
@@ -2727,7 +2739,7 @@ function sectionReadResult(doc, asked, label, options = {}) {
|
|
|
2727
2739
|
const known = ids.filter((id) => all.includes(id));
|
|
2728
2740
|
const found = Object.keys(controls).length > 0 ? { controls } : {};
|
|
2729
2741
|
const asControl = options.controlIds ? void 0 : unknownSections.find((id) => isControlId(id));
|
|
2730
|
-
const policy = asControl ?
|
|
2742
|
+
const policy = asControl ? policyNamedByControl(asControl) : void 0;
|
|
2731
2743
|
const controlNote = asControl ? { note: policy ? `${asControl} is a control of ${policy}: read it with taiga_get_document (type: ${policy}, sections: ["${asControl}"]).` : `${asControl} looks like a policy control id, which only a policy resolves: taiga_get_document without type lists them.` } : {};
|
|
2732
2744
|
if (known.length === 0) {
|
|
2733
2745
|
const { data: _data, ...meta } = cut.doc;
|
package/package.json
CHANGED
package/src/tools/sections.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import type { CallToolResult } from '@modelcontextprotocol/server';
|
|
15
15
|
import { z } from 'zod';
|
|
16
|
-
import { CONTROL_ID_SOURCE, isControlId,
|
|
16
|
+
import { CONTROL_ID_SOURCE, isControlId, policyNamedByControl, policyTypeForControl } from '@taiga/types';
|
|
17
17
|
import { toolError, toolResult } from './errors.js';
|
|
18
18
|
|
|
19
19
|
/** A document's section map, keyed by section id: each value a `StoredSection` or (older rows) a bare string. */
|
|
@@ -177,19 +177,6 @@ export const policySectionsInput = sectionsInput.describe(
|
|
|
177
177
|
'Only these sections, by id, or a policy control id (SEC-5.1) for the sections that state it; [] for the outline (under outline: every section id and its size, no text); omit for the whole document'
|
|
178
178
|
);
|
|
179
179
|
|
|
180
|
-
/**
|
|
181
|
-
* The policy that states a control: the rightmost policy prefix in its id, so an overlay family's
|
|
182
|
-
* TEL-TIC-1.1 is policy_tic and HC-FI-DATA-1.1 policy_data, as the overlays file them.
|
|
183
|
-
*/
|
|
184
|
-
function policyOfControl(id: string): string | undefined {
|
|
185
|
-
const prefixes = id.split('-').filter((part) => /^[A-Z]/.test(part));
|
|
186
|
-
for (const prefix of prefixes.reverse()) {
|
|
187
|
-
const policy = POLICY_TYPE_BY_CONTROL_PREFIX[prefix];
|
|
188
|
-
if (policy) return policy;
|
|
189
|
-
}
|
|
190
|
-
return undefined;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
180
|
/**
|
|
194
181
|
* The sections that state each control id asked for (PRO-2800): policy
|
|
195
182
|
* standing cites SEC-5.1, and the section holding it has an id of its own
|
|
@@ -231,7 +218,7 @@ function withControls(outline: { id: string; characters: number }[], sections: S
|
|
|
231
218
|
// A base control belongs to the policy its prefix names: an SEC row in the data policy is a stale mention,
|
|
232
219
|
// as heldControlMap reads it. An overlay prefix stays where it is written.
|
|
233
220
|
.filter((id) => {
|
|
234
|
-
const owner =
|
|
221
|
+
const owner = policyTypeForControl(id);
|
|
235
222
|
return owner === undefined || owner === policyType;
|
|
236
223
|
})
|
|
237
224
|
),
|
|
@@ -267,7 +254,7 @@ export function sectionReadResult(
|
|
|
267
254
|
const found = Object.keys(controls).length > 0 ? { controls } : {};
|
|
268
255
|
// A control id asked of a document that does not state controls: name the policy that does.
|
|
269
256
|
const asControl = options.controlIds ? undefined : unknownSections.find((id) => isControlId(id));
|
|
270
|
-
const policy = asControl ?
|
|
257
|
+
const policy = asControl ? policyNamedByControl(asControl) : undefined;
|
|
271
258
|
const controlNote = asControl
|
|
272
259
|
? {
|
|
273
260
|
note: policy
|
|
Binary file
|
|
Binary file
|