viora-ui-mcp 1.0.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/dist/index.js ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ const REGISTRY_BASE_URL = "https://vioraui.dedyn.io/registry";
6
+ const server = new Server({
7
+ name: "viora-ui-mcp",
8
+ version: "1.0.0",
9
+ }, {
10
+ capabilities: {
11
+ tools: {},
12
+ },
13
+ });
14
+ // Define the tools
15
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
16
+ return {
17
+ tools: [
18
+ {
19
+ name: "list_viora_components",
20
+ description: "Lists all available Viora UI components from the official registry.",
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {},
24
+ },
25
+ },
26
+ {
27
+ name: "get_viora_component_code",
28
+ description: "Gets the full raw source code and dependencies for a specific Viora UI component.",
29
+ inputSchema: {
30
+ type: "object",
31
+ properties: {
32
+ componentName: {
33
+ type: "string",
34
+ description: "The name of the component (e.g. 'carousel-002', 'accordion').",
35
+ },
36
+ },
37
+ required: ["componentName"],
38
+ },
39
+ },
40
+ ],
41
+ };
42
+ });
43
+ // Handle tool execution
44
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
45
+ if (request.params.name === "list_viora_components") {
46
+ try {
47
+ const res = await fetch(`${REGISTRY_BASE_URL}/index.json`);
48
+ if (!res.ok)
49
+ throw new Error(`Failed to fetch index: ${res.statusText}`);
50
+ const components = await res.json();
51
+ // Just extract names and descriptions/types for brevity
52
+ const summary = components.map((c) => ({
53
+ name: c.name,
54
+ type: c.type,
55
+ dependencies: c.dependencies || []
56
+ }));
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: JSON.stringify(summary, null, 2),
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ catch (e) {
67
+ return {
68
+ isError: true,
69
+ content: [{ type: "text", text: `Failed to fetch registry: ${e.message}` }],
70
+ };
71
+ }
72
+ }
73
+ if (request.params.name === "get_viora_component_code") {
74
+ const componentName = request.params.arguments?.componentName;
75
+ try {
76
+ const res = await fetch(`${REGISTRY_BASE_URL}/${componentName}.json`);
77
+ if (res.status === 404) {
78
+ return {
79
+ isError: true,
80
+ content: [{ type: "text", text: `Component '${componentName}' not found.` }],
81
+ };
82
+ }
83
+ if (!res.ok)
84
+ throw new Error(`Failed to fetch component: ${res.statusText}`);
85
+ const componentData = await res.json();
86
+ // Format the output nicely for an AI agent to consume
87
+ let outputText = `Component: ${componentData.name}\nType: ${componentData.type}\n`;
88
+ if (componentData.dependencies && componentData.dependencies.length > 0) {
89
+ outputText += `Dependencies: ${componentData.dependencies.join(", ")}\n`;
90
+ }
91
+ outputText += `\n--- FILES ---\n\n`;
92
+ for (const file of componentData.files) {
93
+ outputText += `File: ${file.path || file.name || 'unknown'}\n`;
94
+ outputText += `Target: ${file.target || 'unknown'}\n`;
95
+ outputText += `\`\`\`tsx\n${file.content}\n\`\`\`\n\n`;
96
+ }
97
+ return {
98
+ content: [
99
+ {
100
+ type: "text",
101
+ text: outputText,
102
+ },
103
+ ],
104
+ };
105
+ }
106
+ catch (e) {
107
+ return {
108
+ isError: true,
109
+ content: [{ type: "text", text: `Failed to get component code: ${e.message}` }],
110
+ };
111
+ }
112
+ }
113
+ throw new Error(`Tool not found: ${request.params.name}`);
114
+ });
115
+ async function run() {
116
+ const transport = new StdioServerTransport();
117
+ await server.connect(transport);
118
+ console.error("Viora UI MCP Server running on stdio");
119
+ }
120
+ run().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "viora-ui-mcp",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "build": "tsc"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "type": "module",
14
+ "dependencies": {
15
+ "@modelcontextprotocol/sdk": "^1.30.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^26.5.1",
19
+ "typescript": "^7.0.2"
20
+ },
21
+ "bin": {
22
+ "viora-ui-mcp": "./dist/index.js",
23
+ "mcp-server": "./dist/index.js"
24
+ }
25
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":""}
package/src/index.js ADDED
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
7
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
8
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ // The path to the UI library root, passed as an argument or relative to this script
12
+ const UI_LIB_PATH = process.argv[2] || path_1.default.join(__dirname, "../../");
13
+ const REGISTRY_PATH = path_1.default.join(UI_LIB_PATH, "registry", "registry-components.ts");
14
+ const server = new index_js_1.Server({
15
+ name: "viora-ui-mcp",
16
+ version: "1.0.0",
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ // Define the tools
23
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
24
+ return {
25
+ tools: [
26
+ {
27
+ name: "list_viora_components",
28
+ description: "Lists all available Viora UI components by parsing the registry.",
29
+ inputSchema: {
30
+ type: "object",
31
+ properties: {},
32
+ },
33
+ },
34
+ {
35
+ name: "get_viora_component_code",
36
+ description: "Gets the full raw source code for a specific Viora UI component.",
37
+ inputSchema: {
38
+ type: "object",
39
+ properties: {
40
+ componentName: {
41
+ type: "string",
42
+ description: "The name of the component (e.g. 'carousel-002', 'sticky-card').",
43
+ },
44
+ },
45
+ required: ["componentName"],
46
+ },
47
+ },
48
+ ],
49
+ };
50
+ });
51
+ // Handle tool execution
52
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
53
+ if (request.params.name === "list_viora_components") {
54
+ try {
55
+ const registryContent = fs_1.default.readFileSync(REGISTRY_PATH, "utf-8");
56
+ // Extremely simple regex to extract component names
57
+ const nameRegex = /name:\s*"([^"]+)"/g;
58
+ const components = [];
59
+ let match;
60
+ while ((match = nameRegex.exec(registryContent)) !== null) {
61
+ components.push(match[1]);
62
+ }
63
+ return {
64
+ content: [
65
+ {
66
+ type: "text",
67
+ text: JSON.stringify([...new Set(components)], null, 2),
68
+ },
69
+ ],
70
+ };
71
+ }
72
+ catch (e) {
73
+ return {
74
+ isError: true,
75
+ content: [{ type: "text", text: `Failed to read registry: ${e.message}` }],
76
+ };
77
+ }
78
+ }
79
+ if (request.params.name === "get_viora_component_code") {
80
+ const componentName = request.params.arguments?.componentName;
81
+ try {
82
+ const registryContent = fs_1.default.readFileSync(REGISTRY_PATH, "utf-8");
83
+ // Find the component block
84
+ const componentIndex = registryContent.indexOf(`name: "${componentName}"`);
85
+ if (componentIndex === -1) {
86
+ return {
87
+ isError: true,
88
+ content: [{ type: "text", text: `Component '${componentName}' not found in registry.` }],
89
+ };
90
+ }
91
+ // Extract the path
92
+ const pathRegex = /path:\s*"([^"]+)"/g;
93
+ pathRegex.lastIndex = componentIndex;
94
+ const match = pathRegex.exec(registryContent);
95
+ if (!match) {
96
+ return {
97
+ isError: true,
98
+ content: [{ type: "text", text: `Could not find file path for component '${componentName}'.` }],
99
+ };
100
+ }
101
+ const componentPath = path_1.default.join(UI_LIB_PATH, match[1]);
102
+ const componentCode = fs_1.default.readFileSync(componentPath, "utf-8");
103
+ return {
104
+ content: [
105
+ {
106
+ type: "text",
107
+ text: componentCode,
108
+ },
109
+ ],
110
+ };
111
+ }
112
+ catch (e) {
113
+ return {
114
+ isError: true,
115
+ content: [{ type: "text", text: `Failed to get component code: ${e.message}` }],
116
+ };
117
+ }
118
+ }
119
+ throw new Error(`Tool not found: ${request.params.name}`);
120
+ });
121
+ async function run() {
122
+ const transport = new stdio_js_1.StdioServerTransport();
123
+ await server.connect(transport);
124
+ console.error("Viora UI MCP Server running on stdio");
125
+ }
126
+ run().catch(console.error);
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
package/src/index.ts ADDED
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema,
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+
9
+ const REGISTRY_BASE_URL = "https://vioraui.dedyn.io/registry";
10
+
11
+ const server = new Server(
12
+ {
13
+ name: "viora-ui-mcp",
14
+ version: "1.0.0",
15
+ },
16
+ {
17
+ capabilities: {
18
+ tools: {},
19
+ },
20
+ }
21
+ );
22
+
23
+ // Define the tools
24
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
25
+ return {
26
+ tools: [
27
+ {
28
+ name: "list_viora_components",
29
+ description: "Lists all available Viora UI components from the official registry.",
30
+ inputSchema: {
31
+ type: "object",
32
+ properties: {},
33
+ },
34
+ },
35
+ {
36
+ name: "get_viora_component_code",
37
+ description: "Gets the full raw source code and dependencies for a specific Viora UI component.",
38
+ inputSchema: {
39
+ type: "object",
40
+ properties: {
41
+ componentName: {
42
+ type: "string",
43
+ description: "The name of the component (e.g. 'carousel-002', 'accordion').",
44
+ },
45
+ },
46
+ required: ["componentName"],
47
+ },
48
+ },
49
+ ],
50
+ };
51
+ });
52
+
53
+ // Handle tool execution
54
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
55
+ if (request.params.name === "list_viora_components") {
56
+ try {
57
+ const res = await fetch(`${REGISTRY_BASE_URL}/index.json`);
58
+ if (!res.ok) throw new Error(`Failed to fetch index: ${res.statusText}`);
59
+
60
+ const components = await res.json();
61
+
62
+ // Just extract names and descriptions/types for brevity
63
+ const summary = components.map((c: any) => ({
64
+ name: c.name,
65
+ type: c.type,
66
+ dependencies: c.dependencies || []
67
+ }));
68
+
69
+ return {
70
+ content: [
71
+ {
72
+ type: "text",
73
+ text: JSON.stringify(summary, null, 2),
74
+ },
75
+ ],
76
+ };
77
+ } catch (e: any) {
78
+ return {
79
+ isError: true,
80
+ content: [{ type: "text", text: `Failed to fetch registry: ${e.message}` }],
81
+ };
82
+ }
83
+ }
84
+
85
+ if (request.params.name === "get_viora_component_code") {
86
+ const componentName = request.params.arguments?.componentName as string;
87
+
88
+ try {
89
+ const res = await fetch(`${REGISTRY_BASE_URL}/${componentName}.json`);
90
+ if (res.status === 404) {
91
+ return {
92
+ isError: true,
93
+ content: [{ type: "text", text: `Component '${componentName}' not found.` }],
94
+ };
95
+ }
96
+ if (!res.ok) throw new Error(`Failed to fetch component: ${res.statusText}`);
97
+
98
+ const componentData = await res.json();
99
+
100
+ // Format the output nicely for an AI agent to consume
101
+ let outputText = `Component: ${componentData.name}\nType: ${componentData.type}\n`;
102
+ if (componentData.dependencies && componentData.dependencies.length > 0) {
103
+ outputText += `Dependencies: ${componentData.dependencies.join(", ")}\n`;
104
+ }
105
+
106
+ outputText += `\n--- FILES ---\n\n`;
107
+
108
+ for (const file of componentData.files) {
109
+ outputText += `File: ${file.path || file.name || 'unknown'}\n`;
110
+ outputText += `Target: ${file.target || 'unknown'}\n`;
111
+ outputText += `\`\`\`tsx\n${file.content}\n\`\`\`\n\n`;
112
+ }
113
+
114
+ return {
115
+ content: [
116
+ {
117
+ type: "text",
118
+ text: outputText,
119
+ },
120
+ ],
121
+ };
122
+ } catch (e: any) {
123
+ return {
124
+ isError: true,
125
+ content: [{ type: "text", text: `Failed to get component code: ${e.message}` }],
126
+ };
127
+ }
128
+ }
129
+
130
+ throw new Error(`Tool not found: ${request.params.name}`);
131
+ });
132
+
133
+ async function run() {
134
+ const transport = new StdioServerTransport();
135
+ await server.connect(transport);
136
+ console.error("Viora UI MCP Server running on stdio");
137
+ }
138
+
139
+ run().catch(console.error);
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "esModuleInterop": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "strict": true,
11
+ "skipLibCheck": true,
12
+ "types": ["node"]
13
+ },
14
+ "include": ["src/**/*"]
15
+ }