design-constraint-validator 2.0.1 → 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.
Files changed (82) hide show
  1. package/README.md +76 -21
  2. package/cli/commands/build.js +1 -1
  3. package/cli/commands/build.ts +1 -1
  4. package/cli/commands/graph.js +2 -2
  5. package/cli/commands/graph.ts +2 -2
  6. package/cli/commands/validate.d.ts.map +1 -1
  7. package/cli/commands/validate.js +40 -6
  8. package/cli/commands/validate.ts +37 -8
  9. package/cli/config-schema.d.ts +39 -0
  10. package/cli/config-schema.d.ts.map +1 -1
  11. package/cli/config-schema.js +4 -2
  12. package/cli/config-schema.ts +4 -2
  13. package/cli/config.d.ts.map +1 -1
  14. package/cli/config.js +8 -2
  15. package/cli/config.ts +8 -2
  16. package/cli/constraint-registry.d.ts +16 -0
  17. package/cli/constraint-registry.d.ts.map +1 -1
  18. package/cli/constraint-registry.js +64 -31
  19. package/cli/constraint-registry.ts +67 -31
  20. package/cli/dcv.js +8 -24
  21. package/cli/dcv.ts +8 -20
  22. package/cli/json-output.d.ts +3 -1
  23. package/cli/json-output.d.ts.map +1 -1
  24. package/cli/json-output.js +11 -4
  25. package/cli/json-output.ts +13 -4
  26. package/cli/types.d.ts +2 -0
  27. package/cli/types.d.ts.map +1 -1
  28. package/cli/types.ts +2 -0
  29. package/cli/validate-api.d.ts +40 -0
  30. package/cli/validate-api.d.ts.map +1 -0
  31. package/cli/validate-api.js +85 -0
  32. package/cli/validate-api.ts +126 -0
  33. package/core/breakpoints.d.ts +8 -2
  34. package/core/breakpoints.d.ts.map +1 -1
  35. package/core/breakpoints.js +24 -3
  36. package/core/breakpoints.ts +22 -3
  37. package/core/color.js +4 -4
  38. package/core/color.ts +4 -4
  39. package/core/constraints/monotonic-lightness.d.ts.map +1 -1
  40. package/core/constraints/monotonic-lightness.js +9 -5
  41. package/core/constraints/monotonic-lightness.ts +9 -4
  42. package/core/constraints/wcag.d.ts.map +1 -1
  43. package/core/constraints/wcag.js +6 -0
  44. package/core/constraints/wcag.ts +6 -0
  45. package/core/dtcg.d.ts +38 -0
  46. package/core/dtcg.d.ts.map +1 -0
  47. package/core/dtcg.js +88 -0
  48. package/core/dtcg.ts +102 -0
  49. package/core/engine.d.ts +6 -0
  50. package/core/engine.d.ts.map +1 -1
  51. package/core/engine.ts +7 -0
  52. package/core/flatten.d.ts +5 -3
  53. package/core/flatten.d.ts.map +1 -1
  54. package/core/flatten.js +24 -10
  55. package/core/flatten.ts +39 -16
  56. package/core/image-export.d.ts.map +1 -1
  57. package/core/image-export.js +10 -7
  58. package/core/image-export.ts +9 -6
  59. package/core/index.d.ts +2 -0
  60. package/core/index.d.ts.map +1 -1
  61. package/core/index.js +4 -0
  62. package/core/index.ts +6 -0
  63. package/core/why.d.ts +1 -1
  64. package/core/why.d.ts.map +1 -1
  65. package/core/why.ts +1 -1
  66. package/mcp/contracts.d.ts +118 -0
  67. package/mcp/contracts.d.ts.map +1 -0
  68. package/mcp/contracts.js +30 -0
  69. package/mcp/contracts.ts +51 -0
  70. package/mcp/index.d.ts +9 -0
  71. package/mcp/index.d.ts.map +1 -0
  72. package/mcp/index.js +32 -0
  73. package/mcp/index.ts +70 -0
  74. package/mcp/tools.d.ts +52 -0
  75. package/mcp/tools.d.ts.map +1 -0
  76. package/mcp/tools.js +172 -0
  77. package/mcp/tools.ts +254 -0
  78. package/package.json +41 -26
  79. package/server.json +21 -0
  80. package/cli/constraints-loader.d.ts.map +0 -1
  81. package/cli/engine-helpers.d.ts.map +0 -1
  82. package/core/cross-axis-config.d.ts.map +0 -1
