# Postern, for agents

Postern is a self-hosted personal context gateway. A human runs it on
hardware they own; you connect to THEIR gate, at their address. There is
no central Postern endpoint and no Postern cloud.

## What you get

One MCP surface over the sectors of a person's life — finance, mail,
calendar, contacts, health, home. Reads are served from a local cache in
milliseconds; actions dispatch to the source where the source allows
them. You correlate across sectors yourself: there are no cross-sector
joins, by design.

## Connecting

- Endpoint: the owner's gate address + `/mcp` (Streamable HTTP).
- Local (same machine): connect directly; the owner mints you a key in
  their Console and grants sectors.
- Remote: the owner exposes their gate through their own tunnel. Hosted
  agents (claude.ai and similar) use the gate's built-in OAuth bridge:
  standard discovery + dynamic client registration at the owner's public
  address.
- Auth: a per-agent bearer key (32 random bytes, base64url), shown to
  the owner once and stored by the gate only as a hash — or an OAuth
  token derived from it through the bridge. You never receive, see, or
  need the owner's provider passwords.
- The config block, verbatim (the owner's Console hands them this;
  local harnesses paste it into their MCP config):

      {
        "mcpServers": {
          "postern": {
            "type": "http",
            "url": "http://<owner-gate-address>/mcp",
            "headers": { "Authorization": "Bearer <your-agent-key>" }
          }
        }
      }

- There is no stdio transport on a running gate — the gateway owns its
  own stdin. Local means the block above with a localhost address.
- A REST mirror serves the reads for tools that do not speak MCP;
  acting on a source goes through MCP.

## The tools

    describe_context   what you are granted + per-connection freshness
    get_schema         one object's fields, filters, and semantics
    query              cache read: filters, fields, time ranges, aggregates
    get_record         one record by id
    fetch_live         the one read-time path to the source, when freshness matters
    list_actions       what the granted sectors let you DO
    invoke_action      act on the source; a targeted re-sync reflects the result

Start with `describe_context`. Read `get_schema`'s notes before
composing filters — sign conventions and unit traps live there. Responses
are capped: `has_more: true` means you saw a page, not an answer.

## The rules of the gate

- Grants are per-sector and default-deny. You see nothing the owner has
  not granted; within a grant you request bounded slices, never a dump.
- A refusal is explicit, and every visit — reads, actions, refusals —
  lands in a ledger the gateway only appends to, and the owner reads.
- The owner can revoke your key in one click. Nothing upstream changes;
  you stop resolving.
- Mail bodies are never cached; envelope metadata is served and content
  is fetched on demand.

## No gate yet?

If you are setting Postern up for your human, follow
https://raw.githubusercontent.com/getpostern/postern/main/setup-with-your-agent.md
— it installs Postern on their machine and stops for your human at every
sign-in, so you never handle their provider credentials yourself.

By hand, your human runs three commands on a machine they control:

    git clone https://github.com/getpostern/postern.git && cd postern
    printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)" > .env
    docker compose up -d

Your human then opens the Console, connects their sources, mints you a key,
and grants you sectors. Per-provider connection guides live at
https://docs.getpostern.com, and the full index is at
https://docs.getpostern.com/llms.txt. Postern is Apache-2.0, at
github.com/getpostern/postern.
