Skip to content

Commit

Permalink
Fix uv lock for time-server, update Readme
Browse files Browse the repository at this point in the history
  • Loading branch information
maledorak committed Nov 28, 2024
1 parent 774cd0b commit d37ce3c
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 124 deletions.
57 changes: 12 additions & 45 deletions src/time/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ A Model Context Protocol server that provides time and timezone conversion capab
### Available Tools

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

- `convert_time` - Convert time between timezones.
- Required arguments:
Expand Down Expand Up @@ -111,45 +111,25 @@ Example:

## Example Interactions

1. Get current time (using system timezone):
```json
{
"name": "get_current_time",
"arguments": {}
}
```
Response:
```json
{
"timezone": "Europe/London",
"time": "14:30 BST",
"date": "2024-11-25",
"full_datetime": "2024-11-25 14:30:00 BST",
"is_dst": true
}
```

2. Get current time in specific timezone:
1. Get current time:
```json
{
"name": "get_current_time",
"arguments": {
"timezone": "America/New_York"
"timezone": "Europe/Warsaw"
}
}
```
Response:
```json
{
"timezone": "America/New_York",
"time": "09:30 EDT",
"date": "2024-11-25",
"full_datetime": "2024-11-25 09:30:00 EDT",
"is_dst": true
"timezone": "Europe/Warsaw",
"datetime": "2024-01-01T13:00:00+01:00",
"is_dst": false
}
```

3. Convert time between timezones:
2. Convert time between timezones:
```json
{
"name": "convert_time",
Expand All @@ -165,31 +145,18 @@ Response:
{
"source": {
"timezone": "America/New_York",
"time": "16:30 EDT",
"date": "2024-11-25"
"datetime": "2024-01-01T12:30:00-05:00",
"is_dst": false
},
"target": {
"timezone": "Asia/Tokyo",
"time": "05:30 JST",
"date": "2024-11-26"
"datetime": "2024-01-01T12:30:00+09:00",
"is_dst": false
},
"time_difference": "+13.0h",
"date_changed": true,
"day_relation": "next day"
}
```

## Tips for Using IANA Timezone Names

Common timezone formats:
- North America: `America/New_York`, `America/Los_Angeles`, `America/Chicago`
- Europe: `Europe/London`, `Europe/Paris`, `Europe/Berlin`
- Asia: `Asia/Tokyo`, `Asia/Shanghai`, `Asia/Dubai`
- Pacific: `Pacific/Auckland`, `Pacific/Honolulu`
- Australia: `Australia/Sydney`, `Australia/Melbourne`

The server will automatically detect and use your system timezone if no specific timezone is provided.

## Debugging

You can use the MCP inspector to debug the server. For uvx installations:
Expand Down
3 changes: 1 addition & 2 deletions src/time/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "mcp-server-time"
version = "0.5.1.pre3"
version = "0.5.1"
description = "A Model Context Protocol server providing tools for time queries and timezone conversions for LLMs"
readme = "README.md"
requires-python = ">=3.10"
Expand Down Expand Up @@ -33,5 +33,4 @@ dev-dependencies = [
"freezegun>=1.5.1",
"pyright>=1.1.389",
"pytest>=8.3.3",
"ruff>=0.7.3",
]
16 changes: 6 additions & 10 deletions src/time/src/mcp_server_time/server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from dataclasses import dataclass
from datetime import datetime, timedelta
from datetime import datetime
from enum import Enum
import json
from typing import Sequence
Expand Down Expand Up @@ -35,13 +34,10 @@ class TimeConversionInput(BaseModel):
time: str
target_tz_list: list[str]

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

class TimeServer:
def __init__(self, local_tz_override: str | None = None):
self.local_tz = (
pytz.timezone(local_tz_override) if local_tz_override else get_localzone()
)

def get_current_time(self, timezone_name: str) -> TimeResult:
"""Get current time in specified timezone"""
try:
Expand Down Expand Up @@ -109,8 +105,8 @@ def convert_time(

async def serve(local_timezone: str | None = None) -> None:
server = Server("mcp-time")
time_server = TimeServer(local_timezone)
local_tz = str(time_server.local_tz)
time_server = TimeServer()
local_tz = str(get_local_tz(local_timezone))

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

return [TextContent(type="text", text=json.dumps(result, indent=2))]
return [TextContent(type="text", text=json.dumps(result.model_dump(), indent=2))]

except Exception as e:
raise ValueError(f"Error processing mcp-server-time query: {str(e)}")
Expand Down
40 changes: 1 addition & 39 deletions src/time/test/time_server_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from freezegun import freeze_time
import pytest

from mcp_server_time.server import TimeServer
from mcp_server_time.server import TimeServer, serve


@pytest.mark.parametrize(
Expand Down Expand Up @@ -455,41 +455,3 @@ def test_convert_time(test_time, source_tz, time_str, target_tz, expected):
assert result.source.is_dst == expected["source"]["is_dst"]
assert result.target.is_dst == expected["target"]["is_dst"]
assert result.time_difference == expected["time_difference"]


# @pytest.mark.anyio
# async def test_call_tool(mock_forecast_response):
# class Response():
# def raise_for_status(self):
# pass

# def json(self):
# return mock_forecast_response

# class AsyncClient():
# def __aenter__(self):
# return self

# async def __aexit__(self, *exc_info):
# pass

# async def get(self, *args, **kwargs):
# return Response()

# with patch('httpx.AsyncClient', new=AsyncClient) as mock_client:
# result = await call_tool("get_forecast", {"city": "London", "days": 2})

# assert len(result) == 1
# assert result[0].type == "text"
# forecast_data = json.loads(result[0].text)
# assert len(forecast_data) == 1
# assert forecast_data[0]["temperature"] == 18.5
# assert forecast_data[0]["conditions"] == "sunny"


# @pytest.mark.anyio
# async def test_list_tools():
# tools = await list_tools()
# assert len(tools) == 1
# assert tools[0].name == "get_forecast"
# assert "city" in tools[0].inputSchema["properties"]
29 changes: 1 addition & 28 deletions src/time/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d37ce3c

Please sign in to comment.