Commit 20616460 authored by Pham Tuan's avatar Pham Tuan

Merge branch 'main' into 'master'

Main

See merge request !1
parents 8811dfa1 2d596cd4
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
tsconfig.tsbuildinfo
node_modules
dist-ssr
# testing
coverage/*
*.local
# Editor directories and files
# .vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# production
/build
/lib
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/.idea
/tsconfig.tsbuildinfo
tsconfig.tsbuildinfo
public/_framework
\ No newline at end of file
export declare const cache: Map<string, any>;
export declare function getCache<T>(key: string): T | undefined;
export declare function setCache(key: string, value: any): void;
export const cache = new Map();
export function getCache(key) {
return cache.get(key);
}
export function setCache(key, value) {
cache.set(key, value);
}
export interface ProjectContext {
framework: "react";
language: "ts" | "js";
}
export declare function inferProjectContext(): ProjectContext;
export function inferProjectContext() {
return {
framework: "react",
language: "ts",
};
}
export interface UILibraryContext {
packageName: string;
packageRoot: string;
}
export declare function loadUILibraryContext(packageName: string): UILibraryContext;
import path from "path";
export function loadUILibraryContext(packageName) {
const pkgJsonPath = require.resolve(`${packageName}/package.json`);
const packageRoot = path.dirname(pkgJsonPath);
return {
packageName,
packageRoot,
};
}
import { UIIntent } from "./intent.core.js";
export declare function generateReactCode(intent: UIIntent): string;
export function generateReactCode(intent) {
return `import { ${intent.components.join(", ")} } from 'awing-library'
export default function GeneratedUI() {
return (
<div>
${intent.components.map((c) => `<${c} />`).join("\n ")}
</div>
)
}`;
}
import { UILibraryContext } from "../context/ui-library.context.js";
export interface UIComponentMeta {
name: string;
importPath: string;
}
export declare function analyzeDesignSystem(ctx: UILibraryContext): UIComponentMeta[];
import fs from "fs";
import path from "path";
export function analyzeDesignSystem(ctx) {
const indexPath = path.join(ctx.packageRoot, "index.ts");
if (!fs.existsSync(indexPath))
return [];
const content = fs.readFileSync(indexPath, "utf-8");
const exports = [...content.matchAll(/export \{ (\w+)/g)];
return exports.map((m) => ({
name: m[1],
importPath: ctx.packageName,
}));
}
export interface UIIntent {
description: string;
components: string[];
}
export declare function parseUIIntent(prompt: string): UIIntent;
export function parseUIIntent(prompt) {
const components = [];
if (prompt.toLowerCase().includes("button"))
components.push("Button");
if (prompt.toLowerCase().includes("modal"))
components.push("Modal");
return {
description: prompt,
components,
};
}
export declare function analyzeStorybookUsage(component: string): {
component: string;
usage: string;
};
export function analyzeStorybookUsage(component) {
return {
component,
usage: `<${component} />`,
};
}
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { tools, executeTool } from './tools/index.js';
// Create MCP server
const server = new Server({
name: 'ui-platform-mcp',
version: '1.0.0'
}, {
capabilities: {
tools: {}
}
});
// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: tools
};
});
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
const result = await executeTool(name, args);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [
{
type: 'text',
text: `Error: ${errorMessage}`
}
],
isError: true
};
}
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('UI Platform MCP Server running on stdio');
}
main().catch((error) => {
console.error('Server error:', error);
process.exit(1);
});
export declare const analyzeDesignSystemTool: {
name: string;
description: string;
run(): import("../core/design-system.core.js").UIComponentMeta[];
};
import { analyzeDesignSystem } from "../core/design-system.core.js";
import { loadUILibraryContext } from "../context/ui-library.context.js";
export const analyzeDesignSystemTool = {
name: "design_system_analyze",
description: "Analyze UI design system components",
run() {
const ctx = loadUILibraryContext("awing-library");
return analyzeDesignSystem(ctx);
},
};
export declare const analyzeStorybookTool: {
name: string;
run(input: {
component: string;
}): {
component: string;
usage: string;
};
};
import { analyzeStorybookUsage } from "../core/storybook.core.js";
export const analyzeStorybookTool = {
name: "storybook_analyze",
run(input) {
return analyzeStorybookUsage(input.component);
},
};
export declare const generateUICodeTool: {
name: string;
run(input: any): string;
};
import { generateReactCode } from "../core/codegen.core.js";
export const generateUICodeTool = {
name: "ui_codegen_generate",
run(input) {
return generateReactCode(input);
},
};
import { Tool } from '@modelcontextprotocol/sdk/types.js';
export declare const tools: Tool[];
export declare function executeTool(toolName: string, args: Record<string, unknown>): Promise<unknown>;
import { analyzeDesignSystem } from '../core/design-system.core.js';
import { analyzeStorybookUsage } from '../core/storybook.core.js';
import { parseUIIntent } from '../core/intent.core.js';
import { inferProjectContext } from '../context/project.context.js';
import { generateReactCode } from '../core/codegen.core.js';
import { loadUILibraryContext } from '../context/ui-library.context.js';
// Tool definitions theo chuẩn MCP
export const tools = [
{
name: 'analyze_design_system',
description: 'Phân tích các components trong design system của dự án',
inputSchema: {
type: 'object',
properties: {
libraryName: {
type: 'string',
description: 'Tên của UI library cần phân tích (mặc định: awing-library)'
}
}
}
},
{
name: 'analyze_storybook',
description: 'Phân tích usage của một component trong Storybook',
inputSchema: {
type: 'object',
properties: {
component: {
type: 'string',
description: 'Tên component cần phân tích'
}
},
required: ['component']
}
},
{
name: 'parse_ui_intent',
description: 'Phân tích ý định UI từ prompt của người dùng để xác định components cần dùng',
inputSchema: {
type: 'object',
properties: {
prompt: {
type: 'string',
description: 'Mô tả UI mà người dùng muốn tạo'
}
},
required: ['prompt']
}
},
{
name: 'get_project_context',
description: 'Lấy thông tin context của dự án hiện tại (framework, dependencies, structure)',
inputSchema: {
type: 'object',
properties: {}
}
},
{
name: 'generate_ui_code',
description: 'Generate React code dựa trên UI intent đã được parse',
inputSchema: {
type: 'object',
properties: {
description: {
type: 'string',
description: 'Mô tả UI'
},
components: {
type: 'array',
items: { type: 'string' },
description: 'Danh sách components cần sử dụng'
}
},
required: ['description', 'components']
}
}
];
// Execute tool function
export async function executeTool(toolName, args) {
switch (toolName) {
case 'analyze_design_system': {
const libraryName = args.libraryName || 'awing-library';
const ctx = loadUILibraryContext(libraryName);
return analyzeDesignSystem(ctx);
}
case 'analyze_storybook': {
const component = args.component;
return analyzeStorybookUsage(component);
}
case 'parse_ui_intent': {
const prompt = args.prompt;
return parseUIIntent(prompt);
}
case 'get_project_context': {
return inferProjectContext();
}
case 'generate_ui_code': {
const intent = {
description: args.description,
components: args.components
};
return generateReactCode(intent);
}
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
export declare const parseUIIntentTool: {
name: string;
run(input: {
prompt: string;
}): import("../core/intent.core.js").UIIntent;
};
import { parseUIIntent } from "../core/intent.core.js";
export const parseUIIntentTool = {
name: "ui_intent_parse",
run(input) {
return parseUIIntent(input.prompt);
},
};
export declare const projectContextTool: {
name: string;
run(): import("../context/project.context.js").ProjectContext;
};
import { inferProjectContext } from "../context/project.context.js";
export const projectContextTool = {
name: "project_context",
run() {
return inferProjectContext();
},
};
This diff is collapsed.
{
"name": "ui-platform-mcp",
"version": "1.0.0",
"type": "module",
"description": "MCP Server for UI Platform",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx src/index.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0"
},
"devDependencies": {
"@types/node": "^22.0.0",
"tsx": "^4.0.0",
"typescript": "^5.6.0"
}
}
\ No newline at end of file
export const cache = new Map<string, any>();
export function getCache<T>(key: string): T | undefined {
return cache.get(key);
}
export function setCache(key: string, value: any) {
cache.set(key, value);
}
export interface ProjectContext {
framework: "react";
language: "ts" | "js";
}
export function inferProjectContext(): ProjectContext {
return {
framework: "react",
language: "ts",
};
}
import fs from "fs";
import path from "path";
export interface UILibraryContext {
packageName: string;
packageRoot: string;
}
export function loadUILibraryContext(packageName: string): UILibraryContext {
const pkgJsonPath = require.resolve(`${packageName}/package.json`);
const packageRoot = path.dirname(pkgJsonPath);
return {
packageName,
packageRoot,
};
}
import { UIIntent } from "./intent.core.js";
export function generateReactCode(intent: UIIntent): string {
return `import { ${intent.components.join(", ")} } from 'awing-library'
export default function GeneratedUI() {
return (
<div>
${intent.components.map((c) => `<${c} />`).join("\n ")}
</div>
)
}`;
}
import fs from "fs";
import path from "path";
import { UILibraryContext } from "../context/ui-library.context.js";
export interface UIComponentMeta {
name: string;
importPath: string;
}
export function analyzeDesignSystem(ctx: UILibraryContext): UIComponentMeta[] {
const indexPath = path.join(ctx.packageRoot, "index.ts");
if (!fs.existsSync(indexPath)) return [];
const content = fs.readFileSync(indexPath, "utf-8");
const exports = [...content.matchAll(/export \{ (\w+)/g)];
return exports.map((m) => ({
name: m[1],
importPath: ctx.packageName,
}));
}
export interface UIIntent {
description: string;
components: string[];
}
export function parseUIIntent(prompt: string): UIIntent {
const components: string[] = [];
if (prompt.toLowerCase().includes("button")) components.push("Button");
if (prompt.toLowerCase().includes("modal")) components.push("Modal");
return {
description: prompt,
components,
};
}
export function analyzeStorybookUsage(component: string) {
return {
component,
usage: `<${component} />`,
};
}
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'
import { tools, executeTool } from './tools/index.js'
// Create MCP server
const server = new Server(
{
name: 'ui-platform-mcp',
version: '1.0.0'
},
{
capabilities: {
tools: {}
}
}
)
// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: tools
}
})
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params
try {
const result = await executeTool(name, args as Record<string, unknown>)
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error)
return {
content: [
{
type: 'text',
text: `Error: ${errorMessage}`
}
],
isError: true
}
}
})
// Start the server
async function main() {
const transport = new StdioServerTransport()
await server.connect(transport)
console.error('UI Platform MCP Server running on stdio')
}
main().catch((error) => {
console.error('Server error:', error)
process.exit(1)
})
import { analyzeDesignSystem } from "../core/design-system.core.js";
import { loadUILibraryContext } from "../context/ui-library.context.js";
export const analyzeDesignSystemTool = {
name: "design_system_analyze",
description: "Analyze UI design system components",
run() {
const ctx = loadUILibraryContext("awing-library");
return analyzeDesignSystem(ctx);
},
};
import { analyzeStorybookUsage } from "../core/storybook.core.js";
export const analyzeStorybookTool = {
name: "storybook_analyze",
run(input: { component: string }) {
return analyzeStorybookUsage(input.component);
},
};
import { generateReactCode } from "../core/codegen.core.js";
export const generateUICodeTool = {
name: "ui_codegen_generate",
run(input: any) {
return generateReactCode(input);
},
};
import { Tool } from '@modelcontextprotocol/sdk/types.js'
import { analyzeDesignSystem } from '../core/design-system.core.js'
import { analyzeStorybookUsage } from '../core/storybook.core.js'
import { parseUIIntent } from '../core/intent.core.js'
import { inferProjectContext } from '../context/project.context.js'
import { generateReactCode } from '../core/codegen.core.js'
import { loadUILibraryContext } from '../context/ui-library.context.js'
// Tool definitions theo chuẩn MCP
export const tools: Tool[] = [
{
name: 'analyze_design_system',
description: 'Phân tích các components trong design system của dự án',
inputSchema: {
type: 'object',
properties: {
libraryName: {
type: 'string',
description: 'Tên của UI library cần phân tích (mặc định: awing-library)'
}
}
}
},
{
name: 'analyze_storybook',
description: 'Phân tích usage của một component trong Storybook',
inputSchema: {
type: 'object',
properties: {
component: {
type: 'string',
description: 'Tên component cần phân tích'
}
},
required: ['component']
}
},
{
name: 'parse_ui_intent',
description: 'Phân tích ý định UI từ prompt của người dùng để xác định components cần dùng',
inputSchema: {
type: 'object',
properties: {
prompt: {
type: 'string',
description: 'Mô tả UI mà người dùng muốn tạo'
}
},
required: ['prompt']
}
},
{
name: 'get_project_context',
description: 'Lấy thông tin context của dự án hiện tại (framework, dependencies, structure)',
inputSchema: {
type: 'object',
properties: {}
}
},
{
name: 'generate_ui_code',
description: 'Generate React code dựa trên UI intent đã được parse',
inputSchema: {
type: 'object',
properties: {
description: {
type: 'string',
description: 'Mô tả UI'
},
components: {
type: 'array',
items: { type: 'string' },
description: 'Danh sách components cần sử dụng'
}
},
required: ['description', 'components']
}
}
]
// Execute tool function
export async function executeTool(
toolName: string,
args: Record<string, unknown>
): Promise<unknown> {
switch (toolName) {
case 'analyze_design_system': {
const libraryName = (args.libraryName as string) || 'awing-library'
const ctx = loadUILibraryContext(libraryName)
return analyzeDesignSystem(ctx)
}
case 'analyze_storybook': {
const component = args.component as string
return analyzeStorybookUsage(component)
}
case 'parse_ui_intent': {
const prompt = args.prompt as string
return parseUIIntent(prompt)
}
case 'get_project_context': {
return inferProjectContext()
}
case 'generate_ui_code': {
const intent = {
description: args.description as string,
components: args.components as string[]
}
return generateReactCode(intent)
}
default:
throw new Error(`Unknown tool: ${toolName}`)
}
}
import { parseUIIntent } from "../core/intent.core.js";
export const parseUIIntentTool = {
name: "ui_intent_parse",
run(input: { prompt: string }) {
return parseUIIntent(input.prompt);
},
};
import { inferProjectContext } from "../context/project.context.js";
export const projectContextTool = {
name: "project_context",
run() {
return inferProjectContext();
},
};
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}
\ No newline at end of file
{
"config": {
"designSystem": {
"packageName": "awing-library"
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment