Synartesis

Install · configure · check it worked

Your first way back.

Install the CLI, connect your client, then check that its calls reach the journal. Prefer a conversation? Get the desktop app alongside it.

npm install -g synartesis

Requires Node.js 22 or newer.

Prefer a window?

Get the desktop app.

The desktop app is a separate download for macOS (Apple silicon and Intel), Windows, and Linux. It uses the same proxy, policy and journal as the CLI.

Download the desktop app ↗

After installing the app, use its icon or run synartesis desktop. The npm package alone does not include the desktop app.

The builds are unsigned. macOS Gatekeeper blocks the first launch; Windows SmartScreen may block it or show a warning. These warnings mean the operating system cannot verify the publisher. Review the release and source before deciding whether to open it.

Platform instructions and building from source ↗

Your first undo

One folder, one rule, one mistake put back. Every line of output below is what these commands actually print — nothing here is illustrative.

  1. Install it

    This is for you — the screen, undo, watch. Your agent needs nothing installed: the config later on fetches the proxy on demand.

    npm install -g synartesis
  2. Put a folder under guard

    Pick somewhere real but survivable. init asks the server what it can do. This one it recognises, so it uses the policy that ships here and checks every rule against what the server actually advertises. A server it does not know gets every tool guarded, because a tool nobody has said how to undo is one your agent should not be using alone.

    from anywhereone policy, in your home
    $ synartesis init fs -- npx -y @modelcontextprotocol/server-filesystem ~/notes
    
       WROTE  ~/.synartesis/synartesis.yaml
    
      Recognised 14 tools, so the policy that ships for filesystem was used.
      Read it before you trust it.

    That last path is the one thing to choose: everything under it is what your agent can read and write, and nothing outside it exists as far as the server is concerned. Name a real directory you would mind losing but could survive — ~/notes, ~/Documents/drafts, ~/code/some-project. Pass more than one to allow more than one.

  3. Read the one rule that matters

    The filesystem server is one it knows, so this is already written. Open the file and find fs.write_file — it is the whole idea in eight lines, and the shape you will write yourself for a server it does not recognise. snapshot is what to read before the call; inverse is the call that puts that back. $.path is an argument the agent passed; $snapshot.content is what the pre-read found. And absent_when is what this server says when the thing is not there — without it, a file that exists but cannot be read looks identical to one being created, and gets offered for approval as though it were.

    ~/.synartesis/synartesis.yamlan unrecognised server, before you fill it in
    - match: "fs.write_file"
      class: irreversible
      gate: always
    ~/.synartesis/synartesis.yamlwhat a finished rule looks like
    - match: "fs.write_file"
      class: reversible
      snapshot:                        # read this first
        tool: "fs.read_text_file"
        args:
          path: "$.path"
        absent_when: ["ENOENT", "no such file"]   # what "not there" sounds like
      inverse:                         # and this puts it back
        tool: "fs.write_file"
        args:
          path: "$.path"
          content: "$snapshot.content"
  4. Check it before you trust it

    check starts every server and asks whether the tools your policy names actually exist. One reversible tool is enough to begin; the three still guarded will simply stop and ask.

    synartesis checkbefore anything is running
    $ synartesis check
    
       POLICY  ~/.synartesis/synartesis.yaml
    
      servers  fs
      policies 10 readonly, 1 reversible, 3 irreversible
      guarded  3
  5. Point your agent at the proxy, not the server

    One entry, however many servers your policy covers. Then work normally: ask your agent to tidy the folder, rewrite a file, whatever you would have asked anyway.

    .mcp.jsonthe same block in any client
    {
      "mcpServers": {
        "synartesis": {
          "command": "npx",
          "args": ["-y", "synartesis", "proxy",
                   "--manifest", "/Users/you/.synartesis/synartesis.yaml"]
        }
      }
    }
  6. Put it back

    Your agent overwrites roadmap.md with something you did not want. Look first with --dry-run; both default to the most recent run, so there is usually no id to type. The line that matters is state matches — it read the file again and confirmed nothing else had changed it since.

    synartesis undothe file comes back
    $ synartesis undo
    
        1  revert           fs.write_file  state matches; applying inverse
           called fs.write_file {"path":"~/notes/roadmap.md",
             "content":"# Roadmap\n\nQ3: ship the undo layer.\n"}
    
       RESULT  rolled_back

Where the config goes

One command does all of this for you. The configurations below are the same thing by hand, for a client it did not find or if you would rather see the file.

the short way
synartesis install

It finds what Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI, Copilot CLI, Antigravity and Devin Desktop (or Windsurf) already list, writes one policy covering all of them, and points each client at the proxy — keeping a record of what it changed, so synartesis uninstall puts every file back exactly as it was. Add --dry-run to see what it would do first, then synartesis status to check what is covered. A hosted server with a token in its headers is covered directly; one that signs you in through a browser is covered with --remote.

The entries below are for one server, as init sets up. For several, give each its own entry with --server <name> — which is what install writes — or every tool is renamed server__tool.

