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
9 changes: 8 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,12 @@ __pycache__
*.pyc
*.log
venv/
.venv/
.env
tests/
.env.*
tests/
.pytest_cache/
.coverage
.coverage.*
htmlcov/
.mypy_cache/
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Server
fastapi==0.122.0
fastapi==0.141.1
uvicorn==0.38.0
# Environment
python-dotenv==1.2.1
pydantic_settings==2.12.0
python-dotenv==1.2.3
pydantic_settings==2.15.0
truststore==0.10.4
# Crawlers
httpx[http2]==0.28.1
beautifulsoup4==4.14.2
xmltodict==1.0.2
pandas==2.3.3
lxml==6.0.2
lxml==6.1.2
# Search
jieba==0.42.1
python-Levenshtein==0.27.3
thefuzz==0.22.1
# MCP
fastmcp==2.13.1
fastmcp==3.2.0
5 changes: 0 additions & 5 deletions src/data_api/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
Settings are loaded from environment variables and .env file.
"""

import os

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict

Expand Down Expand Up @@ -40,8 +38,5 @@ class Settings(BaseSettings):
)


# FastMCP 要開啟實驗性功能(但之後會變正式版本),不然 openapi.json 解析會有問題
os.environ["FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER"] = "true"

# Global settings instance
settings = Settings()
33 changes: 33 additions & 0 deletions tests/test_mcp_tools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
"""Tests for MCP tools."""

import json

from httpx import ASGITransport, AsyncClient

from data_api.api.api import app
from data_api.mcp.tools.announcements import _get_announcements
from data_api.mcp.tools.buses import _get_bus_stops, _get_next_buses
from data_api.mcp.tools.campus import _search_campus
Expand All @@ -13,6 +18,34 @@
class TestMCPTools:
"""Tests for MCP tools functionality."""

async def test_mcp_http_initialize(self):
"""Test the mounted MCP endpoint accepts an initialize request."""
request = {
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": {"name": "test-client", "version": "1.0"},
},
}

async with app.router.lifespan_context(app):
async with AsyncClient(
transport=ASGITransport(app=app), base_url="http://test"
) as client:
response = await client.post(
"/mcp",
headers={"Accept": "application/json, text/event-stream"},
json=request,
)

assert response.status_code == 200
assert response.headers["content-type"].startswith("text/event-stream")
payload = json.loads(response.text.split("data: ", maxsplit=1)[1])
assert payload["result"]["serverInfo"]["name"] == "NTHU Campus Assistant"

async def test_search_campus(self):
"""Test campus search tool."""
result = await _search_campus(query="教務處")
Expand Down