The CEDARScript MCP Server is a production-grade adapter that exposes the CEDARScript Editor library via the Model Context Protocol (MCP). It enables AI agents (like Claude) to perform intelligent code transformations through a secure, well-defined protocol.
- Core Library (
cedarscript-editor): Pure computation, no protocol awareness - MCP Server (this project): Thin adapter layer, protocol handling, security
This separation ensures:
- Core library remains focused and testable
- MCP server can evolve independently
- Users can choose CLI-only or MCP integration
- Multiple MCP server variants possible (STDIO, HTTP, gRPC)
- Dry-run by default: All mutations require explicit opt-in
- Read-only mode: Optional complete write protection
- Path validation: Strict root directory enforcement
- Explicit confirmation: Multi-step workflows for destructive operations
- Structured logging: JSON format for machine parsing
- Request tracing: Unique IDs for debugging
- Error enrichment: AI-friendly context and suggestions
- Metrics hooks: Performance and reliability monitoring
┌─────────────────────────────────────────────────────────────┐
│ MCP Client (Claude) │
│ Desktop / VS Code / API │
└─────────────────────┬───────────────────────────────────────┘
│ JSON-RPC 2.0 over STDIO
│ (subprocess communication)
┌─────────────────────▼───────────────────────────────────────┐
│ CEDARScript MCP Server │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ server.py - MCP Protocol Handler │ │
│ │ - StdioServerTransport (stdin/stdout) │ │
│ │ - Request routing & validation │ │
│ │ - Signal handling (graceful shutdown) │ │
│ │ - Logging & metrics │ │
│ └─────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────▼───────────────────────────────────────┐ │
│ │ tools.py - MCP Tool Definitions │ │
│ │ - parse_cedarscript(content) → ParseResult │ │
│ │ - apply_cedarscript(commands, root, dry_run=True) │ │
│ │ - explain_error(error_msg) → Explanation │ │
│ │ - list_capabilities() → Features │ │
│ └─────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────▼───────────────────────────────────────┐ │
│ │ adapters.py - Protocol Translation │ │
│ │ - CEDARScript AST ↔ JSON serialization │ │
│ │ - Exception → Structured MCP Error │ │
│ │ - Diff generation (unified format) │ │
│ │ - Result enrichment (line ranges, context) │ │
│ └─────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────▼───────────────────────────────────────┐ │
│ │ security.py - Safety & Validation │ │
│ │ - Path traversal prevention │ │
│ │ - Root directory enforcement │ │
│ │ - File size limits │ │
│ │ - Allowlist/denylist patterns │ │
│ └─────────────────┬───────────────────────────────────────┘ │
└───────────────────┼───────────────────────────────────────────┘
│
┌───────────────────▼───────────────────────────────────────────┐
│ cedarscript-editor (Core Library) │
│ - CEDARScriptEditor.apply_commands() │
│ - find_commands() - AST parsing │
│ - Tree-sitter integration │
│ - File manipulation │
└───────────────────────────────────────────────────────────────┘
Purpose: Validate CEDARScript syntax without execution
Input (JSON-RPC):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "parse_cedarscript",
"arguments": {
"content": "UPDATE myfile.py SET imports.append('import os')"
}
}
}Mapping:
- Calls
find_commands(content) - Returns AST as serialized JSON
- Catches
ValueErrorfor syntax errors
Output (success):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"success": true,
"commands": [
{
"type": "UpdateCommand",
"target": "myfile.py",
"action": "append",
"segment": "imports",
"content": ["import os"]
}
],
"count": 1
}
}Output (error):
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid CEDARScript syntax",
"data": {
"type": "ParseError",
"details": "Expected 'UPDATE' or 'CREATE', found 'UPDAET'",
"suggestion": "Check command spelling. Valid commands: UPDATE, CREATE, DELETE, MOVE"
}
}
}Purpose: Apply code transformations (with preview mode)
Input:
{
"name": "apply_cedarscript",
"arguments": {
"commands": "UPDATE myfile.py SET function:calculate REPLACE 'x + 1' WITH 'x + 2'",
"root": "/path/to/project",
"dry_run": true
}
}Mapping:
- Parse via
find_commands(commands) - Validate
rootpath viasecurity.validate_root() - If
dry_run=False: CallCEDARScriptEditor(root).apply_commands() - If
dry_run=True: Mock file writes, generate diffs
Output (dry_run=true):
{
"success": true,
"dry_run": true,
"preview": {
"affected_files": ["myfile.py"],
"diffs": [
{
"file": "myfile.py",
"diff": "--- myfile.py\n+++ myfile.py\n@@ -10,1 +10,1 @@\n- return x + 1\n+ return x + 2"
}
]
}
}Output (dry_run=false):
{
"success": true,
"dry_run": false,
"results": [
"Updated myfile.py\n -> REPLACE in function calculate: 1 occurrence"
],
"affected_files": ["myfile.py"]
}Purpose: Provide AI-friendly error explanations
Input:
{
"name": "explain_error",
"arguments": {
"error_message": "CEDARScriptEditorException: Command #2 failed: File not found: utils.py"
}
}Output:
{
"explanation": "The second CEDARScript command tried to modify 'utils.py', but the file doesn't exist in the project root.",
"suggestions": [
"Verify the file path is correct",
"Check if the file was created in command #1",
"Use CREATE command if the file should be created first"
],
"recovery_steps": [
"Run parse_cedarscript to validate syntax",
"List project files to verify paths",
"Consider CREATE FILE utils.py before UPDATE"
]
}class PathValidator:
def __init__(self, root: Path, read_only: bool = False):
self.root = root.resolve() # Absolute path
self.read_only = read_only
def validate(self, file_path: str) -> Path:
"""Ensure path is within root, no traversal attacks."""
resolved = (self.root / file_path).resolve()
if not resolved.is_relative_to(self.root):
raise SecurityError(f"Path escape attempt: {file_path}")
return resolved- Root Enforcement: All file operations confined to specified directory
- Read-Only Mode: Optional complete write protection (parsing only)
- File Size Limits: Configurable max file size (default: 10MB)
- Pattern Filtering: Allowlist/denylist for file operations
- Default denylist:
.git/,node_modules/,__pycache__/,.env
- Default denylist:
- No elevation: Server runs with user's permissions
- Explicit mutations: Dry-run by default, require confirmation
- Audit logging: All write operations logged with timestamps
- Protocol Errors (JSON-RPC): Malformed requests, invalid methods
- Validation Errors: Invalid arguments, path violations
- Parse Errors: CEDARScript syntax issues
- Execution Errors: File not found, permission denied, CEDARScript failures
- System Errors: Out of memory, disk full, unexpected exceptions
All errors follow JSON-RPC 2.0 spec with enriched data:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000, // Application error codes
"message": "Human-readable summary",
"data": {
"type": "ErrorType",
"details": "Specific diagnostic info",
"context": {
"file": "myfile.py",
"line": 42,
"command_index": 2
},
"suggestions": ["Fix suggestion 1", "Fix suggestion 2"],
"recovery_steps": ["Step 1", "Step 2"]
}
}
}def translate_exception(exc: Exception) -> dict:
"""Convert Python exceptions to MCP error responses."""
if isinstance(exc, CEDARScriptEditorException):
return {
"code": -32000,
"message": "CEDARScript execution failed",
"data": {
"type": "ExecutionError",
"command_index": exc.ordinal,
"details": exc.description,
"suggestions": parse_suggestions(exc)
}
}
elif isinstance(exc, SecurityError):
return {"code": -32001, "message": "Security violation", ...}
# ... more mappingsCEDARSCRIPT_ROOT: Default project root pathCEDARSCRIPT_LOG_LEVEL: DEBUG, INFO, WARNING, ERRORCEDARSCRIPT_LOG_FORMAT: text, jsonCEDARSCRIPT_READ_ONLY: true/false (force read-only mode)CEDARSCRIPT_MAX_FILE_SIZE: Max file size in bytes
python -m cedarscript_mcp.server \
--root /path/to/project \
--log-level DEBUG \
--read-only \
--max-file-size 10485760- CLI arguments (highest priority)
- Environment variables
- Default values (lowest priority)
{
"timestamp": "2025-01-21T10:30:45.123Z",
"level": "INFO",
"request_id": "req_abc123",
"event": "tool_called",
"tool": "apply_cedarscript",
"args": {"root": "/project", "dry_run": true},
"duration_ms": 234,
"status": "success"
}- DEBUG: Request/response payloads, internal state
- INFO: Tool calls, file operations, high-level events
- WARNING: Validation failures, retryable errors
- ERROR: Execution failures, system errors
- Sensitive data (file contents, API keys) redacted by default
- Opt-in verbose mode for debugging (logged to separate file)
- parse_cedarscript: 10-100ms (depends on command complexity)
- apply_cedarscript (dry_run): 50-500ms (file reading, diff generation)
- apply_cedarscript (execute): 100ms-5s (includes tree-sitter parsing, file writes)
- Memory: Proportional to file sizes (tree-sitter AST parsing)
- CPU: Burst during parsing, minimal during idle
- Disk I/O: Read-heavy (parsing), write-heavy (execution)
- STDIO transport: Single client, single process (by design)
- Stateless: Each request independent (no session state)
- Concurrency: Not applicable (STDIO is sequential)
- Tool function behavior (mocked CEDARScript editor)
- Adapter serialization/deserialization
- Security validation (path traversal attempts)
- Error translation
- Full request/response cycle via STDIO
- Real CEDARScript Editor integration
- File system mutations (in temp directories)
- JSON-RPC 2.0 spec validation
- Error code correctness
- Message format validation
- Path traversal attempts
- File size limit enforcement
- Read-only mode verification
- Denylist pattern matching
{
"mcpServers": {
"cedarscript": {
"command": "python",
"args": ["-m", "cedarscript_mcp.server", "--root", "${workspaceFolder}"]
}
}
}{
"servers": {
"cedarscript": {
"command": "python",
"args": ["-m", "cedarscript_mcp.server"],
"env": {
"CEDARSCRIPT_ROOT": "${workspaceFolder}"
}
}
}
}FROM python:3.12-slim
RUN pip install cedarscript-mcp-server
ENTRYPOINT ["python", "-m", "cedarscript_mcp.server"]
CMD ["--root", "/workspace"]- HTTP Transport: Alternative to STDIO for web-based clients
- Multi-root Support: Work with multiple project directories
- Incremental Parsing: Cache ASTs for performance
- Transaction Support: Rollback on error
- Collaboration Features: Multi-user locking, conflict resolution
- Plugin System: Custom tools via entry points
- Semantic versioning (MAJOR.MINOR.PATCH)
- 6-month deprecation notice for breaking changes
- Compatibility matrix with cedarscript-editor versions
- Migration guides for major version upgrades
Architecture Version: 1.0.0 Last Updated: 2025-01-21 Author: Google Principal Engineer Design Pattern