EMET
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PORT | No | Port for the HTTP server. Required for remote (HTTP) mode. | |
| MONGODB_DB | Yes | MongoDB database name. Required for all modes. | |
| PUBLIC_URL | No | The public URL of the server, used as the OAuth issuer. Must match the deployed URL exactly. Required for remote (HTTP) mode. | |
| MONGODB_URI | Yes | MongoDB connection string (e.g., mongodb://localhost:27017 or an Atlas URI). Required for all modes. | |
| EMET_TIMEZONE | No | Time zone for session ids. Default: America/New_York. | America/New_York |
| EMET_SOURCE_TAG | No | A distinct source tag for this host. Every write records the host that produced it. Defaults to a tag marked as defaulted. | |
| EMET_SIGNING_KEY | No | If set, an HMAC signature is stored over content and metadata digests. The key stays on the service. | |
| EMET_SOURCE_TAGS | No | Comma-separated list of allowed source tags. The source-tag guards (unregistered tags refused on the main records and on another bot's bots/ folder) are off unless this is set. | |
| EMET_SESSION_GRAPH | No | Controls session graph (monorail) mode. Report-only by default. | |
| EMET_OAUTH_PASSPHRASE | No | Passphrase to authorize devices for the remote endpoint. Required for remote (HTTP) mode. | |
| EMET_CLOSE_GRACE_MINUTES | No | Minutes after a complete session close during which one more append is allowed. Default: 5, maximum: 60. | 5 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| emet_initializeA | START HERE. Call this FIRST in every session, before answering anything that might have prior context, and always when the user opens with 'initialize', 'start', 'begin', 'hello' or similar. It is the only setup step a user should ever have to know about. A large startup comes in pages: read |
| emet_statusA | Diagnostic in one call (replaces emet_setup_status, get_status and emet_verify_connection, 2026-09-27). Reports environment, database, collections, vector index, whether identity and user documents exist, and per-layer counts and health. Pass probe: true to also prove the write path - connect, write a probe document, read the same value back, remove it; a read alone cannot reveal a broken write path. Prefer emet_initialize for a normal session start. |
| emet_setup_completeA | First-time setup, the owner's only: record the user's interview answers as bootstrap/IDENTITY.md, bootstrap/CHARACTER.md and bootstrap/USER.md and as an identity-layer entry, and create the owner person. Every write is read-back verified. Refused under a bot tag. On a store that is already set up it is refused unless reissue is true (the owner's explicit word): a re-run writes new versions of the user's identity documents; prior versions are archived, never destroyed. answers.more_than_one_bot is optional. Absent or no leaves sub-keys off. yes writes EMET_SUBKEYS=1, a generated pepper and EMET_SUBKEY_PEPPER_VERSION=1 into .env only when that file is the config source, after the store writes succeed, and does not turn the flag on in this process. A hosted server refuses yes and returns the three variables to set, then redeploy. See docs/SUBKEYS.md. answers.bot_team_backup is optional. Yes or no, in the user's words, the same way as more_than_one_bot. Yes and Yes. record the flag. yes is the recommended choice. Absent or no leaves bot-team backup off. Anything else, including a non-string, is refused before a write. Setup does not copy prompts or settings. |
| corpus_recallA | Semantic search over an optional supplementary knowledge corpus that the user has loaded separately from memory. Returns nothing unless a corpus has been populated; this is not where session memory lives. |
| recallA | Search memories by keyword. Ranked by how many of your words match, then by importance. Current entries come first in every order. Pass order: 'latest' for time order. A standalone latest, newest, or most recent, together with other words, also asks for time order: it reorders those matches and does not change which rows match. A hyphenated word such as latest-budget, a negated 'not the latest', and a bare 'latest' are ordinary keywords. Expired and superseded entries stay in the result, marked with their end date and what replaced them. Pass history: true to read ended entries when current ones fill the limit. |
| query_layerC | Query a specific memory layer with structured filters |
| save_to_layerA | Save memory to a specific layer with full control over metadata. PASS session_id - your transcript session from emet_session_open - on every save made inside a session: the server stamps derived_from with the exchange in progress. Semantic and procedural entries are REFUSED without a source (session_id, or metadata.derived_from); nothing is written when refused. |
| revise_memoryA | Supersede an existing entry with a revised one (supersession, not mutation). Creates a NEW entry carrying metadata.supersedes=<target_id> and marks the target with superseded_by and superseded_at. The old entry stays readable: it is not hidden and is_live is not cleared. Recall, query_layer and semantic_recall return it marked with that end date and the id of the new entry. The current entry is listed first. Episodic revision is prohibited - events are immutable. |
| revise_transcriptA | Supersede a stored transcript part with a corrected one. Nothing is edited or deleted: a NEW document is written under the same session_id with an incremented revision and a pointer to its parent, and the parent is marked superseded. Use when a saved part has a mispaired, missing or wrong exchange. The reason parameter is required - an unexplained correction is a silent rewrite. To ADD a new part, use save_transcript instead. Allowed on a closed session (a correction deletes nothing), but there a revision may only correct the exchanges the part already holds - never add new ones - and must carry exactly the same exchange numbers (none dropped or repeated; numbers sent as text are stored as numbers). |
| query_transcriptsA | Retrieve session transcripts - the second tier, word for word. Reads the live store written by save_transcript AND the legacy archive (exchanges written by earlier hosts, June 2025 to June 2026), grouped into the same session shape; every result carries |
| save_transcriptA | FALLBACK. The primary path is emet_session_open then emet_transcript_append after every reply; use this only where a host cannot append per reply. Saves the full word-for-word dialog of a session - full transcripts only, no summaries. Pass exchanges in the call. The server does not read a file. Refused for a session that was closed complete. |
| emet_session_openA | Open a transcript session. Returns session_id, dated in the configured local time zone (EMET_TIMEZONE, default America/New_York). A slug whose id is already CLOSED is never reopened: the session opens as -2, -3, ... and the result's |
| emet_transcript_appendA | Append ONE exchange to the session transcript. Call after every reply. Idempotent on exchange_index. Rolls to a new part after 8 exchanges. After a complete close the session takes exactly ONE more append - its closing exchange, numbered next, within EMET_CLOSE_GRACE_MINUTES (default 5) of the close; it is written into the session's last part whatever session_id it names, and the result's |
| read_docA | Read a continuity document from the versioned document store. A document longer than one page (18,000 UTF-8 bytes by default) comes back in pages: the result then carries |
| read_doc_historyA | Read a RETAINED revision of a document, or list the revisions retained for it. Every write archives the prior copy (nothing is deleted); this is the reader for that archive. Without a version: the list of retained revisions with their digests and dates. With a version: that revision's full content, re-hashed against its stored digest. Read-only. Use it for an audit question - what did this document say at version N - or to compare a document with what it replaced. |
| write_docA | Write or update a continuity document in the document store (versioned, prior copy archived to documents_history and marked obsolete, sha256 read-back verified). RECORDS - the handoff (HANDOFF.md) and any id in EMET_RECORD_DOCS - are superseded, never amended: patch_doc is refused on them, and a new revision is written here WHOLE with |
| list_docsA | List continuity documents (metadata only; optional doc_id prefix filter, e.g. 'threads/'). Current documents come first. Retired documents stay in the list, marked with retired_at and, when a rename replaced them, what replaced them. |
| retire_docA | Mark a continuity document OBSOLETE. Nothing is deleted: the document keeps its id, its full content, its version and its digest, and read_doc still returns it, flagged retired, with the reason. list_docs and the startup scan keep it too, after the current documents, with retired_at and what replaced it. A retired drop is not an unhandled drop. This is document control as ISO 7.5.3 describes it - issue the revision, mark the prior copy obsolete, retain it - and it is the document-store counterpart of revise_memory superseding a layer entry. THE STORE HAS NO DELETE, BY DESIGN. Use for genuine litter: tombstones, merged staging documents, test scratch. Reversible: write_doc on the same id brings it back into the working view. |
| rename_docA | Reissue a continuity document under a new doc_id. The destination is written first through the normal write path (same redaction, digest, versioning and sha256 read-back), and only then is the old id marked obsolete with retire_doc. NOTHING IS DELETED: the old id keeps its content and stays readable at its own id, flagged retired with the reason 'Reissued as <new_id>'. list_docs keeps it after the current documents and names the new id in replaced_by. No tombstone document is needed, because the retired original IS the tombstone and it still carries the real content. Refuses if the destination already exists, because a rename onto an occupied id is a merge decision and merges are not guessed. |
| restore_docA | Write a retained revision back as the current document. The retained row is copied through the normal write path, with a reason. Nothing is deleted. |
| validate_docA | Check a controlled document against the template that governs it, WITHOUT writing anything. The same check the write path runs on every document write - this is the freestanding form, for auditing records written before validation existed, for counting what adoption will mark before it marks anything, and for checking new content before it is stored. Pass doc_id to check a stored document (the previous revision is pulled from the archive so the carry-forward check runs). Pass content, with template_id or a doc_id the map covers, to check text that is not stored. Checks FORM and CONTINUITY only: sections present, in order and filled; no placeholder left unfilled; NOT COMPLETED carrying a reason; a board's counts matching its rows; every row on the previous revision still present or dispositioned. It cannot check whether an answer is true, or whether a 'none' states its scope honestly - those stay with the author and the reader. |
| accept_nonconformanceA | Record the written disposition for a nonconformance that will not be corrected. A marker is never cleared silently: it leaves either because a later revision passes, or because someone accepts it in writing here. The marker is RETAINED with the acceptance beside it, and the acceptance covers only the revision it names - the next write is validated fresh, and accepted markers stay counted at session start, separately from open ones. The reason must be at least 10 characters: it is what an audit reads later. |
| patch_docA | Replace one exact substring in a document (str_replace semantics) without resending the whole file. THE PREFERRED WAY TO MAKE SMALL EDITS to large docs like STATE.md. old_str must match EXACTLY ONCE - zero or multiple matches are rejected rather than guessed. Pass new_str as an empty string to delete. Same versioning, archiving, and sha256 read-back as write_doc. |
| semantic_recallA | Semantic (meaning-based) memory search across all six memory layers via Atlas Vector Search autoEmbed. Finds conceptually related memories even without keyword overlap. Complements keyword-based recall/query_layer. |
| emet_pageA | Read one compiled topic page for an area slug (areas/.md). A page is a view of current records. It is not a record: this tool writes nothing, stores nothing, and the result is never written back and is not returned by recall. Every displayed line cites its source as [mem: · · · ] or [doc:<doc_id>@v]. A line with no source is dropped. Superseded and retired records stay out of the current sections; pass include_history true to show them under History only. A line is marked stale when its source has not been confirmed or revised within the area's staleness window (default 30 days; the area document may set its own). Owner only. Computed on every call, so cache_hit is false. |
| emet_pagesA | List current area documents. For each area: line count, stale count, and the time of the newest source the page read. Read-only. Owner only. Computed on every call. The page body is not stored. |
| emet_error_reportA | Read the operational error log and show a report the owner can send on. Owner only. Read-only: it writes nothing and sends nothing. EMET has no mail sender and opens no network connection for this tool. The result is the full report, then a mailto link, then a structured email {to, subject, body_text, short_id, version} a calling assistant can pass to its own email tool. The calling assistant may send this report only after showing the report to its user and getting their OK. |
| emet_page_lintA | Flag problems in topic pages and the records they read. Read-only: it never edits a record. Findings cover contradictions (two current records that share a subject and disagree), superseded or retired records still claimed as current, lines with no source, duplicates, broken links, and statuses unconfirmed longer than the area's staleness window. It builds on the emet_gaps classifiers. A fix is a person's revise_memory, retire_doc, or accept_nonconformance. Owner only. Omit area to lint every area. |
| emet_gapsA | The record's honesty about its own holes, as a query. Read-only; identifies and never fills. Counts, with the ids behind them, for each gap class: unsourced assertions, unattributed inferences, ambiguous attribution (by tag and by session), uncertain routing, unattestable rows (pre-2026-09-05 boundary), digest mismatches (the alarm - expect zero), pointer disagreements against the transcript store, broken supersession, expired-but-live rows, consolidation candidates (tag families; a list for a person), and redacted spans by source. Call it when asked how trustworthy the record is, before a consolidation pass, or after any migration. Closing a gap is a person's decision: revise_memory with a real derived_from where the source is knowable; otherwise the gap stands as a fact. |
| emet_floorA | Read the floor: the standing description of how this assistant engages with the person using it. It ships in the server code, so setup cannot overwrite it and no install can lose it - the character document holds the user's modifiers on top of it. emet_initialize already returns the whole floor at session start; call this to read it again without re-running initialize. Use |
| emet_client_approveA | Approve or deny a new client (a bot, or a single-instance AI such as Claude or ChatGPT) that EMET flagged on its first write. A new client is read-limited until approved. Only the owner, or the chief-of-staff bot named by EMET_COS_TAG, may decide. Pending clients are listed in emet_initialize and emet_status as client_approvals. |
| emet_invite_createA | EMET Guest Access: create a one-time code for a guest. They paste it on the connect screen instead of the passphrase. Default access is read-only. Only the owner can create a guest code. EMET Member Access is a different door. |
| emet_member_access_createA | EMET Member Access: create a one-time code for a new person with read and write access. They paste it on the connect screen instead of the passphrase. This is not EMET Guest Access, and it never makes them the owner. Only the owner can create it. Off unless EMET_MEMBER_ACCESS=1. |
| emet_session_closeA | Call this when the session is ending - the user says goodbye, asks you to wrap up, mentions restarting or opening a new session, or you are about to run out of room. An acknowledgement of the turn just completed - thanks, great, perfect - is not a session end; if it is ambiguous, ask rather than close. Checks whether this session's work has actually been written to the store and reports exactly what is missing. It does not write anything itself. RECEIPTS ARE REQUIRED: pass |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 34 tools
The set contains several overlapping retrieval and persistence families: recall, semantic_recall, query_layer, corpus_recall; save_to_layer, save_transcript, emet_transcript_append, revise_transcript; and emet_page versus emet_pages. Detailed descriptions clarify the intended boundaries, but an agent still has many similar-sounding choices and must read carefully to avoid misselection.
All names are snake_case and mostly readable, but the convention is mixed: many tools use an emet_ prefix while core document/memory tools do not, and some names are noun-first or opaque (emet_page, emet_pages, emet_floor, emet_gaps) rather than consistent verb_noun. The pattern is understandable but not predictable.
With 34 tools, the surface is very heavy for a single MCP server, even given EMET's broad memory, document-control, transcript, and access-control scope. Many tools are narrow variants or lifecycle sub-steps, which increases selection burden and makes the set harder to hold in working context.
Coverage is very broad: setup, initialization, session lifecycle, transcript append/save/revise/query, memory save/recall/revise, document write/read/patch/history/retire/rename/restore/validate, pages, lint, gaps, status, and access creation/approval are all present. Minor gaps remain around access revocation or invite listing, but core workflows are covered and the no-delete design is deliberate.