MCP server¶
Chop slop from inside any assistant that speaks the Model Context Protocol. slop-chop mcp
serves the engine over stdio, so Claude Desktop, Claude Code, Cursor, and the rest can clean a
draft on demand without you leaving the chat.
It runs the same deterministic rules engine as everything else, in a process on your machine. Nothing is uploaded and no key is needed. The model rewrite stays off unless a call asks for it.
Run it¶
slop-chop mcp
It speaks the protocol on stdin and stdout, so you point a client at that command rather than running it yourself. Install the binary first:
brew install dcadolph/tap/slop-chop
The tools¶
| Tool | What it does |
|---|---|
chop |
Cleans the text and hands back the human version, with the score before and after. |
check |
Reports the tells and where they are, changing nothing. |
presets |
Lists the built-in packs chop and check accept. |
drift |
Says whether a draft sounds like your own writing, and names what does not. |
chop and check both take text, plus an optional presets list and a dialect of
american, british, or off. chop also takes model_rewrite, off by default, covered
below. drift takes text and compares it against the fingerprint you measured with
slop-chop voice fingerprint, so an agent can check its draft against your own writing
before handing it over. Without a fingerprint it says so and measures nothing. See
VOICE.md.
Ask for a clean in whatever words you use. "Chop the slop out of this," "make this sound like a person wrote it," and "strip the AI tells from my draft" all reach the same tool.
Claude Code¶
claude mcp add slop-chop -- slop-chop mcp
Add --preset cleaver after mcp for the aggressive swaps. Check it took with
claude mcp list, which reports the server as connected.
Claude Desktop¶
Open Settings, Developer, Edit Config, and add the server to
claude_desktop_config.json:
{
"mcpServers": {
"slop-chop": {
"command": "slop-chop",
"args": ["mcp"]
}
}
}
Restart Claude Desktop. If it cannot find the binary, give the full path from
which slop-chop instead, since the app does not always inherit your shell's PATH.
Cursor¶
Add the same block to .cursor/mcp.json in a project, or to ~/.cursor/mcp.json for every
project:
{
"mcpServers": {
"slop-chop": {
"command": "slop-chop",
"args": ["mcp", "--preset", "cleaver"]
}
}
}
ChatGPT custom connectors¶
ChatGPT connectors reach a server over HTTP at a URL, and this one speaks stdio on your own
machine, so the two do not meet directly. The way around it is a stdio-to-HTTP bridge in
front of it, such as mcp-remote, with ChatGPT given the URL the bridge serves. The text
still gets chopped locally.
Your own rules¶
The server reads the same configuration as every other command, so the tools already sound like you:
- A
.slop-chop.jsonin the directory the server starts in. - Your
~/.slop-chop/voice.json, written byslop-chop voice init. See Your voice. - The flags you launch it with:
--profile,--preset,--dialect, and--voice.
Flags set the defaults. A call naming its own presets or dialect overrides them for that
call alone.
The model rewrite¶
model_rewrite is off by default, so the free deterministic clean is what you get unless you
ask for more. Set it to true and the rules run first, then a model reworks what rules cannot,
such as recasting a sentence so it no longer needs a semicolon. It needs a provider key and
makes a paid call.
export ANTHROPIC_API_KEY=sk-...
claude mcp add slop-chop -- slop-chop mcp
Point it at a local model instead and it costs nothing:
claude mcp add slop-chop -- slop-chop mcp \
--provider openai --base-url http://localhost:11434/v1 --model llama3.1
Whatever the model returns is run through the rules again before you see it, so a rewrite cannot put back the tells the rules just cut.
Privacy¶
The rules pass is a function of the text and your profile. It runs in the server process on
your machine, reaches no network, and writes nothing to disk. The only text that leaves is what
you send to a model, and only when a call sets model_rewrite. See Privacy.
Publishing to the MCP registry¶
The registry indexes metadata, not artifacts. It cannot point at a Go binary directly, so
the server ships as MCP bundles: a zip holding the binary and a manifest, attached to the
release and named in server.json by URL and SHA-256. The release workflow builds and
attaches one bundle per platform, which is why the order below puts the release first.
# 1. Cut the release. The workflow builds six bundles and attaches them.
gh release create vX.Y.Z --generate-notes --title "vX.Y.Z: Title"
# 2. Write server.json from the bundles the release published.
make server-json MCPB_VERSION=X.Y.Z
make check-versions
# 3. Publish. The login is a device flow against your own GitHub account.
mcp-publisher login github
mcp-publisher publish
The namespace is io.github.dcadolph/slop-chop, which GitHub authentication proves. A
name under a domain instead would need a DNS TXT record and buys nothing here.
The hashes come from the published assets rather than a local rebuild. A rebuild is not
bit-identical to the one CI produced, since the binary and the zip both carry build-time
detail, and clients verify the hash before installing. Hashing a local copy ships an entry
that fails every install, which is why server-json downloads the release assets instead
of the bundles sitting in dist/.
Two things worth knowing before relying on the listing. The registry is in preview and its
own documentation warns that data resets can happen before general availability, so an
entry may need republishing. And the hashes in server.json have to match bundles that are
already downloadable, which is why server-json runs after the release rather than before.
check-versions fails when server.json names a version or a release URL that disagrees
with the rest of the tree.