Crates.io | semantic-code-edit-mcp |
lib.rs | semantic-code-edit-mcp |
version | 0.1.0 |
created_at | 2025-07-07 13:39:42.038789+00 |
updated_at | 2025-07-07 13:39:42.038789+00 |
description | MCP server for semantic code editing with tree-sitter |
homepage | |
repository | https://github.com/cognitive-glitch/semantic-code-edit-mcp |
max_upload_size | |
id | 1741288 |
size | 270,424 |
[!CAUTION] This repository is written by AI as an experiment. Although I (jbr) review every line, the code quality is not necessarily identical to what I would have written. Caveat usor.
[!IMPORTANT] FOR AI ASSISTANTS: You cannot test changes to this MCP server without asking the user to restart Claude Desktop first. The MCP server must be recompiled and reloaded to test any code changes. Always pause and ask the user to restart Claude Desktop before attempting to test modifications.
A Model Context Protocol (MCP) server for semantic code editing using tree-sitter. This server provides safe, AST-aware code editing operations that preserve syntax structure and prevent file corruption through comprehensive validation.
preview_only: true
- see changes without applying themThis project requires nightly Rust because we use let chains.
cargo install semantic-edit-mcp
Start the server:
semantic-edit-mcp serve
The server communicates via JSON-RPC over stdin/stdout and provides the following tools:
All editing tools support full validation and work across supported languages:
replace_node
Replace an entire AST node with new content.
{
"file_path": "src/main.rs",
"selector": {
"type": "function_item",
"name": "main"
},
"new_content": "fn main() {\n println!(\"Hello, semantic editing!\");\n}",
"preview_only": true
}
insert_before_node
/ insert_after_node
Insert content before or after a specified node.
{
"file_path": "config.json",
"selector": {
"line": 3,
"column": 21
},
"content": ",\n \"description\": \"Added field\"",
"preview_only": false
}
wrap_node
Wrap an existing node with new syntax.
{
"file_path": "src/lib.rs",
"selector": {
"line": 42,
"column": 10
},
"wrapper_template": "if some_condition {\n {{content}}\n}",
"preview_only": true
}
validate_syntax
Multi-language syntax validation.
{
"file_path": "src/main.rs"
}
Or validate content directly:
{
"content": "{\"key\": \"value\"}",
"language": "json"
}
get_node_info
Multi-language node inspection.
{
"file_path": "config.json",
"selector": {
"line": 2,
"column": 5
}
}
These tools provide safer, more semantic insertion at structural boundaries for Rust files:
insert_after_struct
Insert content after a struct definition.
{
"file_path": "src/lib.rs",
"struct_name": "MyStruct",
"content": "impl Default for MyStruct {\n fn default() -> Self {\n Self::new()\n }\n}",
"preview_only": true
}
insert_after_enum
Insert content after an enum definition.
{
"file_path": "src/lib.rs",
"enum_name": "Color",
"content": "impl Color {\n fn is_primary(&self) -> bool {\n matches!(self, Color::Red | Color::Blue | Color::Yellow)\n }\n}",
"preview_only": false
}
insert_after_impl
Insert content after an impl block.
{
"file_path": "src/lib.rs",
"impl_type": "MyStruct",
"content": "impl Display for MyStruct {\n fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n write!(f, \"MyStruct\")\n }\n}",
"preview_only": true
}
insert_after_function
Insert content after a function definition.
{
"file_path": "src/lib.rs",
"function_name": "main",
"content": "fn helper_function() -> i32 {\n 42\n}",
"preview_only": false
}
insert_in_module
Smart module-level insertion with positioning control.
{
"file_path": "src/lib.rs",
"content": "use std::collections::HashMap;",
"position": "start",
"preview_only": true
}
Context Validation (language-specific semantic rules)
Syntax Validation (all languages)
✅ Replace operation result (with context validation):
Successfully replaced function_item node
✅ Insert after operation result (syntax validation only):
Successfully inserted content after pair node
❌ Edit would create invalid syntax and was blocked:
Line 3: Missing }
Line 4: Syntax error
Safe Testing: All editing operations support a preview_only
parameter:
preview_only: true
: Shows what would happen without modifying files, output prefixed with "PREVIEW:"preview_only: false
(default): Actually applies the changes to filesPerfect for testing complex operations safely before applying them.
Get intelligent error messages with suggestions when targeting fails:
Before:
Error: Target node not found
Now:
Function 'mian' not found.
Available options: function: main, function: add, function: multiply
Did you mean: main
Features:
Multiple ways to target nodes for editing:
{
"line": 42,
"column": 10
}
{
"type": "function_item",
"name": "my_function"
}
{
"type": "struct_item"
}
{
"query": "(function_item name: (identifier) @name (#eq? @name \"main\")) @function"
}
Multi-language semantic editing with pluggable language support:
languages/
: Language-specific support (Rust, JSON, extensible)validation/
: Context validation and syntax validationtools/
: Core editing tools with full validationparsers/
: Multi-language tree-sitter integrationoperations/
: Core edit operations and node selectionOur architecture makes it easy to add new programming languages:
{
"name": "replace_node",
"arguments": {
"file_path": "src/main.rs",
"selector": {"type": "function_item", "name": "main"},
"new_content": "fn main() -> Result<(), Box<dyn Error>> {\n println!(\"Safe main!\");\n Ok(())\n}",
"preview_only": true
}
}
{
"name": "insert_after_node",
"arguments": {
"file_path": "package.json",
"selector": {"line": 3, "column": 20},
"content": ",\n \"description\": \"Updated package\"",
"preview_only": false
}
}
{
"name": "insert_after_struct",
"arguments": {
"file_path": "src/lib.rs",
"struct_name": "Point",
"content": "impl Display for Point {\n fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n write!(f, \"({}, {})\", self.x, self.y)\n }\n}",
"preview_only": false
}
}
{
"name": "insert_in_module",
"arguments": {
"file_path": "src/lib.rs",
"content": "#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_basic_functionality() {\n assert!(true);\n }\n}",
"position": "end",
"preview_only": true
}
}
Apache-2.0