DEV Community

tine
tine

Posted on • Originally published at gotimestamp.com

Building a Zero-Dependency MCP Server for the Timestamp Bugs LLMs Get Wrong

Building a Zero-Dependency MCP Server for the Timestamp Bugs LLMs Get Wrong

This is a build log for tsforge-mcp — a pure Node.js MCP server with 16 timestamp/date tools. No npm dependencies, dual transport (stdio + Streamable HTTP). Repo: https://github.com/caresotin/tsforge-mcp

The problem

Most MCP time servers give you get_current_time and convert_time. Fine — but those are also the two things you can just ask the model directly. The real failures show up at the edges:

  • Cron next fire: 0 0 29 2 * (Feb 29) must skip to 2028, not "next year".
  • Excel serial 60: 60 decodes to 1900-02-29 — a date that never existed (the famous 1900 leap-year bug).
  • ISO-8601 week: 2016-01-01 is week 53 of 2015, not week 1.
  • DST-aware tz: Asia/Shanghai → America/New_York is not a fixed offset.
  • SQL dialects: UNIX_TIMESTAMP() vs TO_TIMESTAMP() vs strftime() vs DATEADD — all different.

Every one of those, asked of a frontier model, returns a confident wrong answer. So I extracted boundary-correct algorithms into tools.

Architecture (no dependencies)

One codebase, two transports:

  • stdio for Claude Desktop / local MCP clients.
  • Streamable HTTP for ChatGPT Apps SDK / remote clients.

Everything is Node.js built-ins: JSON-RPC 2.0 framing, HTTP session management, and the algorithms in a single module.

// cron_next: handle the 29 Feb edge case
function cronNext(expr, n = 1) {
  const sched = parseCron(expr);
  const out = [];
  let cur = new Date();
  while (out.length < n) {
    cur = nextMatch(sched, cur);
    if (cur) out.push(cur);
    cur = new Date(cur.getTime() + 1000);
  }
  return out;
}
Enter fullscreen mode Exit fullscreen mode

The Excel bug is just a constant offset with a conditional:

function excelSerialToDate(s) {
  // Excel wrongly treats 1900 as a leap year; serial 60 = fake Feb 29
  const base = new Date(Date.UTC(1899, 11, 30));
  const d = new Date(base.getTime() + (s - (s > 60 ? 1 : 0)) * 86400000);
  return d;
}
Enter fullscreen mode Exit fullscreen mode

Why this helps the web side

The same engine powers a free converter at https://gotimestamp.com/sql-timestamp-converter.html, and we documented the per-dialect gotchas as language guides:

If you're shipping MCP servers, what edge cases have you had to hand-code? Curious whether others hit the same date/time boundary traps.

Repo: https://github.com/caresotin/tsforge-mcp

Top comments (0)