AgentStack
MCP verified MIT Self-run

Tether Md

mcp-tether-md-tether-md · by tether-md

Anchored comments for Markdown. You comment, the agent proposes, you decide. Byte-identical clean export.

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add mcp-tether-md-tether-md

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-tether-md-tether-md)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
13d ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Tether Md? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Tether MD

You comment. The agent proposes. You decide.

[](https://github.com/tether-md/tether-md/actions/workflows/ci.yml) [](https://www.npmjs.com/package/tether-md) [](LICENSE)

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.

  1. CLI + MCP server — npm i -g tether-md (Node 20+). Gives you the tether command and tether mcp.
  2. VS Code extension — download tether-md.vsix from 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.)
  3. Agent compatibility, per project — run tether init in the project root. It writes .mcp.json (project-scoped MCP server) and the AGENTS.md contract note; tether init --skill also installs the Claude Code skill. Details in [Hook up your agent](#hook-up-your-agent).

Quickstart

npm i -g tether-md
printf '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  --to "a tighter version" --write   # the agent's move (or yours)
tether comment diff draft.md             # preview:  - current / + proposed
tether comment accept draft.md  --write  # apply it and clear the comment
tether export draft.md                       # the authored prose, byte-identical

Every 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 (status --check) |

Try it on a real document in 30 seconds: [examples/](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/skills

Claude 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 mcp

The 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 
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   --to "..." --write`,
flag concerns with `tether comment add  --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](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](#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 + per logical line; for a second comment on the same soft-wrapped paragraph, select and use the keybinding) | | 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 .clean.md beside the file |

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. Databases survive until the
next funding round.

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](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 | | needs-review | 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; tether status --check exits 4, so CI can catch it |

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](docs/spec/wire-format-and-projection.md)). 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:

  1. Re-anchor or orphan. After any edit, every comment re-anchors above the confidence floor or orphans loudly. Weak matches are never silent.
  2. Zero perturbation. Adding or removing a comment never changes the exported prose or any other comment's anchor.
  3. Export identity. tether export is 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 | |---|---| | [tether-md](packages/cli) | The tether CLI and MCP server (tether mcp): the stable, file-only contract surface. | | [@tether-md/kernel](packages/kernel) | The pure projection kernel: P(raw) → clean, offset maps, anchoring, store codec. No IO. | | [tether-md-vscode](packages/vscode-ext) | The VS Code extension (native Comments API). | | [skills/](skills) | The agent contract (Claude Code skill). | | [docs/](docs) | 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 test

Limitations

  • 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.md note 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 .gitattributes protects 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: 2 record: 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 to v: 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](CONTRIBUTING.md).

License

MIT

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.