Skip to content

Commit e456eba

Browse files
committed
Fix uv lock for time-server, update Readme
1 parent 995faa1 commit e456eba

File tree

5 files changed

+21
-124
lines changed

5 files changed

+21
-124
lines changed

src/time/README.md

+12-45
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ A Model Context Protocol server that provides time and timezone conversion capab
55
### Available Tools
66

77
- `get_current_time` - Get current time in a specific timezone or system timezone.
8-
- Optional argument: `timezone` (string): IANA timezone name (e.g., 'America/New_York', 'Europe/London')
9-
- If timezone is not provided, returns time in system timezone
8+
- Required arguments:
9+
- `timezone` (string): IANA timezone name (e.g., 'America/New_York', 'Europe/London')
1010

1111
- `convert_time` - Convert time between timezones.
1212
- Required arguments:
@@ -111,45 +111,25 @@ Example:
111111

112112
## Example Interactions
113113

114-
1. Get current time (using system timezone):
115-
```json
116-
{
117-
"name": "get_current_time",
118-
"arguments": {}
119-
}
120-
```
121-
Response:
122-
```json
123-
{
124-
"timezone": "Europe/London",
125-
"time": "14:30 BST",
126-
"date": "2024-11-25",
127-
"full_datetime": "2024-11-25 14:30:00 BST",
128-
"is_dst": true
129-
}
130-
```
131-
132-
2. Get current time in specific timezone:
114+
1. Get current time:
133115
```json
134116
{
135117
"name": "get_current_time",
136118
"arguments": {
137-
"timezone": "America/New_York"
119+
"timezone": "Europe/Warsaw"
138120
}
139121
}
140122
```
141123
Response:
142124
```json
143125
{
144-
"timezone": "America/New_York",
145-
"time": "09:30 EDT",
146-
"date": "2024-11-25",
147-
"full_datetime": "2024-11-25 09:30:00 EDT",
148-
"is_dst": true
126+
"timezone": "Europe/Warsaw",
127+
"datetime": "2024-01-01T13:00:00+01:00",
128+
"is_dst": false
149129
}
150130
```
151131

152-
3. Convert time between timezones:
132+
2. Convert time between timezones:
153133
```json
154134
{
155135
"name": "convert_time",
@@ -165,31 +145,18 @@ Response:
165145
{
166146
"source": {
167147
"timezone": "America/New_York",
168-
"time": "16:30 EDT",
169-
"date": "2024-11-25"
148+
"datetime": "2024-01-01T12:30:00-05:00",
149+
"is_dst": false
170150
},
171151
"target": {
172152
"timezone": "Asia/Tokyo",
173-
"time": "05:30 JST",
174-
"date": "2024-11-26"
153+
"datetime": "2024-01-01T12:30:00+09:00",
154+
"is_dst": false
175155
},
176156
"time_difference": "+13.0h",
177-
"date_changed": true,
178-
"day_relation": "next day"
179157
}
180158
```
181159

182-
## Tips for Using IANA Timezone Names
183-
184-
Common timezone formats:
185-
- North America: `America/New_York`, `America/Los_Angeles`, `America/Chicago`
186-
- Europe: `Europe/London`, `Europe/Paris`, `Europe/Berlin`
187-
- Asia: `Asia/Tokyo`, `Asia/Shanghai`, `Asia/Dubai`
188-
- Pacific: `Pacific/Auckland`, `Pacific/Honolulu`
189-
- Australia: `Australia/Sydney`, `Australia/Melbourne`
190-
191-
The server will automatically detect and use your system timezone if no specific timezone is provided.
192-
193160
## Debugging
194161

195162
You can use the MCP inspector to debug the server. For uvx installations:

src/time/pyproject.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mcp-server-time"
3-
version = "0.5.1.pre3"
3+
version = "0.5.1"
44
description = "A Model Context Protocol server providing tools for time queries and timezone conversions for LLMs"
55
readme = "README.md"
66
requires-python = ">=3.10"
@@ -33,5 +33,4 @@ dev-dependencies = [
3333
"freezegun>=1.5.1",
3434
"pyright>=1.1.389",
3535
"pytest>=8.3.3",
36-
"ruff>=0.7.3",
3736
]

