feat(mcp): add MCP server with availability tool

master
oabrivard 6 days ago
parent bb5ce5e71a
commit 1b23493167

@ -129,6 +129,20 @@ curl -X POST "http://127.0.0.1:8000/a2a/rpc" \
}'
```
### MCP server (availability tool)
Run MCP on a dedicated port:
```bash
uv run uvicorn app.mcp_main:app --host 0.0.0.0 --port 8001
```
MCP streamable HTTP endpoint:
```text
http://127.0.0.1:8001/mcp
```
### Manual unsubscribe digest
```bash

@ -0,0 +1,3 @@
from app.mcp.server import mcp
__all__ = ["mcp"]

@ -0,0 +1,19 @@
from __future__ import annotations
from mcp.server.fastmcp import FastMCP
from app.mcp.tools import check_availability as check_availability_impl
mcp = FastMCP(
"Personal Agent MCP",
streamable_http_path="/",
)
@mcp.tool(description="Check Google Calendar availability for a time range.")
def check_availability(
start: str,
end: str,
calendar_ids: list[str] | None = None,
) -> dict[str, object]:
return check_availability_impl(start=start, end=end, calendar_ids=calendar_ids)

@ -0,0 +1,31 @@
from __future__ import annotations
import logging
from typing import Any
from app.config import get_settings
from app.core.service import CoreAgentService
settings = get_settings()
core_service = CoreAgentService(settings=settings, logger=logging.getLogger("personal-agent.mcp"))
def check_availability(
start: str, end: str, calendar_ids: list[str] | None = None
) -> dict[str, Any]:
"""Return free/busy availability for a time range on one or more calendars."""
result = core_service.check_availability(start=start, end=end, calendar_ids=calendar_ids)
return {
"start": result.start,
"end": result.end,
"available": result.available,
"busy_slots": [
{
"calendar_id": slot.calendar_id,
"start": slot.start,
"end": slot.end,
}
for slot in result.busy_slots
],
"checked_calendars": result.checked_calendars,
}

@ -0,0 +1,22 @@
from __future__ import annotations
from contextlib import asynccontextmanager
from starlette.applications import Starlette
from starlette.routing import Mount
from app.mcp import mcp
@asynccontextmanager
async def lifespan(_: Starlette):
async with mcp.session_manager.run():
yield
app = Starlette(
routes=[
Mount("/mcp", app=mcp.streamable_http_app()),
],
lifespan=lifespan,
)

@ -6,6 +6,7 @@ requires-python = ">=3.11"
dependencies = [
"apscheduler",
"fastapi",
"mcp",
"google-api-python-client",
"google-auth",
"google-auth-oauthlib",

@ -813,6 +813,7 @@ dependencies = [
{ name = "google-api-python-client" },
{ name = "google-auth" },
{ name = "google-auth-oauthlib" },
{ name = "mcp" },
{ name = "python-dotenv" },
{ name = "strands-agents", extra = ["openai"] },
{ name = "uvicorn", extra = ["standard"] },
@ -825,6 +826,7 @@ requires-dist = [
{ name = "google-api-python-client" },
{ name = "google-auth" },
{ name = "google-auth-oauthlib" },
{ name = "mcp" },
{ name = "python-dotenv" },
{ name = "strands-agents", extras = ["openai"] },
{ name = "uvicorn", extras = ["standard"] },

Loading…
Cancel
Save