motionwind-mcp 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 +27 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# motionwind-mcp v2
|
|
2
|
+
|
|
3
|
+
MCP tools generated from Motionwind's shared syntax registry.
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"mcpServers": {
|
|
8
|
+
"motionwind": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "motionwind-mcp@2"]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Tools:
|
|
17
|
+
|
|
18
|
+
- `validate_motionwind` returns unknown tokens, duplicates, diagnostics, and
|
|
19
|
+
parsed output.
|
|
20
|
+
- `explain_motionwind` explains each token.
|
|
21
|
+
- `optimize_motionwind` sorts classes and reports problems.
|
|
22
|
+
- `generate_motionwind` produces React, Vue, JavaScript, or React Native code.
|
|
23
|
+
|
|
24
|
+
The `motionwind://syntax` resource exposes the machine-readable definition
|
|
25
|
+
registry used by the parser and developer tools.
|
|
26
|
+
|
|
27
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as motionwind_core from 'motionwind-core';
|
|
2
|
+
|
|
3
|
+
declare function validateClasses(className: string): {
|
|
4
|
+
valid: boolean;
|
|
5
|
+
unknown: string[];
|
|
6
|
+
duplicates: motionwind_core.DuplicateProp[];
|
|
7
|
+
diagnostics: motionwind_core.MotionwindDiagnostic[];
|
|
8
|
+
parsed: motionwind_core.ParsedResult;
|
|
9
|
+
};
|
|
10
|
+
declare function explainClasses(className: string): {
|
|
11
|
+
token: string;
|
|
12
|
+
recognized: boolean;
|
|
13
|
+
motion: motionwind_core.ParsedResult | undefined;
|
|
14
|
+
passthrough: string | undefined;
|
|
15
|
+
}[];
|
|
16
|
+
declare function optimizeClasses(className: string): {
|
|
17
|
+
className: string;
|
|
18
|
+
duplicates: motionwind_core.DuplicateProp[];
|
|
19
|
+
unknown: string[];
|
|
20
|
+
};
|
|
21
|
+
declare function generateExample(input: {
|
|
22
|
+
className: string;
|
|
23
|
+
tag?: string;
|
|
24
|
+
text?: string;
|
|
25
|
+
target?: "react" | "vue" | "javascript" | "react-native";
|
|
26
|
+
}): string;
|
|
27
|
+
declare function syntaxManifest(): readonly motionwind_core.SyntaxDefinition[];
|
|
28
|
+
|
|
29
|
+
export { explainClasses, generateExample, optimizeClasses, syntaxManifest, validateClasses };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import {
|
|
5
|
+
McpServer,
|
|
6
|
+
ResourceTemplate
|
|
7
|
+
} from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
// src/tools.ts
|
|
12
|
+
import {
|
|
13
|
+
MOTIONWIND_SYNTAX_REGISTRY,
|
|
14
|
+
analyzeClassName,
|
|
15
|
+
parseMotionClasses,
|
|
16
|
+
sortMotionClasses
|
|
17
|
+
} from "motionwind-core";
|
|
18
|
+
import { generateMotionCode } from "motionwind-react/tooling";
|
|
19
|
+
function validateClasses(className) {
|
|
20
|
+
const parsed = parseMotionClasses(className);
|
|
21
|
+
const analysis = analyzeClassName(className);
|
|
22
|
+
return {
|
|
23
|
+
valid: analysis.unknown.length === 0,
|
|
24
|
+
unknown: analysis.unknown,
|
|
25
|
+
duplicates: analysis.duplicates,
|
|
26
|
+
diagnostics: parsed.diagnostics,
|
|
27
|
+
parsed
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function explainClasses(className) {
|
|
31
|
+
const tokens = className.split(/\s+/).filter(Boolean);
|
|
32
|
+
return tokens.map((token) => {
|
|
33
|
+
const parsed = parseMotionClasses(token);
|
|
34
|
+
return {
|
|
35
|
+
token,
|
|
36
|
+
recognized: parsed.hasMotion || !token.startsWith("animate-"),
|
|
37
|
+
motion: parsed.hasMotion ? parsed : void 0,
|
|
38
|
+
passthrough: parsed.tailwindClasses || void 0
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function optimizeClasses(className) {
|
|
43
|
+
const analysis = analyzeClassName(className);
|
|
44
|
+
return {
|
|
45
|
+
className: sortMotionClasses(className),
|
|
46
|
+
duplicates: analysis.duplicates,
|
|
47
|
+
unknown: analysis.unknown
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function generateExample(input) {
|
|
51
|
+
return generateMotionCode(input.tag ?? "div", input.className, {
|
|
52
|
+
text: input.text,
|
|
53
|
+
target: input.target
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function syntaxManifest() {
|
|
57
|
+
return MOTIONWIND_SYNTAX_REGISTRY;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/index.ts
|
|
61
|
+
var server = new McpServer({ name: "motionwind", version: "2.0.0" });
|
|
62
|
+
var text = (value) => ({
|
|
63
|
+
content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
|
|
64
|
+
});
|
|
65
|
+
server.tool(
|
|
66
|
+
"validate_motionwind",
|
|
67
|
+
"Validate Motionwind classes and return diagnostics and parsed Motion output.",
|
|
68
|
+
{ className: z.string() },
|
|
69
|
+
async ({ className }) => text(validateClasses(className))
|
|
70
|
+
);
|
|
71
|
+
server.tool(
|
|
72
|
+
"explain_motionwind",
|
|
73
|
+
"Explain each Motionwind token without changing source code.",
|
|
74
|
+
{ className: z.string() },
|
|
75
|
+
async ({ className }) => text(explainClasses(className))
|
|
76
|
+
);
|
|
77
|
+
server.tool(
|
|
78
|
+
"optimize_motionwind",
|
|
79
|
+
"Canonically sort Motionwind classes and report duplicates or unknown tokens.",
|
|
80
|
+
{ className: z.string() },
|
|
81
|
+
async ({ className }) => text(optimizeClasses(className))
|
|
82
|
+
);
|
|
83
|
+
server.tool(
|
|
84
|
+
"generate_motionwind",
|
|
85
|
+
"Generate framework code from Motionwind classes.",
|
|
86
|
+
{
|
|
87
|
+
className: z.string(),
|
|
88
|
+
tag: z.string().optional(),
|
|
89
|
+
text: z.string().optional(),
|
|
90
|
+
target: z.enum(["react", "vue", "javascript", "react-native"]).optional()
|
|
91
|
+
},
|
|
92
|
+
async (input) => text({ code: generateExample(input) })
|
|
93
|
+
);
|
|
94
|
+
server.resource(
|
|
95
|
+
"motionwind-syntax",
|
|
96
|
+
new ResourceTemplate("motionwind://syntax", { list: void 0 }),
|
|
97
|
+
async (uri) => ({
|
|
98
|
+
contents: [
|
|
99
|
+
{
|
|
100
|
+
uri: uri.href,
|
|
101
|
+
mimeType: "application/json",
|
|
102
|
+
text: JSON.stringify(syntaxManifest())
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
var transport = new StdioServerTransport();
|
|
108
|
+
await server.connect(transport);
|
|
109
|
+
export {
|
|
110
|
+
explainClasses,
|
|
111
|
+
generateExample,
|
|
112
|
+
optimizeClasses,
|
|
113
|
+
syntaxManifest,
|
|
114
|
+
validateClasses
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/tools.ts"],"sourcesContent":["import {\n McpServer,\n ResourceTemplate,\n} from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport {\n explainClasses,\n generateExample,\n optimizeClasses,\n syntaxManifest,\n validateClasses,\n} from \"./tools.js\";\n\nexport {\n explainClasses,\n generateExample,\n optimizeClasses,\n syntaxManifest,\n validateClasses,\n} from \"./tools.js\";\n\nconst server = new McpServer({ name: \"motionwind\", version: \"2.0.0\" });\nconst text = (value: unknown) => ({\n content: [{ type: \"text\" as const, text: JSON.stringify(value, null, 2) }],\n});\n\nserver.tool(\n \"validate_motionwind\",\n \"Validate Motionwind classes and return diagnostics and parsed Motion output.\",\n { className: z.string() },\n async ({ className }) => text(validateClasses(className)),\n);\n\nserver.tool(\n \"explain_motionwind\",\n \"Explain each Motionwind token without changing source code.\",\n { className: z.string() },\n async ({ className }) => text(explainClasses(className)),\n);\n\nserver.tool(\n \"optimize_motionwind\",\n \"Canonically sort Motionwind classes and report duplicates or unknown tokens.\",\n { className: z.string() },\n async ({ className }) => text(optimizeClasses(className)),\n);\n\nserver.tool(\n \"generate_motionwind\",\n \"Generate framework code from Motionwind classes.\",\n {\n className: z.string(),\n tag: z.string().optional(),\n text: z.string().optional(),\n target: z.enum([\"react\", \"vue\", \"javascript\", \"react-native\"]).optional(),\n },\n async (input) => text({ code: generateExample(input) }),\n);\n\nserver.resource(\n \"motionwind-syntax\",\n new ResourceTemplate(\"motionwind://syntax\", { list: undefined }),\n async (uri) => ({\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(syntaxManifest()),\n },\n ],\n }),\n);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","import {\n MOTIONWIND_SYNTAX_REGISTRY,\n analyzeClassName,\n parseMotionClasses,\n sortMotionClasses,\n} from \"motionwind-core\";\nimport { generateMotionCode } from \"motionwind-react/tooling\";\n\nexport function validateClasses(className: string) {\n const parsed = parseMotionClasses(className);\n const analysis = analyzeClassName(className);\n return {\n valid: analysis.unknown.length === 0,\n unknown: analysis.unknown,\n duplicates: analysis.duplicates,\n diagnostics: parsed.diagnostics,\n parsed,\n };\n}\n\nexport function explainClasses(className: string) {\n const tokens = className.split(/\\s+/).filter(Boolean);\n return tokens.map((token) => {\n const parsed = parseMotionClasses(token);\n return {\n token,\n recognized: parsed.hasMotion || !token.startsWith(\"animate-\"),\n motion: parsed.hasMotion ? parsed : undefined,\n passthrough: parsed.tailwindClasses || undefined,\n };\n });\n}\n\nexport function optimizeClasses(className: string) {\n const analysis = analyzeClassName(className);\n return {\n className: sortMotionClasses(className),\n duplicates: analysis.duplicates,\n unknown: analysis.unknown,\n };\n}\n\nexport function generateExample(input: {\n className: string;\n tag?: string;\n text?: string;\n target?: \"react\" | \"vue\" | \"javascript\" | \"react-native\";\n}) {\n return generateMotionCode(input.tag ?? \"div\", input.className, {\n text: input.text,\n target: input.target,\n });\n}\n\nexport function syntaxManifest() {\n return MOTIONWIND_SYNTAX_REGISTRY;\n}\n"],"mappings":";;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,4BAA4B;AACrC,SAAS,SAAS;;;ACLlB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AAE5B,SAAS,gBAAgB,WAAmB;AACjD,QAAM,SAAS,mBAAmB,SAAS;AAC3C,QAAM,WAAW,iBAAiB,SAAS;AAC3C,SAAO;AAAA,IACL,OAAO,SAAS,QAAQ,WAAW;AAAA,IACnC,SAAS,SAAS;AAAA,IAClB,YAAY,SAAS;AAAA,IACrB,aAAa,OAAO;AAAA,IACpB;AAAA,EACF;AACF;AAEO,SAAS,eAAe,WAAmB;AAChD,QAAM,SAAS,UAAU,MAAM,KAAK,EAAE,OAAO,OAAO;AACpD,SAAO,OAAO,IAAI,CAAC,UAAU;AAC3B,UAAM,SAAS,mBAAmB,KAAK;AACvC,WAAO;AAAA,MACL;AAAA,MACA,YAAY,OAAO,aAAa,CAAC,MAAM,WAAW,UAAU;AAAA,MAC5D,QAAQ,OAAO,YAAY,SAAS;AAAA,MACpC,aAAa,OAAO,mBAAmB;AAAA,IACzC;AAAA,EACF,CAAC;AACH;AAEO,SAAS,gBAAgB,WAAmB;AACjD,QAAM,WAAW,iBAAiB,SAAS;AAC3C,SAAO;AAAA,IACL,WAAW,kBAAkB,SAAS;AAAA,IACtC,YAAY,SAAS;AAAA,IACrB,SAAS,SAAS;AAAA,EACpB;AACF;AAEO,SAAS,gBAAgB,OAK7B;AACD,SAAO,mBAAmB,MAAM,OAAO,OAAO,MAAM,WAAW;AAAA,IAC7D,MAAM,MAAM;AAAA,IACZ,QAAQ,MAAM;AAAA,EAChB,CAAC;AACH;AAEO,SAAS,iBAAiB;AAC/B,SAAO;AACT;;;ADlCA,IAAM,SAAS,IAAI,UAAU,EAAE,MAAM,cAAc,SAAS,QAAQ,CAAC;AACrE,IAAM,OAAO,CAAC,WAAoB;AAAA,EAChC,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,CAAC;AAC3E;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA,EAAE,WAAW,EAAE,OAAO,EAAE;AAAA,EACxB,OAAO,EAAE,UAAU,MAAM,KAAK,gBAAgB,SAAS,CAAC;AAC1D;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA,EAAE,WAAW,EAAE,OAAO,EAAE;AAAA,EACxB,OAAO,EAAE,UAAU,MAAM,KAAK,eAAe,SAAS,CAAC;AACzD;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA,EAAE,WAAW,EAAE,OAAO,EAAE;AAAA,EACxB,OAAO,EAAE,UAAU,MAAM,KAAK,gBAAgB,SAAS,CAAC;AAC1D;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,WAAW,EAAE,OAAO;AAAA,IACpB,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,IACzB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,OAAO,cAAc,cAAc,CAAC,EAAE,SAAS;AAAA,EAC1E;AAAA,EACA,OAAO,UAAU,KAAK,EAAE,MAAM,gBAAgB,KAAK,EAAE,CAAC;AACxD;AAEA,OAAO;AAAA,EACL;AAAA,EACA,IAAI,iBAAiB,uBAAuB,EAAE,MAAM,OAAU,CAAC;AAAA,EAC/D,OAAO,SAAS;AAAA,IACd,UAAU;AAAA,MACR;AAAA,QACE,KAAK,IAAI;AAAA,QACT,UAAU;AAAA,QACV,MAAM,KAAK,UAAU,eAAe,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,YAAY,IAAI,qBAAqB;AAC3C,MAAM,OAAO,QAAQ,SAAS;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "motionwind-mcp",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "MCP tools for generating, validating, explaining, and optimizing Motionwind classes.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"motionwind-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"lint": "eslint --max-warnings 0",
|
|
27
|
+
"check-types": "tsc --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
31
|
+
"motionwind-core": "^2.1.0",
|
|
32
|
+
"motionwind-react": "^2.1.0",
|
|
33
|
+
"zod": "^4.3.6"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@repo/eslint-config": "*",
|
|
37
|
+
"@repo/typescript-config": "*",
|
|
38
|
+
"@types/node": "^22.0.0",
|
|
39
|
+
"eslint": "^9.39.1",
|
|
40
|
+
"tsup": "^8.5.0",
|
|
41
|
+
"typescript": "5.9.2",
|
|
42
|
+
"vitest": "^3.2.1"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
47
|
+
}
|