Content
# Morfx
> Safe AST-based code transformations for MCP agents, with standalone JSON tools when you want direct automation.

Morfx gives AI agents a deterministic way to query and rewrite code by AST node
instead of raw text. It ships as `morfx mcp` for MCP clients such as Claude
Desktop and Codex, and as standalone JSON tools such as `query`, `replace`,
`file_query`, `recipe`, and `apply` for direct local automation.
## 30-Second Quick Win
If you want to understand Morfx fast, do not start by building from source.
Download a release, point `query` at a real file, and get back structured AST
matches:
```bash
cat <<'JSON' | ./query
{"language":"go","path":"./cmd/morfx/main.go","query":{"type":"function","name":"main"}}
JSON
```
You get JSON back with the matched node, confidence details, and file metadata.
The same engine is what `morfx mcp` exposes to MCP clients when you ask an
agent to replace, delete, insert, run a recipe, or stage a change safely.
## Why
AI agents edit code by generating diffs or full-file rewrites. That works until it doesn't: off-by-one replacements, broken scope, wrong indentation, silent failures. Morfx solves this by operating on the actual syntax tree. Every transform is targeted by AST node, confidence-scored, and optionally staged for review before applying.
## What it does
- **Query** — Find functions, structs, classes, methods, interfaces by type and name pattern (wildcards supported)
- **Replace** — Swap a matched code element with new code
- **Delete** — Remove a matched element cleanly
- **Insert before / after** — Add code relative to a target element
- **Append** — Smart placement at end of file or scope
- **Stage / Apply / Rollback** — Two-phase commit with SQLite audit trail
- **Confidence scoring** — Every transform gets a score with explainable factors
- **Multi-language** — Go, JavaScript, TypeScript, PHP, Python via tree-sitter
- **Recipes / Rules** - Named repeatable transformations composed from the same safe primitives
- **Structural DSL** - Morfx selectors such as `func:* > call:os.Getenv`
## Modes
Start with **`morfx mcp`** unless you specifically want direct stdin/stdout
automation or repeatable local workflows. Morfx ships in three operational
shapes:
- **`morfx mcp`** for MCP-compatible AI clients such as Claude Desktop or Codex
- **Standalone binaries** such as `query`, `replace`, `file_query`, `recipe`, and `apply`
for direct local automation
- **A TFX-orchestrated runtime** for repeatable flows such as smoke checks,
dogfooding, quality gates, and release packaging
For the standalone stdin/stdout contracts, see
[docs/standalone-tools.md](./docs/standalone-tools.md). For shell-level usage
patterns and TFX recipes, see
[docs/standalone-recipes.md](./docs/standalone-recipes.md).
For the structural selector language, see
[docs/dsl.md](./docs/dsl.md).
For provider authoring, see
[docs/contributing-language-providers.md](./docs/contributing-language-providers.md).
If you are just evaluating Morfx, you can ignore TFX at first. TFX is optional
runtime orchestration around the same standalone tools.
## Morfx vs TFX
Morfx and TFX solve different problems:
- **Morfx** is the refactoring engine: AST query, replace, delete, insert, and
staged apply.
- **TFX** is the terminal runtime around tools like Morfx: prompts, flow
selection, progress, logs, artifacts, and release-style orchestration.
That means TFX does not replace Morfx. It hosts Morfx more effectively when the
same standalone commands need to run as a product workflow instead of as ad-hoc
shell snippets.
## Install
### Release artifacts (recommended)
Prebuilt archives are the primary install path. Every GitHub release publishes:
- `morfx_<version>_linux_amd64.tar.gz`
- `morfx_<version>_linux_arm64.tar.gz`
- `morfx_<version>_darwin_amd64.tar.gz`
- `morfx_<version>_darwin_arm64.tar.gz`
- `morfx_<version>_windows_amd64.zip`
- `SHA256SUMS`
- `MANIFEST.json`
- `SBOM.spdx.json`
Use the [GitHub Releases page](https://github.com/oxhq/morfx/releases) for
manual download, or pull the matching archive with GitHub CLI:
```bash
gh release download --repo oxhq/morfx --pattern 'morfx_*_linux_amd64.tar.gz'
tar -xzf morfx_*_linux_amd64.tar.gz
cd morfx_*
./morfx --version
```
On Windows:
```powershell
gh release download --repo oxhq/morfx --pattern 'morfx_*_windows_amd64.zip'
Expand-Archive .\morfx_*_windows_amd64.zip -DestinationPath .
Get-ChildItem .\morfx_*\morfx.exe
```
Each archive includes `morfx`, the standalone tools, the standalone tool docs,
and `tfx.yaml`.
Release workflows also request GitHub build provenance attestations for the
published archives, checksums, manifest, and SBOM.
### PHP and Composer projects
PHP projects can use the
[oxhq/morfx Composer wrapper](https://github.com/oxhq/morfx-php) once it is
published on Packagist:
```bash
composer require --dev oxhq/morfx
vendor/bin/morfx --version
```
The Composer package is a thin distribution layer. It downloads the matching
native Morfx release binary, verifies it against `SHA256SUMS`, caches it inside
the installed package, and forwards `vendor/bin/morfx` arguments to the native
binary. The AST engine, MCP server, standalone tools, release artifacts, and
language providers remain in this repository.
### Build from source
Use a source build when you want to contribute, test local changes, or produce
custom binaries:
```bash
git clone https://github.com/oxhq/morfx.git
cd morfx
go build -o bin/morfx ./cmd/morfx
make build-standalone
```
### Windows source-build notes
Windows support is practical, but current provider builds require `CGO_ENABLED=1` and a compatible C compiler for tree-sitter grammars. The verified path in this repo uses Zig; set `CC` before running Go commands:
```powershell
$env:CGO_ENABLED = "1"
$env:CC = "zig cc -target x86_64-windows-gnu"
go build ./cmd/morfx
go test ./...
```
For the canonical Windows verification path, run `.\tools\scripts\verify-windows.ps1`. For the standalone smoke path, run `.\tools\scripts\smoke-standalone.ps1`. The other PowerShell helpers in `tools/scripts/` are the Windows-native path; the Unix `make` targets and `.sh` scripts remain for macOS/Linux.
## Setup
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"morfx": {
"command": "/path/to/morfx",
"args": ["mcp"],
"env": {
"HOME": "/Users/you",
"NO_COLOR": "1"
}
}
}
}
```
### OpenAI Codex
Add to `~/.codex/config.toml`:
```toml
[mcp_servers.morfx]
command = "/path/to/morfx"
args = ["mcp"]
[mcp_servers.morfx.env]
HOME = "/Users/you"
NO_COLOR = "1"
```
### Any MCP client
Morfx speaks MCP 2025-11-25 over stdio. Point any MCP-compatible client at the binary with `mcp` as the subcommand.
## Standalone Tools
The standalone binaries are **JSON-over-stdin tools**, not flag-heavy CLIs.
Outside of `-h`/`--help`, you normally send them one JSON request on stdin and
read one JSON response from stdout.
| Tool | Description |
|---|---|
| `query` | Find code elements by type and name pattern |
| `file_query` | Search across multiple files |
| `replace` | Replace matched elements with new code |
| `file_replace` | Replace across multiple files |
| `delete` | Remove matched elements |
| `file_delete` | Delete across multiple files |
| `insert_before` | Insert code before a matched element |
| `insert_after` | Insert code after a matched element |
| `append` | Smart-place code at end of file or scope |
| `recipe` | Run a named repeatable transformation with confidence gates |
| `apply` | Apply a staged transformation |
Build them locally with:
```bash
make build-standalone
```
## Usage examples
These are the JSON payloads your AI agent sends. You don't type these — your agent does.
**Find all functions matching a pattern:**
```json
{
"language": "go",
"path": "/project/handlers.go",
"query": {"type": "function", "name": "Handle*"}
}
```
**Find functions that contain a specific call:**
```json
{
"language": "go",
"path": "/project/config.go",
"dsl": "func:* > call:os.Getenv"
}
```
**Replace a method:**
```json
{
"language": "php",
"path": "/project/app/Http/Controllers/UserController.php",
"target": {"type": "method", "name": "store"},
"replacement": "public function store(StoreUserRequest $request): JsonResponse\n{\n return new UserResource(User::create($request->validated()));\n}"
}
```
**Insert a comment before a function:**
```json
{
"language": "go",
"path": "/project/service.go",
"target": {"type": "function", "name": "DeleteUser"},
"content": "// DeleteUser removes a user permanently. Use with caution."
}
```
## Structural DSL
Morfx also accepts a compact selector syntax when a JSON query would be too
clumsy. Use `dsl` on read tools and `target_dsl` on mutation tools
or recipe steps. The full agent-facing reference lives in
[docs/dsl.md](./docs/dsl.md).
```txt
func:Init
func:Handle*
!func:Test*
func:* > call:os.Getenv
class:* >> method:render
call:$client.$method
call:fetch arg0="/api/user"
struct:* > field:Secret string
func:* | method:*
```
The DSL is intentionally compact: `kind:pattern`, optional attributes, `>` for
descendant containment, `>>` for direct semantic children, `$capture` patterns,
argument/source/order predicates, `!` for negation, and `&` / `|` for logical
composition. The parser keeps `kind` as written; each language provider decides
which names are valid aliases, so Python can own `def`, Go can own `func`, and
PHP/TypeScript can keep their own vocabulary. It compiles to the same
`AgentQuery` model used by the JSON tools, so the existing confidence, dry-run,
staged apply, and recipe workflow still apply.
## Recipes and rules
Use `recipe` when a transformation should be repeatable instead of copied as an
ad-hoc shell snippet. A recipe is a named set of rules. Each rule maps directly
to an existing Morfx primitive: `replace`, `delete`, `insert_before`,
`insert_after`, or `append`.
Apply-mode recipes always run a dry-run preflight first. Morfx only mutates files
after the step meets its `min_confidence` gate.
Recipes are available both as the MCP `recipe` tool and as the standalone
`recipe` JSON binary.
```json
{
"name": "replace-legacy-handlers",
"dry_run": true,
"min_confidence": 0.85,
"steps": [
{
"name": "replace legacy handlers",
"method": "replace",
"scope": {
"path": ".",
"include": ["**/*.go"],
"language": "go",
"max_files": 100
},
"target_dsl": "func:Legacy*",
"replacement": "func Replacement() {}"
}
]
}
```
```bash
cat recipe.json | ./bin/recipe
```
## Confidence scoring
Every transformation returns a confidence score (0.0–1.0) with factors:
```
Confidence: █████████░ 90.0%
Factors:
+0.10 single_target — Only one match found
-0.20 exported_api — Modifying public API
```
When confidence exceeds the threshold (default 0.85), transforms auto-apply. Below threshold, they stage for manual review via `apply`.
## Configuration
```bash
morfx mcp # Start with defaults
morfx mcp --debug # Debug logging to stderr
morfx mcp --db ./my.db # Custom SQLite path
morfx mcp --auto-threshold 0.9 # Stricter auto-apply
```
## TFX Dogfooding
This repository ships a root [`tfx.yaml`](./tfx.yaml) so Morfx can run as a
product workflow, not only as an MCP backend or a pile of standalone binaries.
Typical flows:
```bash
tfx --flow ci --run
tfx --flow standalone --run
tfx --flow dogfood-tfx --run
tfx --flow quality --run
tfx --flow release --lane canary --run
```
The `standalone` flow builds the local binaries and exercises `query`,
`replace`, and `file_query` against a temporary fixture through
[`tools/scripts/smoke-standalone.sh`](./tools/scripts/smoke-standalone.sh).
The `dogfood-tfx` flow targets a local checkout of `oxhq/tfx` through
[`tools/scripts/dogfood-tfx.sh`](./tools/scripts/dogfood-tfx.sh), running
read-only queries on the real repo and a safe replacement against a temporary
copy of a TFX source file. Override the target checkout with
`MORFX_DOGFOOD_TFX_DIR=/path/to/tfx`.
The important boundary is:
- Morfx owns AST edits and standalone JSON contracts.
- TFX owns flow control, prompts, runtime logs, progress, hooks, and artifacts.
## Supported languages
| Language | Provider | Query types |
|---|---|---|
| Go | tree-sitter-go | function, struct, interface, variable, constant, import, type, method, field |
| JavaScript | tree-sitter-javascript | function, class, variable, import, export |
| TypeScript | tree-sitter-typescript | function, class, interface, type, variable, import, export, enum |
| PHP | tree-sitter-php | function, class, method, interface, trait, variable, namespace |
| Python | tree-sitter-python | function, class, variable, import, decorator |
## Architecture
```
morfx mcp (stdio)
├── MCP Protocol (JSON-RPC 2.0, 2025-11-25 spec)
├── Tool Registry (10 tools)
├── Provider Registry
│ ├── Go provider (tree-sitter)
│ ├── JavaScript provider
│ ├── TypeScript provider
│ ├── PHP provider
│ └── Python provider
├── Base Provider (shared AST engine)
│ ├── Query (walkTree + pattern match)
│ ├── Transform (replace/delete/insert/append)
│ ├── Confidence scoring
│ └── AST cache + parser pool
├── Safety Manager (atomic writes, integrity checks)
└── Staging Manager (SQLite, stage/apply/rollback)
```
## Development
```bash
go build ./... # Build everything
go test ./... # Run all tests
go test -race ./... # Race detector
go test -cover ./... # Coverage
make build-standalone # Build standalone JSON tools
make smoke-standalone # Run standalone fixture smoke tests
make verify # Strict local verification
```
Windows equivalents:
```powershell
$env:CGO_ENABLED = "1"
$env:CC = "zig cc -target x86_64-windows-gnu"
.\tools\scripts\build-standalone.ps1
.\tools\scripts\verify-windows.ps1
.\tools\scripts\smoke-standalone.ps1
```
## License
Licensed under the [MIT License](./LICENSE).
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.