@@ -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"}
@@ -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);
@@ -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
+ }
package/mcp/tools.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { z } from 'zod';
3
+ import { type WhyReport } from '../core/why.js';
4
+ import { type ValidateResult } from '../cli/validate-api.js';
5
+ import type { ValidateToolInput, WhyToolInput, GraphToolInput } from './contracts.js';
6
+ export type DcvMcpToolName = 'validate' | 'why' | 'graph';
7
+ export interface ToolFailure {
8
+ ok: false;
9
+ tool: DcvMcpToolName;
10
+ error: {
11
+ code: string;
12
+ message: string;
13
+ details?: Record<string, unknown>;
14
+ };
15
+ }
16
+ export type ToolResponse<T extends {
17
+ ok: boolean;
18
+ } & object> = ({
19
+ tool: DcvMcpToolName;
20
+ } & T) | ToolFailure;
21
+ export declare class ToolExecutionError extends Error {
22
+ readonly code: string;
23
+ readonly details?: Record<string, unknown>;
24
+ constructor(code: string, message: string, details?: Record<string, unknown>);
25
+ }
26
+ export interface GraphToolResult {
27
+ ok: true;
28
+ nodes: string[];
29
+ edges: Array<[string, string]>;
30
+ meta: {
31
+ nodeCount: number;
32
+ edgeCount: number;
33
+ };
34
+ }
35
+ export type WhyToolResult = {
36
+ ok: true;
37
+ } & WhyReport;
38
+ interface ToolDefinition<TInput, TResult extends {
39
+ ok: boolean;
40
+ } & object> {
41
+ name: DcvMcpToolName;
42
+ description: string;
43
+ inputSchema: Record<string, z.ZodTypeAny>;
44
+ handler: (input: TInput) => Promise<ToolResponse<TResult>> | ToolResponse<TResult>;
45
+ }
46
+ export declare function validateTool(input: ValidateToolInput): Promise<ToolResponse<ValidateResult>>;
47
+ export declare function whyTool(input: WhyToolInput): Promise<ToolResponse<WhyToolResult>>;
48
+ export declare function graphTool(input: GraphToolInput): Promise<ToolResponse<GraphToolResult>>;
49
+ export declare const dcvMcpTools: Array<ToolDefinition<ValidateToolInput, ValidateResult> | ToolDefinition<WhyToolInput, WhyToolResult> | ToolDefinition<GraphToolInput, GraphToolResult>>;
50
+ export declare function registerDcvMcpTools(server: McpServer): void;
51
+ export {};
52
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAI7B,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGvE,OAAO,KAAK,EAAc,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGlG,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC;CACH;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,IAAI,CAAC;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC;AAE5G,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAE/B,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAK7E;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/B,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,SAAS,CAAC;AAWrD,UAAU,cAAc,CAAC,MAAM,EAAE,OAAO,SAAS;IAAE,EAAE,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM;IACvE,IAAI,EAAE,cAAc,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IAC1C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;CACpF;AAyFD,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAelG;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAevF;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAe7F;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAC3B,cAAc,CAAC,iBAAiB,EAAE,cAAc,CAAC,GACjD,cAAc,CAAC,YAAY,EAAE,aAAa,CAAC,GAC3C,cAAc,CAAC,cAAc,EAAE,eAAe,CAAC,CAoBlD,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuB3D"}
package/mcp/tools.js ADDED
@@ -0,0 +1,172 @@
1
+ import fs from 'node:fs';
2
+ import { suggestIds } from '../core/cli-format.js';
3
+ import { flattenTokens } from '../core/flatten.js';
4
+ import { explain } from '../core/why.js';
5
+ import { validate } from '../cli/validate-api.js';
6
+ import { graphInputShape, validateInputShape, whyInputShape } from './contracts.js';
7
+ export class ToolExecutionError extends Error {
8
+ code;
9
+ details;
10
+ constructor(code, message, details) {
11
+ super(message);
12
+ this.code = code;
13
+ this.details = details;
14
+ }
15
+ }
16
+ function errorMessage(error) {
17
+ return error instanceof Error ? error.message : 'Unknown tool failure';
18
+ }
19
+ function toFailure(tool, error) {
20
+ if (error instanceof ToolExecutionError) {
21
+ return {
22
+ ok: false,
23
+ tool,
24
+ error: {
25
+ code: error.code,
26
+ message: error.message,
27
+ ...(error.details ? { details: error.details } : {}),
28
+ },
29
+ };
30
+ }
31
+ return {
32
+ ok: false,
33
+ tool,
34
+ error: {
35
+ code: 'tool_execution_failed',
36
+ message: errorMessage(error),
37
+ },
38
+ };
39
+ }
40
+ async function executeTool(tool, fn) {
41
+ try {
42
+ return {
43
+ tool,
44
+ ...(await fn()),
45
+ };
46
+ }
47
+ catch (error) {
48
+ return toFailure(tool, error);
49
+ }
50
+ }
51
+ function isToolFailure(result) {
52
+ return result.ok === false && 'error' in result;
53
+ }
54
+ function responseToContent(result) {
55
+ return JSON.stringify(result, null, 2);
56
+ }
57
+ function parseJsonFile(filePath) {
58
+ if (!fs.existsSync(filePath)) {
59
+ throw new ToolExecutionError('tokens_not_found', `Tokens file not found: ${filePath}`);
60
+ }
61
+ try {
62
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
63
+ }
64
+ catch (error) {
65
+ throw new ToolExecutionError('invalid_tokens', `Tokens file is not valid JSON: ${filePath}`, {
66
+ cause: errorMessage(error),
67
+ });
68
+ }
69
+ }
70
+ function asJsonObject(value, label) {
71
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
72
+ return value;
73
+ }
74
+ throw new ToolExecutionError('invalid_input', `${label} must be a JSON object.`);
75
+ }
76
+ function resolveTokens(input) {
77
+ if (input.tokens !== undefined) {
78
+ return input.tokens;
79
+ }
80
+ if (input.tokensPath !== undefined) {
81
+ return asJsonObject(parseJsonFile(input.tokensPath), 'tokensPath contents');
82
+ }
83
+ throw new ToolExecutionError('invalid_input', 'Provide either tokens or tokensPath.');
84
+ }
85
+ function constraints(input) {
86
+ return input.constraints;
87
+ }
88
+ export async function validateTool(input) {
89
+ return executeTool('validate', () => {
90
+ if (input.tokens === undefined && input.tokensPath === undefined) {
91
+ throw new ToolExecutionError('invalid_input', 'Provide either tokens or tokensPath.');
92
+ }
93
+ return validate({
94
+ ...(input.tokens !== undefined ? { tokens: input.tokens } : {}),
95
+ ...(input.tokens === undefined && input.tokensPath !== undefined ? { tokensPath: input.tokensPath } : {}),
96
+ ...(input.constraints !== undefined ? { constraints: constraints(input) } : {}),
97
+ ...(input.configPath !== undefined ? { configPath: input.configPath } : {}),
98
+ ...(input.constraintsDir !== undefined ? { constraintsDir: input.constraintsDir } : {}),
99
+ ...(input.breakpoint !== undefined ? { breakpoint: input.breakpoint } : {}),
100
+ });
101
+ });
102
+ }
103
+ export async function whyTool(input) {
104
+ return executeTool('why', () => {
105
+ const { flat, edges } = flattenTokens(resolveTokens(input));
106
+ if (!Object.prototype.hasOwnProperty.call(flat, input.tokenId)) {
107
+ throw new ToolExecutionError('unknown_token', `Unknown token id: ${input.tokenId}`, {
108
+ tokenId: input.tokenId,
109
+ suggestions: suggestIds(input.tokenId, Object.keys(flat)).map((suggestion) => suggestion.id),
110
+ });
111
+ }
112
+ return {
113
+ ok: true,
114
+ ...explain(input.tokenId, flat, edges),
115
+ };
116
+ });
117
+ }
118
+ export async function graphTool(input) {
119
+ return executeTool('graph', () => {
120
+ const { flat, edges } = flattenTokens(resolveTokens(input));
121
+ const nodes = Object.keys(flat).sort();
122
+ return {
123
+ ok: true,
124
+ nodes,
125
+ edges,
126
+ meta: {
127
+ nodeCount: nodes.length,
128
+ edgeCount: edges.length,
129
+ },
130
+ };
131
+ });
132
+ }
133
+ export const dcvMcpTools = [
134
+ {
135
+ name: 'validate',
136
+ description: 'Validate DTCG-style design tokens against DCV constraints and return structured violations.',
137
+ inputSchema: validateInputShape,
138
+ handler: validateTool,
139
+ },
140
+ {
141
+ name: 'why',
142
+ description: 'Explain token provenance, aliases, immediate dependencies, dependents, and alias chain.',
143
+ inputSchema: whyInputShape,
144
+ handler: whyTool,
145
+ },
146
+ {
147
+ name: 'graph',
148
+ description: 'Return the token dependency graph as nodes and directed edges.',
149
+ inputSchema: graphInputShape,
150
+ handler: graphTool,
151
+ },
152
+ ];
153
+ export function registerDcvMcpTools(server) {
154
+ for (const tool of dcvMcpTools) {
155
+ server.registerTool(tool.name, {
156
+ description: tool.description,
157
+ inputSchema: tool.inputSchema,
158
+ }, async (input) => {
159
+ const result = await tool.handler(input);
160
+ return {
161
+ content: [
162
+ {
163
+ type: 'text',
164
+ text: responseToContent(result),
165
+ },
166
+ ],
167
+ structuredContent: result,
168
+ ...(isToolFailure(result) ? { isError: true } : {}),
169
+ };
170
+ });
171
+ }
172
+ }