Skip to main content
Glama
jermeyyy
by jermeyyy
README.md
<div align="center">

<p align="center">
  <img src="art/gradle_logo.png" alt="Gradle" width="150"/>
</p>

# Gradle MCP Server

**A Model Context Protocol (MCP) server for seamless Gradle integration with AI assistants**

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![FastMCP 2.0+](https://img.shields.io/badge/FastMCP-2.0+-purple.svg)](https://github.com/jlowin/fastmcp)

*Empower your AI coding assistant to build, test, and manage Gradle projects with real-time monitoring*

[Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [Web Dashboard](#-web-dashboard) • [API Reference](#-mcp-tools-api) • [Contributing](#-contributing)

</div>

---

## ✨ Features

### 🛠️ Build Automation
- **Project Discovery** — Automatically detect and list all Gradle projects in your workspace
- **Task Management** — Browse and execute any Gradle task with full argument support
- **Multi-Task Execution** — Run multiple tasks in a single command
- **Safe Cleaning** — Dedicated clean tool prevents accidental artifact deletion

### 📊 Real-Time Monitoring
- **Live Progress Tracking** — Visual progress updates during task execution
- **Web Dashboard** — Browser-based monitoring with WebSocket updates
- **Daemon Management** — Monitor and control Gradle daemon processes
- **Build Logs** — Searchable, real-time build log viewer

### 🔧 Configuration & Diagnostics
- **Config Inspection** — View JVM args, daemon settings, and Gradle version
- **Memory Monitoring** — Track daemon memory usage and health
- **Structured Error Output** — LLM-friendly error responses with deduplicated compilation errors and task failure summaries

---

## 📸 Web Dashboard

The Gradle MCP Server includes a powerful web dashboard for real-time build monitoring. The dashboard starts automatically when the server runs and is accessible at `http://localhost:3333`.

### Dashboard Overview

<p align="center">
  <img src="art/dashboard.png" alt="Gradle MCP Dashboard" width="100%">
</p>

The main dashboard provides:
- **Daemon Status** — Real-time view of running Gradle daemons with PID, status, and memory usage
- **Active Builds** — Live tracking of currently executing tasks
- **Quick Actions** — One-click daemon management (stop all, refresh status)
- **Auto-Refresh** — WebSocket-powered updates without manual refresh

### Build Logs Viewer

<p align="center">
  <img src="art/logs.png" alt="Build Logs Viewer" width="100%">
</p>

The logs viewer offers:
- **Real-Time Streaming** — Watch build output as it happens
- **Log Filtering** — Search and filter through build history
- **Clear Logs** — One-click log clearing for fresh sessions
- **Persistent History** — Logs persist across page refreshes during a session

---

## 📦 Installation

### Requirements

- **Python 3.10+**
- **Gradle project** with wrapper (`gradlew` / `gradlew.bat`)
- **MCP-compatible client** (e.g., Claude Desktop, Cursor, VS Code with Copilot)

### Install from Source

```bash
git clone https://github.com/jermeyyy/gradle-mcp.git
cd gradle-mcp

# Using uv (recommended)
uv sync

# Or using pip
pip install -e .
```

---

## 🚀 Quick Start

### 1. Start the Server

```bash
# Navigate to your Gradle project directory
cd /path/to/your/gradle/project

# Start the MCP server
uv run gradle-mcp
```

The server will:
1. Auto-detect the Gradle wrapper in the current directory
2. Start the web dashboard at `http://localhost:3333` (or higher if port already occupied)
3. Begin listening for MCP client connections

### 2. Configure Your MCP Client

Add the server to your MCP client configuration. For example, in Claude Desktop's `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "gradle": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/path/to/gradle-mcp/installation",
        "gradle-mcp"
      ]
      "env": {
        "GRADLE_PROJECT_ROOT": "/path/to/your/gradle/project"
      }
    }
  }
}
```

### 3. Start Building!

Your AI assistant can now execute Gradle commands:

```
"Build the app module"
"Run all tests except integration tests"
"Show me the available tasks for the core module"
"Check the Gradle daemon status"
```

---

## 🔧 Configuration

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `GRADLE_PROJECT_ROOT` | Root directory of the Gradle project | Current directory |
| `GRADLE_WRAPPER` | Path to Gradle wrapper script | Auto-detected |
| `GRADLE_OPTS` | JVM options for Gradle client | — |
| `JAVA_OPTS` | General Java options | — |

### Example Configuration

```bash
# Custom project location
export GRADLE_PROJECT_ROOT=/path/to/project
uv run gradle-mcp

