Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/pkg-pr-new.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ on:
push:
branches: [main]
paths:
- 'packages/mcp-server/**'
- 'packages/site-components/**'
- 'packages/theme-generator/**'
pull_request:
branches: [main]
paths:
- 'packages/mcp-server/**'
- 'packages/site-components/**'
- 'packages/theme-generator/**'
- 'site/**'
Expand All @@ -30,7 +32,9 @@ jobs:

- run: pnpm --filter '@tdesign/site-components' --filter '@tdesign/theme-generator' run build

- run: pnpm dlx pkg-pr-new publish './packages/site-components' './packages/theme-generator'
- run: pnpm --filter tdesign-mcp-server run build:mcp

- run: pnpm dlx pkg-pr-new publish './packages/site-components' './packages/theme-generator' './packages/mcp-server'

build-tdesign-vue-site:
if: github.repository == 'Tencent/tdesign' && github.event_name == 'pull_request'
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ dist
results
static_site
lib
packages/mcp-server/docs

## test
coverage
coverage
packages/mcp-server/scripts/dom/snapshots/**/__snapshots__
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"site": "pnpm run build:components && pnpm run --filter tdesign-site build",
"site:preview": "pnpm run build:components && pnpm run --filter tdesign-site site:preview",
"auto-release-collection": "pnpm run --filter auto-release-collection start",
"prepare": "husky install"
"prepare": "husky install",
"build:mcp": "pnpm run --filter tdesign-mcp-server build:mcp",
"build:mcp-docs": "pnpm run --filter tdesign-mcp-server build:docs+dom",
"start:mcp": "pnpm run --filter tdesign-mcp-server start:mcp-http"
},
"license": "MIT",
"dependencies": {
Expand Down
6 changes: 6 additions & 0 deletions packages/mcp-server/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# =============================================
# 设为 local,从项目的 docs 文件夹读取
# 设为 online,从 CDN 上获取文档
# =============================================

DOCS_SOURCE_MODE = 'online'
8 changes: 8 additions & 0 deletions packages/mcp-server/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
root: true,
extends: ["plugin:@typescript-eslint/recommended"],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
ignorePatterns: ["dist", "node_modules"],
rules: {},
};
82 changes: 82 additions & 0 deletions packages/mcp-server/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# <img src="https://tdesign.tencent.com/favicon.ico" height="45"/> 开发指南

## 🏠 项目架构

```bash
# 在仓库根目录安装依赖
pnpm install

#(可选)更新文档
pnpm run --filter tdesign-mcp-server build:docs+dom
```

- 由于该项目在提取文档时,如果找不到本地仓库的话,会自动启动 clone 其它组件库的流程。
- 默认会在**当前 tdesign 仓库的同级目录**下查找/克隆各端框架仓库(如 `tdesign-react`)。
- 在 mono / 沙盒 / CI 环境中,可以通过环境变量 `TD_REPOS_ROOT` 显式指定一个目录用于存放这些仓库(例如工作区内的空目录);未设置时自动 clone 会先创建默认目录。

```bash
📄 .env # 环境变量(仅用于本地调试)
📁 packages/mcp-server
├── 📁 src # 核心业务逻辑
│ ├── 📁 tools
│ └── 📁 prompts
├── 📁 common # 通用工具函数(源码目录)
├── 📁 scripts # 自动化脚本(源码目录)
└── 📁 docs # 已整理的文档(脚本生成,不入库)
```

### ⚠️ Apple Silicon 环境说明

如果你使用 Apple Silicon(M系列)Mac,需要额外安装 Rosetta 才能运行小程序快照构建脚本(`build:snap:mini`)。

- 因为底层依赖的 `miniprogram-simulate` → `miniprogram-compiler` 仅提供了 `x86_64` 架构的二进制文件,需要进行转译。

```bash
softwareupdate --install-rosetta --agree-to-license
```

## 🕹️ 本地启动

| 环境变量 | 说明 | 可选值 | 默认值 |
|:---|:---|:---|:---|
| `DOCS_SOURCE_MODE` | 文档数据来源 | `online`(CDN)<br>`local`(docs 文件夹) | `online` |
| `TD_REPOS_ROOT` | tdesign 系列仓库(tdesign-react 等)的公共目录 | 任意绝对路径 | 当前 tdesign 仓库的同级目录 |

### Stdio

```bash
npm run build:mcp-stdio
```

```json
{
"mcpServers": {
"tdesign-mcp-server": {
"command": "node",
"args": ["your_path_to/tdesign/packages/mcp-server/dist/stdio.js"],
"env": {
"DOCS_SOURCE_MODE": "local"
}
}
}
}
```
### StreamableHttp

```bash
npm run build:mcp-http
npm run start:mcp-http
```

