This is page 1 of 5. Use http://codebase.md/ocean-zhc/dolphinscheduler-mcp?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .env.example ├── .gitignore ├── CHANGELOG.md ├── docker-compose.yml ├── Dockerfile ├── docs │ ├── api.md │ └── installation.md ├── ds-restfuleapi-v1.json ├── example_mcp.py ├── examples │ ├── list_projects.py │ ├── manage_resources.py │ ├── simple_client.py │ └── start_workflow.py ├── install_dev.sh ├── mcp-openapi-split │ ├── base │ │ └── 01_base.json │ ├── paths │ │ ├── 01_azure_datafactory_api.json │ │ ├── 02_dynamic_task_type_api.json │ │ ├── 03_kubernetes_namespace_api.json │ │ ├── 04_project_worker_group_api.json │ │ ├── 05_ui_plugin_api.json │ │ ├── 06_worker_group_api.json │ │ ├── 07_project_preference_api.json │ │ ├── 08_task_definition_api.json │ │ ├── 09_task_instance_api.json │ │ ├── 10_task_analysis_api.json │ │ ├── 11_task_group_api.json │ │ ├── 12_favourite_api.json │ │ ├── 13_alert_plugin_instance_api.json │ │ ├── 14_alert_group_api.json │ │ ├── 15_schedule_api.json │ │ ├── 16_audit_log_api.json │ │ ├── 17_process_task_relation_api.json │ │ ├── 18_workflow_lineage_api.json │ │ ├── 19_datasource_api.json │ │ ├── 20_data_quality_api.json │ │ ├── 21_log_api.json │ │ ├── 22_process_definition_api.json │ │ ├── 23_process_instance_api.json │ │ ├── 24_process_execution_api.json │ │ ├── 25_environment_api.json │ │ ├── 26_login_api.json │ │ ├── 27_user_api.json │ │ ├── 28_monitor_api.json │ │ ├── 29_tenant_api.json │ │ ├── 30_token_api.json │ │ ├── 31_resource_api.json │ │ ├── 32_queue_api.json │ │ ├── 33_cluster_api.json │ │ ├── 34_project_parameter_api.json │ │ └── 35_project_api.json │ ├── schemas │ │ ├── 01_alert_schemas.json │ │ ├── 02_cluster_schemas.json │ │ ├── 03_datasource_schemas.json │ │ ├── 04_environment_schemas.json │ │ ├── 05_k8s_schemas.json │ │ ├── 06_project_schemas.json │ │ ├── 07_queue_schemas.json │ │ ├── 08_remaining_1_schemas.json │ │ ├── 09_remaining_10_schemas.json │ │ ├── 10_remaining_11_schemas.json │ │ ├── 11_remaining_12_schemas.json │ │ ├── 12_remaining_13_schemas.json │ │ ├── 13_remaining_2_schemas.json │ │ ├── 14_remaining_3_schemas.json │ │ ├── 15_remaining_4_schemas.json │ │ ├── 16_remaining_5_schemas.json │ │ ├── 17_remaining_6_schemas.json │ │ ├── 18_remaining_7_schemas.json │ │ ├── 19_remaining_8_schemas.json │ │ ├── 20_remaining_9_schemas.json │ │ ├── 21_resource_schemas.json │ │ ├── 22_result_schemas.json │ │ ├── 23_schedule_schemas.json │ │ ├── 24_task_schemas.json │ │ ├── 25_tenant_schemas.json │ │ ├── 26_user_schemas.json │ │ ├── 27_worker_schemas.json │ │ └── 28_workflow_schemas.json │ └── utils │ ├── combine_openapi.py │ └── split_openapi.py ├── pyproject.toml ├── README.md ├── requirements-dev.txt ├── run.bat ├── run.py ├── run.sh ├── src │ ├── __init__.py │ └── dolphinscheduler_mcp │ ├── __init__.py │ ├── __main__.py │ ├── cli.py │ ├── client.py │ ├── config.py │ ├── fastmcp_compat.py │ ├── server.py │ ├── tools │ ├── tools_generated │ │ ├── __init__.py │ │ ├── access_token_tools.py │ │ ├── audit_log_tools.py │ │ ├── azure_data_factory_tools.py │ │ ├── datasource_tools.py │ │ ├── dynamic_task_type_tools.py │ │ ├── environment_check_tools.py │ │ ├── environment_update_tools.py │ │ ├── k8s_namespace_tools.py │ │ ├── lineage_tools.py │ │ ├── process_task_relation_tools.py │ │ ├── project_parameter_tools.py │ │ ├── project_preference_tools.py │ │ ├── project_tools.py │ │ ├── project_worker_group_tools.py │ │ ├── README.md │ │ ├── template_tools.py │ │ ├── ui_plugin_tools.py │ │ └── worker_group_tools.py │ ├── tools_loader.py │ └── tools.py.bak ├── test_create_project.py ├── test_env_settings.py └── tests ├── __init__.py └── test_config.py ``` # Files -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- ``` 1 | DOLPHINSCHEDULER_API_URL=http://localhost:12345/dolphinscheduler # Default DolphinScheduler REST API URL 2 | DOLPHINSCHEDULER_API_KEY=your_api_key # Optional: Default DolphinScheduler API key ``` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- ``` 1 | # Python 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.so 6 | .Python 7 | build/ 8 | develop-eggs/ 9 | dist/ 10 | downloads/ 11 | eggs/ 12 | .eggs/ 13 | lib/ 14 | lib64/ 15 | parts/ 16 | sdist/ 17 | var/ 18 | wheels/ 19 | *.egg-info/ 20 | .installed.cfg 21 | *.egg 22 | MANIFEST 23 | 24 | # Environment 25 | .env 26 | .venv 27 | env/ 28 | venv/ 29 | ENV/ 30 | env.bak/ 31 | venv.bak/ 32 | 33 | # IDE 34 | .idea/ 35 | .vscode/ 36 | *.swp 37 | *.swo 38 | .trae/ 39 | 40 | # OS 41 | .DS_Store 42 | Thumbs.db ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- ```markdown 1 | # DolphinScheduler MCP Server 2 | 3 | A Model Context Protocol (MCP) server for Apache DolphinScheduler, allowing AI agents to interact with DolphinScheduler through a standardized protocol. 4 | 5 | ## Overview 6 | 7 | DolphinScheduler MCP provides a FastMCP-based server that exposes DolphinScheduler's REST API as a collection of tools that can be used by AI agents. The server acts as a bridge between AI models and DolphinScheduler, enabling AI-driven workflow management. 8 | 9 | ## Features 10 | 11 | - Full API coverage of DolphinScheduler functionality 12 | - Standardized tool interfaces following the Model Context Protocol 13 | - Easy configuration through environment variables or command-line arguments 14 | - Comprehensive tool documentation 15 | 16 | ## Installation 17 | 18 | ```bash 19 | pip install dolphinscheduler-mcp 20 | ``` 21 | 22 | ## Configuration 23 | 24 | ### Environment Variables 25 | 26 | - `DOLPHINSCHEDULER_API_URL`: URL for the DolphinScheduler API (default: http://localhost:12345/dolphinscheduler) 27 | - `DOLPHINSCHEDULER_API_KEY`: API token for authentication with the DolphinScheduler API 28 | - `DOLPHINSCHEDULER_MCP_HOST`: Host to bind the MCP server (default: 0.0.0.0) 29 | - `DOLPHINSCHEDULER_MCP_PORT`: Port to bind the MCP server (default: 8089) 30 | - `DOLPHINSCHEDULER_MCP_LOG_LEVEL`: Logging level (default: INFO) 31 | 32 | ## Usage 33 | 34 | ### Command Line 35 | 36 | Start the server using the command-line interface: 37 | 38 | ```bash 39 | ds-mcp --host 0.0.0.0 --port 8089 40 | ``` 41 | 42 | ### Python API 43 | 44 | ```python 45 | from dolphinscheduler_mcp.server import run_server 46 | 47 | # Start the server 48 | run_server(host="0.0.0.0", port=8089) 49 | ``` 50 | 51 | ## Available Tools 52 | 53 | The DolphinScheduler MCP Server provides tools for: 54 | 55 | - Project Management 56 | - Process Definition Management 57 | - Process Instance Management 58 | - Task Definition Management 59 | - Scheduling Management 60 | - Resource Management 61 | - Data Source Management 62 | - Alert Group Management 63 | - Alert Plugin Management 64 | - Worker Group Management 65 | - Tenant Management 66 | - User Management 67 | - System Status Monitoring 68 | 69 | ## Example Client Usage 70 | 71 | ```python 72 | from mcp_client import MCPClient 73 | 74 | # Connect to the MCP server 75 | client = MCPClient("http://localhost:8089/mcp") 76 | 77 | # Get a list of projects 78 | response = await client.invoke_tool("get-project-list") 79 | 80 | # Create a new project 81 | response = await client.invoke_tool( 82 | "create-project", 83 | {"name": "My AI Project", "description": "Project created by AI"} 84 | ) 85 | ``` 86 | 87 | ## License 88 | 89 | Apache License 2.0 ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/05_k8s_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": {} 4 | } 5 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/06_project_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": {} 4 | } 5 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/21_resource_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": {} 4 | } 5 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/27_worker_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": {} 4 | } 5 | } ``` -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- ```python 1 | """Test package for DolphinScheduler MCP Server.""" ``` -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- ``` 1 | pytest>=7.3.1 2 | black>=23.3.0 3 | isort>=5.12.0 4 | mypy>=1.3.0 5 | pre-commit>=3.3.2 6 | fastmcp ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/__init__.py: -------------------------------------------------------------------------------- ```python 1 | """DolphinScheduler MCP Server Package.""" 2 | 3 | from .server import run_server 4 | 5 | __all__ = ["run_server"] ``` -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- ```python 1 | """DolphinScheduler MCP Package.""" 2 | 3 | # Empty __init__.py to make src directory a proper Python package ``` -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- ```dockerfile 1 | FROM python:3.9-slim 2 | 3 | WORKDIR /app 4 | 5 | # Copy project files 6 | COPY . . 7 | 8 | # Install dependencies 9 | RUN pip install --no-cache-dir -e . 10 | 11 | # Expose MCP server port 12 | EXPOSE 8089 13 | 14 | # Run server 15 | CMD ["python", "-m", "src.dolphinscheduler_mcp"] ``` -------------------------------------------------------------------------------- /install_dev.sh: -------------------------------------------------------------------------------- ```bash 1 | #!/bin/bash 2 | # Install the package in development mode 3 | 4 | # Activate virtual environment if it exists 5 | if [ -d ".venv" ]; then 6 | echo "Activating virtual environment..." 7 | source .venv/bin/activate 8 | fi 9 | 10 | # Install the package in development mode 11 | echo "Installing package in development mode..." 12 | pip install -e . 13 | 14 | echo "Installation complete!" ``` -------------------------------------------------------------------------------- /mcp-openapi-split/base/01_base.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "title": "Apache DolphinScheduler Api Docs", 5 | "description": "Apache DolphinScheduler Api Docs", 6 | "version": "3.3.0" 7 | }, 8 | "servers": [ 9 | { 10 | "url": "http://www.sjjc.dolphinscheduler.dsj.com/dolphinscheduler", 11 | "description": "Generated server url" 12 | } 13 | ] 14 | } ``` -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- ```yaml 1 | version: '3' 2 | 3 | services: 4 | dolphinscheduler-mcp: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | ports: 9 | - "8089:8089" 10 | environment: 11 | - DOLPHINSCHEDULER_API_URL=http://dolphinscheduler-api:12345/dolphinscheduler 12 | - DOLPHINSCHEDULER_API_KEY=${DOLPHINSCHEDULER_API_KEY} 13 | networks: 14 | - dolphinscheduler-network 15 | restart: unless-stopped 16 | 17 | networks: 18 | dolphinscheduler-network: 19 | name: dolphinscheduler-network 20 | driver: bridge ``` -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- ```bash 1 | #!/bin/bash 2 | 3 | # Check for Python 4 | if ! command -v python3 &>/dev/null; then 5 | echo "Python 3 could not be found. Please install Python 3." 6 | exit 1 7 | fi 8 | 9 | # Create virtual environment if it doesn't exist 10 | if [ ! -d ".venv" ]; then 11 | echo "Creating virtual environment..." 12 | python3 -m venv .venv 13 | fi 14 | 15 | # Activate virtual environment 16 | echo "Activating virtual environment..." 17 | source .venv/bin/activate 18 | 19 | # Install requirements 20 | echo "Installing requirements..." 21 | pip install -e . 22 | 23 | # Run the server 24 | echo "Starting DolphinScheduler MCP Server..." 25 | python -m src.dolphinscheduler_mcp ``` -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- ``` 1 | @echo off 2 | SETLOCAL 3 | 4 | :: Check for Python 5 | python --version >nul 2>&1 6 | IF %ERRORLEVEL% NEQ 0 ( 7 | echo Python could not be found. Please install Python 3. 8 | exit /b 1 9 | ) 10 | 11 | :: Create virtual environment if it doesn't exist 12 | IF NOT EXIST .venv ( 13 | echo Creating virtual environment... 14 | python -m venv .venv 15 | ) 16 | 17 | :: Activate virtual environment 18 | echo Activating virtual environment... 19 | call .venv\Scripts\activate.bat 20 | 21 | :: Install requirements 22 | echo Installing requirements... 23 | pip install -e . 24 | 25 | :: Run the server 26 | echo Starting DolphinScheduler MCP Server... 27 | python -m src.dolphinscheduler_mcp 28 | 29 | ENDLOCAL ``` -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- ```markdown 1 | # Changelog 2 | 3 | All notable changes to the DolphinScheduler MCP Server will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [0.1.0] - 2023-06-24 9 | 10 | ### Added 11 | - Initial release of DolphinScheduler MCP Server 12 | - Core MCP server implementation with DolphinScheduler API integration 13 | - Connection management tools for dynamic configuration 14 | - Project management tools (list projects, get project details) 15 | - Workflow management tools (list, view, start, stop) 16 | - Workflow instance management tools 17 | - Task instance monitoring 18 | - System status monitoring tools 19 | - Resource management tools 20 | - Documentation, examples, and tests 21 | - Docker and Docker Compose support for containerized deployment ``` -------------------------------------------------------------------------------- /example_mcp.py: -------------------------------------------------------------------------------- ```python 1 | """Example MCP server using the latest FastMCP API.""" 2 | 3 | from fastmcp import FastMCP, Context 4 | 5 | # Create an MCP server 6 | mcp = FastMCP(title="Example MCP Server") 7 | 8 | # Define a tool using the decorator pattern 9 | @mcp.tool() 10 | def add(a: int, b: int) -> int: 11 | """Add two numbers together. 12 | 13 | Args: 14 | a: First number 15 | b: Second number 16 | 17 | Returns: 18 | The sum of a and b 19 | """ 20 | return a + b 21 | 22 | # Define an async tool 23 | @mcp.tool() 24 | async def fetch_data(url: str, ctx: Context) -> str: 25 | """Fetch data from a URL. 26 | 27 | Args: 28 | url: The URL to fetch data from 29 | ctx: The MCP context 30 | 31 | Returns: 32 | The fetched data 33 | """ 34 | # Report progress 35 | ctx.info(f"Fetching data from {url}") 36 | 37 | # In a real implementation, we would fetch data here 38 | return f"Data from {url}" 39 | 40 | if __name__ == "__main__": 41 | # Start the server 42 | mcp.run(host="0.0.0.0", port=8089) ``` -------------------------------------------------------------------------------- /test_create_project.py: -------------------------------------------------------------------------------- ```python 1 | import asyncio 2 | import os 3 | from src.dolphinscheduler_mcp.client import DolphinSchedulerClient 4 | 5 | async def test_create_project(): 6 | # Create a client with environment variables 7 | client = DolphinSchedulerClient( 8 | api_url=os.environ.get("DOLPHINSCHEDULER_API_URL"), 9 | api_key=os.environ.get("DOLPHINSCHEDULER_API_KEY") 10 | ) 11 | 12 | try: 13 | # Call the create_project method 14 | project_name = "mcp-demo1" 15 | description = "MCP Demo Project" 16 | 17 | print(f"Creating project {project_name}...") 18 | response = await client.request( 19 | "POST", 20 | "projects", 21 | params={ 22 | "projectName": project_name, 23 | "description": description 24 | } 25 | ) 26 | 27 | print("Response:") 28 | print(response) 29 | 30 | finally: 31 | # Close the client 32 | await client.close() 33 | 34 | if __name__ == "__main__": 35 | asyncio.run(test_create_project()) ``` -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- ```toml 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "dolphinscheduler-mcp" 7 | version = "0.1.0" 8 | description = "A Model Context Protocol (MCP) server for DolphinScheduler" 9 | readme = "README.md" 10 | authors = [ 11 | {name = "DolphinScheduler Contributors"} 12 | ] 13 | license = {text = "Apache-2.0"} 14 | classifiers = [ 15 | "Programming Language :: Python :: 3", 16 | "License :: OSI Approved :: Apache Software License", 17 | "Operating System :: OS Independent", 18 | ] 19 | requires-python = ">=3.9" 20 | dependencies = [ 21 | "fastapi", 22 | "python-dotenv", 23 | "pydantic", 24 | "fastmcp", 25 | "aiohttp", 26 | "uvicorn", 27 | ] 28 | 29 | [project.scripts] 30 | ds-mcp = "dolphinscheduler_mcp.cli:main" 31 | 32 | [project.optional-dependencies] 33 | dev = [ 34 | "pytest", 35 | "black", 36 | "isort", 37 | "mypy", 38 | "pre-commit", 39 | ] 40 | 41 | [tool.setuptools] 42 | package-dir = {"" = "src"} 43 | 44 | [tool.black] 45 | line-length = 88 46 | target-version = ["py39"] 47 | 48 | [tool.isort] 49 | profile = "black" 50 | line_length = 88 51 | 52 | [tool.mypy] 53 | python_version = "3.9" 54 | ignore_missing_imports = true ``` -------------------------------------------------------------------------------- /examples/list_projects.py: -------------------------------------------------------------------------------- ```python 1 | #!/usr/bin/env python3 2 | """Example script to list DolphinScheduler projects using the MCP client.""" 3 | 4 | import asyncio 5 | import json 6 | import os 7 | import sys 8 | 9 | # For local development, add the parent directory to the Python path 10 | sys.path.append(".") 11 | 12 | # Import the MCPClient from simple_client.py 13 | from examples.simple_client import MCPClient 14 | 15 | 16 | async def main(): 17 | """List all DolphinScheduler projects using MCP.""" 18 | # Set up the MCP server URL 19 | mcp_url = os.environ.get("MCP_URL", "http://localhost:8089/mcp") 20 | 21 | print(f"Connecting to MCP server at {mcp_url}") 22 | 23 | async with MCPClient(mcp_url) as client: 24 | # Get project list 25 | print("Getting project list:") 26 | response = await client.invoke_tool("get-project-list") 27 | 28 | # Pretty print the result 29 | if "result" in response and "data" in response["result"]: 30 | projects = response["result"]["data"] 31 | print(f"Found {len(projects)} projects:") 32 | for project in projects: 33 | print(f"- {project['name']} (Code: {project['code']})") 34 | else: 35 | print("Error or no projects found:") 36 | print(json.dumps(response, indent=2)) 37 | 38 | 39 | if __name__ == "__main__": 40 | asyncio.run(main()) ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/16_remaining_5_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "AuditModelTypeDto": { 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string" 9 | } 10 | } 11 | }, 12 | "AuditDto": { 13 | "type": "object", 14 | "properties": { 15 | "userName": { 16 | "type": "string" 17 | }, 18 | "modelType": { 19 | "type": "string" 20 | }, 21 | "modelName": { 22 | "type": "string" 23 | }, 24 | "operation": { 25 | "type": "string" 26 | }, 27 | "createTime": { 28 | "type": "string", 29 | "format": "date-time" 30 | }, 31 | "description": { 32 | "type": "string" 33 | }, 34 | "detail": { 35 | "type": "string" 36 | }, 37 | "latency": { 38 | "type": "string" 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/15_remaining_4_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "WorkFlowLineage": { 5 | "type": "object", 6 | "properties": { 7 | "workFlowCode": { 8 | "type": "integer", 9 | "format": "int64" 10 | }, 11 | "workFlowName": { 12 | "type": "string" 13 | }, 14 | "workFlowPublishStatus": { 15 | "type": "string" 16 | }, 17 | "scheduleStartTime": { 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | "scheduleEndTime": { 22 | "type": "string", 23 | "format": "date-time" 24 | }, 25 | "crontab": { 26 | "type": "string" 27 | }, 28 | "schedulePublishStatus": { 29 | "type": "integer", 30 | "format": "int32" 31 | }, 32 | "sourceWorkFlowCode": { 33 | "type": "string" 34 | } 35 | } 36 | }, 37 | "AuditOperationTypeDto": { 38 | "type": "object", 39 | "properties": { 40 | "name": { 41 | "type": "string" 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/11_remaining_12_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "PageInfoDqExecuteResult": { 5 | "type": "object", 6 | "properties": { 7 | "totalList": { 8 | "type": "array", 9 | "items": { 10 | "$ref": "#/components/schemas/DqExecuteResult" 11 | } 12 | }, 13 | "total": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "totalPage": { 18 | "type": "integer", 19 | "format": "int32" 20 | }, 21 | "pageSize": { 22 | "type": "integer", 23 | "format": "int32" 24 | }, 25 | "currentPage": { 26 | "type": "integer", 27 | "format": "int32" 28 | }, 29 | "pageNo": { 30 | "type": "integer", 31 | "format": "int32" 32 | } 33 | } 34 | }, 35 | "ParamsOptions": { 36 | "type": "object", 37 | "properties": { 38 | "label": { 39 | "type": "string" 40 | }, 41 | "value": { 42 | "type": "object" 43 | }, 44 | "disabled": { 45 | "type": "boolean" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/utils/combine_openapi.py: -------------------------------------------------------------------------------- ```python 1 | #!/usr/bin/env python3 2 | ''' 3 | Combine split OpenAPI files back into a single specification. 4 | ''' 5 | import json 6 | import os 7 | import glob 8 | 9 | # Output file 10 | OUTPUT_FILE = '../combined_openapi.json' 11 | 12 | def load_json(filename): 13 | '''Load JSON from a file.''' 14 | with open(filename, 'r', encoding='utf-8') as f: 15 | return json.load(f) 16 | 17 | def combine_openapi(): 18 | '''Combine all the split OpenAPI files into a single specification.''' 19 | # Start with the base information 20 | base_files = sorted(glob.glob('../base/*.json')) 21 | if not base_files: 22 | raise FileNotFoundError("No base files found!") 23 | 24 | combined = load_json(base_files[0]) 25 | combined['paths'] = {} 26 | combined['components'] = {'schemas': {}} 27 | 28 | # Add all paths 29 | path_files = sorted(glob.glob('../paths/*.json')) 30 | for path_file in path_files: 31 | paths_data = load_json(path_file) 32 | if 'paths' in paths_data: 33 | combined['paths'].update(paths_data['paths']) 34 | 35 | # Add all schemas 36 | schema_files = sorted(glob.glob('../schemas/*.json')) 37 | for schema_file in schema_files: 38 | schema_data = load_json(schema_file) 39 | if 'components' in schema_data and 'schemas' in schema_data['components']: 40 | combined['components']['schemas'].update(schema_data['components']['schemas']) 41 | 42 | # Save the combined specification 43 | with open(OUTPUT_FILE, 'w', encoding='utf-8') as f: 44 | json.dump(combined, f, ensure_ascii=False, indent=4) 45 | 46 | print(f"Combined OpenAPI specification saved to {OUTPUT_FILE}") 47 | print(f"Specification contains {len(combined['paths'])} paths and {len(combined['components']['schemas'])} schemas") 48 | 49 | if __name__ == '__main__': 50 | combine_openapi() 51 | ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/environment_check_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tool for checking environment settings.""" 2 | 3 | import json 4 | import logging 5 | from typing import Dict, Any, Optional 6 | 7 | from ..client import DolphinSchedulerClient 8 | from ..config import Config 9 | from ..fastmcp_compat import FastMCPTool 10 | 11 | 12 | class CheckEnvironmentSettings(FastMCPTool): 13 | """Tool for checking the current environment settings for DolphinScheduler API.""" 14 | 15 | name = "check_environment_settings" 16 | description = "Check the current environment settings for DolphinScheduler API" 17 | is_async = False 18 | schema = { 19 | "type": "object", 20 | "properties": { 21 | "id": { 22 | "type": "string", 23 | "description": "Not used, included for compatibility with FastMCP" 24 | } 25 | } 26 | } 27 | 28 | def _run(self, id: Optional[str] = None) -> Dict[str, Any]: 29 | """Check the current environment settings. 30 | 31 | Args: 32 | id: Not used, included for compatibility with FastMCP 33 | 34 | Returns: 35 | Dictionary containing current settings 36 | """ 37 | try: 38 | config = Config() 39 | 40 | return { 41 | "success": True, 42 | "api_url": config.api_url, 43 | "has_api_key": config.has_api_key(), 44 | "api_key_value": config.api_key if config.has_api_key() else None 45 | } 46 | except Exception as e: 47 | self.logger.error(f"Error checking environment settings: {e}") 48 | return { 49 | "success": False, 50 | "error": str(e) 51 | } 52 | 53 | 54 | def register_environment_check_tools(mcp): 55 | """Register environment check tools with FastMCP. 56 | 57 | Args: 58 | mcp: The FastMCP instance to register tools with. 59 | """ 60 | from ..fastmcp_compat import register_tool_class 61 | 62 | register_tool_class(mcp, CheckEnvironmentSettings) 63 | ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/04_environment_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "Environment": { 5 | "type": "object", 6 | "properties": { 7 | "id": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "code": { 12 | "type": "integer", 13 | "format": "int64" 14 | }, 15 | "name": { 16 | "type": "string" 17 | }, 18 | "config": { 19 | "type": "string" 20 | }, 21 | "description": { 22 | "type": "string" 23 | }, 24 | "operator": { 25 | "type": "integer", 26 | "format": "int32" 27 | }, 28 | "createTime": { 29 | "type": "string", 30 | "format": "date-time" 31 | }, 32 | "updateTime": { 33 | "type": "string", 34 | "format": "date-time" 35 | } 36 | } 37 | }, 38 | "ResultEnvironment": { 39 | "type": "object", 40 | "properties": { 41 | "code": { 42 | "type": "integer", 43 | "format": "int32" 44 | }, 45 | "msg": { 46 | "type": "string" 47 | }, 48 | "data": { 49 | "$ref": "#/components/schemas/Environment" 50 | }, 51 | "failed": { 52 | "type": "boolean" 53 | }, 54 | "success": { 55 | "type": "boolean" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/02_dynamic_task_type_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/dynamic/{taskCategory}/taskTypes": { 4 | "get": { 5 | "tags": [ 6 | "DYNAMIC_TASK_TYPE" 7 | ], 8 | "summary": "listDynamicTaskTypes", 9 | "description": "LIST_DYNAMIC_TASK_TYPES", 10 | "operationId": "listDynamicTaskTypes", 11 | "parameters": [ 12 | { 13 | "name": "taskCategory", 14 | "in": "path", 15 | "required": true, 16 | "schema": { 17 | "type": "string" 18 | } 19 | } 20 | ], 21 | "responses": { 22 | "200": { 23 | "description": "OK", 24 | "content": { 25 | "*/*": { 26 | "schema": { 27 | "$ref": "#/components/schemas/Result" 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | }, 35 | "/dynamic/taskCategories": { 36 | "get": { 37 | "tags": [ 38 | "DYNAMIC_TASK_TYPE" 39 | ], 40 | "summary": "listTaskCategories", 41 | "description": "LIST_TASK_TYPE_CATEGORIES", 42 | "operationId": "listDynamicTaskCategories", 43 | "responses": { 44 | "200": { 45 | "description": "OK", 46 | "content": { 47 | "*/*": { 48 | "schema": { 49 | "$ref": "#/components/schemas/Result" 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/__main__.py: -------------------------------------------------------------------------------- ```python 1 | """Main entry point for DolphinScheduler MCP.""" 2 | 3 | import sys 4 | import os 5 | import importlib 6 | from typing import List 7 | 8 | # Clear cache for fastmcp_compat module to ensure changes are loaded 9 | if "dolphinscheduler_mcp.fastmcp_compat" in sys.modules: 10 | del sys.modules["dolphinscheduler_mcp.fastmcp_compat"] 11 | 12 | from .server import run_server 13 | 14 | 15 | def main(args: List[str] = None) -> int: 16 | """Run the MCP server with the given arguments.""" 17 | if args is None: 18 | args = sys.argv[1:] 19 | 20 | # Default configuration 21 | host = "0.0.0.0" 22 | port = 8089 23 | 24 | # Check for environment variables first 25 | if "DOLPHINSCHEDULER_MCP_HOST" in os.environ: 26 | host = os.environ["DOLPHINSCHEDULER_MCP_HOST"] 27 | if "DOLPHINSCHEDULER_MCP_PORT" in os.environ: 28 | try: 29 | port = int(os.environ["DOLPHINSCHEDULER_MCP_PORT"]) 30 | except ValueError: 31 | print(f"Invalid port number in DOLPHINSCHEDULER_MCP_PORT: {os.environ['DOLPHINSCHEDULER_MCP_PORT']}") 32 | return 1 33 | 34 | # Override with command line arguments if provided 35 | if len(args) >= 1: 36 | host = args[0] 37 | if len(args) >= 2: 38 | try: 39 | port = int(args[1]) 40 | except ValueError: 41 | print(f"Invalid port number: {args[1]}") 42 | return 1 43 | 44 | # Check if API URL and key are set 45 | if "DOLPHINSCHEDULER_API_URL" not in os.environ: 46 | print("Warning: DOLPHINSCHEDULER_API_URL environment variable is not set.") 47 | print("Using default: http://localhost:12345/dolphinscheduler") 48 | 49 | if "DOLPHINSCHEDULER_API_KEY" not in os.environ: 50 | print("Warning: DOLPHINSCHEDULER_API_KEY environment variable is not set.") 51 | print("Authentication to the DolphinScheduler API may fail.") 52 | 53 | # Run the server 54 | try: 55 | run_server(host=host, port=port) 56 | return 0 57 | except Exception as e: 58 | print(f"Error running server: {e}") 59 | return 1 60 | 61 | 62 | if __name__ == "__main__": 63 | sys.exit(main()) ``` -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- ```python 1 | #!/usr/bin/env python 2 | """ 3 | DolphinScheduler MCP Server Runner 4 | 5 | This script sets up environment variables and runs the DolphinScheduler MCP server. 6 | """ 7 | 8 | import os 9 | import sys 10 | import logging 11 | 12 | # Configure logging 13 | logging.basicConfig( 14 | level=logging.INFO, 15 | format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", 16 | handlers=[logging.StreamHandler(sys.stdout)], 17 | ) 18 | 19 | logger = logging.getLogger("dolphinscheduler_mcp.runner") 20 | 21 | def main(): 22 | """Main entry point for running DolphinScheduler MCP server.""" 23 | # Default host and port 24 | host = os.environ.get("DOLPHINSCHEDULER_MCP_HOST", "0.0.0.0") 25 | port = int(os.environ.get("DOLPHINSCHEDULER_MCP_PORT", "8089")) 26 | 27 | # Check if API URL is set 28 | api_url = os.environ.get("DOLPHINSCHEDULER_API_URL") 29 | if not api_url: 30 | logger.warning("DOLPHINSCHEDULER_API_URL environment variable is not set!") 31 | logger.warning("Using default URL from Config class.") 32 | 33 | # Check if API key is set - this is required for all API requests 34 | api_key = os.environ.get("DOLPHINSCHEDULER_API_KEY") 35 | if not api_key: 36 | logger.warning("DOLPHINSCHEDULER_API_KEY environment variable is not set!") 37 | logger.warning("API requests may fail due to missing authentication.") 38 | else: 39 | logger.info("Using API key from environment variables.") 40 | 41 | # Print configuration 42 | logger.info(f"Starting DolphinScheduler MCP Server on {host}:{port}") 43 | if api_url: 44 | logger.info(f"Using DolphinScheduler API URL: {api_url}") 45 | 46 | # Import and run the server 47 | try: 48 | from src.dolphinscheduler_mcp.server import run_server 49 | run_server(host=host, port=port) 50 | return 0 51 | except ImportError: 52 | logger.error("Could not import dolphinscheduler_mcp. Make sure it's installed.") 53 | return 1 54 | except Exception as e: 55 | logger.error(f"Error running server: {e}", exc_info=True) 56 | return 1 57 | 58 | if __name__ == "__main__": 59 | sys.exit(main()) ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/dynamic_task_type_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tools for dynamic task type operations in DolphinScheduler.""" 2 | 3 | from typing import Dict, List, Optional 4 | 5 | from ..fastmcp_compat import FastMCPTool 6 | 7 | from ..client import DolphinSchedulerClient 8 | 9 | 10 | class ListDynamicTasktypes(FastMCPTool): 11 | """Tool to list_dynamic_task_types""" 12 | 13 | name = "list_dynamic_tasktypes" 14 | description = "LIST_DYNAMIC_TASK_TYPES" 15 | is_async = True 16 | schema = { 17 | "type": "object", 18 | "properties": { 19 | "task_category": { 20 | "type": "string" 21 | } 22 | }, 23 | "required": [ 24 | "task_category" 25 | ] 26 | } 27 | 28 | async def _run(self, task_category) -> Dict: 29 | """Execute the GET operation on /dynamic/{taskCategory}/taskTypes.""" 30 | client = DolphinSchedulerClient() 31 | try: 32 | response = await client.request( 33 | "GET", 34 | f"/dynamic/{task_category}/taskTypes" 35 | ) 36 | return {"success": True, "data": response} 37 | finally: 38 | await client.close() 39 | 40 | 41 | class ListDynamicTaskcategories(FastMCPTool): 42 | """Tool to list_task_type_categories""" 43 | 44 | name = "list_dynamic_taskcategories" 45 | description = "LIST_TASK_TYPE_CATEGORIES" 46 | is_async = True 47 | 48 | async def _run(self) -> Dict: 49 | """Execute the GET operation on /dynamic/taskCategories.""" 50 | client = DolphinSchedulerClient() 51 | try: 52 | response = await client.request( 53 | "GET", 54 | f"/dynamic/taskCategories" 55 | ) 56 | return {"success": True, "data": response} 57 | finally: 58 | await client.close() 59 | 60 | 61 | def register_dynamic_task_type_tools(mcp): 62 | """Register dynamic task type tools with FastMCP. 63 | 64 | Args: 65 | mcp: The FastMCP instance to register tools with. 66 | """ 67 | from ..fastmcp_compat import register_tool_class 68 | 69 | register_tool_class(mcp, ListDynamicTaskcategories) 70 | register_tool_class(mcp, ListDynamicTasktypes) 71 | ``` -------------------------------------------------------------------------------- /examples/start_workflow.py: -------------------------------------------------------------------------------- ```python 1 | #!/usr/bin/env python3 2 | """Example script to execute a DolphinScheduler process definition using the MCP client.""" 3 | 4 | import argparse 5 | import asyncio 6 | import json 7 | import os 8 | import sys 9 | 10 | # For local development, add the parent directory to the Python path 11 | sys.path.append(".") 12 | 13 | # Import the MCPClient from simple_client.py 14 | from examples.simple_client import MCPClient 15 | 16 | 17 | async def main(): 18 | """Execute a DolphinScheduler process definition using MCP.""" 19 | parser = argparse.ArgumentParser(description="Execute a DolphinScheduler process definition") 20 | parser.add_argument("--project-code", type=int, required=True, help="Project code") 21 | parser.add_argument("--process-definition-code", type=int, required=True, help="Process definition code") 22 | parser.add_argument("--schedule-time", type=str, help="Schedule time (yyyy-MM-dd HH:mm:ss)") 23 | parser.add_argument("--execution-type", type=str, default="PARALLEL", 24 | help="Execution type (PARALLEL/SERIAL_WAIT/SERIAL_DISCARD/SERIAL_PRIORITY)") 25 | args = parser.parse_args() 26 | 27 | # Set up the MCP server URL 28 | mcp_url = os.environ.get("MCP_URL", "http://localhost:8089/mcp") 29 | 30 | print(f"Connecting to MCP server at {mcp_url}") 31 | 32 | async with MCPClient(mcp_url) as client: 33 | # Execute process definition 34 | print(f"Executing process definition {args.process_definition_code} in project {args.project_code}:") 35 | 36 | # Prepare parameters 37 | parameters = { 38 | "project_code": args.project_code, 39 | "process_definition_code": args.process_definition_code, 40 | "execution_type": args.execution_type, 41 | } 42 | 43 | if args.schedule_time: 44 | parameters["schedule_time"] = args.schedule_time 45 | 46 | # Execute the process definition 47 | response = await client.invoke_tool("execute-process-definition", parameters) 48 | 49 | # Pretty print the result 50 | print(json.dumps(response, indent=2)) 51 | 52 | 53 | if __name__ == "__main__": 54 | asyncio.run(main()) ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/20_remaining_9_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "OAuth2ClientProperties": { 5 | "type": "object", 6 | "properties": { 7 | "authorizationUri": { 8 | "type": "string" 9 | }, 10 | "clientId": { 11 | "type": "string" 12 | }, 13 | "redirectUri": { 14 | "type": "string" 15 | }, 16 | "clientSecret": { 17 | "type": "string" 18 | }, 19 | "tokenUri": { 20 | "type": "string" 21 | }, 22 | "userInfoUri": { 23 | "type": "string" 24 | }, 25 | "callbackUrl": { 26 | "type": "string" 27 | }, 28 | "iconUri": { 29 | "type": "string" 30 | }, 31 | "provider": { 32 | "type": "string" 33 | } 34 | } 35 | }, 36 | "Server": { 37 | "type": "object", 38 | "properties": { 39 | "id": { 40 | "type": "integer", 41 | "format": "int32" 42 | }, 43 | "host": { 44 | "type": "string" 45 | }, 46 | "port": { 47 | "type": "integer", 48 | "format": "int32" 49 | }, 50 | "zkDirectory": { 51 | "type": "string" 52 | }, 53 | "resInfo": { 54 | "type": "string" 55 | }, 56 | "createTime": { 57 | "type": "string", 58 | "format": "date-time" 59 | }, 60 | "lastHeartbeatTime": { 61 | "type": "string", 62 | "format": "date-time" 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } ``` -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- ```markdown 1 | # Installation Guide 2 | 3 | This guide provides detailed instructions for installing and setting up the DolphinScheduler MCP server. 4 | 5 | ## Prerequisites 6 | 7 | - Python 3.9 or higher 8 | - pip (Python package installer) 9 | - A running DolphinScheduler instance 10 | - (Optional) Docker and Docker Compose for containerized deployment 11 | 12 | ## Standard Installation 13 | 14 | 1. Clone the repository: 15 | ```bash 16 | git clone https://github.com/yourusername/dolphinscheduler-mcp.git 17 | cd dolphinscheduler-mcp 18 | ``` 19 | 20 | 2. Create and activate a virtual environment: 21 | ```bash 22 | # Linux/macOS 23 | python -m venv .venv 24 | source .venv/bin/activate 25 | 26 | # Windows 27 | python -m venv .venv 28 | .venv\Scripts\activate 29 | ``` 30 | 31 | 3. Install the package in development mode: 32 | ```bash 33 | pip install -e . 34 | ``` 35 | 36 | 4. Configure environment variables by creating a `.env` file in the project root: 37 | ``` 38 | DOLPHINSCHEDULER_API_URL=http://your-dolphinscheduler-server:12345/dolphinscheduler 39 | DOLPHINSCHEDULER_API_KEY=your_api_key 40 | ``` 41 | 42 | ## Docker Installation 43 | 44 | 1. Build and run using Docker Compose: 45 | ```bash 46 | docker-compose up -d 47 | ``` 48 | 49 | This will: 50 | - Build the Docker image 51 | - Start the DolphinScheduler MCP server on port 8089 52 | - Configure it to connect to your DolphinScheduler API 53 | 54 | 2. Check the logs: 55 | ```bash 56 | docker-compose logs -f 57 | ``` 58 | 59 | 3. Stop the service: 60 | ```bash 61 | docker-compose down 62 | ``` 63 | 64 | ## Using the Scripts 65 | 66 | For convenience, we provide scripts to set up and run the server: 67 | 68 | - Linux/macOS: 69 | ```bash 70 | chmod +x run.sh 71 | ./run.sh 72 | ``` 73 | 74 | - Windows: 75 | ```cmd 76 | run.bat 77 | ``` 78 | 79 | These scripts will: 80 | 1. Create a virtual environment if it doesn't exist 81 | 2. Activate the virtual environment 82 | 3. Install the package dependencies 83 | 4. Run the MCP server 84 | 85 | ## Verifying the Installation 86 | 87 | To verify that the MCP server is running correctly: 88 | 89 | 1. Open a web browser and navigate to: `http://localhost:8089/mcp/tools` 90 | 2. You should see a JSON response listing all available tools. 91 | 92 | Alternatively, use the MCP Inspector to test your server: 93 | 94 | ```bash 95 | npx @modelcontextprotocol/inspector python -m src.dolphinscheduler_mcp 96 | ``` ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/08_remaining_1_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "AccessToken": { 5 | "type": "object", 6 | "properties": { 7 | "id": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "userId": { 12 | "type": "integer", 13 | "format": "int32" 14 | }, 15 | "token": { 16 | "type": "string" 17 | }, 18 | "expireTime": { 19 | "type": "string", 20 | "format": "date-time" 21 | }, 22 | "createTime": { 23 | "type": "string", 24 | "format": "date-time" 25 | }, 26 | "updateTime": { 27 | "type": "string", 28 | "format": "date-time" 29 | }, 30 | "userName": { 31 | "type": "string" 32 | } 33 | } 34 | }, 35 | "PageInfoStorageEntity": { 36 | "type": "object", 37 | "properties": { 38 | "totalList": { 39 | "type": "array", 40 | "items": { 41 | "$ref": "#/components/schemas/StorageEntity" 42 | } 43 | }, 44 | "total": { 45 | "type": "integer", 46 | "format": "int32" 47 | }, 48 | "totalPage": { 49 | "type": "integer", 50 | "format": "int32" 51 | }, 52 | "pageSize": { 53 | "type": "integer", 54 | "format": "int32" 55 | }, 56 | "currentPage": { 57 | "type": "integer", 58 | "format": "int32" 59 | }, 60 | "pageNo": { 61 | "type": "integer", 62 | "format": "int32" 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/12_remaining_13_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "PageInfoAccessToken": { 5 | "type": "object", 6 | "properties": { 7 | "totalList": { 8 | "type": "array", 9 | "items": { 10 | "$ref": "#/components/schemas/AccessToken" 11 | } 12 | }, 13 | "total": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "totalPage": { 18 | "type": "integer", 19 | "format": "int32" 20 | }, 21 | "pageSize": { 22 | "type": "integer", 23 | "format": "int32" 24 | }, 25 | "currentPage": { 26 | "type": "integer", 27 | "format": "int32" 28 | }, 29 | "pageNo": { 30 | "type": "integer", 31 | "format": "int32" 32 | } 33 | } 34 | }, 35 | "DeleteDataTransferResponse": { 36 | "type": "object", 37 | "properties": { 38 | "code": { 39 | "type": "integer", 40 | "format": "int32" 41 | }, 42 | "msg": { 43 | "type": "string" 44 | }, 45 | "data": { 46 | "type": "object" 47 | }, 48 | "successList": { 49 | "type": "array", 50 | "items": { 51 | "type": "string" 52 | } 53 | }, 54 | "failedList": { 55 | "type": "array", 56 | "items": { 57 | "type": "string" 58 | } 59 | }, 60 | "failed": { 61 | "type": "boolean" 62 | }, 63 | "success": { 64 | "type": "boolean" 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } ``` -------------------------------------------------------------------------------- /tests/test_config.py: -------------------------------------------------------------------------------- ```python 1 | """Tests for the config module.""" 2 | 3 | import os 4 | import unittest 5 | from unittest.mock import patch 6 | 7 | from src.dolphinscheduler_mcp.config import Config 8 | 9 | 10 | class TestConfig(unittest.TestCase): 11 | """Test cases for the Config class.""" 12 | 13 | def setUp(self): 14 | """Set up test cases.""" 15 | # Reset the Config singleton instance before each test 16 | Config._instance = None 17 | # Clear environment variables that might affect the test 18 | if "DOLPHINSCHEDULER_API_URL" in os.environ: 19 | del os.environ["DOLPHINSCHEDULER_API_URL"] 20 | if "DOLPHINSCHEDULER_API_KEY" in os.environ: 21 | del os.environ["DOLPHINSCHEDULER_API_KEY"] 22 | 23 | def test_default_values(self): 24 | """Test default configuration values.""" 25 | config = Config() 26 | self.assertEqual(config.api_url, "http://localhost:12345/dolphinscheduler") 27 | self.assertIsNone(config.api_key) 28 | self.assertFalse(config.has_api_key()) 29 | 30 | @patch.dict(os.environ, {"DOLPHINSCHEDULER_API_URL": "http://test-server:8080"}) 31 | def test_env_api_url(self): 32 | """Test API URL from environment variable.""" 33 | config = Config() 34 | self.assertEqual(config.api_url, "http://test-server:8080") 35 | 36 | @patch.dict(os.environ, {"DOLPHINSCHEDULER_API_KEY": "test-api-key"}) 37 | def test_env_api_key(self): 38 | """Test API key from environment variable.""" 39 | config = Config() 40 | self.assertEqual(config.api_key, "test-api-key") 41 | self.assertTrue(config.has_api_key()) 42 | 43 | def test_singleton(self): 44 | """Test that Config is a singleton.""" 45 | config1 = Config() 46 | config2 = Config() 47 | self.assertIs(config1, config2) 48 | 49 | def test_update_values(self): 50 | """Test updating configuration values.""" 51 | config = Config() 52 | config.api_url = "http://new-server:9000" 53 | config.api_key = "new-api-key" 54 | 55 | # Get a new instance and verify values are preserved (singleton) 56 | new_config = Config() 57 | self.assertEqual(new_config.api_url, "http://new-server:9000") 58 | self.assertEqual(new_config.api_key, "new-api-key") 59 | self.assertTrue(new_config.has_api_key()) 60 | 61 | 62 | if __name__ == "__main__": 63 | unittest.main() ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/28_monitor_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/monitor/{nodeType}": { 4 | "get": { 5 | "tags": [ 6 | "监控相关操作" 7 | ], 8 | "summary": "listServer", 9 | "description": "SERVER_LIST_NOTES", 10 | "operationId": "listServer", 11 | "parameters": [ 12 | { 13 | "name": "nodeType", 14 | "in": "path", 15 | "required": true, 16 | "schema": { 17 | "type": "string", 18 | "enum": [ 19 | "ALL_SERVERS", 20 | "MASTER", 21 | "MASTER_NODE_LOCK", 22 | "MASTER_FAILOVER_LOCK", 23 | "MASTER_TASK_GROUP_COORDINATOR_LOCK", 24 | "WORKER", 25 | "ALERT_SERVER", 26 | "ALERT_LOCK" 27 | ] 28 | } 29 | } 30 | ], 31 | "responses": { 32 | "200": { 33 | "description": "OK", 34 | "content": { 35 | "*/*": { 36 | "schema": { 37 | "$ref": "#/components/schemas/ResultListServer" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | }, 45 | "/monitor/databases": { 46 | "get": { 47 | "tags": [ 48 | "监控相关操作" 49 | ], 50 | "summary": "queryDatabaseState", 51 | "description": "查询数据库状态", 52 | "operationId": "queryDatabaseState", 53 | "responses": { 54 | "200": { 55 | "description": "OK", 56 | "content": { 57 | "*/*": { 58 | "schema": { 59 | "$ref": "#/components/schemas/ResultListDatabaseMetrics" 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/19_remaining_8_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "PageInfoCommand": { 5 | "type": "object", 6 | "properties": { 7 | "totalList": { 8 | "type": "array", 9 | "items": { 10 | "$ref": "#/components/schemas/Command" 11 | } 12 | }, 13 | "total": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "totalPage": { 18 | "type": "integer", 19 | "format": "int32" 20 | }, 21 | "pageSize": { 22 | "type": "integer", 23 | "format": "int32" 24 | }, 25 | "currentPage": { 26 | "type": "integer", 27 | "format": "int32" 28 | }, 29 | "pageNo": { 30 | "type": "integer", 31 | "format": "int32" 32 | } 33 | } 34 | }, 35 | "CommandStateCount": { 36 | "type": "object", 37 | "properties": { 38 | "errorCount": { 39 | "type": "integer", 40 | "format": "int32" 41 | }, 42 | "normalCount": { 43 | "type": "integer", 44 | "format": "int32" 45 | }, 46 | "commandState": { 47 | "type": "string", 48 | "enum": [ 49 | "START_PROCESS", 50 | "START_CURRENT_TASK_PROCESS", 51 | "RECOVER_TOLERANCE_FAULT_PROCESS", 52 | "RECOVER_SUSPENDED_PROCESS", 53 | "START_FAILURE_TASK_PROCESS", 54 | "COMPLEMENT_DATA", 55 | "SCHEDULER", 56 | "REPEAT_RUNNING", 57 | "PAUSE", 58 | "STOP", 59 | "RECOVER_WAITING_THREAD", 60 | "RECOVER_SERIAL_WAIT", 61 | "EXECUTE_TASK", 62 | "DYNAMIC_GENERATION" 63 | ] 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/server.py: -------------------------------------------------------------------------------- ```python 1 | """DolphinScheduler MCP Server implementation using FastMCP.""" 2 | 3 | import logging 4 | import sys 5 | import os 6 | from typing import Dict, List, Optional 7 | 8 | # Clear module cache for fastmcp_compat 9 | if "dolphinscheduler_mcp.fastmcp_compat" in sys.modules: 10 | del sys.modules["dolphinscheduler_mcp.fastmcp_compat"] 11 | 12 | from mcp.server.fastmcp import FastMCP 13 | 14 | # 导入工具加载器 15 | from .tools_loader import register_all_generated_tools as register_all_tools 16 | from .config import Config 17 | 18 | # Configure logging 19 | logging.basicConfig( 20 | level=logging.INFO, 21 | format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", 22 | handlers=[logging.StreamHandler(sys.stdout)], 23 | ) 24 | 25 | logger = logging.getLogger(__name__) 26 | 27 | # Initialize MCP server 28 | mcp = FastMCP( 29 | title="DolphinScheduler MCP", 30 | description="MCP interface for DolphinScheduler API", 31 | ) 32 | 33 | def register_tools() -> None: 34 | """Register all tools with the MCP server.""" 35 | # Check environment variables first 36 | api_url = os.environ.get("DOLPHINSCHEDULER_API_URL") 37 | api_key = os.environ.get("DOLPHINSCHEDULER_API_KEY") 38 | 39 | # Update config if environment variables are set 40 | if api_url or api_key: 41 | config = Config() 42 | if api_url: 43 | logger.info(f"Using API URL from environment: {api_url}") 44 | config.api_url = api_url 45 | if api_key: 46 | logger.info("Using API key from environment") 47 | config.api_key = api_key 48 | 49 | # 注册工具 50 | try: 51 | logger.info("Registering tools...") 52 | count = register_all_tools(mcp) 53 | logger.info(f"Registered {count} tool modules successfully") 54 | except Exception as e: 55 | logger.error(f"Error registering tools: {e}", exc_info=True) 56 | 57 | # Register all tools 58 | register_tools() 59 | 60 | def run_server(host: str = "0.0.0.0", port: int = 8089) -> None: 61 | """Run the DolphinScheduler MCP server. 62 | 63 | Args: 64 | host: Host to bind the server to 65 | port: Port to bind the server to 66 | """ 67 | logger.info(f"Starting DolphinScheduler MCP Server on {host}:{port}") 68 | logger.info(f"API URL: {Config().api_url}") 69 | logger.info(f"API Key is {'set' if Config().has_api_key() else 'not set'}") 70 | 71 | try: 72 | # FastMCP.run() does not accept uvicorn_config parameter 73 | # Simply call run() without parameters 74 | mcp.run() 75 | except KeyboardInterrupt: 76 | logger.info("Server stopped by user") 77 | except Exception as e: 78 | logger.error(f"Error running server: {e}", exc_info=True) 79 | sys.exit(1) ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/05_ui_plugin_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/ui-plugins/{id}": { 4 | "get": { 5 | "tags": [ 6 | "UI插件相关操作" 7 | ], 8 | "summary": "queryUiPluginDetailById", 9 | "description": "通过ID查询UI插件详情", 10 | "operationId": "queryUiPluginDetailById", 11 | "parameters": [ 12 | { 13 | "name": "id", 14 | "in": "path", 15 | "description": "插件ID", 16 | "required": true, 17 | "schema": { 18 | "type": "integer", 19 | "format": "int32" 20 | } 21 | } 22 | ], 23 | "responses": { 24 | "201": { 25 | "description": "Created", 26 | "content": { 27 | "*/*": { 28 | "schema": { 29 | "$ref": "#/components/schemas/Result" 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } 36 | }, 37 | "/ui-plugins/query-by-type": { 38 | "get": { 39 | "tags": [ 40 | "UI插件相关操作" 41 | ], 42 | "summary": "queryUiPluginsByType", 43 | "description": "通过类型查询UI插件", 44 | "operationId": "queryUiPluginsByType", 45 | "parameters": [ 46 | { 47 | "name": "pluginType", 48 | "in": "query", 49 | "description": "pluginType", 50 | "required": true, 51 | "schema": { 52 | "type": "string", 53 | "enum": [ 54 | "ALERT", 55 | "REGISTER", 56 | "TASK" 57 | ] 58 | } 59 | } 60 | ], 61 | "responses": { 62 | "201": { 63 | "description": "Created", 64 | "content": { 65 | "*/*": { 66 | "schema": { 67 | "$ref": "#/components/schemas/Result" 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/13_remaining_2_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "StorageEntity": { 5 | "type": "object", 6 | "properties": { 7 | "id": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "fullName": { 12 | "type": "string" 13 | }, 14 | "fileName": { 15 | "type": "string" 16 | }, 17 | "alias": { 18 | "type": "string" 19 | }, 20 | "pfullName": { 21 | "type": "string" 22 | }, 23 | "userId": { 24 | "type": "integer", 25 | "format": "int32" 26 | }, 27 | "userName": { 28 | "type": "string" 29 | }, 30 | "type": { 31 | "type": "string", 32 | "enum": [ 33 | "FILE", 34 | "UDF", 35 | "ALL" 36 | ] 37 | }, 38 | "size": { 39 | "type": "integer", 40 | "format": "int64" 41 | }, 42 | "createTime": { 43 | "type": "string", 44 | "format": "date-time" 45 | }, 46 | "updateTime": { 47 | "type": "string", 48 | "format": "date-time" 49 | }, 50 | "directory": { 51 | "type": "boolean" 52 | } 53 | } 54 | }, 55 | "DagData": { 56 | "type": "object", 57 | "properties": { 58 | "processDefinition": { 59 | "$ref": "#/components/schemas/ProcessDefinition" 60 | }, 61 | "processTaskRelationList": { 62 | "type": "array", 63 | "items": { 64 | "$ref": "#/components/schemas/ProcessTaskRelation" 65 | } 66 | }, 67 | "taskDefinitionList": { 68 | "type": "array", 69 | "items": { 70 | "$ref": "#/components/schemas/TaskDefinition" 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/cli.py: -------------------------------------------------------------------------------- ```python 1 | """Command-line interface for DolphinScheduler MCP.""" 2 | 3 | import argparse 4 | import sys 5 | import os 6 | 7 | from .server import run_server 8 | 9 | 10 | def main() -> int: 11 | """Parse command-line arguments and run the server.""" 12 | parser = argparse.ArgumentParser( 13 | description="DolphinScheduler Model Context Protocol (MCP) Server" 14 | ) 15 | parser.add_argument( 16 | "--host", 17 | type=str, 18 | default=os.environ.get("DOLPHINSCHEDULER_MCP_HOST", "0.0.0.0"), 19 | help="Host to bind the server (default: 0.0.0.0 or DOLPHINSCHEDULER_MCP_HOST env var)", 20 | ) 21 | parser.add_argument( 22 | "--port", 23 | type=int, 24 | default=int(os.environ.get("DOLPHINSCHEDULER_MCP_PORT", "8089")), 25 | help="Port to bind the server (default: 8089 or DOLPHINSCHEDULER_MCP_PORT env var)", 26 | ) 27 | parser.add_argument( 28 | "--api-url", 29 | type=str, 30 | default=None, 31 | help="DolphinScheduler API URL (default: DOLPHINSCHEDULER_API_URL env var)", 32 | ) 33 | parser.add_argument( 34 | "--api-key", 35 | type=str, 36 | default=None, 37 | help="DolphinScheduler API key (default: DOLPHINSCHEDULER_API_KEY env var)", 38 | ) 39 | parser.add_argument( 40 | "--log-level", 41 | type=str, 42 | choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], 43 | default=os.environ.get("DOLPHINSCHEDULER_MCP_LOG_LEVEL", "INFO"), 44 | help="Logging level (default: INFO or DOLPHINSCHEDULER_MCP_LOG_LEVEL env var)", 45 | ) 46 | 47 | args = parser.parse_args() 48 | 49 | # Set environment variables if provided through command-line args 50 | if args.api_url: 51 | os.environ["DOLPHINSCHEDULER_API_URL"] = args.api_url 52 | if args.api_key: 53 | os.environ["DOLPHINSCHEDULER_API_KEY"] = args.api_key 54 | 55 | # Check if API URL and key are set 56 | if "DOLPHINSCHEDULER_API_URL" not in os.environ: 57 | print("Warning: DOLPHINSCHEDULER_API_URL environment variable is not set.") 58 | print("Using default: http://localhost:12345/dolphinscheduler") 59 | 60 | if "DOLPHINSCHEDULER_API_KEY" not in os.environ: 61 | print("Warning: DOLPHINSCHEDULER_API_KEY environment variable is not set.") 62 | print("Authentication to the DolphinScheduler API may fail.") 63 | 64 | # Set logging level 65 | os.environ["DOLPHINSCHEDULER_MCP_LOG_LEVEL"] = args.log_level 66 | 67 | # Run the server 68 | try: 69 | run_server(host=args.host, port=args.port) 70 | return 0 71 | except KeyboardInterrupt: 72 | print("\nServer stopped by user") 73 | return 0 74 | except Exception as e: 75 | print(f"Error running server: {e}") 76 | return 1 77 | 78 | 79 | if __name__ == "__main__": 80 | sys.exit(main()) ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/project_worker_group_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tools for project worker group operations in DolphinScheduler.""" 2 | 3 | from typing import Dict, List, Optional 4 | 5 | from ..fastmcp_compat import FastMCPTool 6 | 7 | from ..client import DolphinSchedulerClient 8 | 9 | 10 | class GetProjectsWorkerGroup(FastMCPTool): 11 | """Tool to query_worker_group_list""" 12 | 13 | name = "get_projects_worker_group" 14 | description = "QUERY_WORKER_GROUP_LIST" 15 | is_async = True 16 | schema = { 17 | "type": "object", 18 | "properties": { 19 | "project_code": { 20 | "type": "integer", 21 | "format": "int64", 22 | "description": "\u9879\u76eeCode" 23 | } 24 | }, 25 | "required": [ 26 | "project_code" 27 | ] 28 | } 29 | 30 | async def _run(self, project_code) -> Dict: 31 | """Execute the GET operation on /projects/{projectCode}/worker-group.""" 32 | client = DolphinSchedulerClient() 33 | try: 34 | response = await client.request( 35 | "GET", 36 | f"/projects/{project_code}/worker-group" 37 | ) 38 | return {"success": True, "data": response} 39 | finally: 40 | await client.close() 41 | 42 | 43 | class CreateProjectsWorkerGroup(FastMCPTool): 44 | """Tool to assign_worker_groups_notes""" 45 | 46 | name = "create_projects_worker_group" 47 | description = "ASSIGN_WORKER_GROUPS_NOTES" 48 | is_async = True 49 | schema = { 50 | "type": "object", 51 | "properties": { 52 | "project_code": { 53 | "type": "integer", 54 | "format": "int64", 55 | "description": "\u9879\u76eeCode" 56 | }, 57 | "worker_groups": { 58 | "type": "string", 59 | "description": "Worker\u5de5\u4f5c\u7ec4\u5217\u8868" 60 | } 61 | }, 62 | "required": [ 63 | "project_code" 64 | ] 65 | } 66 | 67 | async def _run(self, project_code, worker_groups) -> Dict: 68 | """Execute the POST operation on /projects/{projectCode}/worker-group.""" 69 | client = DolphinSchedulerClient() 70 | try: 71 | response = await client.request( 72 | "POST", 73 | f"/projects/{project_code}/worker-group" 74 | ) 75 | return {"success": True, "data": response} 76 | finally: 77 | await client.close() 78 | 79 | 80 | def register_project_worker_group_tools(mcp): 81 | """Register project worker group tools with FastMCP. 82 | 83 | Args: 84 | mcp: The FastMCP instance to register tools with. 85 | """ 86 | from ..fastmcp_compat import register_tool_class 87 | 88 | register_tool_class(mcp, CreateProjectsWorkerGroup) 89 | register_tool_class(mcp, GetProjectsWorkerGroup) 90 | ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/environment_update_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tool for updating environment settings.""" 2 | 3 | import json 4 | import logging 5 | import os 6 | from typing import Dict, Any, Optional 7 | 8 | from ..client import DolphinSchedulerClient 9 | from ..config import Config 10 | from ..fastmcp_compat import FastMCPTool 11 | 12 | 13 | class UpdateEnvironmentSettings(FastMCPTool): 14 | """Tool for updating the environment settings for DolphinScheduler API.""" 15 | 16 | name = "update_connection_settings" 17 | description = "更新DolphinScheduler API连接设置" 18 | is_async = True 19 | 20 | schema = { 21 | "type": "object", 22 | "properties": { 23 | "id": { 24 | "type": "string", 25 | "description": "No description" 26 | }, 27 | "api_url": { 28 | "type": "string", 29 | "description": "New API URL to set" 30 | }, 31 | "api_key": { 32 | "type": "string", 33 | "description": "New API key to set" 34 | } 35 | }, 36 | "required": [] 37 | } 38 | 39 | async def _run(self, id: Optional[str] = None, api_url: Optional[str] = None, api_key: Optional[str] = None) -> \ 40 | Dict[str, Any]: 41 | """Update the environment settings. 42 | 43 | Args: 44 | id: Not used, included for compatibility with FastMCP 45 | api_url: New API URL to set (optional) 46 | api_key: New API key to set (optional) 47 | 48 | Returns: 49 | Dictionary containing updated settings 50 | """ 51 | logger = logging.getLogger("dolphinscheduler_mcp.tools.update_env") 52 | 53 | try: 54 | config = Config() 55 | 56 | # Update API URL if provided 57 | if api_url is not None: 58 | logger.info(f"Updating API URL to: {api_url}") 59 | config.api_url = api_url 60 | os.environ["DOLPHINSCHEDULER_API_URL"] = api_url 61 | 62 | # Update API key if provided 63 | if api_key is not None: 64 | logger.info("Updating API key") 65 | config.api_key = api_key 66 | os.environ["DOLPHINSCHEDULER_API_KEY"] = api_key 67 | 68 | return { 69 | "success": True, 70 | "api_url": config.api_url, 71 | "has_api_key": config.has_api_key() 72 | } 73 | except Exception as e: 74 | logger.error(f"Error updating environment settings: {e}") 75 | return { 76 | "success": False, 77 | "error": str(e) 78 | } 79 | 80 | 81 | def register_environment_update_tools(mcp): 82 | """Register environment update tools with FastMCP. 83 | 84 | Args: 85 | mcp: The FastMCP instance to register tools with. 86 | """ 87 | from ..fastmcp_compat import register_tool_class 88 | 89 | register_tool_class(mcp, UpdateEnvironmentSettings) 90 | ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/26_user_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "ResultUser": { 5 | "type": "object", 6 | "properties": { 7 | "code": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "msg": { 12 | "type": "string" 13 | }, 14 | "data": { 15 | "$ref": "#/components/schemas/User" 16 | }, 17 | "failed": { 18 | "type": "boolean" 19 | }, 20 | "success": { 21 | "type": "boolean" 22 | } 23 | } 24 | }, 25 | "User": { 26 | "type": "object", 27 | "properties": { 28 | "id": { 29 | "type": "integer", 30 | "format": "int32" 31 | }, 32 | "userName": { 33 | "type": "string" 34 | }, 35 | "userPassword": { 36 | "type": "string" 37 | }, 38 | "email": { 39 | "type": "string" 40 | }, 41 | "phone": { 42 | "type": "string" 43 | }, 44 | "userType": { 45 | "type": "string", 46 | "enum": [ 47 | "ADMIN_USER", 48 | "GENERAL_USER" 49 | ] 50 | }, 51 | "tenantId": { 52 | "type": "integer", 53 | "format": "int32" 54 | }, 55 | "state": { 56 | "type": "integer", 57 | "format": "int32" 58 | }, 59 | "tenantCode": { 60 | "type": "string" 61 | }, 62 | "queueName": { 63 | "type": "string" 64 | }, 65 | "alertGroup": { 66 | "type": "string" 67 | }, 68 | "queue": { 69 | "type": "string" 70 | }, 71 | "timeZone": { 72 | "type": "string" 73 | }, 74 | "createTime": { 75 | "type": "string", 76 | "format": "date-time" 77 | }, 78 | "updateTime": { 79 | "type": "string", 80 | "format": "date-time" 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/14_remaining_3_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "Property": { 5 | "type": "object", 6 | "properties": { 7 | "prop": { 8 | "type": "string" 9 | }, 10 | "direct": { 11 | "type": "string", 12 | "enum": [ 13 | "IN", 14 | "OUT" 15 | ] 16 | }, 17 | "type": { 18 | "type": "string", 19 | "enum": [ 20 | "VARCHAR", 21 | "INTEGER", 22 | "LONG", 23 | "FLOAT", 24 | "DOUBLE", 25 | "DATE", 26 | "TIME", 27 | "TIMESTAMP", 28 | "BOOLEAN", 29 | "LIST", 30 | "FILE" 31 | ] 32 | }, 33 | "value": { 34 | "type": "string" 35 | } 36 | } 37 | }, 38 | "StateDesc": { 39 | "type": "object", 40 | "properties": { 41 | "time": { 42 | "type": "string", 43 | "format": "date-time" 44 | }, 45 | "state": { 46 | "type": "string", 47 | "enum": [ 48 | "WorkflowExecutionStatus{code=0, desc='submit success'}", 49 | "WorkflowExecutionStatus{code=1, desc='running'}", 50 | "WorkflowExecutionStatus{code=2, desc='ready pause'}", 51 | "WorkflowExecutionStatus{code=3, desc='pause'}", 52 | "WorkflowExecutionStatus{code=4, desc='ready stop'}", 53 | "WorkflowExecutionStatus{code=5, desc='stop'}", 54 | "WorkflowExecutionStatus{code=6, desc='failure'}", 55 | "WorkflowExecutionStatus{code=7, desc='success'}", 56 | "WorkflowExecutionStatus{code=12, desc='delay execution'}", 57 | "WorkflowExecutionStatus{code=14, desc='serial wait'}", 58 | "WorkflowExecutionStatus{code=15, desc='ready block'}", 59 | "WorkflowExecutionStatus{code=16, desc='block'}", 60 | "WorkflowExecutionStatus{code=17, desc='wait to run'}" 61 | ] 62 | }, 63 | "desc": { 64 | "type": "string" 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/12_favourite_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/favourite/{taskType}": { 4 | "post": { 5 | "tags": [ 6 | "偏好相关操作" 7 | ], 8 | "summary": "addTaskType", 9 | "description": "添加任务类型", 10 | "operationId": "addFavTask", 11 | "parameters": [ 12 | { 13 | "name": "taskType", 14 | "in": "path", 15 | "required": true, 16 | "schema": { 17 | "type": "string" 18 | } 19 | } 20 | ], 21 | "responses": { 22 | "200": { 23 | "description": "OK", 24 | "content": { 25 | "*/*": { 26 | "schema": { 27 | "$ref": "#/components/schemas/Result" 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }, 34 | "delete": { 35 | "tags": [ 36 | "偏好相关操作" 37 | ], 38 | "summary": "deleteTaskType", 39 | "description": "删除任务类型", 40 | "operationId": "deleteFavTask", 41 | "parameters": [ 42 | { 43 | "name": "taskType", 44 | "in": "path", 45 | "required": true, 46 | "schema": { 47 | "type": "string" 48 | } 49 | } 50 | ], 51 | "responses": { 52 | "200": { 53 | "description": "OK", 54 | "content": { 55 | "*/*": { 56 | "schema": { 57 | "$ref": "#/components/schemas/Result" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | }, 65 | "/favourite/taskTypes": { 66 | "get": { 67 | "tags": [ 68 | "偏好相关操作" 69 | ], 70 | "summary": "listTaskType", 71 | "description": "查询任务类型列表", 72 | "operationId": "listTaskType", 73 | "responses": { 74 | "200": { 75 | "description": "OK", 76 | "content": { 77 | "*/*": { 78 | "schema": { 79 | "$ref": "#/components/schemas/Result" 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/__init__.py: -------------------------------------------------------------------------------- ```python 1 | # __init__.py 2 | """Tools package for DolphinScheduler MCP.""" 3 | 4 | from mcp.server.fastmcp import FastMCP 5 | 6 | # Import registration functions for each tool module 7 | from .azure_data_factory_tools import register_azure_data_factory_tools 8 | from .dynamic_task_type_tools import register_dynamic_task_type_tools 9 | from .k8s_namespace_tools import register_k8s_namespace_tools 10 | from .project_worker_group_tools import register_project_worker_group_tools 11 | from .ui_plugin_tools import register_ui_plugin_tools 12 | from .worker_group_tools import register_worker_group_tools 13 | from .project_tools import register_project_tools 14 | from .datasource_tools import register_datasource_tools 15 | from .project_parameter_tools import register_project_parameter_tools 16 | from .lineage_tools import register_lineage_tools 17 | from .audit_log_tools import register_audit_log_tools 18 | from .access_token_tools import register_access_token_tools 19 | from .project_preference_tools import register_project_preference_tools 20 | from .environment_check_tools import register_environment_check_tools 21 | from .environment_update_tools import register_environment_update_tools 22 | from .process_task_relation_tools import register_process_task_relation_tools 23 | 24 | # The all_tools list is no longer used since we now rely on registration functions 25 | all_tools = [] 26 | 27 | 28 | def register_all_tools(mcp: FastMCP) -> None: 29 | """Register all available tools with the FastMCP instance. 30 | 31 | Args: 32 | mcp: The FastMCP instance to register tools with. 33 | """ 34 | # Register Cloud-related Tools (e.g., Azure Data Factory) 35 | register_azure_data_factory_tools(mcp) 36 | 37 | # Register Dynamic Task Type Tools 38 | register_dynamic_task_type_tools(mcp) 39 | 40 | # Register Kubernetes Namespace Tools 41 | register_k8s_namespace_tools(mcp) 42 | 43 | # Register Project Worker Group Tools 44 | register_project_worker_group_tools(mcp) 45 | 46 | # Register UI Plugin Tools 47 | register_ui_plugin_tools(mcp) 48 | 49 | # Register Worker Group Tools 50 | register_worker_group_tools(mcp) 51 | 52 | # Register Project Management Tools 53 | register_project_tools(mcp) 54 | 55 | # Register Datasource Management Tools 56 | register_datasource_tools(mcp) 57 | 58 | # Register Project Parameter Tools 59 | register_project_parameter_tools(mcp) 60 | 61 | # Register Data Lineage Tools 62 | register_lineage_tools(mcp) 63 | 64 | # Register Audit Log Tools 65 | register_audit_log_tools(mcp) 66 | 67 | # Register Access Token Tools 68 | register_access_token_tools(mcp) 69 | 70 | # Register Project Preference Tools 71 | register_project_preference_tools(mcp) 72 | 73 | # Register Environment Check Tools 74 | register_environment_check_tools(mcp) 75 | 76 | # Register Environment Update Tools 77 | register_environment_update_tools(mcp) 78 | 79 | # Register Process-Task Relation Tools 80 | register_process_task_relation_tools(mcp) 81 | 82 | 83 | __all__ = ["all_tools", "register_all_tools"] 84 | ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/fastmcp_compat.py: -------------------------------------------------------------------------------- ```python 1 | """Compatibility layer for FastMCP. 2 | 3 | This module provides a FastMCPTool class that emulates the old interface, 4 | but actually uses the new MCP API under the hood. 5 | """ 6 | 7 | from typing import Any, Dict, Optional, Type, TypeVar, get_type_hints 8 | import inspect 9 | 10 | from mcp.server.fastmcp import FastMCP 11 | from mcp.server.fastmcp.tools import Tool 12 | from mcp.types import TextContent, ImageContent, EmbeddedResource 13 | 14 | T = TypeVar('T', bound='FastMCPTool') 15 | 16 | 17 | class FastMCPTool: 18 | """Base class for FastMCP tools that emulates the old interface.""" 19 | 20 | name: str 21 | description: str 22 | is_async: bool = True 23 | schema: Dict[str, Any] 24 | 25 | def __init__(self, mcp: FastMCP): 26 | """Initialize the tool with the MCP instance.""" 27 | self.mcp = mcp 28 | self._register() 29 | 30 | def _register(self): 31 | """Register the tool with the MCP instance.""" 32 | if not hasattr(self, '_run'): 33 | raise NotImplementedError(f"Tool {self.__class__.__name__} must implement _run") 34 | 35 | # Get the run method 36 | run_method = getattr(self, '_run') 37 | 38 | # Get the parameters from the type hints 39 | type_hints = get_type_hints(run_method) 40 | 41 | # Remove return type if present 42 | if 'return' in type_hints: 43 | del type_hints['return'] 44 | 45 | # Get the signature 46 | sig = inspect.signature(run_method) 47 | 48 | # Remove 'self' parameter 49 | parameters = list(sig.parameters.values()) 50 | if parameters and parameters[0].name == 'self': 51 | parameters = parameters[1:] 52 | 53 | # 获取 schema 中定义的参数 54 | param_names = [] 55 | if hasattr(self, 'schema') and self.schema and 'properties' in self.schema: 56 | param_names = list(self.schema['properties'].keys()) 57 | else: 58 | param_names = [p.name for p in parameters] 59 | 60 | # 构造接收具体参数的装饰器函数 61 | # 这是为了避免使用 *args, **kwargs 通用参数 62 | param_decl = ", ".join(param_names) 63 | 64 | # 创建工具函数的代码 65 | tool_func_code = f""" 66 | async def tool_fn({param_decl}): 67 | \"\"\" 68 | {self.description} 69 | \"\"\" 70 | # 调用原始 run 方法 71 | result = await self._run({param_decl}) 72 | # 返回文本内容 73 | return TextContent(type="text", text=str(result)) 74 | """ 75 | 76 | # 执行代码创建函数 77 | namespace = { 78 | 'self': self, 79 | 'TextContent': TextContent 80 | } 81 | exec(tool_func_code, namespace) 82 | tool_fn = namespace['tool_fn'] 83 | 84 | # 装饰并注册工具 85 | self.mcp.tool(name=self.name, description=self.description)(tool_fn) 86 | 87 | @classmethod 88 | def register(cls: Type[T], mcp: FastMCP) -> T: 89 | """Register the tool with the MCP instance.""" 90 | return cls(mcp) 91 | 92 | 93 | def register_tool_class(mcp: FastMCP, tool_class: Type[FastMCPTool]) -> FastMCPTool: 94 | """Register a tool class with the MCP instance.""" 95 | return tool_class.register(mcp) ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/01_azure_datafactory_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/cloud/azure/datafactory/resourceGroups": { 4 | "get": { 5 | "tags": [ 6 | "CLOUD_TAG" 7 | ], 8 | "summary": "listResourceGroup", 9 | "description": "LIST_RESOURCE_GROUP", 10 | "operationId": "listResourceGroup", 11 | "responses": { 12 | "200": { 13 | "description": "OK", 14 | "content": { 15 | "*/*": { 16 | "schema": { 17 | "$ref": "#/components/schemas/Result" 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | }, 25 | "/cloud/azure/datafactory/pipelines": { 26 | "get": { 27 | "tags": [ 28 | "CLOUD_TAG" 29 | ], 30 | "summary": "listPipeline", 31 | "description": "LIST_PIPELINE", 32 | "operationId": "listPipeline", 33 | "parameters": [ 34 | { 35 | "name": "factoryName", 36 | "in": "query", 37 | "required": true, 38 | "schema": { 39 | "type": "string" 40 | } 41 | }, 42 | { 43 | "name": "resourceGroupName", 44 | "in": "query", 45 | "required": true, 46 | "schema": { 47 | "type": "string" 48 | } 49 | } 50 | ], 51 | "responses": { 52 | "200": { 53 | "description": "OK", 54 | "content": { 55 | "*/*": { 56 | "schema": { 57 | "$ref": "#/components/schemas/Result" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | }, 65 | "/cloud/azure/datafactory/factories": { 66 | "get": { 67 | "tags": [ 68 | "CLOUD_TAG" 69 | ], 70 | "summary": "listDataFactory", 71 | "description": "LIST_DATA_FACTORY", 72 | "operationId": "listDataFactory", 73 | "responses": { 74 | "200": { 75 | "description": "OK", 76 | "content": { 77 | "*/*": { 78 | "schema": { 79 | "$ref": "#/components/schemas/Result" 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/azure_data_factory_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tools for azure data factory operations in DolphinScheduler.""" 2 | 3 | from typing import Dict, List, Optional 4 | 5 | from ..fastmcp_compat import FastMCPTool 6 | 7 | from ..client import DolphinSchedulerClient 8 | 9 | 10 | class ListCloudAzureDatafactoryResourcegroups(FastMCPTool): 11 | """Tool to list_resource_group""" 12 | 13 | name = "list_cloud_azure_datafactory_resourcegroups" 14 | description = "LIST_RESOURCE_GROUP" 15 | is_async = True 16 | 17 | async def _run(self) -> Dict: 18 | """Execute the GET operation on /cloud/azure/datafactory/resourceGroups.""" 19 | client = DolphinSchedulerClient() 20 | try: 21 | response = await client.request( 22 | "GET", 23 | f"/cloud/azure/datafactory/resourceGroups" 24 | ) 25 | return {"success": True, "data": response} 26 | finally: 27 | await client.close() 28 | 29 | 30 | class ListCloudAzureDatafactoryPipelines(FastMCPTool): 31 | """Tool to list_pipeline""" 32 | 33 | name = "list_cloud_azure_datafactory_pipelines" 34 | description = "LIST_PIPELINE" 35 | is_async = True 36 | schema = { 37 | "type": "object", 38 | "properties": { 39 | "factoryName": { 40 | "type": "string" 41 | }, 42 | "resourceGroupName": { 43 | "type": "string" 44 | } 45 | }, 46 | "required": [ 47 | "factoryName", 48 | "resourceGroupName" 49 | ] 50 | } 51 | 52 | async def _run(self, factoryName, resourceGroupName) -> Dict: 53 | """Execute the GET operation on /cloud/azure/datafactory/pipelines.""" 54 | client = DolphinSchedulerClient() 55 | try: 56 | params = { 57 | "factoryName": factoryName, 58 | "resourceGroupName": resourceGroupName, 59 | } 60 | response = await client.request( 61 | "GET", 62 | f"/cloud/azure/datafactory/pipelines", params=params 63 | ) 64 | return {"success": True, "data": response} 65 | finally: 66 | await client.close() 67 | 68 | 69 | class ListCloudAzureDatafactoryFactories(FastMCPTool): 70 | """Tool to list_data_factory""" 71 | 72 | name = "list_cloud_azure_datafactory_factories" 73 | description = "LIST_DATA_FACTORY" 74 | is_async = True 75 | 76 | async def _run(self) -> Dict: 77 | """Execute the GET operation on /cloud/azure/datafactory/factories.""" 78 | client = DolphinSchedulerClient() 79 | try: 80 | response = await client.request( 81 | "GET", 82 | f"/cloud/azure/datafactory/factories" 83 | ) 84 | return {"success": True, "data": response} 85 | finally: 86 | await client.close() 87 | 88 | 89 | def register_azure_data_factory_tools(mcp): 90 | """Register azure data factory tools with FastMCP. 91 | 92 | Args: 93 | mcp: The FastMCP instance to register tools with. 94 | """ 95 | from ..fastmcp_compat import register_tool_class 96 | 97 | register_tool_class(mcp, ListCloudAzureDatafactoryFactories) 98 | register_tool_class(mcp, ListCloudAzureDatafactoryPipelines) 99 | register_tool_class(mcp, ListCloudAzureDatafactoryResourcegroups) 100 | ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/04_project_worker_group_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/projects/{projectCode}/worker-group": { 4 | "get": { 5 | "tags": [ 6 | "PROJECT_WORKER_GROUP_TAG" 7 | ], 8 | "summary": "queryWorkerGroups", 9 | "description": "QUERY_WORKER_GROUP_LIST", 10 | "operationId": "queryWorkerGroups", 11 | "parameters": [ 12 | { 13 | "name": "projectCode", 14 | "in": "path", 15 | "description": "项目Code", 16 | "required": true, 17 | "schema": { 18 | "type": "integer", 19 | "format": "int64" 20 | } 21 | } 22 | ], 23 | "responses": { 24 | "200": { 25 | "description": "OK", 26 | "content": { 27 | "*/*": { 28 | "schema": { 29 | "type": "object", 30 | "additionalProperties": { 31 | "type": "object" 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | }, 39 | "post": { 40 | "tags": [ 41 | "PROJECT_WORKER_GROUP_TAG" 42 | ], 43 | "summary": "assignWorkerGroups", 44 | "description": "ASSIGN_WORKER_GROUPS_NOTES", 45 | "operationId": "assignWorkerGroups", 46 | "parameters": [ 47 | { 48 | "name": "projectCode", 49 | "in": "path", 50 | "description": "项目Code", 51 | "required": true, 52 | "schema": { 53 | "type": "integer", 54 | "format": "int64" 55 | } 56 | }, 57 | { 58 | "name": "workerGroups", 59 | "description": "Worker工作组列表", 60 | "schema": { 61 | "type": "string" 62 | } 63 | } 64 | ], 65 | "requestBody": { 66 | "content": { 67 | "application/json": { 68 | "schema": { 69 | "type": "array", 70 | "items": { 71 | "type": "string" 72 | } 73 | } 74 | } 75 | } 76 | }, 77 | "responses": { 78 | "201": { 79 | "description": "Created", 80 | "content": { 81 | "*/*": { 82 | "schema": { 83 | "$ref": "#/components/schemas/Result" 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/23_schedule_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "Schedule": { 5 | "type": "object", 6 | "properties": { 7 | "id": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "processDefinitionCode": { 12 | "type": "integer", 13 | "format": "int64" 14 | }, 15 | "processDefinitionName": { 16 | "type": "string" 17 | }, 18 | "projectName": { 19 | "type": "string" 20 | }, 21 | "definitionDescription": { 22 | "type": "string" 23 | }, 24 | "startTime": { 25 | "type": "string", 26 | "format": "date-time" 27 | }, 28 | "endTime": { 29 | "type": "string", 30 | "format": "date-time" 31 | }, 32 | "timezoneId": { 33 | "type": "string" 34 | }, 35 | "crontab": { 36 | "type": "string" 37 | }, 38 | "failureStrategy": { 39 | "type": "string", 40 | "enum": [ 41 | "END", 42 | "CONTINUE" 43 | ] 44 | }, 45 | "warningType": { 46 | "type": "string", 47 | "enum": [ 48 | "NONE", 49 | "SUCCESS", 50 | "FAILURE", 51 | "ALL", 52 | "GLOBAL" 53 | ] 54 | }, 55 | "createTime": { 56 | "type": "string", 57 | "format": "date-time" 58 | }, 59 | "updateTime": { 60 | "type": "string", 61 | "format": "date-time" 62 | }, 63 | "userId": { 64 | "type": "integer", 65 | "format": "int32" 66 | }, 67 | "userName": { 68 | "type": "string" 69 | }, 70 | "releaseState": { 71 | "type": "string", 72 | "enum": [ 73 | "OFFLINE", 74 | "ONLINE" 75 | ] 76 | }, 77 | "warningGroupId": { 78 | "type": "integer", 79 | "format": "int32" 80 | }, 81 | "processInstancePriority": { 82 | "type": "string", 83 | "enum": [ 84 | "HIGHEST", 85 | "HIGH", 86 | "MEDIUM", 87 | "LOW", 88 | "LOWEST" 89 | ] 90 | }, 91 | "workerGroup": { 92 | "type": "string" 93 | }, 94 | "tenantCode": { 95 | "type": "string" 96 | }, 97 | "environmentCode": { 98 | "type": "integer", 99 | "format": "int64" 100 | }, 101 | "environmentName": { 102 | "type": "string" 103 | } 104 | } 105 | } 106 | } 107 | } 108 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/ui_plugin_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tools for ui plugin operations in DolphinScheduler.""" 2 | 3 | from typing import Dict, List, Optional 4 | 5 | from ..fastmcp_compat import FastMCPTool 6 | 7 | from ..client import DolphinSchedulerClient 8 | 9 | 10 | class GetUiPlugins(FastMCPTool): 11 | """Tool to 通过id查询ui插件详情""" 12 | 13 | name = "get_ui_plugins" 14 | description = "通过ID查询UI插件详情" 15 | is_async = True 16 | schema = { 17 | "type": "object", 18 | "properties": { 19 | "id": { 20 | "type": "integer", 21 | "format": "int32", 22 | "description": "\u63d2\u4ef6ID" 23 | } 24 | }, 25 | "required": [ 26 | "id" 27 | ] 28 | } 29 | 30 | async def _run(self, id) -> Dict: 31 | """Execute the GET operation on /ui-plugins/{id}. 32 | 33 | Args: 34 | id: 插件ID 35 | 36 | Returns: 37 | API响应 38 | """ 39 | client = DolphinSchedulerClient() 40 | try: 41 | # 确保路径参数正确处理 42 | plugin_id = int(id) if id is not None else None 43 | if plugin_id is None: 44 | return { 45 | "success": False, 46 | "error": "Missing required parameter: id" 47 | } 48 | 49 | response = await client.request( 50 | "GET", 51 | f"/ui-plugins/{plugin_id}" 52 | ) 53 | return {"success": True, "data": response} 54 | except ValueError: 55 | return { 56 | "success": False, 57 | "error": f"Invalid ID format: {id}" 58 | } 59 | except Exception as e: 60 | return { 61 | "success": False, 62 | "error": str(e) 63 | } 64 | finally: 65 | await client.close() 66 | 67 | 68 | class GetUiPluginsQueryByType(FastMCPTool): 69 | """Tool to 通过类型查询ui插件""" 70 | 71 | name = "get_ui_plugins_query_by_type" 72 | description = "通过类型查询UI插件" 73 | is_async = True 74 | schema = { 75 | "type": "object", 76 | "properties": { 77 | "plugin_type": { 78 | "type": "string", 79 | "enum": [ 80 | "ALERT", 81 | "REGISTER", 82 | "TASK" 83 | ], 84 | "description": "pluginType" 85 | } 86 | }, 87 | "required": [ 88 | "plugin_type" 89 | ] 90 | } 91 | 92 | async def _run(self, plugin_type) -> Dict: 93 | """Execute the GET operation on /ui-plugins/query-by-type. 94 | 95 | Args: 96 | plugin_type: 插件类型 97 | 98 | Returns: 99 | API响应 100 | """ 101 | client = DolphinSchedulerClient() 102 | try: 103 | if not plugin_type: 104 | return { 105 | "success": False, 106 | "error": "Missing required parameter: plugin_type" 107 | } 108 | 109 | params = { 110 | "pluginType": plugin_type, 111 | } 112 | response = await client.request( 113 | "GET", 114 | f"/ui-plugins/query-by-type", 115 | params=params 116 | ) 117 | return {"success": True, "data": response} 118 | except Exception as e: 119 | return { 120 | "success": False, 121 | "error": str(e) 122 | } 123 | finally: 124 | await client.close() 125 | 126 | 127 | def register_ui_plugin_tools(mcp): 128 | """Register ui plugin tool with FastMCP. 129 | 130 | Args: 131 | mcp: The FastMCP instance to register tools with. 132 | """ 133 | from ..fastmcp_compat import register_tool_class 134 | 135 | register_tool_class(mcp, GetUiPlugins) 136 | register_tool_class(mcp, GetUiPluginsQueryByType) 137 | ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/09_remaining_10_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "DatabaseMetrics": { 5 | "type": "object", 6 | "properties": { 7 | "dbType": { 8 | "type": "string", 9 | "enum": [ 10 | "MYSQL", 11 | "MARIADB", 12 | "ORACLE", 13 | "ORACLE_12C", 14 | "DB2", 15 | "H2", 16 | "HSQL", 17 | "SQLITE", 18 | "POSTGRE_SQL", 19 | "SQL_SERVER2005", 20 | "SQL_SERVER", 21 | "DM", 22 | "XU_GU", 23 | "KINGBASE_ES", 24 | "PHOENIX", 25 | "GAUSS", 26 | "CLICK_HOUSE", 27 | "GBASE", 28 | "GBASE_8S", 29 | "GBASEDBT", 30 | "GBASE_INFORMIX", 31 | "OSCAR", 32 | "SYBASE", 33 | "OCEAN_BASE", 34 | "FIREBIRD", 35 | "HIGH_GO", 36 | "CUBRID", 37 | "GOLDILOCKS", 38 | "CSIIDB", 39 | "SAP_HANA", 40 | "IMPALA", 41 | "VERTICA", 42 | "XCloud", 43 | "OTHER" 44 | ] 45 | }, 46 | "state": { 47 | "type": "string", 48 | "enum": [ 49 | "YES", 50 | "NO" 51 | ] 52 | }, 53 | "maxConnections": { 54 | "type": "integer", 55 | "format": "int64" 56 | }, 57 | "maxUsedConnections": { 58 | "type": "integer", 59 | "format": "int64" 60 | }, 61 | "threadsConnections": { 62 | "type": "integer", 63 | "format": "int64" 64 | }, 65 | "threadsRunningConnections": { 66 | "type": "integer", 67 | "format": "int64" 68 | }, 69 | "date": { 70 | "type": "string", 71 | "format": "date-time" 72 | } 73 | } 74 | }, 75 | "DqRule": { 76 | "type": "object", 77 | "properties": { 78 | "id": { 79 | "type": "integer", 80 | "format": "int32" 81 | }, 82 | "name": { 83 | "type": "string" 84 | }, 85 | "type": { 86 | "type": "integer", 87 | "format": "int32" 88 | }, 89 | "ruleJson": { 90 | "type": "string" 91 | }, 92 | "userId": { 93 | "type": "integer", 94 | "format": "int32" 95 | }, 96 | "userName": { 97 | "type": "string" 98 | }, 99 | "createTime": { 100 | "type": "string", 101 | "format": "date-time" 102 | }, 103 | "updateTime": { 104 | "type": "string", 105 | "format": "date-time" 106 | } 107 | } 108 | } 109 | } 110 | } 111 | } ``` -------------------------------------------------------------------------------- /examples/simple_client.py: -------------------------------------------------------------------------------- ```python 1 | #!/usr/bin/env python 2 | """ 3 | A simple example client for the DolphinScheduler MCP server. 4 | This example demonstrates how to use the MCP client to interact with DolphinScheduler. 5 | """ 6 | 7 | import asyncio 8 | import json 9 | import os 10 | from typing import Any, Dict, Optional 11 | 12 | import aiohttp 13 | 14 | 15 | class MCPClient: 16 | """A simple MCP client for DolphinScheduler.""" 17 | 18 | def __init__(self, url: str): 19 | """Initialize the MCP client. 20 | 21 | Args: 22 | url: The URL of the MCP server. 23 | """ 24 | self.url = url 25 | self.session: Optional[aiohttp.ClientSession] = None 26 | 27 | async def __aenter__(self): 28 | """Enter the async context manager.""" 29 | self.session = aiohttp.ClientSession() 30 | return self 31 | 32 | async def __aexit__(self, exc_type, exc_val, exc_tb): 33 | """Exit the async context manager.""" 34 | if self.session: 35 | await self.session.close() 36 | self.session = None 37 | 38 | async def invoke_tool(self, tool_name: str, arguments: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: 39 | """Invoke a tool on the MCP server. 40 | 41 | Args: 42 | tool_name: The name of the tool to invoke. 43 | arguments: Optional arguments for the tool. 44 | 45 | Returns: 46 | The response from the tool. 47 | """ 48 | if self.session is None: 49 | self.session = aiohttp.ClientSession() 50 | 51 | payload = { 52 | "toolName": tool_name, 53 | } 54 | if arguments: 55 | payload["arguments"] = arguments 56 | 57 | async with self.session.post(self.url, json=payload) as response: 58 | return await response.json() 59 | 60 | 61 | async def main(): 62 | """Run the example client.""" 63 | # Set up the MCP server URL 64 | mcp_url = os.environ.get("MCP_URL", "http://localhost:8089/mcp") 65 | 66 | print(f"Connecting to MCP server at {mcp_url}") 67 | 68 | async with MCPClient(mcp_url) as client: 69 | # Get connection settings 70 | print("\n1. Getting connection settings:") 71 | response = await client.invoke_tool("get-connection-settings") 72 | print(json.dumps(response, indent=2)) 73 | 74 | # Get project list 75 | print("\n2. Getting project list:") 76 | response = await client.invoke_tool("get-project-list") 77 | print(json.dumps(response, indent=2)) 78 | 79 | # Create a new project 80 | print("\n3. Creating a new project:") 81 | response = await client.invoke_tool( 82 | "create-project", 83 | {"name": "MCP Demo Project", "description": "Project created by MCP demo"} 84 | ) 85 | print(json.dumps(response, indent=2)) 86 | 87 | # If the project was created successfully, get its code 88 | if response.get("result", {}).get("success", False): 89 | project_code = response.get("result", {}).get("code") 90 | 91 | # Get project details 92 | print(f"\n4. Getting details for project {project_code}:") 93 | response = await client.invoke_tool("get-project", {"project_code": project_code}) 94 | print(json.dumps(response, indent=2)) 95 | 96 | # Create a process definition 97 | print(f"\n5. Creating a process definition in project {project_code}:") 98 | process_def = { 99 | "project_code": project_code, 100 | "name": "MCP Demo Process", 101 | "description": "Process created by MCP demo", 102 | "task_definitions": [], 103 | "execution_type": "PARALLEL" 104 | } 105 | response = await client.invoke_tool("create-process-definition", process_def) 106 | print(json.dumps(response, indent=2)) 107 | 108 | # Delete the project 109 | print(f"\n6. Deleting project {project_code}:") 110 | response = await client.invoke_tool("delete-project", {"project_code": project_code}) 111 | print(json.dumps(response, indent=2)) 112 | 113 | 114 | if __name__ == "__main__": 115 | asyncio.run(main()) ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_loader.py: -------------------------------------------------------------------------------- ```python 1 | """Tool loader for DolphinScheduler MCP. 2 | 3 | This module provides utilities to load tools from the tools directory. 4 | """ 5 | 6 | import importlib 7 | import importlib.util 8 | import os 9 | import sys 10 | import logging 11 | from pathlib import Path 12 | from typing import List, Optional 13 | 14 | from mcp.server.fastmcp import FastMCP 15 | 16 | logger = logging.getLogger(__name__) 17 | 18 | def get_tools_dir() -> Path: 19 | """Get the path to the tools directory. 20 | 21 | Returns: 22 | Path to the tools directory 23 | """ 24 | return Path(__file__).parent / "tools" 25 | 26 | def get_tools_generated_dir() -> Path: 27 | """Get the path to the tools_generated directory. 28 | 29 | Returns: 30 | Path to the tools_generated directory 31 | """ 32 | return Path(__file__).parent / "tools_generated" 33 | 34 | def is_tool_module(filename: str) -> bool: 35 | """Check if a file is a tool module. 36 | 37 | Args: 38 | filename: Filename to check 39 | 40 | Returns: 41 | True if the file is a tool module, False otherwise 42 | """ 43 | return ( 44 | filename.endswith(".py") 45 | and not filename.startswith("__") 46 | and not filename.startswith("_") 47 | ) 48 | 49 | 50 | def get_tool_modules() -> List[str]: 51 | """Get a list of all tool modules. 52 | 53 | Returns: 54 | List of tool module names 55 | """ 56 | tools_dir = get_tools_dir() 57 | if not tools_dir.exists(): 58 | return [] 59 | 60 | return [ 61 | f.stem 62 | for f in tools_dir.glob("*.py") 63 | if is_tool_module(f.name) 64 | ] 65 | 66 | 67 | def import_tools_module(module_name: str) -> Optional[object]: 68 | """Import a tools module. 69 | 70 | Args: 71 | module_name: Name of the module to import 72 | 73 | Returns: 74 | The imported module, or None if the module could not be imported 75 | """ 76 | try: 77 | module = importlib.import_module(f"dolphinscheduler_mcp.tools.{module_name}") 78 | return module 79 | except ImportError as e: 80 | logger.error(f"Error importing module {module_name}: {e}") 81 | return None 82 | 83 | def ensure_env_variables(): 84 | """Ensure environment variables are properly set. 85 | 86 | Logs warnings if required environment variables are missing. 87 | """ 88 | # Check if API URL and key are set in environment variables 89 | api_url = os.environ.get("DOLPHINSCHEDULER_API_URL") 90 | api_key = os.environ.get("DOLPHINSCHEDULER_API_KEY") 91 | 92 | if not api_url: 93 | logger.warning("DOLPHINSCHEDULER_API_URL environment variable is not set.") 94 | logger.warning("Using default URL from Config class.") 95 | else: 96 | logger.info(f"Using API URL: {api_url}") 97 | 98 | if not api_key: 99 | logger.warning("DOLPHINSCHEDULER_API_KEY environment variable is not set.") 100 | logger.warning("Authentication to the DolphinScheduler API may fail.") 101 | else: 102 | logger.info("API Key is set and will be used for authentication") 103 | 104 | def register_all_generated_tools(mcp: FastMCP) -> int: 105 | """Register all tools with FastMCP. 106 | 107 | Args: 108 | mcp: The FastMCP instance to register tools with 109 | 110 | Returns: 111 | Number of modules successfully registered 112 | """ 113 | # Make sure environment variables are properly set 114 | ensure_env_variables() 115 | 116 | try: 117 | # Import the register_all_tools function from tools_generated 118 | from dolphinscheduler_mcp.tools_generated import register_all_tools 119 | 120 | # Register all tools 121 | register_all_tools(mcp) 122 | 123 | # Count the number of tool modules in tools_generated 124 | tools_generated_dir = get_tools_generated_dir() 125 | if tools_generated_dir.exists(): 126 | tool_count = len([ 127 | f for f in tools_generated_dir.glob("*.py") 128 | if is_tool_module(f.name) 129 | ]) 130 | return tool_count 131 | return 0 132 | except ImportError as e: 133 | logger.error(f"Error importing tools_generated: {e}") 134 | return 0 135 | except Exception as e: 136 | logger.error(f"Error registering tools: {e}") 137 | return 0 ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/07_queue_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "Queue": { 5 | "type": "object", 6 | "properties": { 7 | "id": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "queueName": { 12 | "type": "string" 13 | }, 14 | "queue": { 15 | "type": "string" 16 | }, 17 | "createTime": { 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | "updateTime": { 22 | "type": "string", 23 | "format": "date-time" 24 | } 25 | } 26 | }, 27 | "ResultQueue": { 28 | "type": "object", 29 | "properties": { 30 | "code": { 31 | "type": "integer", 32 | "format": "int32" 33 | }, 34 | "msg": { 35 | "type": "string" 36 | }, 37 | "data": { 38 | "$ref": "#/components/schemas/Queue" 39 | }, 40 | "failed": { 41 | "type": "boolean" 42 | }, 43 | "success": { 44 | "type": "boolean" 45 | } 46 | } 47 | }, 48 | "PageInfoQueue": { 49 | "type": "object", 50 | "properties": { 51 | "totalList": { 52 | "type": "array", 53 | "items": { 54 | "$ref": "#/components/schemas/Queue" 55 | } 56 | }, 57 | "total": { 58 | "type": "integer", 59 | "format": "int32" 60 | }, 61 | "totalPage": { 62 | "type": "integer", 63 | "format": "int32" 64 | }, 65 | "pageSize": { 66 | "type": "integer", 67 | "format": "int32" 68 | }, 69 | "currentPage": { 70 | "type": "integer", 71 | "format": "int32" 72 | }, 73 | "pageNo": { 74 | "type": "integer", 75 | "format": "int32" 76 | } 77 | } 78 | }, 79 | "ResultPageInfoQueue": { 80 | "type": "object", 81 | "properties": { 82 | "code": { 83 | "type": "integer", 84 | "format": "int32" 85 | }, 86 | "msg": { 87 | "type": "string" 88 | }, 89 | "data": { 90 | "$ref": "#/components/schemas/PageInfoQueue" 91 | }, 92 | "failed": { 93 | "type": "boolean" 94 | }, 95 | "success": { 96 | "type": "boolean" 97 | } 98 | } 99 | }, 100 | "ResultListQueue": { 101 | "type": "object", 102 | "properties": { 103 | "code": { 104 | "type": "integer", 105 | "format": "int32" 106 | }, 107 | "msg": { 108 | "type": "string" 109 | }, 110 | "data": { 111 | "type": "array", 112 | "items": { 113 | "$ref": "#/components/schemas/Queue" 114 | } 115 | }, 116 | "failed": { 117 | "type": "boolean" 118 | }, 119 | "success": { 120 | "type": "boolean" 121 | } 122 | } 123 | } 124 | } 125 | } 126 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/config.py: -------------------------------------------------------------------------------- ```python 1 | """Configuration for DolphinScheduler MCP.""" 2 | 3 | import os 4 | import json 5 | from pathlib import Path 6 | from typing import Optional, Dict, Any 7 | 8 | def read_mcp_settings() -> Dict[str, Any]: 9 | """Read MCP settings from the Cursor MCP settings file. 10 | 11 | Returns: 12 | A dictionary containing the MCP settings 13 | """ 14 | # Default location for the Cursor MCP settings file 15 | settings_path = os.path.expanduser("~/Library/Application Support/Cursor/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json") 16 | 17 | if os.path.exists(settings_path): 18 | try: 19 | with open(settings_path, 'r') as f: 20 | settings = json.load(f) 21 | return settings 22 | except Exception as e: 23 | print(f"Error reading MCP settings file: {e}") 24 | 25 | return {} 26 | 27 | def get_env_from_mcp_settings() -> Dict[str, str]: 28 | """Get environment variables from MCP settings. 29 | 30 | Returns: 31 | A dictionary containing environment variables 32 | """ 33 | settings = read_mcp_settings() 34 | env_vars = {} 35 | 36 | print("Reading MCP settings:", settings.keys() if settings else "No settings found") 37 | 38 | # Look for the dolphinscheduler server config 39 | if 'mcpServers' in settings and 'dolphinscheduler' in settings['mcpServers']: 40 | server_config = settings['mcpServers']['dolphinscheduler'] 41 | print("Found dolphinscheduler server config:", server_config.keys()) 42 | if 'env' in server_config: 43 | env_vars = server_config['env'] 44 | print("Found environment variables in MCP settings:", env_vars) 45 | 46 | return env_vars 47 | 48 | class Config: 49 | """Configuration for DolphinScheduler MCP.""" 50 | 51 | _instance = None 52 | 53 | def __new__(cls): 54 | """Create a new instance of Config or return the existing one.""" 55 | if cls._instance is None: 56 | cls._instance = super(Config, cls).__new__(cls) 57 | 58 | # First, try to get env variables from MCP settings 59 | mcp_env = get_env_from_mcp_settings() 60 | 61 | # Get API URL from MCP settings, env var, or use default 62 | cls._instance._api_url = mcp_env.get( 63 | "DOLPHINSCHEDULER_API_URL", 64 | os.environ.get( 65 | "DOLPHINSCHEDULER_API_URL", 66 | "http://localhost:12345/dolphinscheduler" 67 | ) 68 | ) 69 | 70 | # Get API key from MCP settings, env var, or use default 71 | cls._instance._api_key = mcp_env.get( 72 | "DOLPHINSCHEDULER_API_KEY", 73 | os.environ.get("DOLPHINSCHEDULER_API_KEY", "") 74 | ) 75 | 76 | # Set the environment variables for other parts of the app 77 | if cls._instance._api_url: 78 | os.environ["DOLPHINSCHEDULER_API_URL"] = cls._instance._api_url 79 | if cls._instance._api_key: 80 | os.environ["DOLPHINSCHEDULER_API_KEY"] = cls._instance._api_key 81 | 82 | return cls._instance 83 | 84 | @property 85 | def api_url(self) -> str: 86 | """Get the API URL. 87 | 88 | Returns: 89 | The API URL. 90 | """ 91 | return self._api_url 92 | 93 | @api_url.setter 94 | def api_url(self, value: str) -> None: 95 | """Set the API URL. 96 | 97 | Args: 98 | value: The API URL. 99 | """ 100 | self._api_url = value 101 | # We could also update the environment variable here 102 | os.environ["DOLPHINSCHEDULER_API_URL"] = value 103 | 104 | @property 105 | def api_key(self) -> str: 106 | """Get the API key. 107 | 108 | Returns: 109 | The API key. 110 | """ 111 | return self._api_key 112 | 113 | @api_key.setter 114 | def api_key(self, value: str) -> None: 115 | """Set the API key. 116 | 117 | Args: 118 | value: The API key. 119 | """ 120 | self._api_key = value 121 | # We could also update the environment variable here 122 | os.environ["DOLPHINSCHEDULER_API_KEY"] = value 123 | 124 | def has_api_key(self) -> bool: 125 | """Check if an API key is set. 126 | 127 | Returns: 128 | True if an API key is set, False otherwise. 129 | """ 130 | return bool(self._api_key) ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/project_preference_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tools for project preference operations in DolphinScheduler.""" 2 | 3 | from typing import Dict, List, Optional 4 | 5 | from ..fastmcp_compat import FastMCPTool 6 | 7 | from ..client import DolphinSchedulerClient 8 | 9 | 10 | class GetProjectsProjectPreference(FastMCPTool): 11 | """Tool to query project preference""" 12 | 13 | name = "get_projects_project_preference" 14 | description = "query project preference" 15 | is_async = True 16 | schema = { 17 | "type": "object", 18 | "properties": { 19 | "project_code": { 20 | "type": "integer", 21 | "format": "int64", 22 | "description": "\u9879\u76eeCode" 23 | } 24 | }, 25 | "required": [ 26 | "project_code" 27 | ] 28 | } 29 | 30 | async def _run(self, project_code) -> Dict: 31 | """Execute the GET operation on /projects/{projectCode}/project-preference.""" 32 | client = DolphinSchedulerClient() 33 | try: 34 | response = await client.request( 35 | "GET", 36 | f"/projects/{project_code}/project-preference" 37 | ) 38 | return {"success": True, "data": response} 39 | finally: 40 | await client.close() 41 | 42 | 43 | class UpdateProjectsProjectPreference(FastMCPTool): 44 | """Tool to update project preference""" 45 | 46 | name = "update_projects_project_preference" 47 | description = "update project preference" 48 | is_async = True 49 | schema = { 50 | "type": "object", 51 | "properties": { 52 | "project_code": { 53 | "type": "integer", 54 | "format": "int64", 55 | "description": "\u9879\u76eeCode" 56 | }, 57 | "project_preferences": { 58 | "type": "string", 59 | "description": "project preferences" 60 | } 61 | }, 62 | "required": [ 63 | "project_code", 64 | "project_preferences" 65 | ] 66 | } 67 | 68 | async def _run(self, project_code, project_preferences) -> Dict: 69 | """Execute the PUT operation on /projects/{projectCode}/project-preference.""" 70 | client = DolphinSchedulerClient() 71 | try: 72 | params = { 73 | "projectPreferences": project_preferences, 74 | } 75 | response = await client.request( 76 | "PUT", 77 | f"/projects/{project_code}/project-preference", params=params 78 | ) 79 | return {"success": True, "data": response} 80 | finally: 81 | await client.close() 82 | 83 | 84 | class CreateProjectsProjectPreference(FastMCPTool): 85 | """Tool to update the state of the project preference""" 86 | 87 | name = "create_projects_project_preference" 88 | description = "update the state of the project preference" 89 | is_async = True 90 | schema = { 91 | "type": "object", 92 | "properties": { 93 | "project_code": { 94 | "type": "integer", 95 | "format": "int64", 96 | "description": "\u9879\u76eeCode" 97 | }, 98 | "state": { 99 | "type": "string", 100 | "description": "the state of the project preference" 101 | } 102 | }, 103 | "required": [ 104 | "project_code", 105 | "state" 106 | ] 107 | } 108 | 109 | async def _run(self, project_code, state) -> Dict: 110 | """Execute the POST operation on /projects/{projectCode}/project-preference.""" 111 | client = DolphinSchedulerClient() 112 | try: 113 | params = { 114 | "state": state, 115 | } 116 | response = await client.request( 117 | "POST", 118 | f"/projects/{project_code}/project-preference", params=params 119 | ) 120 | return {"success": True, "data": response} 121 | finally: 122 | await client.close() 123 | 124 | 125 | def register_project_preference_tools(mcp): 126 | """Register project preference tools with FastMCP. 127 | 128 | Args: 129 | mcp: The FastMCP instance to register tools with. 130 | """ 131 | from ..fastmcp_compat import register_tool_class 132 | 133 | register_tool_class(mcp, CreateProjectsProjectPreference) 134 | register_tool_class(mcp, GetProjectsProjectPreference) 135 | register_tool_class(mcp, UpdateProjectsProjectPreference) 136 | ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/07_project_preference_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/projects/{projectCode}/project-preference": { 4 | "get": { 5 | "tags": [ 6 | "project preference related operation" 7 | ], 8 | "summary": "queryProjectPreferenceByProjectCode", 9 | "description": "query project preference", 10 | "operationId": "queryProjectPreferenceByProjectCode", 11 | "parameters": [ 12 | { 13 | "name": "projectCode", 14 | "in": "path", 15 | "description": "项目Code", 16 | "required": true, 17 | "schema": { 18 | "type": "integer", 19 | "format": "int64" 20 | } 21 | } 22 | ], 23 | "responses": { 24 | "200": { 25 | "description": "OK", 26 | "content": { 27 | "*/*": { 28 | "schema": { 29 | "$ref": "#/components/schemas/Result" 30 | } 31 | } 32 | } 33 | } 34 | } 35 | }, 36 | "put": { 37 | "tags": [ 38 | "project preference related operation" 39 | ], 40 | "summary": "updateProjectPreference", 41 | "description": "update project preference", 42 | "operationId": "updateProjectPreference", 43 | "parameters": [ 44 | { 45 | "name": "projectCode", 46 | "in": "path", 47 | "description": "项目Code", 48 | "required": true, 49 | "schema": { 50 | "type": "integer", 51 | "format": "int64" 52 | } 53 | }, 54 | { 55 | "name": "projectPreferences", 56 | "in": "query", 57 | "description": "project preferences", 58 | "required": true, 59 | "schema": { 60 | "type": "string" 61 | } 62 | } 63 | ], 64 | "responses": { 65 | "201": { 66 | "description": "Created", 67 | "content": { 68 | "*/*": { 69 | "schema": { 70 | "$ref": "#/components/schemas/Result" 71 | } 72 | } 73 | } 74 | } 75 | } 76 | }, 77 | "post": { 78 | "tags": [ 79 | "project preference related operation" 80 | ], 81 | "summary": "enableProjectPreference", 82 | "description": "update the state of the project preference", 83 | "operationId": "enableProjectPreference", 84 | "parameters": [ 85 | { 86 | "name": "projectCode", 87 | "in": "path", 88 | "description": "项目Code", 89 | "required": true, 90 | "schema": { 91 | "type": "integer", 92 | "format": "int64" 93 | } 94 | }, 95 | { 96 | "name": "state", 97 | "in": "query", 98 | "description": "the state of the project preference", 99 | "required": true, 100 | "schema": { 101 | "type": "string" 102 | } 103 | } 104 | ], 105 | "responses": { 106 | "200": { 107 | "description": "OK", 108 | "content": { 109 | "*/*": { 110 | "schema": { 111 | "$ref": "#/components/schemas/Result" 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/25_tenant_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "ResultTenant": { 5 | "type": "object", 6 | "properties": { 7 | "code": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "msg": { 12 | "type": "string" 13 | }, 14 | "data": { 15 | "$ref": "#/components/schemas/Tenant" 16 | }, 17 | "failed": { 18 | "type": "boolean" 19 | }, 20 | "success": { 21 | "type": "boolean" 22 | } 23 | } 24 | }, 25 | "Tenant": { 26 | "type": "object", 27 | "properties": { 28 | "id": { 29 | "type": "integer", 30 | "format": "int32" 31 | }, 32 | "tenantCode": { 33 | "type": "string" 34 | }, 35 | "description": { 36 | "type": "string" 37 | }, 38 | "queueId": { 39 | "type": "integer", 40 | "format": "int32" 41 | }, 42 | "queueName": { 43 | "type": "string" 44 | }, 45 | "queue": { 46 | "type": "string" 47 | }, 48 | "createTime": { 49 | "type": "string", 50 | "format": "date-time" 51 | }, 52 | "updateTime": { 53 | "type": "string", 54 | "format": "date-time" 55 | } 56 | } 57 | }, 58 | "PageInfoTenant": { 59 | "type": "object", 60 | "properties": { 61 | "totalList": { 62 | "type": "array", 63 | "items": { 64 | "$ref": "#/components/schemas/Tenant" 65 | } 66 | }, 67 | "total": { 68 | "type": "integer", 69 | "format": "int32" 70 | }, 71 | "totalPage": { 72 | "type": "integer", 73 | "format": "int32" 74 | }, 75 | "pageSize": { 76 | "type": "integer", 77 | "format": "int32" 78 | }, 79 | "currentPage": { 80 | "type": "integer", 81 | "format": "int32" 82 | }, 83 | "pageNo": { 84 | "type": "integer", 85 | "format": "int32" 86 | } 87 | } 88 | }, 89 | "ResultPageInfoTenant": { 90 | "type": "object", 91 | "properties": { 92 | "code": { 93 | "type": "integer", 94 | "format": "int32" 95 | }, 96 | "msg": { 97 | "type": "string" 98 | }, 99 | "data": { 100 | "$ref": "#/components/schemas/PageInfoTenant" 101 | }, 102 | "failed": { 103 | "type": "boolean" 104 | }, 105 | "success": { 106 | "type": "boolean" 107 | } 108 | } 109 | }, 110 | "ResultListTenant": { 111 | "type": "object", 112 | "properties": { 113 | "code": { 114 | "type": "integer", 115 | "format": "int32" 116 | }, 117 | "msg": { 118 | "type": "string" 119 | }, 120 | "data": { 121 | "type": "array", 122 | "items": { 123 | "$ref": "#/components/schemas/Tenant" 124 | } 125 | }, 126 | "failed": { 127 | "type": "boolean" 128 | }, 129 | "success": { 130 | "type": "boolean" 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } ``` -------------------------------------------------------------------------------- /examples/manage_resources.py: -------------------------------------------------------------------------------- ```python 1 | #!/usr/bin/env python3 2 | """Example script to manage DolphinScheduler resources using the MCP client.""" 3 | 4 | import argparse 5 | import asyncio 6 | import json 7 | import os 8 | import sys 9 | from typing import Dict, Any 10 | 11 | # For local development, add the parent directory to the Python path 12 | sys.path.append(".") 13 | 14 | # Import the MCPClient from simple_client.py 15 | from examples.simple_client import MCPClient 16 | 17 | 18 | async def list_resources(client: MCPClient, args: argparse.Namespace) -> None: 19 | """List resources in DolphinScheduler.""" 20 | parameters: Dict[str, Any] = {} 21 | 22 | if args.pid is not None: 23 | parameters["pid"] = args.pid 24 | 25 | if args.resource_type is not None: 26 | parameters["resource_type"] = args.resource_type 27 | 28 | if args.search_val is not None: 29 | parameters["search_val"] = args.search_val 30 | 31 | response = await client.invoke_tool("get-resource-list", parameters) 32 | 33 | if "result" in response and "data" in response["result"]: 34 | resources = response["result"]["data"] 35 | print(f"Found {len(resources)} resources:") 36 | for resource in resources: 37 | print(f"- {resource.get('name', 'Unknown')} (ID: {resource.get('id', 'Unknown')})") 38 | print(f" Type: {resource.get('type', 'Unknown')}") 39 | if "description" in resource and resource["description"]: 40 | print(f" Description: {resource['description']}") 41 | print() 42 | else: 43 | print("Error or no resources found:") 44 | print(json.dumps(response, indent=2)) 45 | 46 | 47 | async def upload_resource(client: MCPClient, args: argparse.Namespace) -> None: 48 | """Upload a resource to DolphinScheduler.""" 49 | with open(args.file_path, "rb") as file: 50 | file_content = file.read() 51 | 52 | parameters = { 53 | "pid": args.pid, 54 | "name": os.path.basename(args.file_path), 55 | "description": args.description or "", 56 | "content": file_content.decode("utf-8") if args.is_text else "", 57 | "is_text": args.is_text, 58 | } 59 | 60 | response = await client.invoke_tool("create-resource", parameters) 61 | print(json.dumps(response, indent=2)) 62 | 63 | 64 | async def delete_resource(client: MCPClient, args: argparse.Namespace) -> None: 65 | """Delete a resource from DolphinScheduler.""" 66 | parameters = { 67 | "resource_id": args.resource_id 68 | } 69 | 70 | response = await client.invoke_tool("delete-resource", parameters) 71 | print(json.dumps(response, indent=2)) 72 | 73 | 74 | async def main(): 75 | """Manage DolphinScheduler resources using MCP.""" 76 | parser = argparse.ArgumentParser(description="Manage DolphinScheduler resources") 77 | subparsers = parser.add_subparsers(dest="command", help="Command to execute") 78 | 79 | # List resources command 80 | list_parser = subparsers.add_parser("list", help="List resources") 81 | list_parser.add_argument("--pid", type=int, help="Parent directory ID (0 for root)") 82 | list_parser.add_argument("--resource-type", type=str, choices=["FILE", "UDF"], help="Resource type") 83 | list_parser.add_argument("--search-val", type=str, help="Search value") 84 | 85 | # Upload resource command 86 | upload_parser = subparsers.add_parser("upload", help="Upload a resource") 87 | upload_parser.add_argument("--pid", type=int, required=True, help="Parent directory ID") 88 | upload_parser.add_argument("--file-path", type=str, required=True, help="Path to the file to upload") 89 | upload_parser.add_argument("--description", type=str, help="Resource description") 90 | upload_parser.add_argument("--is-text", action="store_true", help="Whether the file is a text file") 91 | 92 | # Delete resource command 93 | delete_parser = subparsers.add_parser("delete", help="Delete a resource") 94 | delete_parser.add_argument("--resource-id", type=int, required=True, help="Resource ID to delete") 95 | 96 | args = parser.parse_args() 97 | 98 | # Set up the MCP server URL 99 | mcp_url = os.environ.get("MCP_URL", "http://localhost:8089/mcp") 100 | 101 | print(f"Connecting to MCP server at {mcp_url}") 102 | 103 | async with MCPClient(mcp_url) as client: 104 | if args.command == "list": 105 | await list_resources(client, args) 106 | elif args.command == "upload": 107 | await upload_resource(client, args) 108 | elif args.command == "delete": 109 | await delete_resource(client, args) 110 | else: 111 | parser.print_help() 112 | 113 | 114 | if __name__ == "__main__": 115 | asyncio.run(main()) ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/10_remaining_11_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "PageInfoDqRule": { 5 | "type": "object", 6 | "properties": { 7 | "totalList": { 8 | "type": "array", 9 | "items": { 10 | "$ref": "#/components/schemas/DqRule" 11 | } 12 | }, 13 | "total": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "totalPage": { 18 | "type": "integer", 19 | "format": "int32" 20 | }, 21 | "pageSize": { 22 | "type": "integer", 23 | "format": "int32" 24 | }, 25 | "currentPage": { 26 | "type": "integer", 27 | "format": "int32" 28 | }, 29 | "pageNo": { 30 | "type": "integer", 31 | "format": "int32" 32 | } 33 | } 34 | }, 35 | "DqExecuteResult": { 36 | "type": "object", 37 | "properties": { 38 | "id": { 39 | "type": "integer", 40 | "format": "int32" 41 | }, 42 | "processDefinitionId": { 43 | "type": "integer", 44 | "format": "int64" 45 | }, 46 | "processDefinitionName": { 47 | "type": "string" 48 | }, 49 | "processDefinitionCode": { 50 | "type": "integer", 51 | "format": "int64" 52 | }, 53 | "processInstanceId": { 54 | "type": "integer", 55 | "format": "int64" 56 | }, 57 | "processInstanceName": { 58 | "type": "string" 59 | }, 60 | "projectCode": { 61 | "type": "integer", 62 | "format": "int64" 63 | }, 64 | "taskInstanceId": { 65 | "type": "integer", 66 | "format": "int64" 67 | }, 68 | "taskName": { 69 | "type": "string" 70 | }, 71 | "ruleType": { 72 | "type": "integer", 73 | "format": "int32" 74 | }, 75 | "ruleName": { 76 | "type": "string" 77 | }, 78 | "statisticsValue": { 79 | "type": "number", 80 | "format": "double" 81 | }, 82 | "comparisonValue": { 83 | "type": "number", 84 | "format": "double" 85 | }, 86 | "comparisonType": { 87 | "type": "integer", 88 | "format": "int32" 89 | }, 90 | "comparisonTypeName": { 91 | "type": "string" 92 | }, 93 | "checkType": { 94 | "type": "integer", 95 | "format": "int32" 96 | }, 97 | "threshold": { 98 | "type": "number", 99 | "format": "double" 100 | }, 101 | "operator": { 102 | "type": "integer", 103 | "format": "int32" 104 | }, 105 | "failureStrategy": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "userId": { 110 | "type": "integer", 111 | "format": "int32" 112 | }, 113 | "userName": { 114 | "type": "string" 115 | }, 116 | "state": { 117 | "type": "integer", 118 | "format": "int32" 119 | }, 120 | "errorOutputPath": { 121 | "type": "string" 122 | }, 123 | "createTime": { 124 | "type": "string", 125 | "format": "date-time" 126 | }, 127 | "updateTime": { 128 | "type": "string", 129 | "format": "date-time" 130 | } 131 | } 132 | } 133 | } 134 | } 135 | } ``` -------------------------------------------------------------------------------- /src/dolphinscheduler_mcp/tools_generated/audit_log_tools.py: -------------------------------------------------------------------------------- ```python 1 | """Tools for audit log operations in DolphinScheduler.""" 2 | 3 | from typing import Dict, List, Optional 4 | 5 | from ..fastmcp_compat import FastMCPTool 6 | 7 | from ..client import DolphinSchedulerClient 8 | 9 | 10 | class GetProjectsAuditAuditLogOperationType(FastMCPTool): 11 | """Tool to query_audit_operation_type_list""" 12 | 13 | name = "get_projects_audit_audit_log_operation_type" 14 | description = "QUERY_AUDIT_OPERATION_TYPE_LIST" 15 | is_async = True 16 | 17 | async def _run(self) -> Dict: 18 | """Execute the GET operation on /projects/audit/audit-log-operation-type.""" 19 | client = DolphinSchedulerClient() 20 | try: 21 | response = await client.request( 22 | "GET", 23 | f"/projects/audit/audit-log-operation-type" 24 | ) 25 | return {"success": True, "data": response} 26 | finally: 27 | await client.close() 28 | 29 | 30 | class GetProjectsAuditAuditLogModelType(FastMCPTool): 31 | """Tool to query_audit_model_type_list""" 32 | 33 | name = "get_projects_audit_audit_log_model_type" 34 | description = "QUERY_AUDIT_MODEL_TYPE_LIST" 35 | is_async = True 36 | 37 | async def _run(self) -> Dict: 38 | """Execute the GET operation on /projects/audit/audit-log-model-type.""" 39 | client = DolphinSchedulerClient() 40 | try: 41 | response = await client.request( 42 | "GET", 43 | f"/projects/audit/audit-log-model-type" 44 | ) 45 | return {"success": True, "data": response} 46 | finally: 47 | await client.close() 48 | 49 | 50 | class GetProjectsAuditAuditLogList(FastMCPTool): 51 | """Tool to 查询审计日志""" 52 | 53 | name = "get_projects_audit_audit_log_list" 54 | description = "查询审计日志" 55 | is_async = True 56 | schema = { 57 | "type": "object", 58 | "properties": { 59 | "page_no": { 60 | "type": "integer", 61 | "format": "int32", 62 | "description": "\u9875\u7801\u53f7" 63 | }, 64 | "page_size": { 65 | "type": "integer", 66 | "format": "int32", 67 | "description": "\u9875\u5927\u5c0f" 68 | }, 69 | "model_types": { 70 | "type": "string" 71 | }, 72 | "operation_types": { 73 | "type": "string", 74 | "description": "OPERATION_TYPES" 75 | }, 76 | "start_date": { 77 | "type": "string", 78 | "description": "\u5f00\u59cb\u65f6\u95f4" 79 | }, 80 | "end_date": { 81 | "type": "string", 82 | "description": "\u7ed3\u675f\u65f6\u95f4" 83 | }, 84 | "user_name": { 85 | "type": "string", 86 | "description": "\u7528\u6237\u540d" 87 | }, 88 | "model_name": { 89 | "type": "string" 90 | }, 91 | "object_types": { 92 | "type": "string", 93 | "description": "MODEL_TYPES" 94 | }, 95 | "object_name": { 96 | "type": "string", 97 | "description": "MODEL_NAME" 98 | } 99 | }, 100 | "required": [ 101 | "page_no", 102 | "page_size" 103 | ] 104 | } 105 | 106 | async def _run(self, page_no, page_size, model_types, operation_types, start_date, end_date, user_name, model_name, object_types, object_name) -> Dict: 107 | """Execute the GET operation on /projects/audit/audit-log-list.""" 108 | client = DolphinSchedulerClient() 109 | try: 110 | params = { 111 | "pageNo": page_no, 112 | "pageSize": page_size, 113 | "modelTypes": model_types, 114 | "operationTypes": operation_types, 115 | "startDate": start_date, 116 | "endDate": end_date, 117 | "userName": user_name, 118 | "modelName": model_name, 119 | } 120 | response = await client.request( 121 | "GET", 122 | f"/projects/audit/audit-log-list", params=params 123 | ) 124 | return {"success": True, "data": response} 125 | finally: 126 | await client.close() 127 | 128 | 129 | def register_audit_log_tools(mcp): 130 | """Register audit log tools with FastMCP. 131 | 132 | Args: 133 | mcp: The FastMCP instance to register tools with. 134 | """ 135 | from ..fastmcp_compat import register_tool_class 136 | 137 | register_tool_class(mcp, GetProjectsAuditAuditLogList) 138 | register_tool_class(mcp, GetProjectsAuditAuditLogModelType) 139 | register_tool_class(mcp, GetProjectsAuditAuditLogOperationType) 140 | ``` -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- ```markdown 1 | # DolphinScheduler MCP Server API 2 | 3 | This document describes the tools available in the DolphinScheduler MCP server and how to use them. 4 | 5 | ## Connection Management Tools 6 | 7 | ### Get Connection Settings 8 | 9 | Retrieves the current connection settings for the DolphinScheduler API. 10 | 11 | **Tool Name:** `get-connection-settings` 12 | 13 | **Arguments:** None 14 | 15 | **Example Request:** 16 | ```json 17 | { 18 | "name": "get-connection-settings" 19 | } 20 | ``` 21 | 22 | **Example Response:** 23 | ```json 24 | { 25 | "url": "http://localhost:12345/dolphinscheduler", 26 | "has_api_key": true 27 | } 28 | ``` 29 | 30 | ### Update Connection Settings 31 | 32 | Updates the connection settings for the DolphinScheduler API. 33 | 34 | **Tool Name:** `update-connection-settings` 35 | 36 | **Arguments:** 37 | - `url` (string, optional): The new DolphinScheduler API URL 38 | - `api_key` (string, optional): The new API key for authentication 39 | 40 | **Example Request:** 41 | ```json 42 | { 43 | "name": "update-connection-settings", 44 | "arguments": { 45 | "url": "http://new-host:12345/dolphinscheduler", 46 | "api_key": "new-api-key" 47 | } 48 | } 49 | ``` 50 | 51 | **Example Response:** 52 | ```json 53 | { 54 | "success": true, 55 | "url": "http://new-host:12345/dolphinscheduler", 56 | "has_api_key": true 57 | } 58 | ``` 59 | 60 | ## Project Management Tools 61 | 62 | ### Get Projects 63 | 64 | Retrieves a list of all projects in DolphinScheduler. 65 | 66 | **Tool Name:** `get-projects` 67 | 68 | **Arguments:** None 69 | 70 | **Example Request:** 71 | ```json 72 | { 73 | "name": "get-projects" 74 | } 75 | ``` 76 | 77 | ### Get Project 78 | 79 | Retrieves details of a specific project. 80 | 81 | **Tool Name:** `get-project` 82 | 83 | **Arguments:** 84 | - `project_id` (integer): The ID of the project to retrieve 85 | 86 | **Example Request:** 87 | ```json 88 | { 89 | "name": "get-project", 90 | "arguments": { 91 | "project_id": 1 92 | } 93 | } 94 | ``` 95 | 96 | ## Workflow Management Tools 97 | 98 | ### Get Workflows 99 | 100 | Retrieves workflows for a specific project. 101 | 102 | **Tool Name:** `get-workflows` 103 | 104 | **Arguments:** 105 | - `project_id` (integer): The ID of the project 106 | 107 | **Example Request:** 108 | ```json 109 | { 110 | "name": "get-workflows", 111 | "arguments": { 112 | "project_id": 1 113 | } 114 | } 115 | ``` 116 | 117 | ### Get Workflow 118 | 119 | Retrieves details of a specific workflow. 120 | 121 | **Tool Name:** `get-workflow` 122 | 123 | **Arguments:** 124 | - `project_id` (integer): The ID of the project 125 | - `workflow_id` (integer): The ID of the workflow 126 | 127 | **Example Request:** 128 | ```json 129 | { 130 | "name": "get-workflow", 131 | "arguments": { 132 | "project_id": 1, 133 | "workflow_id": 1 134 | } 135 | } 136 | ``` 137 | 138 | ## Workflow Instance Management Tools 139 | 140 | ### Get Workflow Instances 141 | 142 | Retrieves workflow instances for a specific project. 143 | 144 | **Tool Name:** `get-workflow-instances` 145 | 146 | **Arguments:** 147 | - `project_id` (integer): The ID of the project 148 | 149 | **Example Request:** 150 | ```json 151 | { 152 | "name": "get-workflow-instances", 153 | "arguments": { 154 | "project_id": 1 155 | } 156 | } 157 | ``` 158 | 159 | ### Get Workflow Instance 160 | 161 | Retrieves details of a specific workflow instance. 162 | 163 | **Tool Name:** `get-workflow-instance` 164 | 165 | **Arguments:** 166 | - `project_id` (integer): The ID of the project 167 | - `instance_id` (integer): The ID of the workflow instance 168 | 169 | **Example Request:** 170 | ```json 171 | { 172 | "name": "get-workflow-instance", 173 | "arguments": { 174 | "project_id": 1, 175 | "instance_id": 1 176 | } 177 | } 178 | ``` 179 | 180 | ### Start Workflow 181 | 182 | Starts a workflow execution. 183 | 184 | **Tool Name:** `start-workflow` 185 | 186 | **Arguments:** 187 | - `project_id` (integer): The ID of the project 188 | - `workflow_id` (integer): The ID of the workflow to execute 189 | - `params` (object, optional): Workflow parameters 190 | 191 | **Example Request:** 192 | ```json 193 | { 194 | "name": "start-workflow", 195 | "arguments": { 196 | "project_id": 1, 197 | "workflow_id": 1, 198 | "params": { 199 | "param1": "value1", 200 | "param2": "value2" 201 | } 202 | } 203 | } 204 | ``` 205 | 206 | ### Stop Workflow Instance 207 | 208 | Stops a running workflow instance. 209 | 210 | **Tool Name:** `stop-workflow-instance` 211 | 212 | **Arguments:** 213 | - `project_id` (integer): The ID of the project 214 | - `instance_id` (integer): The ID of the workflow instance to stop 215 | 216 | **Example Request:** 217 | ```json 218 | { 219 | "name": "stop-workflow-instance", 220 | "arguments": { 221 | "project_id": 1, 222 | "instance_id": 1 223 | } 224 | } 225 | ``` 226 | 227 | ## Task Instance Management Tools 228 | 229 | ### Get Task Instances 230 | 231 | Retrieves task instances for a workflow instance. 232 | 233 | **Tool Name:** `get-task-instances` 234 | 235 | **Arguments:** 236 | - `project_id` (integer): The ID of the project 237 | - `instance_id` (integer): The ID of the workflow instance 238 | 239 | **Example Request:** 240 | ```json 241 | { 242 | "name": "get-task-instances", 243 | "arguments": { 244 | "project_id": 1, 245 | "instance_id": 1 246 | } 247 | } 248 | ``` 249 | 250 | ## System Status Tools 251 | 252 | ### Get System Status 253 | 254 | Retrieves overall system status including master and worker nodes. 255 | 256 | **Tool Name:** `get-system-status` 257 | 258 | **Arguments:** None 259 | 260 | **Example Request:** 261 | ```json 262 | { 263 | "name": "get-system-status" 264 | } 265 | ``` 266 | 267 | ## Resource Management Tools 268 | 269 | ### Get Resources 270 | 271 | Retrieves a list of resources (files and directories). 272 | 273 | **Tool Name:** `get-resources` 274 | 275 | **Arguments:** None 276 | 277 | **Example Request:** 278 | ```json 279 | { 280 | "name": "get-resources" 281 | } 282 | ``` ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/26_login_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/signOut": { 4 | "post": { 5 | "tags": [ 6 | "用户登录相关操作" 7 | ], 8 | "summary": "signOut", 9 | "description": "退出登录", 10 | "operationId": "signOut", 11 | "responses": { 12 | "200": { 13 | "description": "OK", 14 | "content": { 15 | "*/*": { 16 | "schema": { 17 | "$ref": "#/components/schemas/Result" 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | }, 25 | "/login": { 26 | "post": { 27 | "tags": [ 28 | "用户登录相关操作" 29 | ], 30 | "summary": "login", 31 | "description": "用户登录", 32 | "operationId": "login", 33 | "parameters": [ 34 | { 35 | "name": "userName", 36 | "in": "query", 37 | "description": "用户名", 38 | "required": true, 39 | "schema": { 40 | "type": "string" 41 | } 42 | }, 43 | { 44 | "name": "userPassword", 45 | "in": "query", 46 | "description": "用户密码", 47 | "required": true, 48 | "schema": { 49 | "type": "string" 50 | } 51 | } 52 | ], 53 | "responses": { 54 | "200": { 55 | "description": "OK", 56 | "content": { 57 | "*/*": { 58 | "schema": { 59 | "$ref": "#/components/schemas/Result" 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | }, 67 | "/redirect/login/oauth2": { 68 | "get": { 69 | "tags": [ 70 | "用户登录相关操作" 71 | ], 72 | "summary": "redirectToOauth2", 73 | "description": "REDIRECT_TO_OAUTH2_LOGIN", 74 | "operationId": "loginByAuth2", 75 | "parameters": [ 76 | { 77 | "name": "code", 78 | "in": "query", 79 | "required": true, 80 | "schema": { 81 | "type": "string" 82 | } 83 | }, 84 | { 85 | "name": "provider", 86 | "in": "query", 87 | "required": true, 88 | "schema": { 89 | "type": "string" 90 | } 91 | } 92 | ], 93 | "responses": { 94 | "200": { 95 | "description": "OK" 96 | } 97 | } 98 | } 99 | }, 100 | "/oauth2-provider": { 101 | "get": { 102 | "tags": [ 103 | "用户登录相关操作" 104 | ], 105 | "summary": "getOauth2Provider", 106 | "description": "GET_OAUTH2_PROVIDER", 107 | "operationId": "oauth2Provider", 108 | "responses": { 109 | "200": { 110 | "description": "OK", 111 | "content": { 112 | "*/*": { 113 | "schema": { 114 | "$ref": "#/components/schemas/ResultListOAuth2ClientProperties" 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | }, 122 | "/login/sso": { 123 | "get": { 124 | "tags": [ 125 | "用户登录相关操作" 126 | ], 127 | "summary": "sso login", 128 | "description": "user sso login", 129 | "operationId": "ssoLogin", 130 | "responses": { 131 | "200": { 132 | "description": "OK", 133 | "content": { 134 | "*/*": { 135 | "schema": { 136 | "$ref": "#/components/schemas/Result" 137 | } 138 | } 139 | } 140 | } 141 | } 142 | } 143 | }, 144 | "/cookies": { 145 | "delete": { 146 | "tags": [ 147 | "用户登录相关操作" 148 | ], 149 | "operationId": "clearCookieSessionId", 150 | "responses": { 151 | "200": { 152 | "description": "OK" 153 | } 154 | } 155 | } 156 | } 157 | } 158 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/18_remaining_7_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "PageInfoErrorCommand": { 5 | "type": "object", 6 | "properties": { 7 | "totalList": { 8 | "type": "array", 9 | "items": { 10 | "$ref": "#/components/schemas/ErrorCommand" 11 | } 12 | }, 13 | "total": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "totalPage": { 18 | "type": "integer", 19 | "format": "int32" 20 | }, 21 | "pageSize": { 22 | "type": "integer", 23 | "format": "int32" 24 | }, 25 | "currentPage": { 26 | "type": "integer", 27 | "format": "int32" 28 | }, 29 | "pageNo": { 30 | "type": "integer", 31 | "format": "int32" 32 | } 33 | } 34 | }, 35 | "Command": { 36 | "type": "object", 37 | "properties": { 38 | "id": { 39 | "type": "integer", 40 | "format": "int32" 41 | }, 42 | "commandType": { 43 | "type": "string", 44 | "enum": [ 45 | "START_PROCESS", 46 | "START_CURRENT_TASK_PROCESS", 47 | "RECOVER_TOLERANCE_FAULT_PROCESS", 48 | "RECOVER_SUSPENDED_PROCESS", 49 | "START_FAILURE_TASK_PROCESS", 50 | "COMPLEMENT_DATA", 51 | "SCHEDULER", 52 | "REPEAT_RUNNING", 53 | "PAUSE", 54 | "STOP", 55 | "RECOVER_WAITING_THREAD", 56 | "RECOVER_SERIAL_WAIT", 57 | "EXECUTE_TASK", 58 | "DYNAMIC_GENERATION" 59 | ] 60 | }, 61 | "processDefinitionCode": { 62 | "type": "integer", 63 | "format": "int64" 64 | }, 65 | "executorId": { 66 | "type": "integer", 67 | "format": "int32" 68 | }, 69 | "commandParam": { 70 | "type": "string" 71 | }, 72 | "taskDependType": { 73 | "type": "string", 74 | "enum": [ 75 | "TASK_ONLY", 76 | "TASK_PRE", 77 | "TASK_POST" 78 | ] 79 | }, 80 | "failureStrategy": { 81 | "type": "string", 82 | "enum": [ 83 | "END", 84 | "CONTINUE" 85 | ] 86 | }, 87 | "warningType": { 88 | "type": "string", 89 | "enum": [ 90 | "NONE", 91 | "SUCCESS", 92 | "FAILURE", 93 | "ALL", 94 | "GLOBAL" 95 | ] 96 | }, 97 | "warningGroupId": { 98 | "type": "integer", 99 | "format": "int32" 100 | }, 101 | "scheduleTime": { 102 | "type": "string", 103 | "format": "date-time" 104 | }, 105 | "startTime": { 106 | "type": "string", 107 | "format": "date-time" 108 | }, 109 | "processInstancePriority": { 110 | "type": "string", 111 | "enum": [ 112 | "HIGHEST", 113 | "HIGH", 114 | "MEDIUM", 115 | "LOW", 116 | "LOWEST" 117 | ] 118 | }, 119 | "updateTime": { 120 | "type": "string", 121 | "format": "date-time" 122 | }, 123 | "workerGroup": { 124 | "type": "string" 125 | }, 126 | "tenantCode": { 127 | "type": "string" 128 | }, 129 | "environmentCode": { 130 | "type": "integer", 131 | "format": "int64" 132 | }, 133 | "dryRun": { 134 | "type": "integer", 135 | "format": "int32" 136 | }, 137 | "processInstanceId": { 138 | "type": "integer", 139 | "format": "int32" 140 | }, 141 | "processDefinitionVersion": { 142 | "type": "integer", 143 | "format": "int32" 144 | }, 145 | "testFlag": { 146 | "type": "integer", 147 | "format": "int32" 148 | } 149 | } 150 | } 151 | } 152 | } 153 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/03_datasource_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "BaseDataSourceParamDTO": { 5 | "type": "object", 6 | "properties": { 7 | "id": { 8 | "type": "integer", 9 | "format": "int32" 10 | }, 11 | "name": { 12 | "type": "string" 13 | }, 14 | "note": { 15 | "type": "string" 16 | }, 17 | "host": { 18 | "type": "string" 19 | }, 20 | "port": { 21 | "type": "integer", 22 | "format": "int32" 23 | }, 24 | "database": { 25 | "type": "string" 26 | }, 27 | "userName": { 28 | "type": "string" 29 | }, 30 | "password": { 31 | "type": "string" 32 | }, 33 | "other": { 34 | "type": "object", 35 | "additionalProperties": { 36 | "type": "string" 37 | } 38 | }, 39 | "hostAndPortByAddress": { 40 | "type": "string", 41 | "writeOnly": true 42 | }, 43 | "type": { 44 | "type": "string", 45 | "enum": [ 46 | "MYSQL", 47 | "POSTGRESQL", 48 | "HIVE", 49 | "SPARK", 50 | "CLICKHOUSE", 51 | "ORACLE", 52 | "SQLSERVER", 53 | "DB2", 54 | "PRESTO", 55 | "H2", 56 | "REDSHIFT", 57 | "ATHENA", 58 | "TRINO", 59 | "STARROCKS", 60 | "AZURESQL", 61 | "DAMENG", 62 | "OCEANBASE", 63 | "SSH", 64 | "KYUUBI", 65 | "DATABEND", 66 | "SNOWFLAKE", 67 | "VERTICA", 68 | "HANA", 69 | "DORIS", 70 | "ZEPPELIN", 71 | "SAGEMAKER" 72 | ] 73 | } 74 | } 75 | }, 76 | "DataSource": { 77 | "type": "object", 78 | "properties": { 79 | "id": { 80 | "type": "integer", 81 | "format": "int32" 82 | }, 83 | "userId": { 84 | "type": "integer", 85 | "format": "int32" 86 | }, 87 | "userName": { 88 | "type": "string" 89 | }, 90 | "name": { 91 | "type": "string" 92 | }, 93 | "note": { 94 | "type": "string" 95 | }, 96 | "type": { 97 | "type": "string", 98 | "enum": [ 99 | "MYSQL", 100 | "POSTGRESQL", 101 | "HIVE", 102 | "SPARK", 103 | "CLICKHOUSE", 104 | "ORACLE", 105 | "SQLSERVER", 106 | "DB2", 107 | "PRESTO", 108 | "H2", 109 | "REDSHIFT", 110 | "ATHENA", 111 | "TRINO", 112 | "STARROCKS", 113 | "AZURESQL", 114 | "DAMENG", 115 | "OCEANBASE", 116 | "SSH", 117 | "KYUUBI", 118 | "DATABEND", 119 | "SNOWFLAKE", 120 | "VERTICA", 121 | "HANA", 122 | "DORIS", 123 | "ZEPPELIN", 124 | "SAGEMAKER" 125 | ] 126 | }, 127 | "connectionParams": { 128 | "type": "string" 129 | }, 130 | "createTime": { 131 | "type": "string", 132 | "format": "date-time" 133 | }, 134 | "updateTime": { 135 | "type": "string", 136 | "format": "date-time" 137 | } 138 | } 139 | }, 140 | "ResultDataSource": { 141 | "type": "object", 142 | "properties": { 143 | "code": { 144 | "type": "integer", 145 | "format": "int32" 146 | }, 147 | "msg": { 148 | "type": "string" 149 | }, 150 | "data": { 151 | "$ref": "#/components/schemas/DataSource" 152 | }, 153 | "failed": { 154 | "type": "boolean" 155 | }, 156 | "success": { 157 | "type": "boolean" 158 | } 159 | } 160 | } 161 | } 162 | } 163 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/schemas/17_remaining_6_schemas.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "components": { 3 | "schemas": { 4 | "PageInfoAuditDto": { 5 | "type": "object", 6 | "properties": { 7 | "totalList": { 8 | "type": "array", 9 | "items": { 10 | "$ref": "#/components/schemas/AuditDto" 11 | } 12 | }, 13 | "total": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "totalPage": { 18 | "type": "integer", 19 | "format": "int32" 20 | }, 21 | "pageSize": { 22 | "type": "integer", 23 | "format": "int32" 24 | }, 25 | "currentPage": { 26 | "type": "integer", 27 | "format": "int32" 28 | }, 29 | "pageNo": { 30 | "type": "integer", 31 | "format": "int32" 32 | } 33 | } 34 | }, 35 | "ErrorCommand": { 36 | "type": "object", 37 | "properties": { 38 | "id": { 39 | "type": "integer", 40 | "format": "int32" 41 | }, 42 | "commandType": { 43 | "type": "string", 44 | "enum": [ 45 | "START_PROCESS", 46 | "START_CURRENT_TASK_PROCESS", 47 | "RECOVER_TOLERANCE_FAULT_PROCESS", 48 | "RECOVER_SUSPENDED_PROCESS", 49 | "START_FAILURE_TASK_PROCESS", 50 | "COMPLEMENT_DATA", 51 | "SCHEDULER", 52 | "REPEAT_RUNNING", 53 | "PAUSE", 54 | "STOP", 55 | "RECOVER_WAITING_THREAD", 56 | "RECOVER_SERIAL_WAIT", 57 | "EXECUTE_TASK", 58 | "DYNAMIC_GENERATION" 59 | ] 60 | }, 61 | "processDefinitionCode": { 62 | "type": "integer", 63 | "format": "int64" 64 | }, 65 | "processDefinitionVersion": { 66 | "type": "integer", 67 | "format": "int32" 68 | }, 69 | "processInstanceId": { 70 | "type": "integer", 71 | "format": "int32" 72 | }, 73 | "executorId": { 74 | "type": "integer", 75 | "format": "int32" 76 | }, 77 | "commandParam": { 78 | "type": "string" 79 | }, 80 | "taskDependType": { 81 | "type": "string", 82 | "enum": [ 83 | "TASK_ONLY", 84 | "TASK_PRE", 85 | "TASK_POST" 86 | ] 87 | }, 88 | "failureStrategy": { 89 | "type": "string", 90 | "enum": [ 91 | "END", 92 | "CONTINUE" 93 | ] 94 | }, 95 | "warningType": { 96 | "type": "string", 97 | "enum": [ 98 | "NONE", 99 | "SUCCESS", 100 | "FAILURE", 101 | "ALL", 102 | "GLOBAL" 103 | ] 104 | }, 105 | "warningGroupId": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "scheduleTime": { 110 | "type": "string", 111 | "format": "date-time" 112 | }, 113 | "startTime": { 114 | "type": "string", 115 | "format": "date-time" 116 | }, 117 | "processInstancePriority": { 118 | "type": "string", 119 | "enum": [ 120 | "HIGHEST", 121 | "HIGH", 122 | "MEDIUM", 123 | "LOW", 124 | "LOWEST" 125 | ] 126 | }, 127 | "updateTime": { 128 | "type": "string", 129 | "format": "date-time" 130 | }, 131 | "message": { 132 | "type": "string" 133 | }, 134 | "workerGroup": { 135 | "type": "string" 136 | }, 137 | "tenantCode": { 138 | "type": "string" 139 | }, 140 | "environmentCode": { 141 | "type": "integer", 142 | "format": "int64" 143 | }, 144 | "dryRun": { 145 | "type": "integer", 146 | "format": "int32" 147 | }, 148 | "testFlag": { 149 | "type": "integer", 150 | "format": "int32" 151 | } 152 | } 153 | } 154 | } 155 | } 156 | } ``` -------------------------------------------------------------------------------- /mcp-openapi-split/paths/16_audit_log_api.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "paths": { 3 | "/projects/audit/audit-log-operation-type": { 4 | "get": { 5 | "tags": [ 6 | "审计日志执行相关操作" 7 | ], 8 | "summary": "queryAuditOperationTypeList", 9 | "description": "QUERY_AUDIT_OPERATION_TYPE_LIST", 10 | "operationId": "queryAuditOperationTypeList", 11 | "responses": { 12 | "200": { 13 | "description": "OK", 14 | "content": { 15 | "*/*": { 16 | "schema": { 17 | "$ref": "#/components/schemas/ResultListAuditOperationTypeDto" 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | }, 25 | "/projects/audit/audit-log-model-type": { 26 | "get": { 27 | "tags": [ 28 | "审计日志执行相关操作" 29 | ], 30 | "summary": "queryAuditModelTypeList", 31 | "description": "QUERY_AUDIT_MODEL_TYPE_LIST", 32 | "operationId": "queryAuditModelTypeList", 33 | "responses": { 34 | "200": { 35 | "description": "OK", 36 | "content": { 37 | "*/*": { 38 | "schema": { 39 | "$ref": "#/components/schemas/ResultListAuditModelTypeDto" 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }, 47 | "/projects/audit/audit-log-list": { 48 | "get": { 49 | "tags": [ 50 | "审计日志执行相关操作" 51 | ], 52 | "summary": "queryAuditLogListPaging", 53 | "description": "查询审计日志", 54 | "operationId": "queryAuditLogListPaging", 55 | "parameters": [ 56 | { 57 | "name": "pageNo", 58 | "in": "query", 59 | "description": "页码号", 60 | "required": true, 61 | "schema": { 62 | "type": "integer", 63 | "format": "int32" 64 | } 65 | }, 66 | { 67 | "name": "pageSize", 68 | "in": "query", 69 | "description": "页大小", 70 | "required": true, 71 | "schema": { 72 | "type": "integer", 73 | "format": "int32" 74 | } 75 | }, 76 | { 77 | "name": "modelTypes", 78 | "in": "query", 79 | "required": false, 80 | "schema": { 81 | "type": "string" 82 | } 83 | }, 84 | { 85 | "name": "operationTypes", 86 | "in": "query", 87 | "description": "OPERATION_TYPES", 88 | "required": false, 89 | "schema": { 90 | "type": "string" 91 | } 92 | }, 93 | { 94 | "name": "startDate", 95 | "in": "query", 96 | "description": "开始时间", 97 | "required": false, 98 | "schema": { 99 | "type": "string" 100 | } 101 | }, 102 | { 103 | "name": "endDate", 104 | "in": "query", 105 | "description": "结束时间", 106 | "required": false, 107 | "schema": { 108 | "type": "string" 109 | } 110 | }, 111 | { 112 | "name": "userName", 113 | "in": "query", 114 | "description": "用户名", 115 | "required": false, 116 | "schema": { 117 | "type": "string" 118 | } 119 | }, 120 | { 121 | "name": "modelName", 122 | "in": "query", 123 | "required": false, 124 | "schema": { 125 | "type": "string" 126 | } 127 | }, 128 | { 129 | "name": "objectTypes", 130 | "description": "MODEL_TYPES", 131 | "schema": { 132 | "type": "string" 133 | } 134 | }, 135 | { 136 | "name": "objectName", 137 | "description": "MODEL_NAME", 138 | "schema": { 139 | "type": "string" 140 | } 141 | } 142 | ], 143 | "responses": { 144 | "200": { 145 | "description": "OK", 146 | "content": { 147 | "*/*": { 148 | "schema": { 149 | "$ref": "#/components/schemas/ResultPageInfoAuditDto" 150 | } 151 | } 152 | } 153 | } 154 | } 155 | } 156 | } 157 | } 158 | } ```