Tether MD
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Tether MDaddress my comments in draft.md"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tether MD
You comment. The agent proposes. You decide.
Comment across the draft, as fact or interpretation. The agent works through every comment in one pass; you accept or reject each change. Export stays byte-identical.
Most AI writing surfaces either rewrite your document under you (chat canvases, "apply" buttons) or lock review into a platform (Google Docs, Word, Notion). Markdown in git has no standard suggest mode: a way to leave a comment on a phrase, have an AI act on it, and approve or reject each change yourself.
Tether MD is that layer: anchored comments for Markdown that AI agents act on, but never apply. It is a file format rather than a platform.
Comments live in the file. One invisible HTML-comment marker per comment, plus a machine-readable block at the end. No database, no sidecar, no service; the raw file renders clean on GitHub, in VS Code preview, and through pandoc.
Anchors survive editing. Quote selectors with fuzzy re-anchoring follow the text through edits, flag uncertain matches as needs-review, or orphan with an error.
Agents propose; humans apply. Your comments are anchored instructions. An agent attaches proposals; Accept applies one and clears the comment, Reject discards it. Paragraph moves follow the same rule: mark where text should go, and nothing moves until you press Accept Move.
Clean export is tested in CI. One projection function strips the comment layer; the result is byte-for-byte your prose.
Install
Three pieces. The CLI is the foundation; the other two are optional and independent.
CLI + MCP server —
npm i -g tether-md(Node 20+). Gives you thetethercommand andtether mcp.VS Code extension — download
tether-md.vsixfrom Releases, then Extensions panel →⋯→ Install from VSIX → reload the window. (Or from a clone:npm install && npm run build && npm run package -w tether-md-vscode.)Agent compatibility, per project — run
tether initin the project root. It writes.mcp.json(project-scoped MCP server) and theAGENTS.mdcontract note;tether init --skillalso installs the Claude Code skill. Details in Hook up your agent.
Related MCP server: MD Vision
Quickstart
npm i -g tether-mdprintf 'A draft with some exact phrase in it.\n' > draft.md
tether comment add draft.md --quote "some exact phrase" --body "tighten this" --write
tether status draft.md # comments, proposals, anchor health
tether comment suggest draft.md <id> --to "a tighter version" --write # the agent's move (or yours)
tether comment diff draft.md <id> # preview: - current / + proposed
tether comment accept draft.md <id> --write # apply it and clear the comment
tether export draft.md # the authored prose, byte-identicalEvery mutating command prints its result by default, only edits in place with --write (atomically), and takes --json; comment list and error envelopes are JSON already. Exit codes are stable:
code | meaning |
0 | ok |
1 | usage error |
2 | malformed store block |
3 | IO error |
4 | check failed ( |
Try it on a real document in 30 seconds: examples/ ships a worked walkthrough, including the one-line proof of the export guarantee (tether export reviewed.md | diff - draft.md prints nothing: byte-identical).
Hook up your agent
One command, in your project:
tether init # .mcp.json (project-scoped MCP server) + AGENTS.md contract note
tether init --skill # also installs the Claude Code skill into .claude/skillsClaude Code discovers .mcp.json on its own the next time the project opens, and AGENTS.md carries the contract for agents that bring their own file tools. Both writes are idempotent and merge into existing files. To wire the MCP server by hand instead, any MCP-capable agent works (Claude Code, Cursor, Codex CLI, and others):
claude mcp add tether -- tether mcpThe MCP server exposes tether_list, tether_status, tether_diff, tether_suggest, tether_comment (flag-backs), and tether_export. It deliberately omits accept, reject, and edit, and its server instructions tell every connected agent to stay on that surface. Within it, the trust boundary is structural, not prompt etiquette.
One caveat that matters: most coding agents (Claude Code, Cursor, and friends) also carry their own file tools, and no file format can gate those. An agent that has never been told the contract will treat a Tether file like any other markdown and edit it in place. So tell it: run tether init, install the skill below, or add this to your project's AGENTS.md or CLAUDE.md:
Markdown files here may contain tether-md comments: invisible <!--tether:...-->
markers plus a store block at EOF. Never edit these files directly; never touch
the markers or the store block. Read the threads with `tether comment list`,
propose rewrites with `tether comment suggest <file> <id> --to "..." --write`,
flag concerns with `tether comment add <file> --quote "..." --body "..."
--author agent --write`. Accept, reject, and export belong to the human.For Claude Code there is also a full skill, skills/tether-edit/SKILL.md. It teaches the contract end to end: read the document, read the comments, propose per instruction, flag back anything that can't be grounded, hand control back. The agent never applies, resolves, or exports.
The working loop becomes: comment on phrases, tell the agent to "address my comments", then review each suggestion in your editor and accept or reject it.
In VS Code
Install per Install above, open any markdown file, and everything below works on it. Comments render as native inline threads; nothing needs configuring.
keys / surface | what it does |
select prose, ⌘⌥C (Ctrl+Alt+C) | comment on the selection: type the note, pick fact or interpretation |
gutter | same, mouse-first (one |
caret in a paragraph, ⌘⌥M (Ctrl+Alt+M) | pick the paragraph up to move (no selection needed); then click where it should go — the click snaps to the nearest paragraph boundary |
⌘⌥M again while a move is armed | destination list with a live "move here" preview in the editor |
Esc | cancel an armed move (any edit also cancels it) |
thread buttons | Accept / Reject on an agent's suggestion; Accept Move / Reject on a move; Delete on a plain comment |
right-click menu | Tether: Add Comment from Selection, Tether: Move Paragraph |
command palette | Tether: Export Clean Document — writes |
A marked move is just a comment with a destination: the excerpt gets a ① badge, the destination a ⇣① badge, and nothing actually moves until you press Accept Move on its thread. Moves show up in tether comment list (a moveTo field) and tether comment accept applies them, so the CLI and the editor stay interchangeable.
If anchoring ever degrades, you hear about it: fuzzy re-anchors get a dashed warning underline and a diagnostic, and Accept refuses until re-confirmed; orphans land in the Problems panel with a one-click fix.
The editor and the agent never talk to each other. Both only touch the file, so you can watch proposals arrive in your open editor.
What the file actually looks like
The pattern is always the same. The app starts as a text editor and becomes a
database. <!--tether:c=01KWQ2QFDFTHXWAF7RJS1ZNSSX-->Databases survive until the
next funding round.
<!--tether:store
{"id":"01KWQ2QFDFTHXWAF7RJS1ZNSSX","v":1,"trust":"fact","author":"human","body":"sharpen this",...}
tether:store-->One caret marker per comment (a ULID, which can never form the -- sequence HTML comments forbid), and all data in one JSONL store block at the end of the file, escaped to stay grammar-legal. Renderers hide HTML comments, so the raw file previews clean on GitHub, in VS Code preview, and through pandoc. The grammar, the projection algorithm, the selector model, and the re-anchoring confidence bands are specified in docs/spec/wire-format-and-projection.md. The spec is the product; the TypeScript here is the reference implementation.
What happens when you edit the text
A comment points at a phrase, and you keep editing the document. Each time the file is read, every comment is re-matched to the current text and gets a confidence score between 0 and 1. The score decides one of three outcomes:
outcome | when | what you see |
anchored | the phrase still matches (score ≥ 0.75) | the comment follows its text |
| the phrase changed enough to blur the match (0.50–0.75) | a dashed warning underline and a diagnostic; Accept refuses until you re-confirm |
orphaned | the phrase is effectively gone (below 0.50) | a loud error; |
A weak match downgrades to needs-review or orphans loudly; it does not silently attach to the wrong words.
Matching tries the exact phrase first, disambiguates duplicates by their surrounding context, and only then falls back to fuzzy matching, which is where the score comes from (details in the spec). One extra safeguard on top: accepting a proposal requires the anchored text to still read exactly as it did when the proposal was made, so a stale suggestion can never splice onto changed wording.
The three invariants
Everything above reduces to three properties, tested on every commit:
Re-anchor or orphan. After any edit, every comment re-anchors above the confidence floor or orphans loudly. Weak matches are never silent.
Zero perturbation. Adding or removing a comment never changes the exported prose or any other comment's anchor.
Export identity.
tether exportis byte-for-byte the authored prose.
How it compares
comments in the file | survive edits | AI propose, human accept | works with any agent | clean export guarantee | |
Tether MD | yes | fuzzy, loud orphans | native threads / CLI | CLI + MCP + skill | byte-identical, in CI |
Google Docs / Word / Notion | no (platform DB) | yes | their AI only | no | export differs from source |
GitHub PR suggestions | no (PR thread) | no (stale on rebase) | in the PR UI | PR-bound bots | n/a (reviews a diff, not the doc) |
CriticMarkup | yes (visible syntax) | inline, no drift detection | no native flow | format only | processor-dependent |
Cursor / chat canvases | no (session diff) | — | until the session ends | no | — |
Roughdraft | yes (CriticMarkup) | inline, no drift detection | in its local web UI | yes (CLI) | not spec'd or CI-tested |
The bet: suggest mode should be a property of the document, not of an app. That is also why the wire format is specified independently of this implementation; ports are welcome.
Why not CriticMarkup? Its syntax is visible noise in any CriticMarkup-unaware renderer (GitHub included), and its comments bind only by adjacency: nothing detects when the prose they were about is rewritten. Tether's markers hide in rendered views and re-anchor by quoted text. Why not PR review? Suggestions there attach to diff lines in a forge's database, need a remote and a pull request, and go stale on rebase; here the document itself carries the review, offline, in any repo state.
Monorepo
Package | What |
The | |
The pure projection kernel: | |
The VS Code extension (native Comments API). | |
The agent contract (Claude Code skill). | |
The wire-format spec, architecture decision records, milestone history. |
git clone https://github.com/tether-md/tether-md && cd tether-md
npm install && npm run build && npm testLimitations
Editor UI is VS Code-only today. The kernel is editor-agnostic; Obsidian and nvim ports are the most-wanted contributions.
The propose-not-apply contract is structural on the MCP surface, but an agent with its own file tools follows it only once it has the skill or the
AGENTS.mdnote above. An untold agent edits the file like any other markdown.Store blocks are LF-only by grammar. CRLF hard-fails loudly rather than mis-parsing; the repo's
.gitattributesprotects checkouts, and tolerant reads are tracked.Paragraph moves are LF-only and paragraph-granular (paragraphs are blank-line separated). Seams that touch CRLF or whitespace-only blank lines, and destinations whose text repeats verbatim elsewhere, are refused loudly rather than guessed at.
A file with a pending move is written as a
v: 2record: tether-md 0.1.x refuses the whole file until the move is accepted or rejected (deliberate — an older version could otherwise half-apply it). Accepting or rejecting all moves returns the file tov: 1.One store block per file; concurrent writers race at the file level. Treat the raw file like source code (git merges the store poorly).
A comment anchored inside a code region relocates its marker to just before that region. Two pathological shapes are rejected with clear errors.
Roadmap
Verification gate (the origin of this project): fact-grounding and claim-strength checks whose findings arrive as anchored comments.
CriticMarkup import/export, conformance test vectors for ports, an Obsidian plugin, a browser build of the kernel.
Contributing
The spec comes first, the three invariants are non-negotiable, and correctness bugs get priority over everything else. See CONTRIBUTING.md.
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tether-md/tether-md'
If you have feedback or need assistance with the MCP directory API, please join our Discord server