
This is a PySpark migration and optimization toolkit built on SQLGlot. It converts SQL between dialects (PostgreSQL, Oracle, Redshift, MySQL, Snowflake) and generates PySpark DataFrame API code from SQL queries. The AWS Glue integration generates complete job templates, handles DynamicFrame conversions, and analyzes S3 partitioning strategies. You also get code review tools that scan existing PySpark for performance issues, suggest join strategies, and detect duplication across hundreds of files with concurrent batch processing. Reach for this when migrating legacy SQL workloads to Spark or when you need to generate Glue jobs without writing boilerplate. It won't handle recursive CTEs natively but provides Spark SQL equivalents and guidance for edge cases.
SQL migration assistance, AWS Glue job template generation, and Spark code optimization — as an MCP server.
Not the live-Spark
pyspark-mcppackage. This project is SQL → PySpark / Glue source generation, published aspyspark-tools. SemyonSinchenko/pyspark-mcp introspects a running SparkSession. A deprecatedpyspark-mcpconsole script remains here so old configs keep working; it prints a warning, then starts this server.
optimize(mode="code") returns suggestions; it does not rewrite your codeglue_s3 is a path heuristic (no AWS call, no measured speedups)SQLGlot already transpiles dialects. This MCP adds three things around that kernel: DataFrame-API pretty-printing with join/window/cast mappings that the conversion tests lock, Glue job boilerplate strings (bookmarks, DynamicFrames, catalog tables) so an agent can emit a file instead of assembling one, and a 14-tool FastMCP surface so an LLM picks convert / mode=sql instead of wiring sqlglot itself. If you only need sqlglot.transpile(...), use sqlglot.
pip install pyspark-tools
pyspark-tools
Zero-clone alternative: uvx pyspark-tools. run_server.py is a development convenience that inserts sys.path and prints startup banners. Prefer pyspark-tools in configs and production.
pip install pyspark-tools
python -c "from pathlib import Path; from pyspark_tools.sql_converter import SQLToPySparkConverter as C; from pyspark_tools.consolidated_tools import glue_job; c,s,o=C(),Path('examples'),Path('examples/out'); [(o/f'{n}.py').write_text(c.convert_sql_to_pyspark((s/f'{n}.sql').read_text(), dialect=d).pyspark_code) for n,d in [('postgres_orders','postgres'),('oracle_decode','oracle')]]; (o/'orders_etl_glue.py').write_text(glue_job(mode='template', job_name='orders_etl', sql_query=(s/'postgres_orders.sql').read_text())['template'])"
Writes the same files as examples/out/. MCP stdio CLI: pyspark-tools.
SELECT o.customer_id, c.name, SUM(o.amount) AS total
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.status = 'paid'
GROUP BY o.customer_id, c.name
Call convert with mode=sql. Captured converter output (dialect=spark):
from pyspark.sql import SparkSession
from pyspark.sql.functions import (
col, lit, when, count, sum as spark_sum, avg, min, max, countDistinct,
coalesce, concat, datediff, date_add, to_date,
row_number, rank, lag, lead,
)
from pyspark.sql.window import Window
# Generated from SPARK SQL
spark = SparkSession.builder.appName('SQLToPySpark').getOrCreate()
# Load table: customers
customers_df = spark.table('customers')
# Load table: orders
orders_df = spark.table('orders')
# Main query
result_df = (orders_df.alias('o')
.join(customers_df.alias('c'), (col('o.customer_id') == col('c.id')), 'inner')
.filter((col('o.status') == lit('paid')))
.groupBy(col('o.customer_id'), col('c.name'))
.select(col('o.customer_id'), col('c.name'), (spark_sum(col('o.amount'))).alias('total')))
Exact output depends on dialect detection and fallbacks; conversion tests in tests/test_sql_conversion_fixes.py pin the important constructs. Notebook-style import * / show() is opt-in via style="notebook" on the converter.
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"pyspark": {
"command": "pyspark-tools",
"args": []
}
}
}
Add to ~/.hermes/config.yaml:
mcp:
servers:
pyspark:
command: pyspark-tools
enabled_tools: all
The image is stdio only (FastMCP over stdin/stdout). There is no HTTP server
on port 8000. docker compose up is for local tests, not a health-checkable
web service.
docker compose --profile test run --rm pyspark-tools-test
Three primary tools. The other eleven routers stay registered this minor
version but are deprecated — prefer convert, glue_job, and review.
convert — SQL → PySpark (including mode=batch_dir)convert(mode="sql", sql_query="SELECT id FROM users", dialect="postgres")
convert(mode="batch_dir", directory_path="etl/", output_dir="out")
glue_job — Glue 5.0 job template stringsglue_job(mode="template", job_name="orders_etl", sql_query="SELECT * FROM orders")
review — code review, patterns, duplicatesreview(mode="code", code="df = spark.table('t')\ndf.collect()")
Legacy / deprecated: analyze, optimize, glue_schema, glue_s3,
glue_data, refactor, search, context, batch_status, s3_source,
analytics. Still callable; do not advertise to new agents.
This MCP can read local files (SQL, TXT, PDF) and, if the [aws] extra is installed, list/read S3 with the host's default AWS credentials. File tools only allow paths under the process working directory (or an explicit base_path / FileHandler(base_directory=...)). That is not a sandbox.
Run the server under a restricted OS account. Do not point it at secrets directories. Do not attach AWS credentials with write access unless you intend S3 reads via s3_source / glue_s3. Optional extras:
pip install "pyspark-tools[aws]" # boto3 for S3/Glue catalog helpers
pip install "pyspark-tools[spark]" # pyspark — not required at runtime; generated code only
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Test
pytest tests/ -v --cov=pyspark_tools
# Format
black pyspark_tools tests
isort pyspark_tools tests
# Lint
flake8 pyspark_tools tests
Requires Python 3.11+ (matches the CI matrix).
pyspark_tools/
├── server.py # FastMCP server + helper implementations
├── consolidated_tools.py # 14 @app.tool() routers
├── sql_converter.py # SQLGlot-based transpilation + DataFrame API generation
├── aws_glue_integration.py # Glue job templates, DynamicFrame, Data Catalog
├── advanced_optimizer.py # Performance analysis + optimization suggestions
├── batch_processor.py # Concurrent file processing
├── code_reviewer.py # PySpark code review patterns
├── duplicate_detector.py # Code deduplication
├── data_source_analyzer.py # Data source analysis (optional boto3)
└── file_utils.py # File I/O with allow-root checks
MIT — see LICENSE.
mcp-name: io.github.AnnasMazhar/pyspark-mcp