Skip to content

[Bug]: DateTime UTC Fixes Required #942

@crivetimihai

Description

@crivetimihai

DateTime UTC Fixes Required

See PR #938

Overview

Fix MacOS datetime UTC timestamp bug by replacing deprecated datetime.utcnow() with datetime.now(tz=timezone.utc) or datetime.now(tz=UTC). This ensures consistent UTC timestamp handling across platforms.

CRITICAL - JWT Related (Same MacOS Bug)

1. mcpgateway/routers/email_auth.py:167

Status: 🔴 CRITICAL - JWT token generation

# Line 167
- now = datetime.utcnow()
+ now = datetime.now(tz=UTC)

Import: Already has from datetime import datetime, timedelta, UTC

HIGH PRIORITY - Time Comparisons

2. mcpgateway/middleware/token_scoping.py:175

Status: 🟡 HIGH - Token time restrictions

# Line 175
- now = datetime.utcnow()
+ now = datetime.now(tz=timezone.utc)

Import needed: from datetime import datetime, timezone

3. mcpgateway/services/token_storage_service.py:403

Status: 🟡 HIGH - Token cleanup/expiry

# Line 403
- cutoff_date = datetime.utcnow() - timedelta(days=max_age_days)
+ cutoff_date = datetime.now(tz=timezone.utc) - timedelta(days=max_age_days)

Import needed: from datetime import datetime, timezone

MEDIUM PRIORITY - Session/Activity Tracking

4. mcpgateway/routers/reverse_proxy.py (5 instances)

Status: 🟠 MEDIUM - Session timestamps

# Line 52
- self.connected_at = datetime.utcnow()
+ self.connected_at = datetime.now(tz=timezone.utc)

# Line 53
- self.last_activity = datetime.utcnow()
+ self.last_activity = datetime.now(tz=timezone.utc)

# Line 66
- self.last_activity = datetime.utcnow()
+ self.last_activity = datetime.now(tz=timezone.utc)

# Line 77
- self.last_activity = datetime.utcnow()
+ self.last_activity = datetime.now(tz=timezone.utc)

# Line 210
- "timestamp": datetime.utcnow().isoformat()
+ "timestamp": datetime.now(tz=timezone.utc).isoformat()

# Line 351
- "timestamp": datetime.utcnow().isoformat()
+ "timestamp": datetime.now(tz=timezone.utc).isoformat()

Import needed: from datetime import datetime, timezone

5. mcpgateway/routers/rbac.py:424

Status: 🟠 MEDIUM - Permission check timestamps

# Line 424
- checked_at=datetime.utcnow()
+ checked_at=datetime.now(tz=timezone.utc)

Import needed: from datetime import datetime, timezone

LOW PRIORITY - Test Files (Consistency)

6. tests/unit/mcpgateway/test_oauth_manager.py

Status: 🟢 LOW - Test consistency (11 instances)

  • Lines: 1777, 1811, 1852, 1882, 1908, 1953, 1993, 2046, 2100, 2122, 2144
  • Replace all datetime.utcnow() with datetime.now(tz=timezone.utc)

7. tests/unit/mcpgateway/test_main.py:1479

Status: 🟢 LOW - Test consistency

- expired_payload = {"sub": "test_user", "exp": datetime.datetime.utcnow() - datetime.timedelta(hours=1)}
+ expired_payload = {"sub": "test_user", "exp": datetime.datetime.now(tz=datetime.timezone.utc) - datetime.timedelta(hours=1)}

LOWEST PRIORITY - Documentation/Examples

8. Documentation Files

Status: 🟢 LOW - Documentation consistency

mcpgateway/services/token_storage_service.py

  • Docstring examples at lines: 43, 182, 195, 269, 270, 303

docs/docs/architecture/oauth-authorization-code-ui-design.md

  • Lines: 155, 169, 220

Other MCP Server Files

  • mcp-servers/python/mcp_eval_server/mcp_eval_server/tools/workflow_tools.py (4 instances)
  • agent_runtimes/langchain_agent/app.py (2 instances)

Priority Execution Order

  1. 🔴 CRITICAL: mcpgateway/routers/email_auth.py:167 (JWT token generation)
  2. 🟡 HIGH: token_scoping.py, token_storage_service.py, rbac.py (time comparisons)
  3. 🟠 MEDIUM: reverse_proxy.py (session tracking)
  4. 🟢 LOW: Test files and documentation

Additional Considerations Found

User-Facing DateTime Display

The admin UI correctly handles user-facing timestamps:

  • mcpgateway/static/admin.js uses new Date().toLocaleString() and toLocaleDateString() which automatically converts UTC timestamps to user's local timezone
  • Boot time display in mcpgateway/templates/version_info_partial.html:321 shows system boot time (likely local time)

Datetime Formatting in Transport Layer

  • mcpgateway/transports/sse_transport.py:369 uses obj.strftime("%Y-%m-%d %H:%M:%S") for JSON serialization
  • This formats datetime objects without timezone info - potential issue if mixing UTC/local datetimes

File Naming Timestamps

Several files use datetime.now().strftime() for generating filenames (admin.py, cli_export_import.py):

  • These are fine as local timestamps since they're for file organization
  • No timezone issues here

Recommendations

  1. Fix Critical JWT Issues First (email_auth.py:167)
  2. Consider SSE Transport: Review if sse_transport.py:369 needs timezone handling
  3. Keep Current Admin UI: The JavaScript properly handles timezone conversion for display
  4. File Timestamps: Current local time usage for filenames is appropriate

Notes

  • The PR already fixed mcpgateway/routers/email_auth.py:118
  • Most of the codebase already uses the correct datetime.now(timezone.utc) pattern
  • The CHANGELOG.md already documents this migration: "Replaced deprecated stdlib functions - datetime.utcnow()datetime.now(timezone.utc)"
  • This is part of Python's deprecation of datetime.utcnow() in favor of timezone-aware alternatives
  • Admin UI properly handles timezone display using JavaScript's built-in locale functions

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingtriageIssues / Features awaiting triage

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions