# atomic-clock [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/theoddden/atomic-clock-mcp  
**GitHub Stars:** 0  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/atomic-clock

## Description
Current UTC time from NTP atomic clocks. Zero-dependency stdio server.

## Tools
Capabilities this server exposes over MCP:

- **get_time**
- **get_drift**
- **generate_uuid**
- **diff**
- **text_a**
- **text_b**
- **calculate**
- **attest**
- **verify**

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "atomic-clock": {
    "command": "uvx",
    "args": ["stamp-mcp"]
  }
}
```

## Documentation & README

# Stamp

HTTPS URL Endpoint:

https://stamp-mcp.terradev.cloud

<!-- mcp-name: io.github.theoddden/stamp -->

The concierge MCP for agentic workflows: the small tools agents reach for
constantly -- NTP time and clock drift, UUIDs, diffs, safe arithmetic --
behind one endpoint. Zero dependencies, fully synchronous, raw JSON-RPC
2.0 over stdio -- no MCP library, no asyncio.

A single NTP query tells you where your clock is right now. Drift history
tells you where it is going: a clock that is consistently 200ms fast and
accelerating is a different problem than one that is stable at 200ms fast.
`get_time` takes the measurement; every call appends to a local log;
`get_drift` reads the log and reports the trend.

## Install

```bash
pip install stamp-mcp
```

## Use with Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "stamp": {
      "command": "stamp-mcp"
    }
  }
}
```

Or run the module directly:

```json
{
  "mcpServers": {
    "stamp": {
      "command": "python3",
      "args": ["-m", "stamp_mcp"]
    }
  }
}
```

## Tools

- **`get_time`** -- one NTP query: UTC time, this clock's offset in ms,
  network delay, stratum. Appends the sample to the drift log. Optional
  argument: `server` (default `time.cloudflare.com`).
- **`get_drift`** -- analyzes the drift log: sample count, timespan,
  current/mean/stddev offset, drift rate in ms/day (least-squares fit),
  first-half vs. second-half rates, and a verdict: `stable`, `drifting`,
  or `accelerating`. Optional argument: `server` to filter samples.
- **`generate_uuid`** -- random UUIDv4s for records, sessions, and
  identifiers. Optional argument: `count` (1-1000, default 1).
- **`diff`** -- unified diff between `text_a` and `text_b`, with
  added/removed line counts and an `identical` flag. Optional argument:
  `context` (lines of context, default 3).
- **`calculate`** -- safe math evaluator: `+ - * / // % **`, parentheses,
  functions (`abs round min max sqrt floor ceil exp log log2 log10 pow
  sin cos tan`), constants `pi e tau inf`. The expression is parsed to an
  AST and only whitelisted nodes are computed -- no `eval()`, no names,
  no arbitrary code. Required argument: `expression`.
- **`attest`** -- wrap any JSON payload in a tamper-evident record: a
  UUID, a timestamp (NTP-verified when reachable, local clock otherwise --
  the record's `time_source` says which), and a `sha256` over the
  canonical record. Required argument: `payload`. Optional: `server`.
- **`verify`** -- recompute an attested record's hash and compare.
  Returns `valid` pass/fail plus a reason; any modified field -- payload,
  timestamp, id -- breaks it. Required argument: `attested`.

## The drift log

Every `get_time` call appends one JSON line to `~/.stamp/drift.jsonl`
(override with `STAMP_DRIFT_LOG`). The file is capped at 10,000 samples.
Call `get_time` periodically -- a cron job, a heartbeat, or just asking
Claude "check the clock" now and then -- and `get_drift` turns the
accumulated offsets into a trend.

## Hosted endpoint (streamable HTTP)

The same `dispatch()` also serves MCP's streamable-HTTP transport via
`stamp_mcp/http_server.py` -- still zero dependencies (`http.server`):

```bash
stamp-mcp-http                      # binds 127.0.0.1:8000
STAMP_PORT=9000 stamp-mcp-http      # custom port
```

- `POST /mcp` -- JSON-RPC requests (single or batch); notifications get
  `202`, requests get `200 application/json`.
- `GET /mcp` -- `405` (no SSE streams; nothing server-initiated exists).
- `GET /health` -- `200` for proxies and monitors.

TLS is terminated by a reverse proxy, not Python. The production layout
is two containers on one AWS instance, wired by `docker-compose.yml`:

- **`stamp`** -- the server, built from `Dockerfile`, exposed only to the
  internal compose network. Drift log persists in the `stamp-data` volume.
- **`caddy`** -- official Caddy image, terminates HTTPS at
  `stamp-mcp.terradev.cloud` (automatic Let's Encrypt once DNS points at
  the instance) and reverse-proxies to `stamp:8000`.

`deploy/` also has a non-container path (`stamp-mcp.service` systemd unit,
`deploy.sh`) if you ever want to run it bare-metal.

## Connecting to Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "ntp-scratch": {
      "command": "/usr/bin/python3",
      "args": ["/Users/theowolfenden/CascadeProjects/mcp-from-scratch/server.py"]
    }
  }
}
```

Restart Claude Desktop, then ask it "what tools do you have?" -- `get_time`
should appear. If it doesn't, check the logs at
`~/Library/Logs/Claude/mcp*.log` -- a stray print or missing flush is the
usual culprit.

## The wire protocol, in one glance

```
>>> {"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
<<< {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05",...}}
>>> {"jsonrpc":"2.0","method":"notifications/initialized"}     (no reply)
>>> {"jsonrpc":"2.0","id":2,"method":"tools/list"}
<<< {"jsonrpc":"2.0","id":2,"result":{"tools":[...]}}
>>> {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_time","arguments":{}}}
<<< {"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"..."}]}}
```

*DISCLAIMER*
Stamp queries public NTP infrastructure (Cloudflare, stratum 3) and is suitable for general agentic workflows. It is not intended for use cases requiring certified atomic precision, legal timestamp authority, or regulated audit trails. Use in production systems is at the implementer's risk.

