MCP reference

Four tools. Read, search, propose. Nothing writes directly.

Unforgetter exposes a stateless MCP server over Streamable HTTP. The tool surface is deliberately small: an agent can list the projects its token allows, get a compiled context bundle, search deeper, and propose a change. It cannot write canonical memory.

Transport: Streamable HTTP at /mcpAuth: scoped bearer token (guided), OAuth 2.1 (in build)Compatible with Claude, ChatGPT / Codex, Cursor and Grok Bot

Identity and scope

Authority comes from the token, never from the request.

Workspace

Bound to the token

Every call is evaluated inside one workspace. There is no parameter to name another.

Actor and trust zone

Bound to the token

Claude, Codex and the Grok Bot zone each hold their own token. The Grok Bot zone is treated as one shared trust zone with a shorter lifetime.

Project catalogue

Filtered by the token

list_projects returns only allowed projects. Selecting one in later calls cannot widen authority; an unlisted project id is refused.

Data class

Enforced on the server

Restricted material is absent from the catalogue and refused on direct retrieval, search, cursor replay and as a proposal target.

Tools

The tool surface.

The shapes below represent the current contract and are labelled Working now. Client-facing schemas are versioned as the alpha evolves; behaviour and security boundaries will not loosen silently.

list_projects · returns the projects this token may selectWorking now
list_projects()
→ { projects: [ { id, name, data_class, updated_at } ] }

Only allowed projects are returned. Restricted projects are not listed.
get_context · returns the compiled bundle for a task in one projectWorking now
get_context({ project_id, task })
→ {
    context_id,           // request id, used for dedupe and audit
    freshness: { compiled_at, replica_at },
    identity: { actor, trust_zone, role },
    policies: [ ... ],    // protected, always included where relevant
    facts: [ { state, kind, text, provenance: { source, date, actor } } ],
    open_threads: [ ... ],
    methods: [ ... ],     // instruction-only skills relevant to the task
    pointers: [ { ref, why } ]   // deeper retrieval, not the vault
  }

The bundle is bounded. The whole workspace is never returned.
search_memory · scoped deeper retrievalWorking now
search_memory({ project_id, query, cursor? })
→ { results: [ { ref, excerpt, provenance, data_class } ], cursor? }

Results are limited to the selected project and the token's data classes.
A cursor from one project is invalid in another.
propose_memory · the only write pathWorking now
propose_memory({
  project_id,
  request_id,           // client-supplied; replays are acknowledged, not duplicated
  change: { op: "add_fact" | "update_fact" | "open_thread" | "close_thread" | "reject",
            target?, text, supersedes? },
  evidence: [ { ref | text, trust } ]
})
→ { proposal_id, status: "queued" | "quarantined", taint }

Proposals are append-only and attested. They are delivered to the
consolidator exactly once. Nothing is published until it is reviewed.

Proposal flow

What happens after propose_memory returns.

  1. 01

    Queued or quarantined

    A proposal whose evidence is trusted is queued. A proposal carrying untrusted evidence, or coming from a lower-trust zone, is quarantined and marked for stricter review. Taint never decreases.

  2. 02

    Delivered once

    The consolidator pulls pending proposals from a watermark. Retries are safe; a replayed request id is acknowledged without creating a duplicate.

  3. 03

    Validated

    Schema, scope, protected targets, conflicts with newer decisions and provenance are checked. Protected targets and concrete injection signals are rejected.

  4. 04

    Published or rejected

    Accepted changes become part of the working truth and are served from the next get_context. Rejected proposals are kept as rejected so they are not re-proposed.

Errors and recovery

Errors are specific so agents can recover without guessing.

ErrorWhenWhat the agent should do
forbidden_scopeThe project id is not in the token's catalogue, or the data class is not allowedCall list_projects and select an allowed project. Do not retry with the same id.
unknown_projectThe project does not exist in this workspaceCall list_projects. The catalogue is authoritative.
invalid_cursorA search cursor from another project or an expired pageRestart the search without a cursor.
protected_targetA proposal targets goals, policies, permissions or identitiesDo not retry. Surface the change to the workspace owner instead.
duplicate_requestA replayed request idTreat as success; the original result is returned.
stale_replicaThe gateway replica is older than the freshness thresholdProceed with caution and cite freshness, or wait for the next publish cycle.
unauthorizedThe token is expired or revokedStop. A new token must be issued by the owner; there is no self-service refresh in the current setup.

Provenance and freshness

Every bundle says how current it is and where each line came from.

freshness.compiled_at is when the consolidator last published the working truth. freshness.replica_at is when the gateway received it. If the two differ by more than the publish cadence, the bundle is marked stale rather than served as current.

Each fact carries provenance: the source reference, the date and the actor. Agents are expected to cite it when a decision depends on it, and reviewers use it to trace a served fact to its origin.

Revoke and deletion

Status of the controls that end access.

Working now

Token revocation

Current tokens are revocable and time-limited by the owner. A revoked token receives unauthorized on every tool.

In build

Self-service revoke

A connections view where the owner revokes an agent and confirms the old token no longer works.

In build

Workspace export

Readable Markdown plus a provenance manifest; must open without Unforgetter.

In build

Workspace deletion

Removal from all serving paths, indexes and, after the documented retention window, backups.

Clients

Per-client notes.

ClientCurrent transportStatus
ClaudeRemote MCP in web and Desktop, or local stdio proxy in Claude CodeCompatible
ChatGPT webCustom remote MCP connectionCompatible
CodexLocal stdio proxy or remote MCPCompatible
Cursor, VS Code and other MCP clientsStreamable HTTP or stdio proxyCompatible
Grok BotCustom remote MCP connection over Streamable HTTPCompatible
Codex Cloud session hookPrefetch a scoped snapshot in environment setup; open evaluation taskIn build
Access

Connect a supported client.

Tokens and endpoints are issued during private-alpha onboarding. Apply and mention which clients you use.