npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dag-mcp-service

v1.0.4

Published

DAG图组件助手 MCP 服务,用于自动生成和管理DAG图组件代码

Readme

DAG MCP Service 用户指南

📋 目录

  1. 项目简介
  2. 快速开始
  3. 核心功能
  4. API 接口
  5. 使用示例
  6. 最佳实践
  7. 配置说明
  8. 常见问题
  9. 更新日志

🎯 项目简介

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 dev

MCP 配置

.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协议支持
  • ✨ 代码自动生成

📞 支持与反馈

如果您在使用过程中遇到问题或有改进建议: