session-clock
A minimal remote MCP server that gives an AI assistant a clock via a single 'now' tool, enabling models to timestamp exchanges and answer "how long ago" questions with best-effort, stateless time capture.
README
mcp-server-session-clock
A minimal remote MCP server that gives an AI assistant a clock.
Models in a chat or agent host usually have no reliable sense of wall-clock time
— often not even the current time of day — so they can't say when a message
happened or how long ago. This server exposes a single MCP tool, now, that
returns the current instant. A standing instruction
tells the model to call it at the start of each reply to timestamp the exchange,
and again on read-back to work out "how long ago".
It is stateless — nothing is stored server-side; the timestamps live in the conversation itself. It works with any host that accepts remote (Streamable HTTP) MCP servers.
⚠️ Timestamp capture is best-effort, not guaranteed — read this before relying on it. MCP tool use runs under the host's default
tool_choice: auto: the model decides per turn whether to call a tool. It will sometimes skipnowdespite the standing instruction — most often on short or trivial messages — so some messages won't get a timestamp, and most hosts give you no way to force a call. If you need guaranteed per-message timestamps, an instruction-driven MCP tool (this or any other) is the wrong mechanism — that needs control at the API layer (tool_choice: "any"), which chat/agent hosts don't expose. This server fits "roughly when did things happen", not an audit log.
How it works
- Write: the instruction tells the model to call
nowat the start of each reply and not repeat the value in its answer. That call ≈ when your message was received. - Storage: the conversation itself — each
nowcall and its result are kept in context as a tool-use record, not as prose. - Read: when you ask "how long ago was X", the model finds the recorded
nowresult nearest message X and compares it to a freshnow.
Prerequisites
- Node 18+ and npm (built with Node 22 / npm 11)
- A Cloudflare account (free tier)
- An MCP host/client that supports remote (Streamable HTTP) MCP servers
Setup
npm install
Copy the local secret template so dev and type generation can see MCP_SECRET:
cp .dev.vars.example .dev.vars
Generate TypeScript types (worker-configuration.d.ts, git-ignored) — also run
automatically by npm run typecheck:
npm run cf-typegen
Generate a secret for the path segment (32+ random chars) and add it to .dev.vars:
node -e "console.log(require('crypto').randomBytes(24).toString('base64url'))"
Put the printed value in .dev.vars as MCP_SECRET (replacing the placeholder) —
this is the secret local dev uses. The deployed Worker gets its own copy in the
Deploy step below.
Run locally
npm run dev
Your endpoint is http://localhost:8787/mcp/<MCP_SECRET>. Any other path returns
404.
Deploy
Install the Wrangler CLI (once per machine):
npm install -g wrangler
Log in to Cloudflare (opens a browser; once per machine):
wrangler login
Publish the Worker:
npm run deploy
Set the secret on the deployed Worker — Wrangler can only attach a secret once the
Worker exists, so this runs after the first deploy. Use the same value you put in
.dev.vars:
npx wrangler secret put MCP_SECRET
Wrangler prints your public URL. The endpoint is that origin plus the secret path:
https://session-clock.<your-subdomain>.workers.dev/mcp/<MCP_SECRET>
Add to your MCP host
- In your host's MCP-server / connector settings, add a new remote server.
- Paste the full URL above (including
/mcp/<MCP_SECRET>). Leave auth empty — this is an authless server; the secret in the path is the access control. - Open a conversation and confirm the
nowtool is available. - Add the standing instruction wherever your host injects persistent instructions (system prompt, custom instructions, a per-project instruction field, a saved "style", etc.).
Standing instruction
The server only makes the now tool available; this is what makes the model
use it. Paste it into your host's persistent-instruction field:
I've connected a `now` tool that returns the current time so you can tell me how long ago things happened. This is my own preference and my app shows me every tool call, so nothing here is hidden from me. At the start of each reply, call `now` once to record the time, then answer my message normally — you don't need to repeat the timestamp or describe the call (it's just for later reference), though you can if it's relevant. When I ask how long ago something happened, compare the `now` result nearest that message with a fresh `now` call.
- Word it transparently — this is load-bearing. An earlier draft said "silently … never mention the tool … reply exactly as you would have without it." Models read that as a request to take hidden, undisclosed actions and refuse it as a possible prompt injection (they decline to call the tool at all, which looks like a random skip but isn't). The version above frames the tool as your own, benign, self-disclosed preference and notes the calls are already visible to you — don't reintroduce "silently" / "never mention" phrasing.
- The timestamp doesn't need to appear in the reply, but your host still shows a
tool-call indicator for each
nowcall, so nothing is actually concealed. - Times are UTC. "How long ago" is a difference, which is timezone-independent.
- Even well-worded, capture is best-effort — see the note at the top.
Test it
- Open a new conversation → send a message; the assistant replies normally (no visible timestamp, though your host may show a tool-call indicator).
- Send a couple more messages over a few minutes.
- Ask: "How long ago was my first message?" — the assistant reads the recorded
nowcalls and answers within a few minutes' accuracy.
Security model
The tool only reveals the current time and stores nothing, so a leaked URL is low-stakes (someone could ask what time it is, or try to spam it). Protection is therefore deliberately light:
- Secret path segment (
/mcp/<32+ chars>) as a de-facto access key; every other path 404s. The secret lives in your host's server configuration and in Cloudflare's request logs — it's a speed bump against scanners, not real auth. Rotate by runningwrangler secret put MCP_SECRETagain and re-pasting the URL. - Rate limiting: add a Cloudflare WAF rate-limit rule on the route so a discovered endpoint can't be flooded.
Limits
- Not deterministic (see the note at the top): the model won't call
nowon every turn, so some messages have no nearby timestamp and their timing can only be inferred from the nearest recorded call. - Compaction erases history: if a long conversation is summarized, early
nowresults fall out of context and their timing is lost (current time still works). - Small tax per reply: one extra tool round-trip and a tool-call indicator in the host UI (the timestamp value is not printed).
Upgrade (Branch B) — server-side log
If compaction-loss bites, move the log server-side. Two routes:
- Add storage to this stateless handler: bind a KV namespace or D1 database,
persist
(session_token, seq, ts)keyed by a model-minted token, and add aget_timelinetool. Least new machinery. - Switch to the stateful legacy path (
createLegacyMcpHandler/McpAgentWorkerTransport), which gives each client session its own Durable Object. That also lets you test empirically whether an MCP session maps 1:1 to a conversation in your host (does a second conversation get a fresh DO?) — if so, attribution is automatic with no token needed.
Note that Branch B moves the storage server-side; it does not make capture deterministic — the write still depends on the model choosing to call the tool.
Project structure
src/index.ts The Worker: the `now` tool + secret-path gate
src/worker-env.d.ts Types the MCP_SECRET Worker secret
wrangler.jsonc Worker config (name, entry point, compatibility)
tsconfig.json TypeScript config
.dev.vars.example Template for the local secret
Runtime/binding types live in worker-configuration.d.ts, generated by
wrangler types (git-ignored) — rerun npm run cf-typegen after editing
wrangler.jsonc, keeping .dev.vars present so the secret stays typed.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。