dag-mcp-service
v1.0.4
Published
DAG图组件助手 MCP 服务,用于自动生成和管理DAG图组件代码
Maintainers
Readme
DAG MCP Service 用户指南
📋 目录
🎯 项目简介
DAG MCP Service 是基于 Model Context Protocol (MCP) 的智能 DAG 图组件生成服务,专为 Dataphin 项目设计。它能够自动识别用户输入中的 DAG 图创建意图,并生成符合项目规范的 OneGraphDag 组件代码。
核心优势
- 🤖 智能识别: 基于正则表达式的智能触发机制
- 📦 开箱即用: 预配置多种常用场景模板
- 🎨 高度可定制: 支持自定义节点、样式和布局
- ⚡ 高性能: 优化的代码生成和渲染性能
- 📖 完整文档: 详细的API文档和使用示例
技术栈
- 前端框架: React + TypeScript
- 状态管理: Raft (全局可用)
- 样式方案: Tailwind CSS + SCSS
- 组件库: DPAntd (定制化 Ant Design)
- 协议: Model Context Protocol (MCP)
🚀 快速开始
环境要求
Node.js >= 18.0.0
npm >= 8.0.0
TypeScript >= 5.0.0安装与运行
# 1. 安装依赖
npm install
# 2. 构建项目
npm run build
# 3. 启动服务
npm start
# 4. 开发模式
npm run devMCP 配置
在 .mcprc.json 中配置服务:
{
"mcpServers": {
"dag-service": {
"command": "node",
"args": ["dist/index.js"],
"env": {}
}
}
}⭐ 核心功能
1. 智能触发检测
自动识别以下关键词模式:
- 创建/添加/显示/生成 + DAG图/流程图/依赖图
- 节点关系图、依赖关系、血缘图、数据血缘
- 工作流、流程设计、任务流程等
2. 代码自动生成
- 生成完整的 React 组件代码
- 包含必要的导入语句和类型定义
- 符合 Dataphin 项目代码规范
- 支持 TypeScript 类型安全
3. 自定义配置
- 节点类型和样式自定义
- 布局方向控制 (水平/垂直)
- 连线类型选择 (曲线/折线/直线)
- 工具栏和交互功能配置
🔧 API 接口
check_dag_trigger
检测输入文本是否包含 DAG 图创建意图
参数:
{
text: string // 待检测的文本内容
}返回:
{
matched: boolean,
rule?: DagRule
}示例:
// 输入
{ "text": "创建一个DAG图显示数据血缘关系" }
// 输出
{ "matched": true, "rule": { "name": "dag_mcp_trigger", ... } }generate_dag_component
生成标准的 DAG 图组件代码
参数:
{
ruleName?: string // 可选:指定使用的规则名称
}返回:
string // 完整的 React 组件代码generate_custom_dag_component
根据自定义配置生成 DAG 图组件代码
参数:
{
nodes: Array<{
id: string,
name: string,
type?: string
}>,
relations: Array<{
sourceId: string,
targetId: string,
label?: string
}>,
direction?: "HORIZONTAL" | "VERTICAL",
linkType?: "Normal" | "Broken" ,
showToolbar?: boolean,
autoCenter?: boolean,
customNodeStyle?: string
}返回:
string // 自定义配置的 React 组件代码get_component_info
获取组件详细信息
参数:
{
componentName: string // 组件名称
}get_best_practices
获取最佳实践建议
返回:
string[] // 最佳实践指南数组💡 使用示例
基础使用
import OneGraphDag from 'src/components/OneGraphDag';
import { Direction, LinkType } from 'src/components/OneGraphDag/define';
const graphData = [
{
id: 'node-1',
name: '数据源',
type: 'source',
downRelations: [
{ sourceId: 'node-1', targetId: 'node-2' }
],
upRelations: []
},
{
id: 'node-2',
name: '数据处理',
type: 'process',
downRelations: [],
upRelations: [
{ sourceId: 'node-1', targetId: 'node-2' }
]
}
];
const CustomNode = (node) => (
<div className="bg-white border rounded-lg p-8 shadow-sm">
<div className="text-black-85 font-medium">{node.name}</div>
<div className="text-black-45 text-sm">{node.type}</div>
</div>
);
<OneGraphDag
graphData={graphData}
customNodeDom={CustomNode}
direction={Direction.HORIZONTAL}
linkType={LinkType.Broken}
nodeWidth={200}
nodeHeight={38}
showToolbar={true}
autoCenter={true}
/>数据血缘图示例
const lineageData = [
{
id: 'source_table',
name: '用户行为表',
type: 'table',
database: 'user_db',
downRelations: [
{ sourceId: 'source_table', targetId: 'etl_job' }
],
upRelations: []
},
{
id: 'etl_job',
name: '数据清洗任务',
type: 'job',
downRelations: [
{ sourceId: 'etl_job', targetId: 'target_table' }
],
upRelations: [
{ sourceId: 'source_table', targetId: 'etl_job' }
]
},
{
id: 'target_table',
name: '用户画像表',
type: 'table',
database: 'analysis_db',
downRelations: [],
upRelations: [
{ sourceId: 'etl_job', targetId: 'target_table' }
]
}
];
const graphLegend = [
{ color: '#1890ff', text: '数据表', icon: 'table' },
{ color: '#52c41a', text: 'ETL任务', icon: 'sync' }
];
const LineageNode = (node) => (
<div className={`dag-node ${node.type} bg-white border-l-4 border-brand p-8`}>
<div className="text-black-85 font-medium">{node.name}</div>
{node.database && (
<div className="text-black-45 text-xs mt-4">{node.database}</div>
)}
</div>
);
<OneGraphDag
graphData={lineageData}
graphLegend={graphLegend}
customNodeDom={LineageNode}
direction={Direction.HORIZONTAL}
linkType={LinkType.Broken}
searchProps={{
searchAttrs: ['name', 'database'],
showSearchInput: true,
placeholder: '搜索表或任务...'
}}
/>工作流程图示例
const workflowData = [
{
id: 'review',
name: '代码审查',
type: 'review',
status: 'pending',
downRelations: [
{ sourceId: 'review', targetId: 'test' },
{ sourceId: 'review', targetId: 'build' }
],
upRelations: []
},
{
id: 'test',
name: '单元测试',
type: 'test',
status: 'running',
downRelations: [
{ sourceId: 'test', targetId: 'deploy' }
],
upRelations: [
{ sourceId: 'review', targetId: 'test' }
]
},
{
id: 'build',
name: '构建打包',
type: 'build',
status: 'success',
downRelations: [
{ sourceId: 'build', targetId: 'deploy' }
],
upRelations: [
{ sourceId: 'review', targetId: 'build' }
]
},
{
id: 'deploy',
name: '部署发布',
type: 'deploy',
status: 'waiting',
downRelations: [],
upRelations: [
{ sourceId: 'test', targetId: 'deploy' },
{ sourceId: 'build', targetId: 'deploy' }
]
}
];
const WorkflowNode = (node) => {
const statusColors = {
pending: 'border-warning bg-warning-background',
running: 'border-brand bg-brand-background',
success: 'border-success bg-success-background',
waiting: 'border-black-45 bg-white'
};
return (
<div className={`dag-node rounded-lg p-12 border-2 ${statusColors[node.status]}`}>
<div className="text-black-85 font-medium mb-4">{node.name}</div>
<div className="text-xs text-black-65">状态: {node.status}</div>
</div>
);
};
<OneGraphDag
graphData={workflowData}
customNodeDom={WorkflowNode}
direction={Direction.VERTICAL}
linkType={LinkType.Normal}
layoutConfig={{
nodeAndNodeSpace: 80,
levelSpace: 120
}}
/>🎯 最佳实践
布局设计
水平布局 (HORIZONTAL)
- ✅ 推荐:使用
LinkType.Broken智能折线 - ✅ 适用:数据血缘图、工作流程、时间序列
- ✅ 优势:清晰的从左到右逻辑流向
垂直布局 (VERTICAL)
- ✅ 推荐:使用
LinkType.Normal平滑曲线 - ✅ 适用:组织架构图、依赖层次图
- ✅ 优势:符合自顶向下阅读习惯
样式规范
// ✅ 正确的颜色使用
<div className="bg-brand text-white border-brand-hover">
// ✅ 正确的间距使用
<div className="p-8 m-12 gap-16">
// ✅ 正确的自定义节点
const CustomNode = (node) => (
<div
className="bg-white border rounded-lg p-8"
style={{ height: '38px' }} // 必须与 nodeHeight 一致
>
{node.name}
</div>
);性能优化
// 1. 大图数据优化
<OneGraphDag
graphData={graphData}
hideLinksIds={['heavy-node-1', 'heavy-node-2']} // 隐藏部分连线
layoutConfig={{
useSimplePos: true // 使用简单定位
}}
/>
// 2. 内存管理
const resetStatus = useCallback(() => {
// 清理状态逻辑
}, []);
<OneGraphDag
resetStatus={resetStatus}
// ... 其他属性
/>代码组织
/**
* @description DAG图组件 - 数据血缘展示
* @author 景媛
*/
// 1. 类型定义放在单独文件
// types/dag-types.ts
export interface LineageNode {
id: string;
name: string;
type: 'table' | 'job' | 'view';
database?: string;
}
// 2. 工具方法放在单独文件
// utils/dag-utils.ts
export const buildGraphData = (nodes: LineageNode[]) => {
// 构建图数据逻辑
};
// 3. 主组件文件
import { LineageNode } from './types/dag-types';
import { buildGraphData } from './utils/dag-utils';
const DataLineageComponent = () => {
// 组件逻辑
};⚙️ 配置说明
OneGraphDag 组件属性
| 属性名 | 类型 | 必需 | 默认值 | 说明 |
|--------|------|------|--------|------|
| graphData | GraphData[] | ✅ | - | 图数据数组 |
| customNodeDom | function | ✅ | - | 自定义节点渲染函数 |
| direction | Direction | ✅ | VERTICAL | 布局方向 |
| linkType | LinkType | ✅ | NORMAL | 连线类型 |
| nodeWidth | number | ✅ | 200 | 节点宽度 |
| nodeHeight | number | ✅ | 38 | 节点高度 |
| showToolbar | boolean | ✅ | true | 显示工具栏 |
| autoCenter | boolean | ✅ | true | 自动居中 |
| needArrow | boolean | ✅ | true | 连线箭头 |
| graphLegend | array | ❌ | - | 图例配置 |
| searchProps | object | ❌ | - | 搜索配置 |
| layoutConfig | object | ❌ | - | 布局配置 |
布局配置详解
const layoutConfig = {
nodeAndNodeSpace: 50, // 节点间距
paddingLineSpace: 150, // 边距线间距
levelSpace: 150, // 层级间距
sortable: false, // 是否可排序
hasCrossScene: false, // 是否有跨场景
useSimplePos: false, // 是否使用简单位置
margin: { // 边距配置
left: 50,
right: 50,
top: 50,
bottom: 50
}
};搜索配置详解
const searchProps = {
searchAttrs: ['name', 'type', 'database'], // 搜索属性
showSearchInput: true, // 显示搜索框
placeholder: '搜索节点...', // 占位符
onSearchNodeChange: (nodeId: string) => { // 搜索变化回调
console.log('Selected node:', nodeId);
}
};❓ 常见问题
Q1: 节点样式不一致怎么办?
A: 确保自定义节点高度与 nodeHeight 一致:
// ❌ 错误
const CustomNode = (node) => (
<div className="p-12">{node.name}</div> // 高度不确定
);
// ✅ 正确
const CustomNode = (node) => (
<div
className="p-8"
style={{ height: '38px', overflow: 'hidden' }}
>
{node.name}
</div>
);Q2: 大数据量性能问题如何解决?
A: 使用以下优化策略:
// 1. 隐藏部分连线
hideLinksIds={heavyNodeIds}
// 2. 使用简单定位
layoutConfig={{ useSimplePos: true }}
// 3. 禁用自动居中
autoCenter={false}
// 4. 分页加载数据
const [visibleNodes, setVisibleNodes] = useState(initialNodes);Q3: 如何处理复杂的节点关系?
A: 正确构建上下游关系:
const buildRelations = (nodes, edges) => {
const nodeMap = new Map();
// 初始化节点
nodes.forEach(node => {
nodeMap.set(node.id, {
...node,
downRelations: [],
upRelations: []
});
});
// 添加关系
edges.forEach(edge => {
const sourceNode = nodeMap.get(edge.sourceId);
const targetNode = nodeMap.get(edge.targetId);
if (sourceNode && targetNode) {
sourceNode.downRelations.push(edge);
targetNode.upRelations.push(edge);
}
});
return Array.from(nodeMap.values());
};Q4: 如何实现节点点击交互?
A: 在自定义节点中添加事件处理:
const InteractiveNode = (node) => {
const handleClick = () => {
// 处理点击事件
console.log('Node clicked:', node.id);
};
return (
<div
className="cursor-pointer hover:bg-brand-hover transition-colors"
onClick={handleClick}
style={{ height: '38px' }}
>
{node.name}
</div>
);
};📋 更新日志
v1.0.2 (2024-01-15)
- 🆕 新增自定义节点样式支持
- 🛠️ 优化大数据量渲染性能
- 🐛 修复连线重叠问题
- 📖 完善文档和示例
v1.0.1 (2024-01-10)
- 🆕 新增搜索功能
- 🆕 新增图例配置
- 🛠️ 优化布局算法
- 🐛 修复内存泄漏问题
v1.0.0 (2024-01-01)
- 🎉 首次发布
- ✨ 基础DAG图功能
- ✨ MCP协议支持
- ✨ 代码自动生成
📞 支持与反馈
如果您在使用过程中遇到问题或有改进建议:
- 📧 提交 Issue: GitHub Issues
- 💬 参与讨论: GitHub Discussions
- 🔧 贡献代码: Fork 项目并提交 Pull Request
