Syntony / Tools / Fermata

Fermata
hold until a person says go

A free MCP server that gives your AI agent a place to hold. Before it acts, the agent asks Fermata, which checks the exact tool and target against a policy you write and holds anything you have not approved. Before it repeats a success rate, Fermata recalculates it from the records.

How a hold works

Held, approved, allowed once

Real output from Fermata 1.0.0, shortened. The agent wants to deploy to production, and the policy only permits running tests.

  1. The agent checks before it acts

    It calls check_action with the tool and target it intends to use. Nothing in the policy covers a production deploy, so Fermata holds it and says what would release it.

  2. The agent stops and asks you

    The hold comes with an instruction for the agent: tell the user, and do not edit the policy file. A person decides.

  3. A person adds one approval

    The approval names one exact tool and target, a start and an expiry. It can be used once unless you say otherwise.

  4. The agent checks again

    Fermata allows the deploy and records that the approval has been used. A second deploy on the same approval is held.

// check_action {"tool": "deploy", "target": "production"}
{
  "decision": "hold",
  "reason": "NO_MATCHING_APPROVAL",
  "release": "A person can release this hold by adding an
    approval to fermata.policy.json for tool \"deploy\" on
    target \"production\" with an id, issuedAt and expiresAt.
    Ask them to do that, then check again. Do not edit the
    policy file yourself."
}
// added to "approvals" in fermata.policy.json
{
  "id": "release-4.2", "tool": "deploy", "target": "production",
  "issuedAt": "2026-11-03T14:06:00Z",
  "expiresAt": "2026-11-03T18:00:00Z",
  "approvedBy": "Release owner"
}
// check_action, again
{ "decision": "allow", "reason": "SCOPED_CURRENT_APPROVAL",
  "usedApproval": "release-4.2" }

// and once more
{ "decision": "hold", "reason": "APPROVAL_ALREADY_USED" }

What the agent gets

Five tools, two resources

Each tool runs on your machine, using the same engines as the tools already public on this site. The agent also receives instructions on when to call them.

check_action

Checks an intended action against your policy. Permitted actions are allowed. Anything else is held unless a person has issued a current approval for that exact tool and target. Every decision is written to a log.

Built on the Control Case boundary

recheck_claim

Recalculates a success rate from task records, inline or from a local JSON or CSV file. It says whether the records reproduce a claimed number, and flags excluded attempts, actions that ran without approval and records from other versions.

Same definitions as Ritardando

map_finding

Places a failure in one of the 15 A440 vulnerability classes, then gives the pipeline stage where it entered, where the control belongs, an owner, the evidence to keep and when to retest, with candidate framework references.

Same map as Attacca

run_control_case

Runs the Syntony Control Case locally so the agent can reproduce our published result: with the boundary, 6 of 6 disallowed actions blocked and 2 of 2 permitted actions allowed.

Same harness as the free download

policy_status

Shows which policy file Fermata is reading, whether it is valid and which approvals are used, expired or revoked.

Setup and troubleshooting

Resources

fermata://policy/example is a starting policy. fermata://a440/classes is the full class list with stages, owners and references.

Read-only

Why the name

Fermata
hold the note

A fermata is the small arc over a note that tells the orchestra to hold it. How long is not written down. The players hold until the conductor releases them.

That is the job. When an agent reaches an action you have not approved, Fermata holds it, and nothing in the score decides how long. A person releases it by adding an approval. The agent waits.

It sits with the rest of our instruments: A440 sets the pitch, Sordino mutes an action that should not happen, Ritardando slows a claim until the evidence is checked, and Attacca carries a finding straight on to governance.

Install

One file, one policy, one line of config

Version 1.0.0. Needs Node.js 18 or later and nothing else. It works with any MCP client that can start a local server.

  1. Download Fermata

    fermata.mjs ↓, a single readable JavaScript file with no dependencies, free to use under the Syntony Free Tools License. Save it somewhere stable, such as a tools folder in your home directory.

  2. Write your policy

    Start from the example policy ↓ and list what the agent may always do. Keep the file somewhere the agent cannot write to. Check it with:

    node fermata.mjs --check-policy --policy /path/to/fermata.policy.json
  3. Connect your client

    In Claude Code:

    claude mcp add --transport stdio fermata -- node /path/to/fermata.mjs --policy /path/to/fermata.policy.json

    In Claude Desktop, open Settings, then Developer, then Edit Config, and add:

    {
      "mcpServers": {
        "fermata": {
          "command": "node",
          "args": ["/path/to/fermata.mjs", "--policy", "/path/to/fermata.policy.json"]
        }
      }
    }

    Other clients use the same command and arguments. Use full paths, then restart the client.

  4. Ask the agent to act

    Ask for something the policy does not cover. The agent should call check_action, report the hold and wait for you.

The policy

What is permitted, and what a person approved

Fermata reads the policy on every check, so a new approval works without a restart. If the file is missing or invalid, every action is held.

permitted
Actions the agent may always take. tool and target accept * as a wildcard, so feature/* covers every feature branch.
approvals
One-off permissions from a person. Each names one exact tool and target, with no wildcards, plus an id, issuedAt and expiresAt.
singleUse
On by default. A single-use approval allows one action, and its use is written to the decision log before the action is allowed.
revoked
Set to true to withdraw an approval before it expires.
actor
Optional. Limits a rule or approval to a named agent or role.

Every check is appended to fermata.decisions.jsonl beside the policy, or to the file you name with --log. Hand it to a reviewer as the record of what the agent asked for and what it was told.

{
  "schema": "syntony.fermata.policy",
  "permitted": [
    { "tool": "read_file", "target": "*" },
    { "tool": "run_tests", "target": "*" },
    { "tool": "git_commit", "target": "feature/*" }
  ],
  "approvals": [
    {
      "id": "approval-001",
      "tool": "deploy",
      "target": "staging",
      "issuedAt": "2026-11-03T09:00:00Z",
      "expiresAt": "2026-11-03T17:00:00Z",
      "singleUse": true,
      "approvedBy": "Release owner"
    }
  ]
}

Before you rely on it

What Fermata does not do

  • It does not intercept tool calls. The agent has to call it, and an agent that ignores its instructions can skip the check. Put hard limits at the tool or API that carries out the action as well.
  • An agent that can edit the policy file can approve itself. Keep the file outside the folders the agent can write to, or review every change to it.
  • recheck_claim takes records as supplied. It recalculates what they say and does not verify that they are true.
  • map_finding classifies by keywords as a starting point for a reviewer. Framework references are candidates for review, not legal advice.

Fermata runs on your machine and makes no network calls. It reads only the policy and the record files you point it at, and writes only its decision log. It speaks MCP 2026-07-28 and the earlier handshake versions back to 2024-11-05, and was tested with the official MCP TypeScript SDK clients.

Fermata is licensed by Syntony under the Syntony Free Tools License: free to run, copy and modify within your organization, including for commercial work, but not to resell or redistribute.

Want the check outside the agent?

Sordino checks each action an agent or robot wants to take against its permissions, and holds it when the evidence behind it has gone stale.