Skip to main content
Glama
jordanburke

temporal-mcp-server

temporal-mcp-server

npm version

MCP server for time, timezone, and duration tools.

Run it locally over stdio (Claude Desktop, Claude Code, any local MCP client), locally over HTTP, or use the hosted instance — same tools, same code, three ways to run it.

A public instance runs on Cloudflare Workers at https://time.somamcp.com/mcp:

claude mcp add --transport http temporal https://time.somamcp.com/mcp

Built on somamcp, which supplies the MCP plumbing, telemetry, and health/introspection endpoints for both runtimes. Time logic is pure and functional, using functype.

Tools

Tool

Purpose

get_current_time

Current time as epoch, UTC ISO-8601, and wall-clock in any IANA timezone

convert_timezone

Render an ISO-8601 timestamp in a target timezone

add_duration

Add or subtract an ISO-8601 duration, with calendar-aware month arithmetic

time_between

Elapsed time between two timestamps, in whole units plus a readable summary

somamcp also registers an info tool and /health, /health/detail, /info, and /dashboard endpoints.

Behaviour worth knowing

Month arithmetic clamps rather than overflows. add_duration on 2026-01-31 with P1M returns 2026-02-28, not 2026-03-03. Adding "a month" to the end of a long month lands on the end of the short one.

Offsets are resolved per instant, not per zone. America/New_York reports -04:00 in August and -05:00 in January. DST comes from the runtime's tz database, so there is no offset table here to go stale.

Errors carry a hint. An unknown timezone returns the bad value and the expected format, so a calling agent can correct itself instead of guessing again.

Related MCP server: mcp-datetimeday

Running as a local MCP server

Stdio is the default and the mode local clients expect. Nothing is hosted, nothing listens on a port — your client launches the process and talks to it over stdin/stdout.

Claude Code

claude mcp add temporal -- npx -y temporal-mcp-server

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "temporal": {
      "command": "npx",
      "args": ["-y", "temporal-mcp-server"]
    }
  }
}

On macOS that file lives at ~/Library/Application Support/Claude/claude_desktop_config.json; on Windows, %APPDATA%\Claude\claude_desktop_config.json. Restart Claude Desktop after editing it.

Running from a clone

If you'd rather not go through npm:

pnpm install
pnpm build
pnpm start          # stdio

Then point your client at the built entry point:

claude mcp add temporal -- node /absolute/path/to/temporal-mcp-server/dist/node.js
{
  "mcpServers": {
    "temporal": {
      "command": "node",
      "args": ["/absolute/path/to/temporal-mcp-server/dist/node.js"]
    }
  }
}

The package also installs a temporal-mcp-server binary, so a global install (npm i -g temporal-mcp-server) lets you use that name directly as the command.

Verifying it works

The server speaks JSON-RPC on stdout, so you can drive it by hand:

printf '%s\n%s\n%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"1.0.0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_current_time","arguments":{"timezone":"Asia/Tokyo"}}}' \
  | node dist/node.js

Only JSON-RPC goes to stdout; logs go to stderr, so piping is safe.

Running locally over HTTP

For clients that speak streamable HTTP rather than stdio:

pnpm start:http     # http://localhost:3333/mcp — override the port with PORT

This is the same server and the same tools; only the transport differs.

Running remotely on Cloudflare Workers

pnpm cf:dev         # local workerd runtime
pnpm cf:deploy      # build + edge-safety check + deploy

cf:deploy runs pnpm build first, which includes check:worker — so a bundle carrying a Node built-in fails before anything reaches Cloudflare.

Continuous deployment

Deploys run through Cloudflare Workers Builds rather than GitHub Actions, so no Cloudflare API token is stored in GitHub at all — Cloudflare connects to the repo through its own GitHub App.

Set it up once in the dashboard (Workers & Pages → temporal-mcp-server → Settings → Build):

Field

Value

Deploy command

pnpm cf:deploy

Build command

(leave empty — cf:deploy builds)

Root directory

(repo root)

Pointing the deploy command at a package script keeps the gating logic in version control; the dashboard holds one stable line. The Worker name in the dashboard must match name in wrangler.jsonc (temporal-mcp-server), or the build fails.

The build image ships pnpm and honours .nvmrc (ours pins Node 24). Non-production branches default to npx wrangler versions upload, so branch pushes produce preview versions without touching the live deployment.

