Revise MCP
by davidfstr
README.md
# Revise MCP
<img src="https://github.com/davidfstr/revise-mcp/blob/main/README/logo-big-notext.svg?raw=true" alt="Revise MCP logo" align="right" width="200" />
Tools to revise and refactor code via MCP (Model Context Protocol).
## Installation
* Install [Python 3.14+](https://www.python.org/downloads/)
* Install pipx: `python3 -m pip install pipx`
* Install Revise MCP:
```bash
pipx install revise-mcp
which revise
# /Users/YOUR_USERNAME/.local/bin/revise
```
## Usage
### VS Code MCP Configuration
Add to your VS Code MCP settings:
```json
{
"servers": {
"revise": {
"type": "stdio",
"command": "/Users/YOUR_USERNAME/.local/bin/revise",
"args": []
},
}
}
```
### Claude Code MCP Configuration
Run once to register Revise MCP for all your projects:
```bash
claude mcp add --scope user revise -- /Users/YOUR_USERNAME/.local/bin/revise
```
## Tools
### `move_string_in_file`
Moves a contiguous range of lines from one location to another within a file
(or between files). Uses substring matching with a `⬥` marker to identify
cut boundaries and paste location — no line counting or coordinate math required.
Does not alter indentation of the moved text. Use `indent_dedent` afterward
if the moved text needs re-indentation at its new location.
**Parameters:**
- `cutFilePath` — Absolute path to the file containing the text to move
- `cutStartAt` — Substring fragment identifying the line where the cut begins. The `⬥` marks a position on the target line; the cut starts at the beginning of that line
- `cutEndAt` — Substring fragment identifying the line *after* the cut ends. The cut ends *before* this line (exclusive)
- `pasteAt` — Substring fragment marking the insertion point, with `⬥` adjacent to a `\n` or file boundary. Matched against the pre-cut file state
- `pasteFilePath` (optional) — Absolute path to the paste destination file. Defaults to `cutFilePath` (same-file move)
**Example — move a class before another definition:**
```json
{
"cutFilePath": "/path/to/file.py",
"cutStartAt": "class MyClass:",
"cutEndAt": "class NextClass:",
"pasteAt": "\n⬥def top_level_function():"
}
```
### `indent_dedent`
Indents or unindents a contiguous range of lines by a specified number of
levels. Uses substring matching with a `⬥` marker to identify the range
boundaries — no line counting required.
Empty lines within the range are left unchanged. Indent size is auto-detected
from the file if not specified.
**Parameters:**
- `filePath` — Absolute path to the file to edit
- `indentStartAt` — Substring fragment identifying the first line to indent/unindent. The `⬥` marks a position on the target line; the entire line is included
- `indentEndAt` — Substring fragment identifying the last line to indent/unindent (inclusive)
- `indentDelta` — Number of indent levels to add (positive) or remove (negative)
- `indentSize` (optional) — Spaces per indent level (e.g., `4`), or `"\t"` for tabs. Auto-detected if omitted
**Example — indent a block, then wrap it:**
```json
{
"filePath": "/path/to/file.py",
"indentStartAt": "# Create home URL\n⬥",
"indentEndAt": "(home_ti,) = root_ti.Children⬥\n",
"indentDelta": 1
}
```
Then use `replace_string_in_file` to insert `if condition:` before the indented block.
### `outline_file`
Returns a high-level outline of a file, similar to VS Code's folded view.
Useful for quickly understanding the structure of a large file before reading
it in full.
Includes only structurally significant lines,
currently optimized for the **Python** language only:
- `class`, `def`, and `async def` definitions (at any indentation level)
- `if __name__ == '__main__':` guards
- Section separator comments (`# === ...` or `# --- ...`), plus the
immediately following section-name comment if present
Output is one line per entry in the form `LINE_NUMBER:LINE_CONTENT` (1-indexed).
**Parameters:**
- `filePath` — Absolute path to the file to outline
**Example:**
```json
{
"filePath": "/path/to/file.py"
}
```
### `rename_symbol` *(optional)*
Renames a symbol (function, variable, class, etc.) and all its references
across the workspace using VS Code's LSP-backed rename. Uses text-based
matching to locate the symbol — no coordinate counting required.
> **Note:** This tool is optional and has additional setup requirements. See
> [Optional: `rename_symbol` Setup](#optional-rename_symbol-setup) below.
>
> It is most useful for AI coding harnesses that **do not** provide their own
> symbolic rename tool (e.g. Claude Code). VS Code users already have a native
> rename tool and may skip this.
**Parameters:**
- `filePath` — Absolute path to the file containing the symbol to rename
- `oldString` — Line fragment containing the original symbol name. Must be unique within the file (or within the specified line). Example: `'def mocked_show_modal('`
- `newString` — Line fragment with all occurrences of the symbol renamed. Example: `'def mocked_show_modal_renamed('`
- `line` (optional) — 1-indexed line number to limit the search for `oldString`. Use when `oldString` appears on multiple lines
**Example:**
```json
{
"filePath": "/path/to/file.py",
"oldString": "def helper_function(",
"newString": "def _helper_function("
}
```
This renames `helper_function` to `_helper_function` everywhere it is referenced.
## Optional: `rename_symbol` Setup
The `rename_symbol` tool delegates the actual rename operation to VS Code via
the [VSC as MCP](https://marketplace.visualstudio.com/items?itemName=lsegal.vsc-as-mcp)
extension. This means:
1. **VS Code must be running** with the project open.
2. **The "VSC as MCP" extension must be installed** in VS Code. It exposes a
local MCP server (by default at `http://localhost:4000/mcp`) that Revise MCP
calls internally.
### Steps
1. Install the [VSC as MCP extension](https://marketplace.visualstudio.com/items?itemName=lsegal.vsc-as-mcp) in VS Code.
2. Open VS Code with the project you want to rename symbols in.
3. Ensure Revise MCP is configured in your AI coding harness (see [Installation](#installation) and [Usage](#usage)).
No additional configuration of Revise MCP itself is required — `rename_symbol`
will automatically connect to the VSC as MCP server on `localhost:4000`.
## Contributing
See [`doc/DESIGN.md`](doc/DESIGN.md) for a high-level introduction to the server design and the principles guiding tool development.
To publish a new release to PyPI, see [`doc/RELEASING.md`](doc/RELEASING.md).
### Local Development Setup
Requires Python 3.14+ and [Poetry](https://python-poetry.org/).
```bash
# Checkout code
git checkout https://github.com/davidfstr/revise-mcp.git
cd revise-mcp
# Create/update the virtual environment at .venv/
poetry install
# Run the server locally
poetry run python -m revise
# Run tests
poetry run pytest tests/
```
### Testing with MCP Inspector
```bash
# Start in HTTP mode for testing with MCP Inspector
poetry run python -m revise --transport streamable-http
# In another terminal, start the inspector
npx -y @modelcontextprotocol/inspector
```
### VS Code MCP Configuration (Development)
To run the MCP server from your development checkout rather than an installed binary, point VS Code at the Poetry-managed venv:
```json
{
"servers": {
"revise": {
"type": "stdio",
"cwd": "/path/to/revise-mcp",
"command": "poetry",
"args": ["run", "python", "-m", "revise"]
},
}
}
```
TDQS
A4.2/5.0
Scored across 4 tools
Disambiguation5/5
Each tool addresses a distinct editing operation: indentation, moving lines, outlining, and renaming. No overlap or confusion among them.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern with underscores (e.g., indent_dedent, move_string_in_file), making them predictable and readable.
Tool Count5/5
With 4 tools, the server is well-scoped for a focused code editing purpose, not too few or too many.
Completeness2/5
The server lacks basic text editing tools like replace, insert, or delete, which are essential for comprehensive file editing. The mention of 'replace_string_in_file' in descriptions suggests a gap.
Maintenance
ActivityInactive
ResponsivenessNo issues