design-constraint-validator 1.1.0 → 2.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 +90 -21
- package/adapters/decisionthemes.d.ts +44 -0
- package/adapters/decisionthemes.d.ts.map +1 -0
- package/adapters/decisionthemes.js +35 -0
- package/adapters/decisionthemes.ts +59 -0
- package/cli/commands/build.js +1 -1
- package/cli/commands/build.ts +1 -1
- package/cli/commands/graph.js +4 -4
- package/cli/commands/graph.ts +4 -4
- package/cli/commands/validate.d.ts.map +1 -1
- package/cli/commands/validate.js +43 -6
- package/cli/commands/validate.ts +41 -8
- package/cli/config-schema.d.ts +39 -0
- package/cli/config-schema.d.ts.map +1 -1
- package/cli/config-schema.js +4 -2
- package/cli/config-schema.ts +4 -2
- package/cli/config.d.ts.map +1 -1
- package/cli/config.js +8 -2
- package/cli/config.ts +8 -2
- package/cli/constraint-registry.d.ts +16 -0
- package/cli/constraint-registry.d.ts.map +1 -1
- package/cli/constraint-registry.js +64 -31
- package/cli/constraint-registry.ts +67 -31
- package/cli/dcv.js +8 -24
- package/cli/dcv.ts +8 -20
- package/cli/json-output.d.ts +8 -1
- package/cli/json-output.d.ts.map +1 -1
- package/cli/json-output.js +13 -4
- package/cli/json-output.ts +20 -4
- package/cli/types.d.ts +2 -0
- package/cli/types.d.ts.map +1 -1
- package/cli/types.ts +2 -0
- package/cli/validate-api.d.ts +40 -0
- package/cli/validate-api.d.ts.map +1 -0
- package/cli/validate-api.js +85 -0
- package/cli/validate-api.ts +126 -0
- package/cli/version-banner.d.ts +20 -0
- package/cli/version-banner.d.ts.map +1 -0
- package/cli/version-banner.js +49 -0
- package/cli/version-banner.ts +61 -0
- package/core/breakpoints.d.ts +8 -2
- package/core/breakpoints.d.ts.map +1 -1
- package/core/breakpoints.js +24 -3
- package/core/breakpoints.ts +22 -3
- package/core/color.js +4 -4
- package/core/color.ts +4 -4
- package/core/constraints/monotonic-lightness.d.ts.map +1 -1
- package/core/constraints/monotonic-lightness.js +9 -5
- package/core/constraints/monotonic-lightness.ts +9 -4
- package/core/constraints/wcag.d.ts.map +1 -1
- package/core/constraints/wcag.js +6 -0
- package/core/constraints/wcag.ts +6 -0
- package/core/dtcg.d.ts +38 -0
- package/core/dtcg.d.ts.map +1 -0
- package/core/dtcg.js +88 -0
- package/core/dtcg.ts +102 -0
- package/core/engine.d.ts +6 -0
- package/core/engine.d.ts.map +1 -1
- package/core/engine.ts +7 -0
- package/core/flatten.d.ts +5 -3
- package/core/flatten.d.ts.map +1 -1
- package/core/flatten.js +24 -10
- package/core/flatten.ts +39 -16
- package/core/image-export.d.ts.map +1 -1
- package/core/image-export.js +10 -7
- package/core/image-export.ts +9 -6
- package/core/index.d.ts +2 -0
- package/core/index.d.ts.map +1 -1
- package/core/index.js +4 -0
- package/core/index.ts +6 -0
- package/core/why.d.ts +1 -1
- package/core/why.d.ts.map +1 -1
- package/core/why.ts +1 -1
- package/mcp/contracts.d.ts +118 -0
- package/mcp/contracts.d.ts.map +1 -0
- package/mcp/contracts.js +30 -0
- package/mcp/contracts.ts +51 -0
- package/mcp/index.d.ts +9 -0
- package/mcp/index.d.ts.map +1 -0
- package/mcp/index.js +32 -0
- package/mcp/index.ts +70 -0
- package/mcp/tools.d.ts +52 -0
- package/mcp/tools.d.ts.map +1 -0
- package/mcp/tools.js +172 -0
- package/mcp/tools.ts +254 -0
- package/package.json +41 -26
- package/server.json +21 -0
- package/cli/constraints-loader.d.ts +0 -30
- package/cli/constraints-loader.d.ts.map +0 -1
- package/cli/constraints-loader.js +0 -58
- package/cli/constraints-loader.ts +0 -83
- package/cli/engine-helpers.d.ts +0 -41
- package/cli/engine-helpers.d.ts.map +0 -1
- package/cli/engine-helpers.js +0 -135
- package/cli/engine-helpers.ts +0 -133
- package/core/cross-axis-config.d.ts +0 -34
- package/core/cross-axis-config.d.ts.map +0 -1
- package/core/cross-axis-config.js +0 -173
- package/core/cross-axis-config.ts +0 -182
package/core/flatten.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { normalizeDtcgValue } from "./dtcg.js";
|
|
2
|
+
const REF_RE = /\{([a-z0-9_.-]+)\}/gi;
|
|
3
|
+
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
2
4
|
export function flattenTokens(root) {
|
|
3
5
|
const flat = {};
|
|
4
6
|
const edges = [];
|
|
@@ -8,13 +10,17 @@ export function flattenTokens(root) {
|
|
|
8
10
|
return;
|
|
9
11
|
if (Object.prototype.hasOwnProperty.call(node, '$value')) {
|
|
10
12
|
const id = path.join('.');
|
|
11
|
-
|
|
12
|
-
if (raw === undefined)
|
|
13
|
+
if (node.$value === undefined)
|
|
13
14
|
return; // Skip tokens without values
|
|
15
|
+
// Normalize DTCG 2025.10 structured color/dimension objects to the
|
|
16
|
+
// string/number form the engine + plugins expect (strings, incl. aliases,
|
|
17
|
+
// pass through unchanged). Keeps the color math in core/color.ts untouched.
|
|
18
|
+
const raw = node.$value;
|
|
19
|
+
const normalized = normalizeDtcgValue(raw, node.$type);
|
|
14
20
|
const refs = [];
|
|
15
21
|
// Find all references in the value
|
|
16
|
-
if (typeof
|
|
17
|
-
const matches =
|
|
22
|
+
if (typeof normalized === 'string') {
|
|
23
|
+
const matches = normalized.matchAll(REF_RE);
|
|
18
24
|
for (const match of matches) {
|
|
19
25
|
refs.push(match[1]);
|
|
20
26
|
}
|
|
@@ -22,7 +28,7 @@ export function flattenTokens(root) {
|
|
|
22
28
|
flat[id] = {
|
|
23
29
|
id,
|
|
24
30
|
type: String(node.$type ?? 'unknown'),
|
|
25
|
-
value:
|
|
31
|
+
value: normalized,
|
|
26
32
|
raw,
|
|
27
33
|
refs
|
|
28
34
|
};
|
|
@@ -44,7 +50,7 @@ export function flattenTokens(root) {
|
|
|
44
50
|
// Second pass: resolve references iteratively
|
|
45
51
|
let changed = true;
|
|
46
52
|
let iterations = 0;
|
|
47
|
-
const maxIterations = Object.keys(flat).length * 2; // Safety limit
|
|
53
|
+
const maxIterations = Object.keys(flat).length * 2 + 1; // Safety limit (never 0)
|
|
48
54
|
while (changed && iterations < maxIterations) {
|
|
49
55
|
changed = false;
|
|
50
56
|
iterations++;
|
|
@@ -63,7 +69,7 @@ export function flattenTokens(root) {
|
|
|
63
69
|
break;
|
|
64
70
|
}
|
|
65
71
|
// Replace the reference with the resolved value
|
|
66
|
-
const refPattern = new RegExp(`\\{${refId}\\}`, 'g');
|
|
72
|
+
const refPattern = new RegExp(`\\{${escapeRegExp(refId)}\\}`, 'g');
|
|
67
73
|
newValue = newValue.replace(refPattern, String(refToken.value));
|
|
68
74
|
}
|
|
69
75
|
if (fullyResolved && newValue !== token.value) {
|
|
@@ -73,8 +79,16 @@ export function flattenTokens(root) {
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
// A token still carrying an unresolved "{ref}" placeholder after the fixpoint
|
|
83
|
+
// means a genuine cycle (a -> b -> a) or a self-reference. An empty or
|
|
84
|
+
// fully-literal token set resolves cleanly and must never trip this guard —
|
|
85
|
+
// the old `iterations >= maxIterations` check threw a bogus "circular
|
|
86
|
+
// reference" error whenever no tokens were found (maxIterations === 0).
|
|
87
|
+
const unresolved = Object.values(flat).filter((t) => typeof t.value === 'string' && t.value.includes('{'));
|
|
88
|
+
if (unresolved.length > 0) {
|
|
89
|
+
throw new Error(`Token resolution exceeded maximum iterations - possible circular reference (unresolved: ${unresolved
|
|
90
|
+
.map((t) => t.id)
|
|
91
|
+
.join(', ')})`);
|
|
78
92
|
}
|
|
79
93
|
return { flat, edges };
|
|
80
94
|
}
|
package/core/flatten.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
+
import { normalizeDtcgValue } from "./dtcg.js";
|
|
2
|
+
|
|
1
3
|
export type TokenId = string; // e.g. "color.palette.brand.600"
|
|
2
4
|
export type TokenValue = string | number;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// $value may also be a DTCG 2025.10 structured object (color / dimension); it is
|
|
6
|
+
// normalized to a TokenValue at ingestion. See normalizeDtcgValue.
|
|
7
|
+
export type DtcgStructuredValue = Record<string, unknown>;
|
|
8
|
+
export type TokenNode = {
|
|
9
|
+
$type?: string;
|
|
10
|
+
$value?: TokenValue | DtcgStructuredValue;
|
|
11
|
+
$extensions?: DtcgStructuredValue; // spec passthrough — preserved, never interpreted
|
|
12
|
+
[k: string]: TokenNode | string | number | DtcgStructuredValue | undefined;
|
|
7
13
|
};
|
|
8
14
|
|
|
9
15
|
export type FlatToken = {
|
|
10
16
|
id: TokenId;
|
|
11
17
|
type: string;
|
|
12
18
|
value: TokenValue; // resolved (if ref)
|
|
13
|
-
raw: TokenValue;
|
|
19
|
+
raw: TokenValue | DtcgStructuredValue; // original $value
|
|
14
20
|
refs: TokenId[]; // referenced token IDs found in raw
|
|
15
21
|
};
|
|
16
22
|
|
|
@@ -19,7 +25,8 @@ export type FlattenResult = {
|
|
|
19
25
|
edges: Array<[from: TokenId, to: TokenId]>; // from ref -> to dependent
|
|
20
26
|
};
|
|
21
27
|
|
|
22
|
-
const REF_RE = /\{([a-z0-
|
|
28
|
+
const REF_RE = /\{([a-z0-9_.-]+)\}/gi;
|
|
29
|
+
const escapeRegExp = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
23
30
|
|
|
24
31
|
export function flattenTokens(root: TokenNode): FlattenResult {
|
|
25
32
|
const flat: Record<TokenId, FlatToken> = {};
|
|
@@ -31,14 +38,18 @@ export function flattenTokens(root: TokenNode): FlattenResult {
|
|
|
31
38
|
|
|
32
39
|
if (Object.prototype.hasOwnProperty.call(node, '$value')) {
|
|
33
40
|
const id = path.join('.');
|
|
41
|
+
if (node.$value === undefined) return; // Skip tokens without values
|
|
42
|
+
// Normalize DTCG 2025.10 structured color/dimension objects to the
|
|
43
|
+
// string/number form the engine + plugins expect (strings, incl. aliases,
|
|
44
|
+
// pass through unchanged). Keeps the color math in core/color.ts untouched.
|
|
34
45
|
const raw = node.$value;
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
const normalized = normalizeDtcgValue(raw, node.$type);
|
|
47
|
+
|
|
37
48
|
const refs: TokenId[] = [];
|
|
38
49
|
|
|
39
50
|
// Find all references in the value
|
|
40
|
-
if (typeof
|
|
41
|
-
const matches =
|
|
51
|
+
if (typeof normalized === 'string') {
|
|
52
|
+
const matches = normalized.matchAll(REF_RE);
|
|
42
53
|
for (const match of matches) {
|
|
43
54
|
refs.push(match[1]);
|
|
44
55
|
}
|
|
@@ -47,7 +58,7 @@ export function flattenTokens(root: TokenNode): FlattenResult {
|
|
|
47
58
|
flat[id] = {
|
|
48
59
|
id,
|
|
49
60
|
type: String(node.$type ?? 'unknown'),
|
|
50
|
-
value:
|
|
61
|
+
value: normalized,
|
|
51
62
|
raw,
|
|
52
63
|
refs
|
|
53
64
|
};
|
|
@@ -72,8 +83,8 @@ export function flattenTokens(root: TokenNode): FlattenResult {
|
|
|
72
83
|
// Second pass: resolve references iteratively
|
|
73
84
|
let changed = true;
|
|
74
85
|
let iterations = 0;
|
|
75
|
-
const maxIterations = Object.keys(flat).length * 2; // Safety limit
|
|
76
|
-
|
|
86
|
+
const maxIterations = Object.keys(flat).length * 2 + 1; // Safety limit (never 0)
|
|
87
|
+
|
|
77
88
|
while (changed && iterations < maxIterations) {
|
|
78
89
|
changed = false;
|
|
79
90
|
iterations++;
|
|
@@ -96,7 +107,7 @@ export function flattenTokens(root: TokenNode): FlattenResult {
|
|
|
96
107
|
}
|
|
97
108
|
|
|
98
109
|
// Replace the reference with the resolved value
|
|
99
|
-
const refPattern = new RegExp(`\\{${refId}\\}`, 'g');
|
|
110
|
+
const refPattern = new RegExp(`\\{${escapeRegExp(refId)}\\}`, 'g');
|
|
100
111
|
newValue = newValue.replace(refPattern, String(refToken.value));
|
|
101
112
|
}
|
|
102
113
|
|
|
@@ -108,8 +119,20 @@ export function flattenTokens(root: TokenNode): FlattenResult {
|
|
|
108
119
|
}
|
|
109
120
|
}
|
|
110
121
|
|
|
111
|
-
|
|
112
|
-
|
|
122
|
+
// A token still carrying an unresolved "{ref}" placeholder after the fixpoint
|
|
123
|
+
// means a genuine cycle (a -> b -> a) or a self-reference. An empty or
|
|
124
|
+
// fully-literal token set resolves cleanly and must never trip this guard —
|
|
125
|
+
// the old `iterations >= maxIterations` check threw a bogus "circular
|
|
126
|
+
// reference" error whenever no tokens were found (maxIterations === 0).
|
|
127
|
+
const unresolved = Object.values(flat).filter(
|
|
128
|
+
(t) => typeof t.value === 'string' && t.value.includes('{'),
|
|
129
|
+
);
|
|
130
|
+
if (unresolved.length > 0) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Token resolution exceeded maximum iterations - possible circular reference (unresolved: ${unresolved
|
|
133
|
+
.map((t) => t.id)
|
|
134
|
+
.join(', ')})`,
|
|
135
|
+
);
|
|
113
136
|
}
|
|
114
137
|
|
|
115
138
|
return { flat, edges };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-export.d.ts","sourceRoot":"","sources":["image-export.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image-export.d.ts","sourceRoot":"","sources":["image-export.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AACrC,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;AAEzC,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EAAe,6BAA6B;AAC7D,OAAO,EAAE,MAAM,EAAiB,wBAAwB;AACxD,GAAG,EAAE,QAAQ,EAAmB,gBAAgB;AAChD,QAAQ,EAAE,QAAQ,GACjB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAoBhC"}
|
package/core/image-export.js
CHANGED
|
@@ -5,13 +5,16 @@ import { spawnSync } from "node:child_process";
|
|
|
5
5
|
function which(cmd) {
|
|
6
6
|
const paths = (process.env.PATH || "").split(path.delimiter);
|
|
7
7
|
for (const p of paths) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const names = process.platform === "win32" ? [cmd + ".cmd", cmd + ".exe", cmd] : [cmd];
|
|
9
|
+
for (const name of names) {
|
|
10
|
+
const full = path.join(p, name);
|
|
11
|
+
try {
|
|
12
|
+
fs.accessSync(full, fs.constants.X_OK);
|
|
13
|
+
return full;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// File not accessible, continue to next path
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
return null;
|
package/core/image-export.ts
CHANGED
|
@@ -6,12 +6,15 @@ import { spawnSync } from "node:child_process";
|
|
|
6
6
|
function which(cmd: string): string | null {
|
|
7
7
|
const paths = (process.env.PATH || "").split(path.delimiter);
|
|
8
8
|
for (const p of paths) {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const names = process.platform === "win32" ? [cmd + ".cmd", cmd + ".exe", cmd] : [cmd];
|
|
10
|
+
for (const name of names) {
|
|
11
|
+
const full = path.join(p, name);
|
|
12
|
+
try {
|
|
13
|
+
fs.accessSync(full, fs.constants.X_OK);
|
|
14
|
+
return full;
|
|
15
|
+
} catch {
|
|
16
|
+
// File not accessible, continue to next path
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
return null;
|
package/core/index.d.ts
CHANGED
|
@@ -7,4 +7,6 @@
|
|
|
7
7
|
export type { TokenId, TokenValue } from "./flatten.js";
|
|
8
8
|
export type { ConstraintIssue, ConstraintPlugin, Graph } from "./engine.js";
|
|
9
9
|
export { Engine } from "./engine.js";
|
|
10
|
+
export { validate } from "../cli/validate-api.js";
|
|
11
|
+
export type { ValidateInput, ValidateResult } from "../cli/validate-api.js";
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
package/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAKrC,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
package/core/index.js
CHANGED
|
@@ -5,3 +5,7 @@
|
|
|
5
5
|
* See engine.ts for full implementation with Phase 3C enhancements.
|
|
6
6
|
*/
|
|
7
7
|
export { Engine } from "./engine.js";
|
|
8
|
+
// Programmatic convenience API (validate tokens against constraints in one call).
|
|
9
|
+
// Implemented in the CLI layer atop the shared registry; surfaced here as the
|
|
10
|
+
// package's public entry point.
|
|
11
|
+
export { validate } from "../cli/validate-api.js";
|
package/core/index.ts
CHANGED
|
@@ -8,3 +8,9 @@
|
|
|
8
8
|
export type { TokenId, TokenValue } from "./flatten.js";
|
|
9
9
|
export type { ConstraintIssue, ConstraintPlugin, Graph } from "./engine.js";
|
|
10
10
|
export { Engine } from "./engine.js";
|
|
11
|
+
|
|
12
|
+
// Programmatic convenience API (validate tokens against constraints in one call).
|
|
13
|
+
// Implemented in the CLI layer atop the shared registry; surfaced here as the
|
|
14
|
+
// package's public entry point.
|
|
15
|
+
export { validate } from "../cli/validate-api.js";
|
|
16
|
+
export type { ValidateInput, ValidateResult } from "../cli/validate-api.js";
|
package/core/why.d.ts
CHANGED
package/core/why.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"why.d.ts","sourceRoot":"","sources":["why.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,GAAG,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"why.d.ts","sourceRoot":"","sources":["why.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAQxF;AAED,wBAAgB,OAAO,CACrB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAC/B,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC,EAC7B,MAAM,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAO,GACpF,SAAS,CAkCX"}
|
package/core/why.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { FlatToken } from "./flatten.js";
|
|
|
3
3
|
export type WhyReport = {
|
|
4
4
|
id: string;
|
|
5
5
|
value: string | number | undefined;
|
|
6
|
-
raw?:
|
|
6
|
+
raw?: unknown;
|
|
7
7
|
refs?: string[];
|
|
8
8
|
provenance: "base" | "theme" | "override" | "unknown";
|
|
9
9
|
dependsOn: string[]; // immediate refs (parents)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
3
|
+
export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
4
|
+
export interface JsonObject {
|
|
5
|
+
[key: string]: JsonValue;
|
|
6
|
+
}
|
|
7
|
+
export declare const jsonValueSchema: z.ZodType<JsonValue>;
|
|
8
|
+
export declare const jsonObjectSchema: z.ZodType<JsonObject>;
|
|
9
|
+
export declare const tokenInputShape: {
|
|
10
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
11
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
12
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
13
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
14
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
15
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
16
|
+
};
|
|
17
|
+
export declare const validateInputShape: {
|
|
18
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
19
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
20
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
21
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
22
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
23
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
24
|
+
};
|
|
25
|
+
export declare const whyInputShape: {
|
|
26
|
+
tokenId: z.ZodString;
|
|
27
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
28
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
29
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
30
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
31
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
32
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
33
|
+
};
|
|
34
|
+
export declare const graphInputShape: {
|
|
35
|
+
format: z.ZodOptional<z.ZodLiteral<"json">>;
|
|
36
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
37
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
38
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
39
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
40
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
41
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
42
|
+
};
|
|
43
|
+
export declare const validateInputSchema: z.ZodObject<{
|
|
44
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
45
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
46
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
47
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
48
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
49
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
tokens?: JsonObject | undefined;
|
|
52
|
+
constraints?: JsonObject | undefined;
|
|
53
|
+
constraintsDir?: string | undefined;
|
|
54
|
+
breakpoint?: "sm" | "md" | "lg" | undefined;
|
|
55
|
+
tokensPath?: string | undefined;
|
|
56
|
+
configPath?: string | undefined;
|
|
57
|
+
}, {
|
|
58
|
+
tokens?: JsonObject | undefined;
|
|
59
|
+
constraints?: JsonObject | undefined;
|
|
60
|
+
constraintsDir?: string | undefined;
|
|
61
|
+
breakpoint?: "sm" | "md" | "lg" | undefined;
|
|
62
|
+
tokensPath?: string | undefined;
|
|
63
|
+
configPath?: string | undefined;
|
|
64
|
+
}>;
|
|
65
|
+
export declare const whyInputSchema: z.ZodObject<{
|
|
66
|
+
tokenId: z.ZodString;
|
|
67
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
68
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
69
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
70
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
71
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
72
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
73
|
+
}, "strip", z.ZodTypeAny, {
|
|
74
|
+
tokenId: string;
|
|
75
|
+
tokens?: JsonObject | undefined;
|
|
76
|
+
constraints?: JsonObject | undefined;
|
|
77
|
+
constraintsDir?: string | undefined;
|
|
78
|
+
breakpoint?: "sm" | "md" | "lg" | undefined;
|
|
79
|
+
tokensPath?: string | undefined;
|
|
80
|
+
configPath?: string | undefined;
|
|
81
|
+
}, {
|
|
82
|
+
tokenId: string;
|
|
83
|
+
tokens?: JsonObject | undefined;
|
|
84
|
+
constraints?: JsonObject | undefined;
|
|
85
|
+
constraintsDir?: string | undefined;
|
|
86
|
+
breakpoint?: "sm" | "md" | "lg" | undefined;
|
|
87
|
+
tokensPath?: string | undefined;
|
|
88
|
+
configPath?: string | undefined;
|
|
89
|
+
}>;
|
|
90
|
+
export declare const graphInputSchema: z.ZodObject<{
|
|
91
|
+
format: z.ZodOptional<z.ZodLiteral<"json">>;
|
|
92
|
+
tokens: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
93
|
+
tokensPath: z.ZodOptional<z.ZodString>;
|
|
94
|
+
constraints: z.ZodOptional<z.ZodType<JsonObject, z.ZodTypeDef, JsonObject>>;
|
|
95
|
+
configPath: z.ZodOptional<z.ZodString>;
|
|
96
|
+
constraintsDir: z.ZodOptional<z.ZodString>;
|
|
97
|
+
breakpoint: z.ZodOptional<z.ZodEnum<["sm", "md", "lg"]>>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
tokens?: JsonObject | undefined;
|
|
100
|
+
constraints?: JsonObject | undefined;
|
|
101
|
+
format?: "json" | undefined;
|
|
102
|
+
constraintsDir?: string | undefined;
|
|
103
|
+
breakpoint?: "sm" | "md" | "lg" | undefined;
|
|
104
|
+
tokensPath?: string | undefined;
|
|
105
|
+
configPath?: string | undefined;
|
|
106
|
+
}, {
|
|
107
|
+
tokens?: JsonObject | undefined;
|
|
108
|
+
constraints?: JsonObject | undefined;
|
|
109
|
+
format?: "json" | undefined;
|
|
110
|
+
constraintsDir?: string | undefined;
|
|
111
|
+
breakpoint?: "sm" | "md" | "lg" | undefined;
|
|
112
|
+
tokensPath?: string | undefined;
|
|
113
|
+
configPath?: string | undefined;
|
|
114
|
+
}>;
|
|
115
|
+
export type ValidateToolInput = z.infer<typeof validateInputSchema>;
|
|
116
|
+
export type WhyToolInput = z.infer<typeof whyInputSchema>;
|
|
117
|
+
export type GraphToolInput = z.infer<typeof graphInputSchema>;
|
|
118
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAC7D,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,EAAE,CAAC;AAEjE,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAID,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAEhD,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAA6B,CAAC;AAEjF,eAAO,MAAM,eAAe;;;;;;;CAW3B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;CAE9B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;CAGzB,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;CAG3B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;EAA+B,CAAC;AAChE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;EAA0B,CAAC;AACtD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;EAA4B,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAC1D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
package/mcp/contracts.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const jsonPrimitiveSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
3
|
+
export const jsonValueSchema = z.lazy(() => z.union([jsonPrimitiveSchema, z.array(jsonValueSchema), z.record(jsonValueSchema)]));
|
|
4
|
+
export const jsonObjectSchema = z.record(jsonValueSchema);
|
|
5
|
+
export const tokenInputShape = {
|
|
6
|
+
tokens: jsonObjectSchema
|
|
7
|
+
.optional()
|
|
8
|
+
.describe('Inline DTCG-style token tree. Takes precedence over tokensPath.'),
|
|
9
|
+
tokensPath: z.string().optional().describe('Path to a token JSON file on the server filesystem.'),
|
|
10
|
+
constraints: jsonObjectSchema
|
|
11
|
+
.optional()
|
|
12
|
+
.describe('Inline constraints block from dcv.config.json. Takes precedence over configPath.'),
|
|
13
|
+
configPath: z.string().optional().describe('Path to a JSON DCV config file.'),
|
|
14
|
+
constraintsDir: z.string().optional().describe('Directory holding order and cross-axis constraints.'),
|
|
15
|
+
breakpoint: z.enum(['sm', 'md', 'lg']).optional().describe('Optional constraint breakpoint.'),
|
|
16
|
+
};
|
|
17
|
+
export const validateInputShape = {
|
|
18
|
+
...tokenInputShape,
|
|
19
|
+
};
|
|
20
|
+
export const whyInputShape = {
|
|
21
|
+
...tokenInputShape,
|
|
22
|
+
tokenId: z.string().describe('Token id to explain, for example color.role.text.default.'),
|
|
23
|
+
};
|
|
24
|
+
export const graphInputShape = {
|
|
25
|
+
...tokenInputShape,
|
|
26
|
+
format: z.literal('json').optional().describe('Only json is supported; omitted defaults to json.'),
|
|
27
|
+
};
|
|
28
|
+
export const validateInputSchema = z.object(validateInputShape);
|
|
29
|
+
export const whyInputSchema = z.object(whyInputShape);
|
|
30
|
+
export const graphInputSchema = z.object(graphInputShape);
|
package/mcp/contracts.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
4
|
+
export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
5
|
+
|
|
6
|
+
export interface JsonObject {
|
|
7
|
+
[key: string]: JsonValue;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const jsonPrimitiveSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
11
|
+
|
|
12
|
+
export const jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>
|
|
13
|
+
z.union([jsonPrimitiveSchema, z.array(jsonValueSchema), z.record(jsonValueSchema)]),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export const jsonObjectSchema: z.ZodType<JsonObject> = z.record(jsonValueSchema);
|
|
17
|
+
|
|
18
|
+
export const tokenInputShape = {
|
|
19
|
+
tokens: jsonObjectSchema
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Inline DTCG-style token tree. Takes precedence over tokensPath.'),
|
|
22
|
+
tokensPath: z.string().optional().describe('Path to a token JSON file on the server filesystem.'),
|
|
23
|
+
constraints: jsonObjectSchema
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Inline constraints block from dcv.config.json. Takes precedence over configPath.'),
|
|
26
|
+
configPath: z.string().optional().describe('Path to a JSON DCV config file.'),
|
|
27
|
+
constraintsDir: z.string().optional().describe('Directory holding order and cross-axis constraints.'),
|
|
28
|
+
breakpoint: z.enum(['sm', 'md', 'lg']).optional().describe('Optional constraint breakpoint.'),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const validateInputShape = {
|
|
32
|
+
...tokenInputShape,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const whyInputShape = {
|
|
36
|
+
...tokenInputShape,
|
|
37
|
+
tokenId: z.string().describe('Token id to explain, for example color.role.text.default.'),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const graphInputShape = {
|
|
41
|
+
...tokenInputShape,
|
|
42
|
+
format: z.literal('json').optional().describe('Only json is supported; omitted defaults to json.'),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const validateInputSchema = z.object(validateInputShape);
|
|
46
|
+
export const whyInputSchema = z.object(whyInputShape);
|
|
47
|
+
export const graphInputSchema = z.object(graphInputShape);
|
|
48
|
+
|
|
49
|
+
export type ValidateToolInput = z.infer<typeof validateInputSchema>;
|
|
50
|
+
export type WhyToolInput = z.infer<typeof whyInputSchema>;
|
|
51
|
+
export type GraphToolInput = z.infer<typeof graphInputSchema>;
|
package/mcp/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
export { graphInputSchema, graphInputShape, jsonObjectSchema, jsonValueSchema, validateInputSchema, validateInputShape, whyInputSchema, whyInputShape, } from './contracts.js';
|
|
4
|
+
export type { GraphToolInput, JsonObject, JsonPrimitive, JsonValue, ValidateToolInput, WhyToolInput, } from './contracts.js';
|
|
5
|
+
export { dcvMcpTools, graphTool, registerDcvMcpTools, ToolExecutionError, validateTool, whyTool, } from './tools.js';
|
|
6
|
+
export type { DcvMcpToolName, GraphToolResult, ToolFailure, ToolResponse, WhyToolResult, } from './tools.js';
|
|
7
|
+
export declare function createDcvMcpServer(): McpServer;
|
|
8
|
+
export declare function startStdioServer(): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,cAAc,EACd,UAAU,EACV,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,eAAe,EACf,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,wBAAgB,kBAAkB,IAAI,SAAS,CAQ9C;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
|
package/mcp/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
6
|
+
import { registerDcvMcpTools } from './tools.js';
|
|
7
|
+
export { graphInputSchema, graphInputShape, jsonObjectSchema, jsonValueSchema, validateInputSchema, validateInputShape, whyInputSchema, whyInputShape, } from './contracts.js';
|
|
8
|
+
export { dcvMcpTools, graphTool, registerDcvMcpTools, ToolExecutionError, validateTool, whyTool, } from './tools.js';
|
|
9
|
+
export function createDcvMcpServer() {
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: 'dcv-mcp',
|
|
12
|
+
version: '2.1.0',
|
|
13
|
+
});
|
|
14
|
+
registerDcvMcpTools(server);
|
|
15
|
+
return server;
|
|
16
|
+
}
|
|
17
|
+
export async function startStdioServer() {
|
|
18
|
+
const server = createDcvMcpServer();
|
|
19
|
+
const transport = new StdioServerTransport();
|
|
20
|
+
await server.connect(transport);
|
|
21
|
+
}
|
|
22
|
+
function isEntrypoint() {
|
|
23
|
+
const entry = process.argv[1];
|
|
24
|
+
return entry !== undefined && resolve(fileURLToPath(import.meta.url)) === resolve(entry);
|
|
25
|
+
}
|
|
26
|
+
if (isEntrypoint()) {
|
|
27
|
+
startStdioServer().catch((error) => {
|
|
28
|
+
const message = error instanceof Error ? error.message : 'Unknown MCP server failure';
|
|
29
|
+
console.error(`[dcv-mcp] ${message}`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
});
|
|
32
|
+
}
|
package/mcp/index.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
6
|
+
|
|
7
|
+
import { registerDcvMcpTools } from './tools.js';
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
graphInputSchema,
|
|
11
|
+
graphInputShape,
|
|
12
|
+
jsonObjectSchema,
|
|
13
|
+
jsonValueSchema,
|
|
14
|
+
validateInputSchema,
|
|
15
|
+
validateInputShape,
|
|
16
|
+
whyInputSchema,
|
|
17
|
+
whyInputShape,
|
|
18
|
+
} from './contracts.js';
|
|
19
|
+
export type {
|
|
20
|
+
GraphToolInput,
|
|
21
|
+
JsonObject,
|
|
22
|
+
JsonPrimitive,
|
|
23
|
+
JsonValue,
|
|
24
|
+
ValidateToolInput,
|
|
25
|
+
WhyToolInput,
|
|
26
|
+
} from './contracts.js';
|
|
27
|
+
export {
|
|
28
|
+
dcvMcpTools,
|
|
29
|
+
graphTool,
|
|
30
|
+
registerDcvMcpTools,
|
|
31
|
+
ToolExecutionError,
|
|
32
|
+
validateTool,
|
|
33
|
+
whyTool,
|
|
34
|
+
} from './tools.js';
|
|
35
|
+
export type {
|
|
36
|
+
DcvMcpToolName,
|
|
37
|
+
GraphToolResult,
|
|
38
|
+
ToolFailure,
|
|
39
|
+
ToolResponse,
|
|
40
|
+
WhyToolResult,
|
|
41
|
+
} from './tools.js';
|
|
42
|
+
|
|
43
|
+
export function createDcvMcpServer(): McpServer {
|
|
44
|
+
const server = new McpServer({
|
|
45
|
+
name: 'dcv-mcp',
|
|
46
|
+
version: '2.1.0',
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
registerDcvMcpTools(server);
|
|
50
|
+
return server;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function startStdioServer(): Promise<void> {
|
|
54
|
+
const server = createDcvMcpServer();
|
|
55
|
+
const transport = new StdioServerTransport();
|
|
56
|
+
await server.connect(transport);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isEntrypoint(): boolean {
|
|
60
|
+
const entry = process.argv[1];
|
|
61
|
+
return entry !== undefined && resolve(fileURLToPath(import.meta.url)) === resolve(entry);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (isEntrypoint()) {
|
|
65
|
+
startStdioServer().catch((error: unknown) => {
|
|
66
|
+
const message = error instanceof Error ? error.message : 'Unknown MCP server failure';
|
|
67
|
+
console.error(`[dcv-mcp] ${message}`);
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
});
|
|
70
|
+
}
|