```json
{
"mcpServers": {
"tdesign-mcp-server": {
"url": "localhost:9000/mcp",
"env": {
"DOCS_SOURCE_MODE": "local"
}
}
}
}
```
35 changes: 35 additions & 0 deletions packages/mcp-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# <img src="https://tdesign.tencent.com/favicon.ico" height="45"/> TDesign MCP Server

## 🎉 功能介绍

### 🔨 支持框架
- 桌面端:`react` / `vue-next` / `vue`
- 移动端:`mobile-react` / `mobile-vue` / `miniprogram` / `uniapp`
- AI 对话:`react-chat` / `vue-next-chat` / `miniprogram-chat` / `uniapp-chat`

### 🔨 支持工具
- [x] `search-icon`:搜索可用的图标列表,适用场景:图标查找与名称确认
- [x] `get-component-docs`:获取组件的文档,适用场景:代码生成和代码转换
- [x] `get-component-dom`:获取组件的 DOM 结构,适用场景:转换自定义的 CSS 样式
- [x] `get-component-list`:获取所有可用的组件列表,适用场景:选择合适组件进行组合实现不存在的功能
- [x] `get-component-changelog`:获取组件的变更日志,适用场景:组件库版本升级

## 📦 使用说明
```json
{
"mcpServers": { // 或 servers(根据不同的 MCP 客户端决定)
"tdesign-mcp-server": {
"command": "npx",
"args": ["-y", "tdesign-mcp-server@latest"]
}
}
}
```

> 💡 如果在 MCP 客户端中连接失败,可以在终端手动输入 `npx tdesign-mcp-server`,并反馈对应的报错信息在 issue。

## 🔮 开发指南

![Node.js >=18](https://img.shields.io/badge/node-%3E%3D18-brightgree)

详见[文档](DEVELOPMENT.md)
18 changes: 18 additions & 0 deletions packages/mcp-server/common/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createRequire } from "module";
import path from "path";
import { getDirname } from "./toolkit";

const __dirname = getDirname(import.meta.url);

export const isProduction = process.env.NODE_ENV === "production";

if (!isProduction) {
// 避免打包时把 dotenv 也打入产物
const require = createRequire(import.meta.url); // 兼容 cjs
const dotenv = require("dotenv");
dotenv.config({ path: path.join(__dirname, "../../.env"), quiet: true });
}

export const DOCS_SOURCE_MODE = process.env.DOCS_SOURCE_MODE as "online" | "local";

export const isLocalMode = DOCS_SOURCE_MODE === "local";
50 changes: 50 additions & 0 deletions packages/mcp-server/common/framework.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export const addTdPrefix = (suffix: string) => `tdesign-${suffix}`;

export const PLATFORMS = {
web: "web",
mobile: "mobile"
} as const;
export type Platform = (typeof PLATFORMS)[keyof typeof PLATFORMS];

export const WEB_FRAMEWORKS = ["react", "react-chat", "vue", "vue-next", "vue-next-chat"] as const;

export const MOBILE_FRAMEWORKS = [
"mobile-react",
"mobile-vue",
"miniprogram",
"miniprogram-chat",
"uniapp",
"uniapp-chat"
] as const;

export const FRAMEWORKS = [...WEB_FRAMEWORKS, ...MOBILE_FRAMEWORKS] as const;
export type Framework = (typeof FRAMEWORKS)[number];

// wxss 内容置空,聚焦组件本身
export const MINIPROGRAM_DEMO_EXTS = [".wxml", ".js", ".json"] as const;

/* 组件库是否为大仓结构 */
const MONOREPO: Framework[] = ["react", "vue-next", "miniprogram"] as const;
export const isMonorepo = (fw: Framework) => MONOREPO.includes(fw);

export const isMiniProgram = (fw: Framework) => ["miniprogram", "miniprogram-chat"].includes(fw);

export const isUniapp = (fw: Framework) => ["uniapp", "uniapp-chat"].includes(fw);

export const isChatFramework = (fw: Framework) => fw.includes("chat") || fw === "uniapp-chat";

const SPECIAL_CHAT_COMPONENTS = ["attachments"];
export const isChatComponent = (name: string) => name.startsWith("chat-") || SPECIAL_CHAT_COMPONENTS.includes(name);

export const getSuffixByFramework = (fw: Framework) => (fw.includes("react") ? "tsx" : "vue");

/** uniapp 相关框架的源仓库映射 */
export const getUniappSourceFramework = (fw: Framework): Framework => (fw === "uniapp-chat" ? "uniapp" : "uniapp");

export const getPlatformByFramework = (fw: Framework): Platform => {
if ((MOBILE_FRAMEWORKS as readonly Framework[]).includes(fw)) {
return PLATFORMS.mobile;
}

return PLATFORMS.web;
};
4 changes: 4 additions & 0 deletions packages/mcp-server/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./framework";
export * from "./parser";
export * from "./toolkit";
export * from "./config";
Loading
Loading