This MCP (Model Context Protocol) server provides external access to MyTaskly's functionality through HTTP requests to the FastAPI backend, instead of direct database queries.
MyTaskly-mcp/
├── src/
│ ├── core/ # Core MCP server
│ │ ├── __init__.py
│ │ └── server.py # FastMCP instance & tool registration
│ │
│ ├── client/ # HTTP client layer
│ │ ├── __init__.py
│ │ ├── base.py # Base HTTP client with auth
│ │ ├── categories.py # Category API endpoints
│ │ ├── tasks.py # Task API endpoints
│ │ ├── notes.py # Note API endpoints
│ │ └── health.py # Health check endpoint
│ │
│ ├── tools/ # MCP tools (business logic)
│ │ ├── __init__.py
│ │ ├── categories.py # Category tools (4 methods)
│ │ ├── tasks.py # Task tools (8 methods)
│ │ ├── notes.py # Note tools (4 methods)
│ │ ├── meta.py # Meta tools (3 methods)
│ │ └── health.py # Health check tool (1 method)
│ │
│ ├── formatters/ # Response formatters
│ │ ├── __init__.py
│ │ └── tasks.py # Task formatting for React Native UI
│ │
│ ├── auth.py # JWT authentication
│ ├── config.py # Configuration settings
│ └── http_server.py # Optional HTTP server wrapper
│
├── tests/ # Test suite
├── run_server.py # Main entry point
├── pyproject.toml # Project configuration
└── requirements.txt # Python dependencies
Purpose: Handle HTTP communication with FastAPI server
Responsibilities:
- JWT token generation for user authentication
- HTTP request execution (GET, POST, PUT, DELETE)
- Error handling for network issues
- Response parsing
Example:
# src/client/tasks.py
class TaskClient(BaseClient):
async def get_tasks(self, user_id, filters...):
token = await self._get_user_token(user_id)
return await self._get("/tasks/", token, params=filters)Purpose: MCP tool definitions with business logic
Responsibilities:
- JWT authentication verification (from MCP client)
- Input validation
- Calling appropriate client methods
- Response formatting
- Error handling and user-friendly messages
Example:
# src/tools/tasks.py
async def get_tasks(authorization: str, filters...) -> Dict[str, Any]:
"""Get tasks with authentication and formatting."""
user_id = verify_jwt_token(authorization) # Auth
tasks = await task_client.get_tasks(user_id, filters) # HTTP call
return format_tasks_for_ui(tasks) # FormattingPurpose: Transform API responses for specific UI frameworks
Responsibilities:
- Format dates for Italian locale
- Add color codes for priorities/categories
- Calculate summary statistics
- Generate voice-friendly summaries for TTS
- Create UI hints for mobile rendering
Example:
# src/formatters/tasks.py
def format_tasks_for_ui(tasks):
return {
"type": "task_list",
"tasks": [format_task(t) for t in tasks],
"summary": calculate_stats(tasks),
"voice_summary": generate_voice_summary(tasks),
"ui_hints": {...}
}Purpose: MCP server instance and tool registration
Responsibilities:
- Create FastMCP server instance
- Register all tools from tools/ modules
- Server configuration
- get_my_categories - Get all user categories
- create_category - Create new category
- update_category - Update category by ID
- search_categories - Search categories with fuzzy matching
- get_tasks - Get tasks with filters (formatted for React Native)
- update_task - Update task fields
- complete_task - Quick shortcut to mark as completed
- get_task_stats - Get statistics (total, completed, by priority, etc.)
- get_next_due_task - Get N upcoming tasks
- get_overdue_tasks - Get all overdue tasks
- get_upcoming_tasks - Get tasks due in next N days
- add_task - Create new task with smart category handling
- get_notes - Get all user notes
- create_note - Create new note (post-it style)
- update_note - Update note text/position/color
- delete_note - Delete a note
- get_or_create_category - Smart category finder/creator with fuzzy matching
- move_all_tasks_between_categories - Bulk move tasks
- add_multiple_tasks - Bulk create tasks
- health_check - Check server health (no auth required)
1. User authenticates with frontend → receives MCP JWT token
2. Frontend calls MCP tool with: authorization="Bearer <mcp_jwt_token>"
3. MCP tool verifies MCP token → extracts user_id
4. MCP client generates FastAPI JWT token for user_id
5. MCP client calls FastAPI endpoint with FastAPI token
6. FastAPI validates token → executes operation → returns data
7. MCP tool formats response → returns to frontend
Two JWT Tokens:
- MCP Token: Authenticates MCP client (issued by frontend)
- FastAPI Token: Authenticates with backend (generated by MCP client)
# src/client/tasks.py
async def new_operation(self, user_id: int, params...) -> Dict[str, Any]:
"""Call new FastAPI endpoint."""
token = await self._get_user_token(user_id)
return await self._post("/new-endpoint", token, json={...})# src/tools/tasks.py
async def new_tool(authorization: str, params...) -> Dict[str, Any]:
"""Tool documentation here."""
user_id = verify_jwt_token(authorization)
result = await task_client.new_operation(user_id, params)
return format_response(result)# src/core/server.py
from src.tools.tasks import new_tool
mcp.tool()(new_tool)Add the new tool to the list in print_banner().
Environment Variables (.env):
FASTAPI_BASE_URL=http://localhost:8080
FASTAPI_API_KEY=your_api_key_here
JWT_SECRET_KEY=your_mcp_jwt_secret
MCP_AUDIENCE=mytaskly-mcp
MCP_SERVER_NAME=MyTaskly-MCP
MCP_SERVER_VERSION=2.0.0
LOG_LEVEL=INFO# Install dependencies
pip install -r requirements.txt
# Run MCP server (stdio mode)
python run_server.py
# Test with MCP client
# Configure your MCP client to connect to this server# Run all tests
pytest tests/ -v
# Run specific test module
pytest tests/test_auth.py -v
# Run with coverage
pytest tests/ --cov=src --cov-report=html- Each module is small (~200-300 lines max)
- Easy to add new features without touching existing code
- Clear separation of concerns
- Changes to HTTP client don't affect tool logic
- Changes to formatting don't affect HTTP calls
- Each layer can be tested independently
- Mock HTTP responses to test tools
- Mock client to test formatters
- Unit test each component in isolation
- Clear file organization by domain (categories, tasks, notes)
- Each file has a single responsibility
- Easy to find and understand code
Old: All logic in src/server.py (240 lines) and src/client.py (170 lines)
New:
src/client/- 5 files (base + 4 domains)src/tools/- 5 files (4 domains + health)src/formatters/- 1 filesrc/core/- 1 file (server registration)
Total: Much more organized, maintainable, and scalable!