A Model Context Protocol (MCP) server that provides Python refactoring capabilities powered by the Rope library. Enables AI agents like Claude to perform safe, project-wide refactoring operations.
- Move Symbol - Move classes and functions between files with automatic import updates
- Move Module - Move entire modules or packages to different folders
- Move and Rename Module - Move module to folder and rename (e.g.,
foo_extra.py→foo/extra.py) - Convert Module to Init - Transform
foo.pyintofoo/__init__.py(no import changes!) - Convert Module to Package - Transform
foo.pyintofoo/foo.pywith import updates - Rename Symbol - Rename variables, functions, classes across entire projects
- Extract Method - Extract code blocks into new methods
- Inline Variable - Inline variables at all usage sites
- List Symbols - Discover top-level symbols in Python files
All operations are project-aware and automatically update imports and references throughout your codebase.
# Global installation (all projects)
claude mcp add rope-refactor uvx rope-mcp-server -s user
# Or for current project only
claude mcp add rope-refactor uvx rope-mcp-server -s localpip install rope-mcp-serverclaude mcp add rope-refactor uvx rope-mcp-server -s user
claude mcp list # verifyThat's it.
List all top-level symbols (classes, functions, variables) in a Python file.
project_path: /path/to/your/project
file_path: src/models.py
Move a class or function to another file. Automatically updates all imports.
project_path: /path/to/your/project
source_file: src/models.py
symbol_name: UserModel
dest_file: src/users/models.py
Move a module or package to another folder. Automatically updates all imports.
project_path: /path/to/your/project
module_path: src/utils.py
dest_folder: src/lib
Convert a module file into a package by moving it to __init__.py. No import changes needed!
This is the recommended way to convert a module to a package. After conversion, you can use move_module to move related files (like foo_mixins.py) into the new package.
project_path: /path/to/your/project
module_path: app/views/customer_order.py
Before:
app/views/customer_order.py
app/views/customer_order_mixins.py
After running convert_module_to_init:
app/views/customer_order/__init__.py (was customer_order.py)
app/views/customer_order_mixins.py (move this next with move_module)
Import from app.views.customer_order import X stays unchanged!
Move a module to a folder and optionally rename it. Perfect for moving related files (like _mixins.py, _extra.py) into a package created with convert_module_to_init.
Auto-detection: If the module name starts with the destination folder name + underscore, it strips that prefix automatically.
Rope bug workaround: This tool includes a workaround for a Rope bug that crashes when a file has imports from BOTH the destination package AND the module being moved. Such files are temporarily hidden during the move, then their imports are fixed manually.
project_path: /path/to/your/project
module_path: app/views/customer_order_mixins.py
dest_folder: app/views/customer_order
new_name: mixins # Optional - auto-detected from prefix
Before:
app/views/customer_order/__init__.py
app/views/customer_order_mixins.py
Import: from app.views.customer_order_mixins import MyMixin
After:
app/views/customer_order/__init__.py
app/views/customer_order/mixins.py
Import: from app.views.customer_order.mixins import MyMixin
Convert a module file into a package with the same name. Transforms foo.py into foo/foo.py while updating all imports project-wide.
Use this when you want the original module content in a submodule, not in __init__.py.
project_path: /path/to/your/project
module_path: app/views/service_contractor.py
Before:
app/views/service_contractor.py
Import: from app.views.service_contractor import MyClass
After:
app/views/service_contractor/
├── __init__.py
└── service_contractor.py
Import: from app.views.service_contractor.service_contractor import MyClass
Rename a symbol across the entire project.
project_path: /path/to/your/project
file_path: src/utils.py
symbol_name: old_function_name
new_name: new_function_name
Extract a code region into a new method.
project_path: /path/to/your/project
file_path: src/service.py
start_line: 15
start_col: 4
end_line: 20
end_col: 30
new_name: extracted_helper
Inline a variable at all usage sites.
project_path: /path/to/your/project
file_path: src/handler.py
variable_name: temp_result
line: 42
Close a Rope project to free memory. Call when done with refactoring.
project_path: /path/to/your/project
# Install dependencies
uv sync
# Run tests
uv run pytest tests/ -v
# Run server locally
uv run python -m rope_mcp_server.serverThis server wraps the Rope refactoring library and exposes its capabilities via the Model Context Protocol. When Claude (or any MCP-compatible agent) needs to refactor Python code, it can use these tools to perform safe, AST-aware transformations that preserve code correctness.
Key implementation details:
- Project caching - Rope projects are cached to avoid re-parsing on every operation
- AST-based offset calculation - Symbol locations are computed via Python's AST module for accuracy
- Automatic import handling - Rope handles all import updates when moving/renaming symbols
- Only supports Python code (Rope limitation)
- Moving methods between classes requires the target class to exist
- Large projects may have slower initial indexing
- Rope bug workaround: Files with imports from both the destination package and the module being moved are handled specially (hidden during move, then imports fixed manually) - see
move_and_rename_module
MIT
Contributions welcome! Please open an issue first to discuss what you would like to change.