# Custom wrapper location
export GRADLE_WRAPPER=/path/to/custom/gradlew
uv run gradle-mcp
```

---

## 📚 MCP Tools API

### Project & Task Management

#### `list_projects()`
List all Gradle projects in the workspace.

**Returns:** List of projects with name, path, and description

---

#### `list_project_tasks(project, include_descriptions, group)`
List available tasks for a project, optionally filtered by group.

| Parameter | Type | Description |
|-----------|------|-------------|
| `project` | `str \| None` | Project path (e.g., `:app`). Use `None`, `""`, or `:` for root |
| `include_descriptions` | `bool` | Include task descriptions (default: `False`) |
| `group` | `str \| None` | Filter by task group (e.g., `Build`, `Verification`) |

**Returns:** Grouped list of tasks

---

#### `run_task(task, args)`
Execute one or more Gradle tasks.

| Parameter | Type | Description |
|-----------|------|-------------|
| `task` | `str \| list[str]` | Task(s) to run. Examples: `build`, `:app:build`, `[':core:build', ':app:assemble']` |
| `args` | `list[str] \| None` | Additional Gradle arguments (e.g., `['--info', '-x', 'test']`) |

**Returns:** `TaskResult` with:
- `success: bool` — Whether the task completed successfully
- `error: ErrorInfo | None` — Structured error information (see [Structured Error Output](#structured-error-output))

> ⚠️ **Note:** Cleaning tasks are blocked — use the `clean` tool instead.

---

#### `clean(project)`
Clean build artifacts for a project.

| Parameter | Type | Description |
|-----------|------|-------------|
| `project` | `str \| None` | Project path (e.g., `:app`). Use `None`, `""`, or `:` for root |

**Returns:** `TaskResult` with:
- `success: bool` — Whether clean completed successfully
- `error: ErrorInfo | None` — Structured error information (see [Structured Error Output](#structured-error-output))

---

### Daemon Management

#### `daemon_status()`
Get status of all running Gradle daemons.

**Returns:** Running status, list of daemon info (PID, status, memory), and any errors

---

#### `stop_daemon()`
Stop all Gradle daemons. Useful for freeing memory or resolving daemon issues.

**Returns:** Success status and error message if failed

---

### Configuration

#### `get_gradle_config()`
Get current Gradle configuration including memory settings.

**Returns:** Configuration object with:
- `jvm_args` — JVM arguments from gradle.properties
- `daemon_enabled` — Whether daemon is enabled
- `parallel_enabled` — Whether parallel execution is enabled
- `caching_enabled` — Whether build caching is enabled
- `max_workers` — Maximum worker count
- `distribution_url` — Gradle distribution URL
- `gradle_version` — Gradle version

---

## 💡 Usage Examples

### With MCP Client

```python
# Discover projects
list_projects()

# List build tasks for a module
list_project_tasks(project=":app", group="Build")

# Build with verbose output
run_task(task=":app:build", args=["--info"])

# Run tests, skipping integration tests
run_task(task=":app:test", args=["-x", "integrationTest"])

# Run multiple tasks
run_task(task=[":core:build", ":app:assemble"])

# Check daemon health
daemon_status()

# Free up memory
stop_daemon()
```

### As Python Library

```python
from gradle_mcp.gradle import GradleWrapper

gradle = GradleWrapper("/path/to/gradle/project")

# List projects
projects = gradle.list_projects()
for project in projects:
    print(f"Project: {project.name} at {project.path}")

# List tasks with descriptions
tasks = gradle.list_tasks(":app", include_descriptions=True)
for group in tasks:
    print(f"\n{group.group}:")
    for task in group.tasks:
        print(f"  {task.name}: {task.description}")

# Run a task
result = await gradle.run_task([":app:build"])
if result["success"]:
    print("✅ Build succeeded!")
else:
    print(f"❌ Build failed: {result['error']}")
```

---

## 🏗️ Architecture

### Safety by Design

- **Separated Cleaning** — The `run_task` tool blocks all cleaning operations (`clean`, `cleanBuild`, etc.). Use the dedicated `clean` tool for artifact removal.
- **Gradle Wrapper** — Always uses the project's Gradle wrapper for version consistency
- **Progress Reporting** — Real-time progress via MCP protocol

### Structured Error Output

The `run_task` and `clean` tools return structured error information optimized for LLM consumption:

```python
class ErrorInfo:
    summary: str                        # e.g., "Build failed: 2 tasks failed with 12 compilation errors in 1 file"
    failed_tasks: list[FailedTask]      # List of failed task names and reasons
    compilation_errors: list[CompilationError]  # Deduplicated compilation errors

