Skip to main content
Glama
timeaissr

datetime-mcp-server

by timeaissr

datetime MCP Server

現在の日付/時刻を照会する Model Context Protocol サーバーです。TypeScript で記述され、AWS Lambda 上にデプロイして Streamable HTTP で外部にサービスを提供する設計になっています。

機能特性

  • 2つの MCP ツール:get_date、get_datetime。ISO 8601 形式で出力

  • オプションのタイムゾーン引数:IANA タイムゾーン名(Asia/Shanghai)と UTC オフセット(+08:00)に対応、デフォルトは UTC

  • サードパーティの時刻ライブラリ不要:完全に Node.js 内蔵の Intl(ICU)ベース。moment/luxon/dayjs への依存なし

  • Serverless デプロイ:単一ファイル bundle(約 2MB)+ 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

MCP が現在唯一推奨する HTTP トランスポート。HTTP+SSE は非推奨

Stateless モード

各リクエストが自己完結し、セッションを保持しない。Lambda のフリーズ/解凍モデルに適合

enableJsonResponse: true

レスポンスが SSE ストリームではなく通常の JSON になり、Lambda のレスポンスバッファ制限を回避

Lambda Web Adapter (LWA)

AWS 公式のパブリック Layer。Lambda invoke を localhost:8080 への実際の HTTP リクエストに変換

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 error を返す

時刻の取得元と精度

時刻は実行環境のシステムクロック(new Date())から読み取ります。ローカルでは自機のクロック(NTP 校正に依存)。Lambda 上ではホストマシンのクロックが Amazon Time Sync Service(GPS/原子時計ソース、PTP/NTP)によって自動同期され、誤差はミリ秒未満。設定は一切不要です。

毎回外部 NTP を照会することは意図的に行いません。AWS のクロックは継続的に同期済みであり、外部照会はレイテンシ(+10〜100ms)を増やし、ネットワーク障害面とレート制限の問題を持ち込むだけで、精度は向上しません。

出力の分解能は秒単位(ミリ秒は切り捨て)。タイムゾーン変換は純粋な算術演算です。すべてのタイムゾーンが取得するのは同じ絶対瞬間であり、壁時計時刻の表現が異なるだけです。

ローカル開発

要件: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 ヘッダーで両方のメディアタイプを宣言する必要があります。これは 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 locale は自然に YYYY-MM-DD を出力するため、手動での組み立て不要

  2. オフセット付き時刻:formatToParts で対象タイムゾーンの壁時計時刻の各フィールドを取得 → Date.UTC() でそれを UTC として逆算 → 元の instant と減算して分単位の offset を取得 → ±HH:MM または Z に整形

  3. hourCycle: "h23":hour12: false が一部の locale で "24" 時の境界バグを生むのを回避

  4. DST と特殊タイムゾーン:offset はリクエスト時点で計算されるため、夏時間の切り替えは自然に正しく処理される(ニューヨーク -04:00→-05:00)。30分/15分刻みのタイムゾーン(インド +05:30、ネパール +05:45、チャタム +12:45)はすべて単体テストでカバー

  5. Formatter キャッシュ:timezone ごとに 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、512MB、タイムアウト 10s)→ 認証なしの 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

コンソールで NONE タイプの Function URL を作成すると、公開呼び出し用のリソースポリシーが自動的に追加されます。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〜200ms vs Python 約300〜800ms)。bundle が小さい。Python の利点はデコレーター記法がより簡潔なこと

トランスポート

Streamable HTTP + stateless + JSON response

Lambda には永続プロセスがないため stdio は不可。セッション状態なしはフリーズ/解凍モデルに自然に適合。純粋な JSON で SSE ストリーミング制限を回避

SDK バージョン

安定版 @modelcontextprotocol/sdk@1.x(1.30.0)

プロトコルバージョン交渉を正しく実装し、旧クライアントと後方互換。2026-07-28 改訂版の新機能(TTL キャッシュなど)は静的ツールリストには無意味。beta の分割パッケージ API は未安定

タイムゾーン実装

Intl でありサードパーティライブラリではない

依存ゼロ、Lambda 上で tzdata の追加インストール不要、精度は十分

時刻ソース

毎回 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 モードはサーバープッシュストリームをサポートせず、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") のエイリアステーブルを引数ヒントに使用しておらず、エラーメッセージは3つの例のみ

  • SDK が将来、安定版 1.x から分割パッケージ(2026-07-28 改訂版対応)に移行する際は API 変更への追従が必要

License

ISC

Related MCP Connectors

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
    -
  • A
    license
    A
    quality
    D
    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
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides time-related tools including current time retrieval, timezone conversion, time formatting, and timezone info via MCP.
    7 npm
    MIT