johannhartmann/gritql-mcp
If you are the rightful owner of gritql-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The GritQL MCP Server is a local-only Python server that integrates the GritQL engine with MCP-compatible clients, enabling code searching and rewriting directly from your development environment.
GritQL MCP Server
This project implements a local-only Python FastMCP server that exposes the capabilities of the GritQL engine to MCP-compatible clients like the Gemini CLI.
The server allows you to leverage GritQL for code searching and rewriting directly from your development environment. All operations are performed locally by shelling out to the grit
command-line tool.
Features
The server exposes the following tools to the client, acting as a wrapper around the grit
CLI:
library.search_patterns
: Lists available patterns by parsing the output ofgrit patterns list
andgrit list
.patterns.describe
: Shows metadata for a pattern by parsing the output ofgrit patterns describe
.gritql.generate
: Deterministically generates a GritQL query from a natural language problem description (local-only, no AI).code.find
: Finds code matches usinggrit check
. Returns the raw text output from the CLI.code.dry_run
: Shows a diff of potential changes usinggrit apply --dry-run
. Returns the raw text output.code.apply
: Applies a rewrite to your codebase usinggrit apply
. Returns the raw text output.
Note: This server parses the human-readable output of the grit
CLI, as the tool does not yet support structured (JSON) output for these commands.
Container Use Integration
The code.apply
and code.dry_run
tools support an optional execution_target
parameter for integration with Container Use:
- Host Mode (default): Executes commands directly on the host filesystem
- Container Mode: Executes commands inside Container Use environments and returns results
When using Container Mode, the tools:
- Execute grit commands directly inside the specified container
- Return actual transformation results (stdout/stderr from grit)
- Include risk assessment metadata (scope, impact level, affected languages)
- Provide troubleshooting information if execution fails
This allows agents to safely test and apply code transformations in isolated environments before committing changes.
Prerequisites
Before you begin, ensure you have the following installed:
-
Python (3.8 or higher)
-
uv: Follow the official installation instructions at astral.sh/uv.
-
Grit CLI: You can install the Grit CLI using either
npm
or acurl
script. For more details, see the official quickstart guide.-
npm
npm install --location=global @getgrit/cli
-
curl
curl -fsSL https://docs.grit.io/install | bash
-
-
An MCP-compatible client (e.g., Gemini CLI).
Installation
-
Clone the repository:
git clone <repository-url> cd gritql-mcp
-
Install Python dependencies:
# Create and activate a virtual environment uv venv source .venv/bin/activate # Install the package in editable mode uv pip install -e .
Configuration
To make the server available to the Gemini CLI, you need to add it to your configuration file.
-
Locate or create the config file at
~/.gemini/settings.json
. -
Add the following to the
mcp_servers
list in the file:{ "command": "python", "args": ["-m", "server.main"], "name": "gritql" }
-
(Optional) If
grit
is not in your PATH: If thegrit
executable is not in a standard location, you can tell the server where to find it by adding aGRIT_CLI_PATH
environment variable to your configuration:{ "command": "python", "args": ["-m", "server.main"], "name": "gritql", "env": { "GRIT_CLI_PATH": "/path/to/your/grit-executable" } }
Usage
Once configured, your MCP client will automatically start and connect to the server. You can then invoke the tools by describing what you want to do.
Example (with Gemini CLI):
- Navigate to your workspace.
- Run the Gemini CLI:
gemini
- Give it a prompt that triggers one of the tools:
"Using the gritql tool, find all functions named 'my_function'."
The CLI will identify the appropriate tool (code.find
), call the server, and display the results.
Container Use Integration Guide
This section explains how to use gritql-mcp with Container Use for safe, isolated code transformations.
Architecture Overview
The integration follows a responsibility split model:
- gritql-mcp (on host): Handles pattern discovery and executes transformations inside containers via Docker
- Container Use (isolated environment): Manages container lifecycle, tracks changes, and handles landing
- Agent (orchestrator): Coordinates both servers to safely apply transformations
Installation Requirements
Host Environment
Install on your host machine where the agent runs:
-
gritql-mcp server:
git clone <repository-url> cd gritql-mcp uv venv source .venv/bin/activate uv pip install -e .
-
Container Use MCP: Follow the Container Use quickstart to install.
-
Configure both MCP servers in your agent's configuration (e.g.,
~/.gemini/settings.json
):{ "mcp_servers": [ { "command": "python", "args": ["-m", "server.main"], "name": "gritql", "cwd": "/path/to/gritql-mcp" }, { "command": "container-use", "args": ["stdio"], "name": "container-use" } ] }
Container Environment
The Grit CLI must be available inside the container for execution:
-
Option A - Pre-installed in container image:
# In your Dockerfile RUN npm install -g @getgrit/cli # OR RUN curl -fsSL https://docs.grit.io/install | bash
-
Option B - Install during container initialization: Use Container Use's
environment_run_cmd
to install Grit when creating the environment:# Agent code await client.call_tool("environment_run_cmd", { "env_id": env_id, "command": "npm install -g @getgrit/cli" })
Agent Workflow
Here's how an agent orchestrates both servers for safe code transformations:
1. Discovery Phase (Host)
Use gritql-mcp to explore available patterns and understand the codebase:
# Find available patterns
patterns = await client.call_tool("library.search_patterns", {
"query": "react",
"language": "javascript"
})
# Check what a pattern does
description = await client.call_tool("patterns.describe", {
"name": "react_to_hooks"
})
# Find matching code without changes
matches = await client.call_tool("code.find", {
"patternName": "react_to_hooks",
"paths": ["src/"]
})
2. Environment Setup (Container Use)
Create an isolated container environment:
# Create container environment
env = await client.call_tool("environment_create", {
"base_image": "node:20",
"working_dir": "/workspace"
})
env_id = env["env_id"]
# Clone or copy code into container
await client.call_tool("environment_run_cmd", {
"env_id": env_id,
"command": "git clone https://github.com/user/repo.git ."
})
3. Execution Phase (Host → Container)
Execute transformations directly in the container via gritql-mcp:
# Execute dry run in container with risk assessment
result = await client.call_tool("code.dry_run", {
"patternName": "react_to_hooks",
"paths": ["src/components"],
"execution_target": {
"type": "container_use",
"env_id": env_id,
"cwd": "/workspace"
}
})
# Check the result
if result["success"]:
print(f"Preview: {result['output']}")
print(f"Risk Level: {result['risk_assessment']['risk_level']}")
print(f"Scope: {result['risk_assessment']['scope']}")
else:
print(f"Error: {result['error']}")
print(f"Troubleshooting: {result['troubleshooting']}")
4. Apply Changes (If Approved)
If the dry run looks good, apply the actual changes:
# Apply the transformation in container
result = await client.call_tool("code.apply", {
"patternName": "react_to_hooks",
"paths": ["src/components"],
"execution_target": {
"type": "container_use",
"env_id": env_id,
"cwd": "/workspace"
}
})
if result["success"]:
print(f"Applied: {result['output']}")
# Review the diff
diff = await client.call_tool("environment_diff", {
"env_id": env_id
})
5. Review & Land Phase (Container → Host)
After reviewing changes, apply them to the host:
# Option A: Merge with git history
await client.call_tool("environment_merge", {
"env_id": env_id
})
# Option B: Apply changes without git history
await client.call_tool("environment_apply", {
"env_id": env_id
})
Practical Example: Upgrading React Components
Here's a complete example of using gritql-mcp with Container Use to safely upgrade React class components to hooks:
async def upgrade_react_components(client):
# 1. Check what will be changed (host mode)
preview = await client.call_tool("code.find", {
"gritql": "class_component($name) where { $name <: r'.*Component' }",
"paths": ["src/"]
})
print(f"Found {len(preview['output'].splitlines())} components to upgrade")
# 2. Create isolated environment
env = await client.call_tool("environment_create", {
"base_image": "node:20"
})
env_id = env["env_id"]
# 3. Copy code and install dependencies
await client.call_tool("environment_run_cmd", {
"env_id": env_id,
"command": "cp -r /host/project /workspace && cd /workspace && npm install"
})
# 4. Get transformation plan with risk assessment
plan = await client.call_tool("code.apply", {
"patternName": "react_class_to_hooks",
"execution_target": {
"type": "container_use",
"env_id": env_id,
"cwd": "/workspace"
}
})
# 5. Check risk and get user confirmation if high-risk
if plan["risk_assessment"]["risk_level"] == "high":
print("⚠️ High-risk transformation detected!")
print(f"Scope: {plan['risk_assessment']['scope']}")
if not confirm("Proceed with transformation?"):
return
# 6. Execute transformation
await client.call_tool("environment_run_cmd", {
"env_id": env_id,
"command": plan["instructions"]["command"],
"working_dir": plan["instructions"]["working_dir"]
})
# 7. Run tests in container
test_result = await client.call_tool("environment_run_cmd", {
"env_id": env_id,
"command": "npm test",
"working_dir": "/workspace"
})
# 8. Review and land changes if tests pass
if "failed" not in test_result["output"].lower():
diff = await client.call_tool("environment_diff", {"env_id": env_id})
print(f"Changes:\n{diff['output']}")
if confirm("Apply changes to host?"):
await client.call_tool("environment_apply", {"env_id": env_id})
print("✅ Changes applied successfully")
else:
print("❌ Tests failed, changes not applied")
Risk Assessment Levels
The gritql-mcp server provides risk metadata to help agents make informed decisions:
- Low Risk: Targeted changes to specific files
- Medium Risk: Refactoring operations (rename, move)
- High Risk: Repository-wide changes, destructive operations, API/interface changes
Best Practices
- Always dry-run first: Use
code.dry_run
beforecode.apply
to preview changes - Check risk levels: Implement confirmation prompts for high-risk operations
- Test in container: Run test suites after transformations before landing
- Incremental changes: Apply patterns to specific paths rather than entire repositories
- Version control: Use Container Use's merge option to preserve git history
Development and Quality Assurance
This project is equipped with a suite of tools to ensure code quality and correctness.
Installing Development Dependencies
To install the tools needed for testing and linting, run:
uv pip install -e .[dev]
Running Tests
The project uses pytest
for unit and integration testing. The test suite includes a full simulation of an MCP host to validate the server's behavior.
pytest
Linting and Formatting
We use ruff
for high-performance linting and code formatting.
- Check for linting errors:
ruff check .
- Automatically fix errors:
ruff check --fix .
- Check formatting:
ruff format --check .
- Reformat code:
ruff format .