The MCP endpoint is at /mcp. To require a bearer token:

wrangler secret put MCP_AUTH_TOKEN

With MCP_AUTH_TOKEN set, unauthenticated calls to /mcp get a 401. Leave it unset and the endpoint is public — reasonable for a clock, not for much else.

Optional vars: GIT_COMMIT and ENVIRONMENT are surfaced by the info tool and /info.

Connecting a client to the deployed worker

The public instance is served from a custom domain:

claude mcp add --transport http temporal https://time.somamcp.com/mcp

With a token set, pass it as a header:

claude mcp add --transport http temporal https://time.somamcp.com/mcp \
  --header "Authorization: Bearer $MCP_AUTH_TOKEN"

Health check: https://time.somamcp.com/health.

pnpm cf:dev serves the same thing on http://localhost:8787/mcp, so you can point a client at a local workerd instance before deploying.

Why the worker imports somamcp/edge

somamcp's root barrel re-exports helpers that import node:fs. Importing it from a Worker drags Node built-ins into the bundle. src/worker.ts therefore imports somamcp/edge, and pnpm check:worker fails the build if a node: import, a bare Node built-in, or the root somamcp specifier reaches the worker bundle.

The check walks the actual import graph from dist/worker.js rather than matching filenames — the bundler hoists code shared with the Node entry into a chunk with a generated name, and a filename glob would skip exactly the file most likely to carry a leak.

nodejs_compat is deliberately not enabled in wrangler.jsonc. If a Node built-in ever arrives, the build should fail loudly rather than be silently shimmed.

The alias block in wrangler.jsonc

xsschema (transitive, via fastmcp) probes for every schema library it supports — valibot, effect, sury — through dynamic import. We only use zod, so those branches never run, but esbuild still has to resolve the specifiers. They are aliased to an empty module instead of installing three unused libraries.

Architecture

src/
  clock.ts    pure time logic — Either<TemporalError, T>, no I/O, no globals
  tools.ts    MCP tool registration; takes a server, creates none
  index.ts    library surface (runtime-agnostic)
  node.ts     entry: somamcp      -> stdio + httpStream
  worker.ts   entry: somamcp/edge -> export default { fetch }

registerTemporalTools(server) takes the server rather than building one, so both entry points register identical tools. Nothing in clock.ts, tools.ts, or index.ts touches process, the filesystem, or any Node built-in.

Failures are values. Every fallible function in clock.ts returns Either<TemporalError, T>; the tool layer folds a Left into an MCP error result. Nothing depends on stack unwinding, which is what lets the same logic run unchanged on both runtimes.

Development

pnpm validate       # format + lint + typecheck + test + build
pnpm test           # 34 tests
pnpm check:worker   # verify the worker bundle is edge-safe

test/worker.spec.ts drives real Request objects through the Worker's fetch handler over the MCP wire protocol, so integration breakage surfaces in CI rather than after a deploy.

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Related MCP Servers

  • A
    license
    -
    quality
    C
    maintenance
    The Time MCP Server is a Model Context Protocol (MCP) server that provides AI assistants and other MCP clients with standardized tools to perform time and date-related operations. This server acts as a bridge between AI tools and a robust time-handling back
    122
    26
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    A lightweight MCP server providing comprehensive date, time, and day-of-week information. It supports relative time calculations, timezone conversions, and detailed calendar metadata like week numbers and quarters.
    5
    1
    MIT
  • A
    license
    D
    quality
    C
    maintenance
    A lightweight MCP server that provides date and time tools, including the ability to retrieve current timestamps and parse date strings with IANA timezone support. It enables AI models to interact with the host OS clock and perform temporal calculations via stdio transport.
    3
    11
    7
    MIT
  • A
    license
    A
    quality
    F
    maintenance
    MCP server providing various date/time functions including current time, timezone conversion, and relative time calculations. Supports both local stdio and remote HTTP access via Cloudflare Workers.
    6
    322
    2
    MIT

View all related MCP servers

Related MCP Connectors

  • Timezone MCP — wraps WorldTimeAPI (free, no auth)

  • Time MCP server via HTTP

  • Hosted MCP server for business-day math, deadline planning, meeting overlap, and SLA calculations.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jordanburke/temporal-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server