class CompilationError:
    file: str      # Full path (without file:// prefix)
    line: int
    column: int | None
    message: str

class FailedTask:
    name: str      # e.g., ":app:compileKotlin"
    reason: str    # e.g., "Compilation finished with errors"
```

**Example response:**
```json
{
  "success": false,
  "error": {
    "summary": "Build failed: 2 tasks failed with 2 compilation errors in 1 file",
    "failed_tasks": [
      {"name": ":app:compileKotlin", "reason": "Compilation finished with errors"}
    ],
    "compilation_errors": [
      {
        "file": "/Users/dev/project/src/Main.kt",
        "line": 45,
        "column": 49,
        "message": "Argument type mismatch: actual type is 'String', but 'Int' was expected."
      }
    ]
  }
}
```

**Key features:**
- **Deduplication** — Identical errors from multiple targets (e.g., iOS Arm64 + Simulator) are merged
- **Clean paths** — `file://` prefix is stripped from file paths
- **Concise summaries** — Human-readable summary with task/error/file counts
- **Token efficient** — Structured data instead of raw build output

---

## 🧪 Development

### Setup Development Environment

```bash
# Clone the repository
git clone https://github.com/jermeyyy/gradle-mcp.git
cd gradle-mcp

# Install with dev dependencies
uv sync --all-extras
```

### Run Tests

```bash
pytest tests/
```

### Code Quality

```bash
# Format code
black src/

# Lint code
ruff check src/

# Type checking
mypy src/
```

### Project Structure

```
gradle-mcp/
├── src/gradle_mcp/
│   ├── __init__.py           # Package initialization
│   ├── server.py             # MCP server implementation
│   ├── gradle.py             # Gradle wrapper interface
│   └── dashboard/            # Web dashboard
│       ├── app.py            # Flask application
│       ├── daemon_monitor.py # Daemon monitoring
│       ├── log_store.py      # Log management
│       ├── templates/        # HTML templates
│       └── static/           # CSS/JS assets
├── tests/                    # Test suite
├── art/                      # Screenshots and artwork
├── pyproject.toml            # Project configuration
└── README.md
```

---

## 🤝 Contributing

Contributions are welcome! Here's how you can help:

1. **Fork** the repository
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
4. **Push** to the branch (`git push origin feature/amazing-feature`)
5. **Open** a Pull Request

### Ideas for Contribution

- [ ] Additional build system support (Maven, Bazel)
- [ ] Enhanced error visualization in dashboard
- [ ] Build statistics and history
- [ ] Custom task presets

---

## 📄 License

This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.

---

<div align="center">

**Built with ❤️ for the Gradle and AI community**

[Report Bug](https://github.com/jermeyyy/gradle-mcp/issues) • [Request Feature](https://github.com/jermeyyy/gradle-mcp/issues)

</div>

TDQS

A3.9/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a distinct purpose with clear boundaries: clean removes artifacts, daemon_status monitors daemons, get_gradle_config retrieves configuration, list_projects enumerates projects, list_project_tasks shows available tasks, run_task executes tasks, and stop_daemon terminates daemons. There is no overlap or ambiguity between these functions.

Naming Consistency4/5

Tools follow a consistent verb_noun pattern (e.g., clean, daemon_status, get_gradle_config, list_projects, list_project_tasks, run_task, stop_daemon), with all using snake_case. The minor deviation is 'get_gradle_config' using 'get_' prefix while others like 'list_' or 'run_' use different verbs, but overall naming is predictable and readable.

Tool Count5/5

With 7 tools, the server is well-scoped for Gradle project management. It covers essential operations like cleaning, task execution, project listing, configuration retrieval, and daemon control, without being overly sparse or bloated. Each tool serves a clear purpose in the domain.

Completeness4/5

The toolset provides comprehensive coverage for core Gradle workflows, including project discovery, task management, execution, and daemon handling. A minor gap is the lack of tools for modifying configuration (e.g., updating gradle.properties) or advanced operations like dependency management, but agents can work around this with existing tools for most common tasks.

Maintenance

ActivityInactive
ResponsivenessNo issues