Zuger MCP

One address.
Every assistant

Zuger speaks the Model Context Protocol. Claude, ChatGPT, Cursor and any MCP client can brief your agents, follow their Runs and read what is waiting on you. Nothing that decides: that stays yours, in the Console.

IN CONVERSATION

A call goes in,
an answer comes back.

What an assistant and Zuger say to each other, with the frame that was really sent. The third exchange is a refusal.

14tools, each one call into the same store the Console uses
0tools that approve, sign, file, pay or hire
1address, one message per POST: beta.zuger.ai/mcp

THE ENDPOINT

One address,
two ways in.

WhatHow
Endpointhttps://beta.zuger.ai/mcp
TransportStreamable HTTP: one JSON-RPC 2.0 message per POST, answered as JSON. No session, no event stream (GET is 405). A notification is 202 with no body.
Protocol versions2025-06-18, 2025-03-26, 2024-11-05
Sign in as a personOAuth 2.1: the client registers itself, the person says yes on a Console screen, PKCE proves every exchange. Metadata at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource/mcp.
Sign in with a keyAuthorization: Bearer zk_live_…, an API key from the Console under Developers, with the scopes you chose.
IdentityserverInfo is Zuger, with the connector page and the icon, so a client that shows connectors shows this one by name.
# one message per POST; the answer comes back as JSON
curl https://beta.zuger.ai/mcp \
  -H "Authorization: Bearer $ZUGER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"whats_waiting","arguments":{}}}'

THE HANDSHAKE

Four messages,
and the assistant knows the house.

  1. 01

    initialize

    The client says which protocol version it speaks; Zuger answers with its name, its capabilities, and its instructions: the rule of the house, read by the model before it does anything.

  2. 02

    tools/list

    Fourteen tools with JSON schemas. Readers carry readOnlyHint; nothing carries destructiveHint, because nothing destroys.

  3. 03

    tools/call

    One tool, its arguments. The scope is checked per call: a key without it hears why as a result the model reads, not a protocol error. A frozen company reads but starts nothing.

  4. 04

    the answer

    A sentence first, then the data, and a Console link wherever a person has to act. Ids, statuses and short text; never a credential, never a connected tool’s raw payload.

WHAT A CALL LOOKS LIKE

The frame in,
the frame out.

{
  "jsonrpc": "2.0", "id": 7,
  "method": "tools/call",
  "params": {
    "name": "brief_agent",
    "arguments": {
      "agent": "LEDGER",
      "text": "Reconcile August.",
      "idempotency_key": "aug-recon-1"
    }
  }
}
{
  "jsonrpc": "2.0", "id": 7,
  "result": {
    "content": [{ "type": "text",
      "text": "Briefed LEDGER: \"Reconcile August.\" …
        If it stops at an approval, the person
        decides in the Console: …/#/approvals" }],
    "structuredContent": {
      "queued": true, "agent": "LEDGER",
      "title": "Reconcile August."
    }
  }
}

Send the same idempotency_key again within a day and the answer is the first Run, with replayed: true, not a second one.

TOOLS

Fourteen tools,
each one store call.

whats_waiting

The short answer to “what is waiting on me?”: approvals pending, Runs in progress, Runs held by Bernina, with links. approvals:read

brief_agent

Hand an agent work in plain words; the words become one Run. Takes an idempotency key so a retry is the same Run. runs:write

list_runs · get_run

Recent Runs; one in full: steps, answer, documents, Bernina’s verdicts, approvals with the link to decide. runs:read

list_approvals · get_approval

What an agent prepared and stopped for. Read only, always with the Console link. approvals:read

list_agents

The agents by kind and name, and who is on shift. Only an agent on shift can be briefed. agents:read

list_routines · create_routine · pause_routine

Standing instructions every day, week or month, in the company’s timezone. routines:read · routines:write

list_memory · remember

Company memory, read and added to: a preference, a fact, a rule of the house. memory:read · memory:write

list_findings

What Säntis found sweeping the books: claim, evidence, proposed action, severity. findings:read

export_audit

The hash-chained audit log, oldest first. Founder Max and Ultra; an owner or admin. audit:read

Resources: zuger://approvals, zuger://agents, and one Run at zuger://runs/{id}. Prompts: What needs me? and Close the month.

WHAT NO TOOL DOES

The line,
in the server’s own words.

Zuger prepares; a person files, signs and pays. Approvals are decided by a person in the
Console, with a passkey: no assistant, key or connected app can approve, reject, sign,
file, pay, hire, connect a tool or change billing.

No deciding tool exists

There is no approve, sign, file, pay or hire, and no combination of tools that adds up to one. The scope list has no scope for them either.

The model is told first

The sentence above is in instructions, returned by initialize. Asked to decide, the assistant answers with the Console link.

Bernina reads every brief

A brief from Claude is inspected exactly as one typed in the Console: the same gate, the same holds, the same refusals. She is not a prompt; she is the platform.

Answers carry no secrets

Ids, statuses, short text and links. Never a credential, never a connected tool’s raw payload, never another company’s artefact.

A person connects, a person disconnects

A key or a connected app cannot connect another. Every connected app is listed in Settings, by whom and last used; owners and admins see them all.

The same limits

Your plan’s Runs, 1,000 requests a minute for the company, and the freeze for non-payment: a frozen company reads and starts nothing.

SETUP

Every client,
the same address.

Claude

Settings → Connectors → Add custom connector → https://beta.zuger.ai/mcp. Claude opens the sign-in; say yes once.

ChatGPT

Settings → Connectors → Create → MCP → the same address. You sign in on the Console.

Claude Code

claude mcp add --transport http zuger https://beta.zuger.ai/mcp, with --header "Authorization: Bearer …" for a key, or without it for a sign-in.

Cursor, VS Code

An MCP server of type http at the address; add the Authorization header for a key.

Any other client

Read /.well-known/oauth-protected-resource/mcp, register at the authorization server it names, and follow the code flow with PKCE. Or send a key.

Disconnect

Settings → Connected apps in the Console: every connected app, by whom, last used. Owners and admins see them all.

Available on every plan, including Free. The same limits as the Console: your plan’s Runs, and 1,000 requests a minute for a company.

QUESTIONS

Asked by the person
setting it up.

Is there a session?

No. Every request carries the bearer that identifies the caller; nothing is remembered between two of them. That is what makes one address serve every client.

Why no event stream?

Nothing here needs a server-to-client channel: a Run is followed by asking. GET /mcp answers 405 so a client never waits on one.

What does a key see that a person does not?

Less. A key holds the scopes it was made with; a person’s token holds what they granted, which is never more than the scopes a key could hold. Neither can decide.

What if the model retries a brief?

Send an idempotency_key. The same key from the same person within a day answers with the first Run, replayed: true.

Where do I see what an assistant did?

On the Run: a brief from an assistant says where it came from. In the audit log: every grant, connection and disconnection is a row.

Can I run it against a test company?

Make a second company on the Free plan, load a month of example data from Settings → Connectors, and connect to that. There is no sandbox key, on purpose: every key is live, and the gate is what keeps it from anything binding.

Free plan · No card

Your company, in a sentence.

Connect Zuger MCP to the assistant you already use, and ask what is waiting on you.