Claude Code

One command, no file to find. Or write .mcp.json at the root of a project to share it with everyone working on that repo.

terminalanywhere
$ claude mcp add synartesis -- npx -y synartesis proxy \
    --manifest ~/.synartesis/synartesis.yaml
Claude Desktop

Settings → Developer → Edit Config opens this file, creating it if it is not there. Quit and reopen the app afterwards — it only reads the file at startup.

claude_desktop_config.jsonmacOS · Windows
~/Library/Application Support/Claude/claude_desktop_config.json
%APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "synartesis": {
      "command": "npx",
      "args": ["-y", "synartesis", "proxy",
               "--manifest", "/Users/you/.synartesis/synartesis.yaml"]
    }
  }
}
Cursor

~/.cursor/mcp.json for everywhere, .cursor/mcp.json in a project for just that one. Cursor wants the transport named explicitly.

~/.cursor/mcp.jsonnote the type field
{
  "mcpServers": {
    "synartesis": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "synartesis", "proxy",
               "--manifest", "/Users/you/.synartesis/synartesis.yaml"]
    }
  }
}
Codex CLI

OpenAI’s local agent, which does run stdio servers. One command, and it writes the TOML below into ~/.codex/config.toml for you. codex mcp list shows it afterwards.

terminalopenai codex
$ codex mcp add synartesis -- npx -y synartesis proxy \
    --manifest ~/.synartesis/synartesis.yaml

  Added global MCP server 'synartesis'.
~/.codex/config.tomlwhat that writes
[mcp_servers.synartesis]
command = "npx"
args = ["-y", "synartesis", "proxy", "--manifest", "/Users/you/.synartesis/synartesis.yaml"]
Anything else, and one that will not work

Any client that runs a local MCP server takes the same two fields, whatever it calls its config file. ChatGPT is the one that will not: its connectors accept a remote HTTPS endpoint only and will not start a process on your machine, so a command entry has nowhere to go. For that, serve the proxy over HTTP instead — it refuses to start without a token, and binds to loopback until you say otherwise.

an endpoint instead of a process/mcp, bearer token
$ synartesis proxy --manifest ~/.synartesis/synartesis.yaml \
    --http 9123 --token "$SYNARTESIS_TOKEN"

  a session that goes quiet for half an hour is closed;
  --http-idle changes that

Reaching that from the internet means a tunnel in front of it, and that stays your decision rather than a flag. What is on the other end can write through every server in your policy: treat the token like a password, and prefer a tunnel that does its own authentication.

Telling whether it worked

The failure worth knowing about is the quiet one: your agent connects, ignores the tools, and uses its own instead. Nothing errors. Nothing is recorded.

  1. Ask the agent to do something, then look

    Leave synartesis watch running in a second terminal. Rows appear as calls happen. A live run beside zero actions is the diagnostic — it means your agent connected and then did the work with its own file tools. Name the tools you want it to use, or take the built-in ones away.

    synartesis watchsecond terminal
    $ synartesis watch
    
      ⧗ watching  1 runs, 1 live  ·  0 recent actions
            ↑ connected, and not being used
  2. When the server will not start

    Run the same command by hand: whatever it prints is what your client saw and hid. check starts every server in the policy and reports which named tools do not exist. Claude Desktop keeps per-server logs, and they are the fastest answer when a connector simply never appears.

    three places to lookin this order
    $ synartesis check
    $ npx -y synartesis proxy --manifest ~/.synartesis/synartesis.yaml
    $ tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
  3. Paths, which are most of it

    Use absolute paths in the config — a client does not start in the directory you think it does, and ~ is not expanded inside a JSON string. Give --manifest the real path. If npx cannot be found, the client is running with a smaller PATH than your shell: give the full path to npx, or install with npm install -g synartesis and use synartesis directly.

A server nobody has written a policy for

Four ship with one. For anything else — a database, a ticketing system, the MCP server you wrote last week — start by asking the server what it has.

  1. Draft it from the server

    init connects, lists every tool, and writes a manifest from what the server says about itself. If it recognises the server as one that already ships with a policy it adopts that instead — but only when every tool that policy calls is really there, because a policy whose inverses cannot be called is worse than a file of TODOs: it looks finished.

    your own serverdrafted, not decided
    $ synartesis init crm -- ./crm-mcp
    
       WROTE  ~/.synartesis/synartesis.yaml
    
      Every tool is guarded until you say how to undo it.
      Work through the TODOs, then point your MCP client at:
  2. Open it, and open it up one tool at a time

    A tool the server marks read-only is written readonly with a comment telling you to check it, because that hint is a statement of intent and not a guarantee. Everything else lands irreversible and guarded. That is the safe end of the trade and the intended starting point: the draft is fail-closed, and you open it up as you work out how each tool is put back.

  3. Check it against the running server

    check loads the manifest, starts every server it names, and says which tools your policy covers, which it does not, and where the two disagree. A policy naming a tool the server no longer has is an error, not a warning — a rule that cannot fire is the kind of mistake that reads as protection.