src/time/src/mcp_server_time/server.py

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from dataclasses import dataclass
2-
from datetime import datetime, timedelta
1+
from datetime import datetime
32
from enum import Enum
43
import json
54
from typing import Sequence
@@ -35,13 +34,10 @@ class TimeConversionInput(BaseModel):
3534
time: str
3635
target_tz_list: list[str]
3736

37+
def get_local_tz(local_tz_override: str | None = None) -> pytz.timezone:
38+
return pytz.timezone(local_tz_override) if local_tz_override else get_localzone()
3839

3940
class TimeServer:
40-
def __init__(self, local_tz_override: str | None = None):
41-
self.local_tz = (
42-
pytz.timezone(local_tz_override) if local_tz_override else get_localzone()
43-
)
44-
4541
def get_current_time(self, timezone_name: str) -> TimeResult:
4642
"""Get current time in specified timezone"""
4743
try:
@@ -109,8 +105,8 @@ def convert_time(
109105

110106
async def serve(local_timezone: str | None = None) -> None:
111107
server = Server("mcp-time")
112-
time_server = TimeServer(local_timezone)
113-
local_tz = str(time_server.local_tz)
108+
time_server = TimeServer()
109+
local_tz = str(get_local_tz(local_timezone))
114110

115111
@server.list_tools()
116112
async def list_tools() -> list[Tool]:
@@ -183,7 +179,7 @@ async def call_tool(
183179
case _:
184180
raise ValueError(f"Unknown tool: {name}")
185181

186-
return [TextContent(type="text", text=json.dumps(result, indent=2))]
182+
return [TextContent(type="text", text=json.dumps(result.model_dump(), indent=2))]
187183

188184
except Exception as e:
189185
raise ValueError(f"Error processing mcp-server-time query: {str(e)}")

src/time/test/time_server_test.py

+1-39
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from freezegun import freeze_time
44
import pytest
55

6-
from mcp_server_time.server import TimeServer
6+
from mcp_server_time.server import TimeServer, serve
77

88

99
@pytest.mark.parametrize(
@@ -455,41 +455,3 @@ def test_convert_time(test_time, source_tz, time_str, target_tz, expected):
455455
assert result.source.is_dst == expected["source"]["is_dst"]
456456
assert result.target.is_dst == expected["target"]["is_dst"]
457457
assert result.time_difference == expected["time_difference"]
458-
459-
460-
# @pytest.mark.anyio
461-
# async def test_call_tool(mock_forecast_response):
462-
# class Response():
463-
# def raise_for_status(self):
464-
# pass
465-
466-
# def json(self):
467-
# return mock_forecast_response
468-
469-
# class AsyncClient():
470-
# def __aenter__(self):
471-
# return self
472-
473-
# async def __aexit__(self, *exc_info):
474-
# pass
475-
476-
# async def get(self, *args, **kwargs):
477-
# return Response()
478-
479-
# with patch('httpx.AsyncClient', new=AsyncClient) as mock_client:
480-
# result = await call_tool("get_forecast", {"city": "London", "days": 2})
481-
482-
# assert len(result) == 1
483-
# assert result[0].type == "text"
484-
# forecast_data = json.loads(result[0].text)
485-
# assert len(forecast_data) == 1
486-
# assert forecast_data[0]["temperature"] == 18.5
487-
# assert forecast_data[0]["conditions"] == "sunny"
488-
489-
490-
# @pytest.mark.anyio
491-
# async def test_list_tools():
492-
# tools = await list_tools()
493-
# assert len(tools) == 1
494-
# assert tools[0].name == "get_forecast"
495-
# assert "city" in tools[0].inputSchema["properties"]

src/time/uv.lock

+1-28
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)