Aletheia Token Guard (ATG)
Aletheia Token Guard (ATG) is a slim MCP sidecar server that lets agents check token/usage limits and durably save and resume work checkpoints.
Check usage (
check_usage): pass provider headers or remaining token/request counts to get an advisoryproceed,budget_low, orpausesignal.Save checkpoints (
save_checkpoint): persist work progress under awork_id, with optionalplatform,token_snapshot, and free-formmeta(e.g., Horos receipt or Mneme memory key).Load checkpoints (
load_checkpoint): retrieve the latest saved checkpoint for awork_id.List checkpoints (
list_checkpoints): list incomplete/recent work, optionally filtered by platform, with a clamped limit (1–500).Mark work done (
mark_done): mark all in-progress checkpoints for awork_idas complete.Durable storage: SQLite-backed persistence with WAL, busy-timeout, retry logic, integrity verification via optional HMAC key, and pruning of old checkpoint versions.
Flexible transport: run over stdio for MCP hosts, or opt-in unauthenticated streamable-HTTP for local development.
Provides integration with OpenAI API usage and rate-limit headers so ATG can return budget signals like proceed, budget_low, or pause.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Aletheia Token Guard (ATG)check if I can keep going with my current token budget"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Aletheia Token Guard (ATG)
Slim MCP server for token/usage awareness and durable work checkpoints.
Plugin-ready companion to Horos (context router + signed receipts) and Mneme (persistent memory).
Status: experimental v0.1 — single-user local sidecar. See SECURITY.md.
Why ATG?
Agents die mid-task when they hit rate limits, spend caps, or context budgets. ATG gives any MCP host a thin side-car that:
Answers "can I keep going?" (rate-limit headers + simple policy)
Lets the agent save a checkpoint and resume later
Stays out of the way of context selection (Horos) and long-term memory (Mneme)
It is deliberately minimal. No multi-tenant auth, no dashboards, no full connector zoo in v0.
Related MCP server: snapshot-mcp-server
Tools (v0)
Tool | Purpose |
| Rate-limit / budget signal. Returns |
| Persist work progress under a |
| Retrieve the latest checkpoint for a |
| List incomplete / recent work (limit clamped 1–500) |
| Mark a work item complete |
Optional meta on checkpoints can hold a Horos receipt_hash or Mneme memory key.
check_usage — header path
Preferred: pass the raw provider response headers plus platform:
{
"platform": "openai",
"estimated_tokens": 5000,
"headers": {
"x-ratelimit-remaining-tokens": "42000",
"x-ratelimit-remaining-requests": "8"
}
}ATG parses OpenAI / Anthropic header names (case-insensitive). You may also pass remaining_tokens / remaining_requests directly if the host already extracted them.
Pass the real platform name when you pass headers. platform has no default — if you omit it (or pass something ATG doesn't recognize), ATG merges both the OpenAI and Anthropic parsers rather than guessing OpenAI, so real Anthropic headers are never silently misread as "no limit data" and turned into a false proceed.
ATG does not intercept provider traffic. The host/agent must supply headers or remaining counts. Policy is advisory.
Policy:
pause — remaining tokens ≤ 0, remaining < estimate, or requests ≤ 1
budget_low — remaining < 1000, or remaining < estimate /
low_threshold(default 0.2)proceed — otherwise, or when no limit data is supplied
Quick start
git clone https://github.com/holeyfield33-art/ATG.git
cd ATG
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# stdio (recommended for MCP hosts)
python -m atg
# streamable-HTTP is UNAUTHENTICATED — local-only
# requires explicit opt-in; binds to 127.0.0.1 by default:
python -m atg --transport streamable-http --port 8765 --allow-remote-http
# to actually expose it beyond this machine, pass --host explicitly too
# (still requires --allow-remote-http):
python -m atg --transport streamable-http --port 8765 --host 0.0.0.0 --allow-remote-httpSecurity: streamable-HTTP
streamable-HTTP has no authentication. It is intended for local development only. The server refuses to start HTTP mode unless you pass --allow-remote-http or set ATG_ALLOW_REMOTE_HTTP=1. Prefer stdio for real hosts.
Full notes: SECURITY.md.
Configuration
Env | Meaning |
| SQLite path (default |
| Optional HMAC-SHA256 key (covers work_id, platform, status, data, meta, token_snapshot, created_at) |
| Set to |
JSON fields (data, meta, token_snapshot) are capped at ~512 KB. Store large blobs externally and pass a URI.
work_id max 256 chars; charset [A-Za-z0-9._:/-].
SQLite uses WAL + busy_timeout=5000 for lock contention, and _connect() separately retries (up to 3 attempts, exponential backoff starting at 50ms) on a sqlite3.OperationalError raised before a connection is established — e.g. transient contention creating the db file/directory on cold start. Old versions per work_id are pruned (keep last 20).
Example agent loop
See examples/agent_loop.py: extract headers → check_usage policy → checkpoint on pause → resume.
python examples/agent_loop.pyLocal development & testing (Codespaces)
Everything below runs the same way in a GitHub Codespace as it does anywhere else — no extra setup beyond what's already in this repo.
1. Get the code and a clean environment
git clone https://github.com/holeyfield33-art/ATG.git
cd ATG
python -m venv .venv
source .venv/bin/activate # every new terminal/session needs this re-run
pip install -e ".[dev]"pip install -e . is an "editable" install — it links the package to this
checkout instead of copying it, so edits to atg/*.py take effect immediately
without reinstalling.
2. Run the automated test suite
pytest -qExpect every test to pass, with no failures or errors (46 passed as of this writing — the exact count will drift as tests are added). -q just means quiet output (dots instead of a line per test);
drop it (pytest) if you want to see each test name as it runs.
To run one file or one test while you're iterating:
pytest tests/test_checkpoint.py -v # one file, verbose
pytest tests/test_checkpoint.py -k tamper # only tests with "tamper" in the name3. Run the server by hand (stdio)
python -m atgThis starts the MCP server on stdio and blocks, waiting for an MCP client to talk
to it over stdin/stdout — it won't print anything on its own. Ctrl+C to stop.
This is how a real MCP host (Claude Desktop, an agent framework, etc.) would run it;
there's nothing to click or browse to.
4. Run the worked example
python examples/agent_loop.pyThis exercises the whole flow in-process — no MCP host needed — so it's the
fastest way to see check_usage → save_checkpoint → load_checkpoint actually
working end to end. Read examples/agent_loop.py alongside the output; it's short
and it's the clearest map of how the pieces fit together.
5. Verify the security fixes yourself
If you want to see the properties SECURITY.md claims actually hold — rather than take the docs' word for it — drop this into a scratch file and run it. It tries the exact three attacks that were open before this round of fixes and confirms each is now blocked:
# scratch_verify.py — safe to delete after running
import sqlite3, tempfile
from pathlib import Path
from atg.checkpoint import CheckpointStore
with tempfile.TemporaryDirectory() as td:
db = Path(td) / "verify.db"
s = CheckpointStore(db_path=db, integrity_key="test-key")
s.save("job1", {"step": 1}, meta={"receipt_hash": "abc123"},
token_snapshot={"remaining_tokens": 90000})
# 1. Tamper with meta/token_snapshot directly in the DB file, bypassing the API
conn = sqlite3.connect(db)
conn.execute("UPDATE checkpoints SET meta = ? WHERE work_id = ?",
('{"receipt_hash": "FORGED"}', "job1"))
conn.execute("UPDATE checkpoints SET token_snapshot = ? WHERE work_id = ?",
('{"remaining_tokens": 1}', "job1"))
conn.commit()
conn.close()
print("tamper detected:", s.load("job1")["integrity_ok"] is False) # expect True
# 2. Oversized / malformed work_id
try:
s.save("x" * 5000, {"a": 1})
print("work_id validation: FAILED (accepted bad input)")
except ValueError:
print("work_id validation: OK (rejected)")
# 3. Non-JSON-serializable data
class Weird:
pass
try:
s.save("w2", {"bad": Weird()})
print("serialization check: FAILED (silently accepted)")
except ValueError:
print("serialization check: OK (rejected)")python scratch_verify.pyAll three lines should say the guarantee held. If any of them don't, that's a regression worth opening an issue over before it ships.
6. Sanity-check a fresh dependency install
Because mcp[cli] is a range (>=1.0.0,<3.0.0), not a single pinned version, it's
worth occasionally confirming what actually gets installed matches what's tested:
pip show mcp | grep Version # should currently print 2.1.1If this ever prints something outside the tested range, don't trust the security posture claims until the test suite has been re-run against that version.
Design principles
Side-car, not platform. Compose with Horos and Mneme via MCP.
Headers first. Prefer live rate-limit headers over Admin APIs.
SQLite by default. Zero ops for personal / consulting use.
Loose integration seams. Checkpoint
metacan reference Horos / Mneme IDs.Honest limits. Single-user, local, no encryption at rest, advisory policy only.
License
MIT
Part of the Aletheia family — tools that make AI systems inspectable and trustworthy.
Available Tools
5 toolscheck_usageA
Pre-work / mid-work usage check.
Preferred path: pass the raw provider response headers dict and the
platform name; ATG will parse rate-limit fields. Alternatively pass
remaining_tokens / remaining_requests explicitly (host-extracted).
platform should name the actual provider ("openai" or "anthropic") when
headers is supplied — an omitted/unrecognized platform merges both
parsers instead of guessing OpenAI, so real Anthropic headers are never
silently misread as "no limit data" (which would report a false proceed
on an exhausted budget).
If neither headers nor remaining_* are provided, returns a neutral proceed signal so agents do not block.
| Name | Required | Description | Default |
|---|---|---|---|
| headers | No | ||
| platform | No | ||
| low_threshold | No | ||
| estimated_tokens | No | ||
| remaining_tokens | No | ||
| remaining_requests | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. It discloses that ATG parses rate-limit fields, that an omitted/unrecognized platform merges parsers to avoid false proceeds, and that a no-input call returns a neutral proceed signal. It doesn't detail output shape, but an output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight paragraphs with the purpose front-loaded. Every sentence adds either usage guidance or behavioral context, and the platform warning is detailed without being bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter optional tool with no schema descriptions, two parameters are undocumented in the description. The core call path is clear and the output schema covers return values, so the tool is usable but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must supply parameter meaning. It explains headers, platform, remaining_tokens, and remaining_requests well, but it never mentions low_threshold or estimated_tokens, leaving two parameters semantically underdetermined.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Pre-work / mid-work usage check', naming the exact operation and timing. It clarifies the tool consumes provider headers or remaining counts to determine whether to proceed, which cleanly separates it from sibling checkpoint and done tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit preferred path ('pass the raw provider response headers dict and platform name') and an alternative via remaining_tokens/remaining_requests. It also warns when platform must be set, what happens if omitted, and that empty input returns a neutral proceed signal, so an agent knows when and how to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_checkpointsB
List incomplete work items (limit clamped to 1–500).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| platform | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds useful behavioral detail by disclosing that limit is clamped to 1–500. With no annotations provided, the description carries the disclosure burden, but it does not mention ordering, pagination, default behavior beyond the schema, or whether the operation is purely read-only, though 'List' strongly implies that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single efficient sentence with no filler. The core purpose is front-loaded, and the critical clamping detail is provided in a compact parenthetical that earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter list tool, the description is mostly adequate, and the presence of an output schema reduces the need to describe return values. The main gap is the undocumented platform parameter, which could cause an agent to misuse filtering or miss an important behavioral nuance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning for the limit parameter by stating the clamping range, which is genuinely useful beyond the raw schema. However, the platform parameter is entirely unexplained, and schema description coverage is 0%, so an agent is left guessing what values platform accepts, what null means, and how filtering behaves.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and a clear resource ('incomplete work items'), so an agent knows the core action and scope. It doesn't explicitly differentiate from siblings, but the sibling names are self-explanatory enough that listing is clearly distinct from saving, loading, marking done, or checking usage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for viewing incomplete work items, which gives some usage context. However, it does not explicitly state when to use this instead of load_checkpoint, mark_done, or save_checkpoint, nor does it mention any exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
load_checkpointB
Load the latest in-progress checkpoint for work_id.
| Name | Required | Description | Default |
|---|---|---|---|
| work_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full behavioral burden. It explains what is loaded but does not disclose side effects, what happens when no checkpoint exists, whether loading is read-only or restores state, or any requirements such as prior save_checkpoint usage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no filler or redundant detail. It front-loads the core operation and scoping parameter effectively.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has one parameter, and an output schema is present, so return values do not need explanation. Still, the description omits important behavioral context such as error handling, side effects, and the relationship between loading and saving checkpoints, making it only minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It only mentions work_id as the scope for loading, adding little beyond the schema's existing 'Work Id' title; it does not clarify format, origin, or relationship to other tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('load') and a specific resource ('latest in-progress checkpoint') scoped by 'work_id'. This clearly distinguishes it from sibling tools like save_checkpoint, list_checkpoints, and mark_done.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: use this tool when you need the latest in-progress checkpoint for a work_id. However, it does not explicitly explain when to prefer list_checkpoints or save_checkpoint, nor does it state any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_doneA
Mark all in-progress checkpoints for work_id as done.
| Name | Required | Description | Default |
|---|---|---|---|
| work_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral disclosure burden. It clearly states that all in-progress checkpoints are affected and that they become 'done', but it does not mention whether the action is reversible, whether permissions are required, or what happens if there are no in-progress checkpoints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no filler. The action, scope, and target are all front-loaded and every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity of one required parameter and the presence of an output schema, the description covers the essential call information. Missing details like no-op behavior or reversibility are minor for this simple bulk state-change tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It only repeats the parameter name 'work_id' without explaining what a work_id represents, how to obtain it, or any format constraints. The meaning is largely inferred from the tool's purpose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb, 'Mark', and names the exact resource: 'all in-progress checkpoints for work_id'. It clearly distinguishes this tool from siblings like list_checkpoints and load_checkpoint by stating the state transition it performs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: call this when in-progress checkpoints should be marked done. However, it does not explicitly state when not to use it or how it compares to sibling tools like save_checkpoint or check_usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_checkpointA
Save a durable checkpoint for work_id.
meta is a free-form bag — useful for Horos receipt_hash or Mneme memory keys.
JSON fields are capped (~512 KB); store large blobs externally.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | ||
| meta | No | ||
| work_id | Yes | ||
| platform | No | ||
| token_snapshot | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and adds meaningful behavioral context: 'durable' implies persistence, and the size cap ('~512 KB') plus 'store large blobs externally' disclose important limitations. It does not cover overwrite semantics or side effects, but the provided constraints are valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: one sentence states purpose, followed by two short, high-value sentences about meta and size constraints. Every sentence earns its place with no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Required parameters is work_id and data, both understandable from the description and schema. But optional parameters platform and token_snapshot are not contextualized, and behavior around overwriting or updating an existing checkpoint for the same work_id is absent. The output schema exists, so return-value details are not needed, but the gaps around optional params and lifecycle behavior make this only partially complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains meta as a free-form bag for Horos receipt_hash or Mneme memory keys and notes JSON size limits. However, platform and token_snapshot are left unexplained, and data is only implicitly described via 'checkpoint' and the size cap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Save a durable checkpoint for work_id,' which names a specific verb, resource, and target. It clearly differentiates from siblings like load_checkpoint, list_checkpoints, and mark_done by indicating this is the write/save operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states what the tool does but does not explicitly say when to use it versus alternatives. There is no mention of when to call save_checkpoint instead of mark_done or check_usage; usage is only implied by the verb 'save' and the checkpoint resource.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
check_usage - First observed
list_checkpoints - First observed
load_checkpoint - First observed
mark_done - First observed
save_checkpoint
TDQS
Scored across 5 tools
Each tool has a clear, singular responsibility: usage checking, checkpoint persistence, resume, listing, and completion. Even the related save/load/list checkpoint tools are easy to distinguish by their action and return value.
All tool names follow a consistent snake_case verb_noun convention: check_usage, save_checkpoint, load_checkpoint, list_checkpoints, mark_done. The pattern makes behavior predictable and easy to infer.
Five tools is well-scoped for a focused guard/checkpoint server. Each tool addresses a distinct step in the pre-work, mid-work, resume, and completion lifecycle without unnecessary overlap.
The core workflow is covered: usage check, checkpoint save/load, incomplete work listing, and completion marking. A minor gap is the lack of an explicit checkpoint delete/abort operation for abandoned work, but this does not create a dead end for the primary use case.
Maintenance
Related MCP Connectors
Persistent work tracking for AI agents: tasks, status and history that follow you across machines
Agent checkpoints. Resume after context resets and handoffs with retry-safe, versioned saves.
Durable agent-to-agent handoffs and shared scratchpad for multi-agent workflows.
Gives your AI assistant persistent memory and intelligence about your work patterns.
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides intelligent context management for AI development sessions, allowing users to track token usage, manage conversation context, and seamlessly restore context when reaching token limits.85 npm2Apache 2.0
- AlicenseNot gradedqualityDmaintenanceSave conversation state, resume work across sessions, and organize multiple snapshots with minimal token overhead.10 npmMIT
- AlicenseAqualityDmaintenanceProvides state and log management tools designed for long-lived AI agents that may be interrupted and resumed. It enables tracking agent progress and maintaining an append-only event history to ensure continuity across multiple sessions.4MIT
- AlicenseNot gradedqualityBmaintenanceProvides operational continuity for AI coding agents, preserving task state, decisions, checkpoints, and project context across sessions and model switches via MCP.1Apache 2.0