Skip to main content
Glama
timeaissr

datetime-mcp-server

by timeaissr

datetime MCP Server

Сервер Model Context Protocol, предоставляющий запросы текущей даты/времени, написан на TypeScript и предназначен для развёртывания на AWS Lambda с对外 предоставлением услуг через Streamable HTTP.

Возможности

  • Два MCP-инструмента: get_date, get_datetime, вывод в формате ISO 8601

  • Необязательный параметр часового пояса: поддержка имён IANA (Asia/Shanghai) и смещений UTC (+08:00), по умолчанию UTC

  • Ноль сторонних библиотек времени: полностью на встроенном Intl (ICU) Node.js, без зависимостей moment/luxon/dayjs

  • Serverless-развёртывание: один bundle-файл (~2 МБ) + Lambda Web Adapter, после холодного старта горячие экземпляры отвечают за миллисекунды

  • Соответствие последним стандартам MCP: транспортировка Streamable HTTP, stateless-режим работы, согласование версий протокола обрабатывается официальным SDK

Related MCP server: date-today-mcp

Архитектура

MCP Client ──HTTP POST /mcp──▶ Function URL ──▶ Lambda 函数
                                                │
                                                ├─ LWA Layer (AWS_LAMBDA_EXEC_WRAPPER=/opt/bootstrap)
                                                │    └─ 执行 zip 根目录 bootstrap → node dist/index.js
                                                │
                                                └─ Express app (端口 8080)
                                                     └─ POST /mcp → StreamableHTTPServerTransport
                                                          (stateless:每请求新建 transport,
                                                            enableJsonResponse 返回普通 JSON)

Ключевые механизмы:

Компонент

Описание

Streamable HTTP

Единственная рекомендуемая в настоящее время HTTP-транспортировка MCP; HTTP+SSE устарел

Stateless-режим

Каждый запрос самодостаточен, сессии не поддерживаются, что соответствует модели заморозки/разморозки Lambda

enableJsonResponse: true

Ответ идёт обычным JSON, а не потоком SSE, что обходит ограничения буферизации ответов Lambda

Lambda Web Adapter (LWA)

Официальный публичный Layer AWS, преобразующий вызов Lambda в реальный HTTP-запрос к localhost:8080

Скрипт bootstrap

Настоящая точка входа процесса после接管 LWA (node dist/index.js); поле handler в конфигурации — просто заглушка

MCP-инструменты

get_date

Возвращает текущую календарную дату в формате ISO 8601 YYYY-MM-DD.

Параметр

Тип

Обязателен

Описание

timezone

string

нет

Имя часового пояса IANA или смещение UTC, по умолчанию "UTC"

{"result":{"content":[{"type":"text","text":"2026-08-24"}]}}

get_datetime

Возвращает текущие дату и время в формате ISO 8601 с суффиксом смещения (для вывода UTC используется Z).

{"result":{"content":[{"type":"text","text":"2026-08-23T14:30:00+08:00"}]}}

Поведение при ошибках

  • Часовой пояс отсутствует или является пустой строкой → рассматривается как UTC

  • Непустой, но недопустимый часовой пояс → возвращается результат с isError: true и подсказкой:

Error: Invalid IANA timezone "Mars/Olympus". Use a name like "UTC", "Asia/Shanghai" or "America/New_York".
  • Ошибки уровня протокола (например, отсутствие заголовка Accept) возвращаются SDK как стандартная ошибка JSON-RPC

Источник времени и точность

Время считывается из системных часов среды выполнения (new Date()). Локально — это часы машины (зависит от калибровки NTP); на Lambda часы хоста автоматически синхронизируются Amazon Time Sync Service (источник GPS/атомные часы, PTP/NTP), погрешность в пределах миллисекунд, никакой настройки не требуется.

Намеренно не выполняется внешний NTP-запрос при каждом вызове: часы AWS уже постоянно синхронизированы, внешний запрос лишь добавит задержку (+10~100 мс), внесёт сетевую точку отказа и проблемы с лимитами, а точность выше не станет.

Разрешение вывода — до секунды (миллисекунды отбрасываются). Преобразование часовых поясов — чистая арифметика: все часовые пояса получают один и тот же абсолютный момент, различается лишь представление в местном времени.

Локальная разработка

Требуется Node.js ≥ 22.

npm install        # 安装依赖
npm run dev        # 构建 + 启动(默认 http://localhost:3000/mcp)
npm test           # vitest 单测(14 个用例)
npm run typecheck  # tsc --noEmit
npm run lint       # eslint
npm run build      # esbuild 打包为 CJS 单文件 dist/index.js

Локальное ручное тестирование (заголовок Accept должен объявлять оба типа media — это проверка протокола SDK):

