Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions src/time/src/mcp_server_time/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ async def list_tools() -> list[Tool]:
"properties": {
"timezone": {
"type": "string",
"description": f"IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use '{local_tz}' as local timezone if no timezone provided by the user.",
"description": f"IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Defaults to '{local_tz}' if not provided.",
}
},
"required": ["timezone"],
"required": [],
},
annotations=ToolAnnotations(
readOnlyHint=True,
Expand All @@ -157,18 +157,18 @@ async def list_tools() -> list[Tool]:
"properties": {
"source_timezone": {
"type": "string",
"description": f"Source IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use '{local_tz}' as local timezone if no source timezone provided by the user.",
"description": f"Source IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Defaults to '{local_tz}' if not provided.",
},
"time": {
"type": "string",
"description": "Time to convert in 24-hour format (HH:MM)",
},
"target_timezone": {
"type": "string",
"description": f"Target IANA timezone name (e.g., 'Asia/Tokyo', 'America/San_Francisco'). Use '{local_tz}' as local timezone if no target timezone provided by the user.",
"description": f"Target IANA timezone name (e.g., 'Asia/Tokyo', 'America/San_Francisco'). Defaults to '{local_tz}' if not provided.",
},
},
"required": ["source_timezone", "time", "target_timezone"],
"required": ["time"],
},
annotations=ToolAnnotations(
readOnlyHint=True,
Expand All @@ -187,23 +187,17 @@ async def call_tool(
try:
match name:
case TimeTools.GET_CURRENT_TIME.value:
timezone = arguments.get("timezone")
if not timezone:
raise ValueError("Missing required argument: timezone")

timezone = arguments.get("timezone") or local_tz
result = time_server.get_current_time(timezone)

case TimeTools.CONVERT_TIME.value:
if not all(
k in arguments
for k in ["source_timezone", "time", "target_timezone"]
):
raise ValueError("Missing required arguments")
if "time" not in arguments:
raise ValueError("Missing required argument: time")

result = time_server.convert_time(
arguments["source_timezone"],
arguments.get("source_timezone") or local_tz,
arguments["time"],
arguments["target_timezone"],
arguments.get("target_timezone") or local_tz,
)
case _:
raise ValueError(f"Unknown tool: {name}")
Expand Down
44 changes: 43 additions & 1 deletion src/time/test/time_server_test.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@

import json
from freezegun import freeze_time
from mcp.shared.exceptions import McpError
import pytest
from unittest.mock import patch
from zoneinfo import ZoneInfo

from mcp_server_time.server import TimeServer, get_local_tz
from mcp.server import Server
from mcp_server_time.server import TimeServer, get_local_tz, serve


@pytest.mark.parametrize(
Expand Down Expand Up @@ -526,3 +528,43 @@ def test_get_local_tz_various_timezones(mock_get_localzone, timezone_name):
result = get_local_tz()
assert str(result) == timezone_name
assert isinstance(result, ZoneInfo)


@freeze_time("2024-01-01 12:00:00+00:00")
@pytest.mark.asyncio
async def test_get_current_time_defaults_to_local_tz():
"""Test that get_current_time uses local_tz when timezone is omitted."""
server_obj = Server("mcp-time")
time_server = TimeServer()
local_tz = str(get_local_tz("America/New_York"))

# Import the handler logic directly to test it
# Simulate calling with empty arguments
timezone = {} .get("timezone") or local_tz
result = time_server.get_current_time(timezone)
assert result.timezone == "America/New_York"
assert "2024-01-01T07:00:00" in result.datetime


@freeze_time("2024-01-01 12:00:00+00:00")
@pytest.mark.asyncio
async def test_convert_time_defaults_source_to_local_tz():
"""Test that convert_time uses local_tz when source_timezone is omitted."""
time_server = TimeServer()
local_tz = str(get_local_tz("America/New_York"))

source_tz = {} .get("source_timezone") or local_tz
result = time_server.convert_time(source_tz, "12:00", "Europe/London")
assert result.source.timezone == "America/New_York"


@freeze_time("2024-01-01 12:00:00+00:00")
@pytest.mark.asyncio
async def test_convert_time_defaults_target_to_local_tz():
"""Test that convert_time uses local_tz when target_timezone is omitted."""
time_server = TimeServer()
local_tz = str(get_local_tz("America/New_York"))

target_tz = {} .get("target_timezone") or local_tz
result = time_server.convert_time("Europe/London", "12:00", target_tz)
assert result.target.timezone == "America/New_York"
Loading