curl -s http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_datetime","arguments":{"timezone":"Asia/Shanghai"}}}'

Также можно использовать официальный отладчик: npx @modelcontextprotocol/inspector, тип подключения — Streamable HTTP.

Примечание: если на машине задана переменная окружения http_proxy, curl нужно запускать с --noproxy '*', иначе запросы к localhost будут перехвачены прокси и вернут 502.

Структура проекта

├── src/
│   ├── time.ts      # 核心纯函数:ISO 格式化、时区校验(可独立单测)
│   ├── server.ts    # McpServer 实例 + 工具注册
│   └── index.ts     # Express app + stateless transport 挂载 + 进程入口
├── test/
│   └── time.test.ts # 固定时间戳验证多时区/DST/半小时偏移/错误输入
├── build.mjs        # esbuild 构建脚本(bundle: platform=node22, format=cjs)
├── bootstrap        # LWA 进入口(zip 根目录,需可执行位 755)
├── deploy.sh        # CLI 一键部署脚本
├── function.zip     # 部署包(构建产物,不入库)
└── dist/index.js    # 打包产物(约 2MB,零运行时依赖安装)

Ключевые моменты реализации

Форматирование часовых поясов полностью выполняется через Intl.DateTimeFormat, основные приёмы:

  1. Дата: локаль en-CA естественным образом выводит YYYY-MM-DD, ручная сборка не нужна

  2. Время со смещением: formatToParts берёт поля местного времени целевого пояса → с помощью Date.UTC() обратно вычисляет его как UTC → вычитает из исходного момента, получая смещение в минутах → форматирует как ±HH:MM или Z

  3. hourCycle: "h23": позволяет избежать граничного бага с часом "24", который возникает с hour12: false в некоторых локалях

  4. DST и особые часовые пояса: смещение вычисляется на момент запроса, переход на летнее время обрабатывается корректно (Нью-Йорк -04:00-05:00), пояса с получасовым/четвертьчасовым сдвигом (Индия +05:30, Непал +05:45, Чатем +12:45) покрыты юнит-тестами

  5. Кэш форматтеров: экземпляры Intl.DateTimeFormat кэшируются по часовому поясу, повторные вызовы на горячем экземпляре не несут затрат на создание

  6. Проверка часового пояса: try/catch при создании Intl.DateTimeFormat, недопустимое значение выбрасывает RangeError и считается недействительным. Новая версия ECMA-402 позволяет ICU принимать и строки смещения UTC (например, +08:00), вся цепочка проверена на корректность вывода и включена в тесты

Развёртывание на AWS Lambda

Предварительные условия: настроены учётные данные AWS CLI; роль выполнения с разрешением AWSLambdaBasicExecutionRole (если нет — можно создать командой ниже):

aws iam create-role --role-name datetime-mcp-role \
  --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}'

aws iam attach-role-policy --role-name datetime-mcp-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Способ 1: CLI-скрипт

ROLE_ARN=arn:aws:iam::<账号ID>:role/datetime-mcp-role ./deploy.sh

Необязательные переменные окружения: AWS_REGION (по умолчанию us-east-1), FUNCTION_NAME (по умолчанию datetime-mcp), ARCH (arm64/x86_64, по умолчанию arm64).

Ход скрипта: динамический запрос последней версии LWA Layer для региона → сборка esbuild → упаковка bsdtar (в системе нет команды zip) → create/update функции (nodejs22.x, 512 МБ, таймаут 10 с) → создание Function URL без аутентификации и разрешение публичного вызова → вывод endpoint. Повторный запуск безопасен, автоматически идёт по пути обновления.

Способ 2: Консоль AWS

  1. Локальная упаковка:

    npm run build && bsdtar --format zip -cf function.zip bootstrap dist/index.js
  2. Консоль Lambda → Create function → Author from scratch

    • Runtime: Node.js 22.x; Architecture: arm64

    • Permissions: Create a new role with basic Lambda permissions

  3. Вкладка Code → Upload from → .zip file → выбрать function.zip (внутренняя структура должна быть: корневой bootstrap + dist/index.js)

  4. Раздел Layers → Add a layer → AWS layers → LambdaAdapterLayerArm64 (выбрать последнюю версию)

  5. Configuration → Environment variables:

    Key

    Value

    AWS_LAMBDA_EXEC_WRAPPER

    /opt/bootstrap

    PORT

    8080

  6. Configuration → General configuration → Memory 512 MB、Timeout 10 s

  7. Configuration → Function URL → Create → Auth type NONE

При создании Function URL типа NONE через консоль ресурсная политика публичного вызова добавляется автоматически, выполнять add-permission не нужно (в этом отличие от CLI).

Прямой доступ браузером к Function URL с ответом 405 — это нормально (разрешён только POST). При последующем обновлении кода: пересобрать и упаковать, затем заново загрузить на вкладке Code.

Подключение MCP-клиента

На примере opencode — добавить remote MCP server в конфигурацию:

{
  "mcp": {
    "datetime": {
      "type": "remote",
      "url": "https://<identifier>.lambda-url.<region>.on.aws/mcp"
    }
  }
}

Журнал проектных решений

Решение

Вывод

Обоснование

Язык

TypeScript

Встроенная поддержка часовых поясов Intl без зависимостей; самый быстрый холодный старт Lambda (~100-200 мс против ~300-800 мс у Python); маленький bundle. Преимущество Python — более лаконичный синтаксис декораторов

Транспорт

Streamable HTTP + stateless + JSON response

У Lambda нет постоянного процесса, stdio неприменим; отсутствие состояния сессии естественно соответствует модели заморозки/разморозки; чистый JSON обходит ограничения потоковой передачи SSE

Версия SDK

Стабильная @modelcontextprotocol/sdk@1.x (1.30.0)

Корректно реализует согласование версий протокола, обратная совместимость со старыми клиентами; новые возможности редакции от 2026-07-28 (кэш TTL и др.) бессмысленны для статического списка инструментов; API бета-раздельных пакетов нестабилен

Реализация часовых поясов

Intl, а не сторонние библиотеки

Ноль зависимостей, не нужно доустанавливать tzdata на Lambda, точности достаточно

Источник времени

Системные часы, а не NTP при каждом запросе

AWS уже выполняет субмиллисекундную синхронизацию; внешний NTP добавляет задержку/точки отказа/затраты без выигрыша в точности

Развёртывание

Ручной CLI/консоль + LWA Layer

Без первоначальных вложений в SAM/CDK/Terraform; deploy.sh — просто пакетная обработка команд, не IaC

Устранение неполадок

Симптом

Причина и решение

Not Acceptable: Client must accept both application/json and text/event-stream

В запросе отсутствует заголовок Accept. Для теста curl нужен -H "Accept: application/json, text/event-stream"; настоящие MCP-клиенты добавляют его автоматически

Handler 'handler' missing on module 'index'

Забыли подключить LWA Layer или не задали AWS_LAMBDA_EXEC_WRAPPER — среда ищет handler по пути по умолчанию. Добавьте Layer и переменные окружения

GET /mcp возвращает 405

Это ожидаемо. Stateless-режим не поддерживает серверные push-потоки, принимается только POST

Локальный тест curl возвращает 502, ответ мгновенный

Системный прокси перехватил localhost. Добавьте --noproxy '*'

Первый запрос к Function URL на холодном старте медленный

Это следствие механизма заморозки/разморозки Lambda, последующие запросы — миллисекунды

При упаковке ошибка zip: command not found

На машине не установлен пакет zip (в Arch это отдельный пакет от unzip). В проекте уже используется bsdtar (входит в libarchive), сохраняющий биты прав

Известные ограничения и будущие улучшения

  • Защитный handler не добавлен: при запуске в среде выполнения Node.js по умолчанию (без LWA) сообщение об ошибке невнятное. Можно экспортировать подсказывающий handler-заглушку для улучшения опыта при ошибочной конфигурации; на нормальный путь это не влияет

  • Вывод только с точностью до секунды, миллисекунды не раскрываются

  • Нет аутентификации и ограничения частоты — публичный endpoint могут злоупотреблять, накручивая вызовы (хотя стоимость одного вызова стремится к нулю)

  • Таблица алиасов Intl.supportedValuesOf("timeZone") не используется для подсказок параметров, в сообщении об ошибке приведены лишь три примера

  • При будущем переходе SDK со стабильной версии 1.x на раздельные пакеты (поддержка редакции от 2026-07-28) потребуется отслеживать изменения API

Лицензия

ISC

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

Maintenance

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

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    A
    quality
    Not graded
    maintenance
    Provides timezone-aware date and time information with configurable time formats and timezone support. Enables users to get current date and time in their preferred timezone and format through simple MCP tools.
    2
  • F
    license
    A
    quality
    C
    maintenance
    A simple MCP server that returns the current date and time with timezone information in ISO 8601, Unix timestamp, and human-readable formats.
    1
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides time-related tools including current time retrieval, timezone conversion, time formatting, and timezone info via MCP.
    15
    MIT

View all related MCP servers

Related MCP Connectors

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

  • A real clock for AI agents: current time, timezone conversion, and DST facts from the IANA tzdb.

  • Time MCP server via HTTP

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/timeaissr/datetime-mcp-server'

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