MyTaskly MCP Server
Model Context Protocol (MCP) server for MyTaskly with OAuth 2.1 JWT authentication and seamless integration with the FastAPI backend.
📋 Key Features
🔐 Enterprise-Grade Authentication
- OAuth 2.1 JWT - Token-based authentication following MCP 2025 standards (RFC 8707)
- SSE Transport - Server-Sent Events for HTTP-based deployment (Railway-ready)
- Context-Based Auth - Token extracted automatically from SSE request headers
🚀 High-Performance Integration
- HTTP API Gateway - Communicates with FastAPI backend, no direct database access
- Stateless Architecture - No session management, fully scalable
- Connection Pooling - Optimized async HTTP client (httpx)
📱 Mobile-First Design
- React Native Optimized -
show_*tools return data formatted for native mobile components - Voice-Friendly Responses - Includes
voice_summaryfor TTS in chat applications - Dual-Mode Tools -
get_*for internal data processing,show_*to trigger UI updates
🛠️ Available MCP Tools (18 Active)
The MCP server provides 18 active tools organized into 3 categories. All tools require JWT authentication via SSE Authorization header.
Tools follow a dual pattern:
get_*returns raw data for model reasoning,show_*triggers UI rendering in the mobile app.
📋 Task Tools (8)
| Tool | Description |
|---|---|
get_tasks |
Get tasks with filters — for internal model use (raw data) |
add_task |
Create a new task with smart category lookup |
update_task |
Update one or more fields of an existing task |
complete_task |
Quick shortcut to mark a task as completed |
get_task_stats |
Get aggregate statistics by status, priority, and category |
get_overdue_tasks |
Get all overdue pending tasks |
get_upcoming_tasks |
Get tasks due in the next N days |
show_tasks_to_user |
Display task list in the mobile app UI |
Example Response — get_tasks:
{
"tasks": [
{
"task_id": 123,
"title": "Pizza",
"description": "Ordinare pizza margherita",
"end_time": "2025-12-15T18:00:00",
"start_time": null,
"priority": "Alta",
"status": "In sospeso",
"category_id": 5,
"duration_minutes": 30
}
],
"total": 10
}
Example Response — add_task (success):
{
"success": true,
"task_id": 124,
"category_used": "Cibo"
}
Example Response — add_task (category not found):
{
"success": false,
"message": "Categoria 'Cibo' non trovata.",
"category_suggestions": ["Alimentari", "Cucina"],
"action_required": "ask_user_to_create_category"
}
Example Response — get_task_stats:
{
"success": true,
"by_status": {
"In sospeso": 5,
"Completato": 3,
"Annullato": 1
},
"by_priority": {
"Alta": 2,
"Media": 4,
"Bassa": 3
},
"by_category": { "5": 4, "3": 2 },
"total": 9
}
Example Response — get_overdue_tasks:
{
"tasks": [
{
"task_id": 10,
"title": "Consegnare report",
"priority": "Alta",
"status": "In sospeso",
"end_time": "2025-12-01T09:00:00",
"days_overdue": 14
}
],
"total": 1
}
Example Response — show_tasks_to_user:
{
"type": "task_list",
"success": true,
"filters_applied": {
"priority": "Alta",
"status": "In sospeso"
}
}
📂 Category Tools (5)
| Tool | Description |
|---|---|
get_my_categories |
Get all user categories — for internal model use (raw data) |
create_category |
Create a new category |
update_category |
Update name or description of an existing category |
show_categories_to_user |
Display category list in the mobile app UI |
show_category_details |
Display details of a single category in the mobile app UI |
Example Response — get_my_categories:
{
"categories": [
{
"category_id": 1,
"name": "Lavoro",
"description": "Task di lavoro"
},
{
"category_id": 2,
"name": "Casa",
"description": "Faccende domestiche"
}
],
"total": 2
}
Example Response — create_category:
{
"success": true,
"type": "category_created",
"category_id": 3
}
Example Response — show_categories_to_user:
{
"type": "category_list",
"success": true
}
📝 Note Tools (5)
| Tool | Description |
|---|---|
get_notes |
Get all user notes — for internal model use (raw data) |
create_note |
Create a new post-it style note |
update_note |
Update text, position, or color of a note |
delete_note |
Delete a note (irreversible) |
show_notes_to_user |
Display note board in the mobile app UI |
Available note colors: #FFEB3B (yellow), #FF9800 (orange), #4CAF50 (green), #2196F3 (blue), #E91E63 (pink), #9C27B0 (purple)
Example Response — get_notes:
{
"notes": [
{
"note_id": 456,
"title": "Comprare il latte",
"color": "#FFEB3B",
"position_x": "100",
"position_y": "250",
"created_at": "2025-01-15T10:30:00Z"
}
],
"total": 3
}
Example Response — create_note:
{
"success": true,
"type": "note_created",
"note_id": 456
}
Example Response — show_notes_to_user:
{
"type": "note_list",
"success": true
}
⚕️ Inactive Tools (2 — commented out)
| Tool | Description |
|---|---|
add_multiple_tasks |
Bulk create multiple tasks at once |
health_check |
Check server health and connectivity (no auth required) |
These tools are defined in src/tools/ but not registered. Uncomment in src/core/server.py to enable.
🚀 Getting Started
Usage Options
You have two ways to use the MyTaskly MCP Server:
Option 1: Use Official Public Server (Recommended)
Use the official MyTaskly MCP server (coming soon) - no setup required!
# Configure your MCP client to connect to:
# https://mcp.mytasklyapp.com (URL will be published soon)
Benefits:
- ✅ No installation or configuration needed
- ✅ Always up-to-date with latest features
- ✅ Managed and monitored by MyTaskly team
- ✅ Works out-of-the-box with MyTaskly mobile app
Option 2: Self-Host (Advanced Users)
Run your own local MCP server instance.
Prerequisites:
- Python 3.11+ (virtual environment recommended)
- MyTaskly FastAPI Server running locally (see MyTaskly-server)
- JWT Secret Key matching your FastAPI server configuration
Quick Start (5 minutes):
git clone https://github.com/Gabry848/MyTaskly-mcp.git
cd MyTaskly-mcp
python -m venv venv && pip install -r requirements.txt
cp .env.example .env && python main.py
Self-Hosting Setup Guide
1. Clone & Install
# Clone the repository
git clone https://github.com/Gabry848/MyTaskly-mcp.git
cd MyTaskly-mcp
# Create virtual environment
python -m venv venv
# Activate virtual environment
# Windows:
venv\Scripts\activate
# Linux/Mac:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
2. Configure Environment Variables
Create .env file in the root directory:
# ============ FASTAPI BACKEND ============
FASTAPI_BASE_URL=http://localhost:8080
FASTAPI_API_KEY=your_api_key_here
# ============ JWT CONFIGURATION ============
# CRITICAL: Must match FastAPI server configuration!
JWT_SECRET_KEY=your_jwt_secret_key_here
JWT_ALGORITHM=HS256
MCP_AUDIENCE=mcp://mytaskly-mcp-server
# ============ SERVER CONFIGURATION ============
MCP_SERVER_NAME=MyTaskly MCP Server
MCP_SERVER_VERSION=0.1.1
LOG_LEVEL=INFO
# ============ DEPLOYMENT ============
HOST=0.0.0.0
PORT=8000
⚠️ CRITICAL: JWT_SECRET_KEY MUST match your FastAPI server's SECRET_KEY environment variable!
3. Start the MCP Server
python main.py
The server starts in SSE (Server-Sent Events) mode on http://0.0.0.0:8000. Configure your MCP client to connect to this URL.
🔐 Authentication & Security
OAuth 2.1 Flow
The MCP server uses JWT tokens following OAuth 2.1 and RFC 8707 standards. The token is extracted automatically from the SSE Authorization header — tools receive a ctx: Context parameter, not an explicit authorization string.
┌─────────────────┐
│ Mobile Client │
│ (React Native) │
└────────┬────────┘
│ 1. Login request
▼
┌─────────────────┐
│ FastAPI Server │ 2. Validates credentials
│ (Auth Server) │ 3. Generates JWT with MCP audience claim
└────────┬────────┘
│ 4. Returns JWT token
▼
┌─────────────────┐
│ Mobile Client │ 5. Stores token securely
└────────┬────────┘
│ 6. Calls MCP tools via SSE with Authorization header
▼
┌─────────────────┐
│ MCP Server │ 7. Extracts token from SSE context
│ (This project) │ 8. Validates JWT signature + audience
│ │ 9. Extracts user_id from "sub" claim
└────────┬────────┘
│ 10. Makes HTTP request to FastAPI with user_id
▼
┌─────────────────┐
│ FastAPI Server │ 11. Returns user-specific data
│ (Resource API) │
└────────┬────────┘
│ 12. Formats data for mobile UI
▼
┌─────────────────┐
│ MCP Server │ 13. Returns formatted response
└────────┬────────┘
│
▼
┌─────────────────┐
│ Mobile Client │ 14. Renders UI / plays TTS
└─────────────────┘
JWT Token Structure
The JWT must include these claims (following RFC 7519 and RFC 8707):
{
"sub": "123", // User ID (required)
"aud": "mcp://mytaskly-mcp-server", // Audience (required, RFC 8707)
"iss": "https://api.mytasklyapp.com", // Issuer (optional)
"exp": 1735689600, // Expiration timestamp (required)
"iat": 1735686000, // Issued at timestamp (required)
"scope": "tasks:read tasks:write notes:write" // Scopes (optional)
}
Security Features:
| Feature | Implementation |
|---|---|
| Signature Validation | HS256 with shared secret |
| Audience Claim | Prevents token reuse across services (RFC 8707) |
| Expiration Check | Automatic token invalidation |
| User Isolation | Each request scoped to authenticated user |
Getting a JWT Token
Option 1: From FastAPI (Production)
Add this endpoint to your FastAPI server:
@router.post("/auth/mcp-token")
async def get_mcp_token(current_user: User = Depends(get_current_user)):
"""Generate JWT token for MCP server access."""
payload = {
"sub": str(current_user.user_id),
"aud": "mcp://mytaskly-mcp-server",
"iss": "https://api.mytasklyapp.com",
"exp": datetime.utcnow() + timedelta(minutes=30),
"iat": datetime.utcnow(),
"scope": "tasks:read tasks:write categories:read notes:read notes:write"
}
token = jwt.encode(payload, settings.JWT_SECRET_KEY, algorithm="HS256")
return {"mcp_token": token, "expires_in": 1800}
Option 2: Generate Test Token (Development)
from src.auth import create_test_token
# Generate test token for user_id=1
token = create_test_token(user_id=1, expires_minutes=30)
print(f"Test Token: {token}")
🧪 Testing & Development
Generate Test Token
python -c "from src.auth import create_test_token; print(create_test_token(1))"
Manual Testing with cURL
# Export token to environment variable
export MCP_TOKEN="your_token_here"
# Test get_tasks (SSE endpoint)
curl -X POST http://localhost:8000/mcp/get_tasks \
-H "Authorization: Bearer $MCP_TOKEN" \
-H "Content-Type: application/json"
# Test add_task
curl -X POST http://localhost:8000/mcp/add_task \
-H "Authorization: Bearer $MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Comprare latte", "category_name": "Casa", "priority": "Bassa"}'
Automated Test Suite
# Run all unit tests
python -m pytest tests/ -v
# Run specific test file
python -m pytest tests/test_auth.py -v
# Run with coverage report
python -m pytest tests/ --cov=src --cov-report=html
🔒 Security Best Practices
- Always use HTTPS in production
- Keep JWT_SECRET_KEY secure - never commit to git
- Use short-lived tokens (15-30 minutes)
- Implement token refresh in your client
- Validate audience claim (RFC 8707) - prevents token reuse
- Log authentication failures for monitoring
🏗️ Architecture & Project Structure
System Architecture
┌─────────────────────────────────────────────────────────────┐
│ MyTaskly Ecosystem │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ Mobile Client │ 1. User authentication │
│ │ (React Native) │ 2. Receives JWT token │
│ └────────┬────────┘ 3. Calls MCP tools via SSE │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ MCP Server │ 4. Validates JWT (OAuth 2.1) │
│ │ (This project) │ 5. Extracts user_id from token │
│ └────────┬────────┘ 6. Formats data for mobile UI │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ FastAPI Server │ 7. Handles business logic │
│ │ (MyTaskly-API) │ 8. Manages database operations │
│ └────────┬────────┘ 9. Returns raw data │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ PostgreSQL │ 10. Persistent storage │
│ │ Database │ 11. Triggers & notifications │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Project Structure
MyTaskly-mcp/
├── src/
│ ├── core/ # Core MCP server
│ │ ├── __init__.py
│ │ └── server.py # FastMCP instance, log_tool decorator & tool registration
│ │
│ ├── client/ # HTTP client layer
│ │ ├── __init__.py
│ │ ├── base.py # BaseClient with async HTTP methods + JWT token generation
│ │ ├── categories.py # CategoryClient
│ │ ├── tasks.py # TaskClient (with status/priority normalization)
│ │ ├── notes.py # NoteClient
│ │ └── health.py # HealthClient
│ │
│ ├── tools/ # MCP tool definitions
│ │ ├── __init__.py
│ │ ├── categories.py # 5 category tools
│ │ ├── tasks.py # 8 task tools
│ │ ├── notes.py # 5 note tools
│ │ ├── meta.py # add_multiple_tasks (inactive)
│ │ └── health.py # health_check (inactive)
│ │
│ ├── formatters/ # Response formatters for React Native
│ │ ├── __init__.py
│ │ └── tasks.py # format_tasks_for_ui, format_categories_for_ui, format_notes_for_ui
│ │
│ ├── auth.py # JWT authentication (extract, verify, create_test_token)
│ ├── config.py # Pydantic settings (loaded from .env)
│ └── http_server.py # HTTP server wrapper
│
├── tests/ # Test suite
├── main.py # Entry point — runs FastMCP in SSE mode
├── pyproject.toml # Project configuration
├── requirements.txt # Python dependencies
├── ARCHITECTURE.md # Detailed architecture documentation
└── README.md # This file
Layer Architecture
| Layer | Files | Responsibility |
|---|---|---|
| Core Layer | src/core/ |
FastMCP instance, log_tool decorator, tool registration |
| Tools Layer | src/tools/ |
MCP tool definitions — auth, business logic, response shaping |
| Client Layer | src/client/ |
Async HTTP communication with FastAPI backend |
| Formatters Layer | src/formatters/ |
Transform API responses into React Native-ready structures |
Key Components
| Component | Technology | Purpose |
|---|---|---|
| MCP Server | FastMCP + SSE | Request handling, tool orchestration, Railway deployment |
| JWT Authentication | PyJWT (HS256) | Token validation via SSE context headers |
| HTTP Client | httpx (async) | FastAPI backend communication |
| Data Formatters | Custom formatters | Mobile-optimized response structure with voice summaries |
📚 For detailed architecture information, see ARCHITECTURE.md
🛠️ Development Guide
Adding New MCP Tools
Follow the layered architecture pattern:
1. Add HTTP Client Method
# 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={...})
2. Add MCP Tool
# src/tools/tasks.py
from fastmcp import Context
from src.auth import authenticate_from_context
async def new_tool(ctx: Context, params...) -> Dict[str, Any]:
"""Tool documentation here."""
user_id = await authenticate_from_context(ctx)
result = await task_client.new_operation(user_id, params)
return format_response(result)
3. Register Tool
# src/core/server.py
from src.tools.tasks import new_tool
mcp.tool()(log_tool(new_tool))
For more details, see ARCHITECTURE.md
Code Quality
# Format code with Black
black src/ tests/
# Lint with Ruff
ruff check src/ tests/
# Type checking with mypy
mypy src/
# Run tests with coverage
pytest tests/ --cov=src --cov-report=html
Common Development Tasks
| Task | Command |
|---|---|
| Run server | python main.py |
| Generate test token | python -c "from src.auth import create_test_token; print(create_test_token(1))" |
| Run tests | pytest tests/ -v |
| Check coverage | pytest tests/ --cov=src |
| Format code | black src/ tests/ |
| Install dependencies | pip install -r requirements.txt |
📚 Resources & Related Projects
MyTaskly Ecosystem
- MyTaskly Mobile App - React Native frontend
- MyTaskly Server - FastAPI backend
- MyTaskly MCP (this project) - Model Context Protocol server
Documentation
- Model Context Protocol Specification
- RFC 8707 - Resource Indicators for OAuth 2.0
- RFC 7519 - JSON Web Token (JWT)
- FastAPI Official Docs
🤝 Contributing
We welcome contributions! This project is part of the MyTaskly ecosystem.
How to Contribute
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes with clear commit messages
- Add tests for new functionality
- Ensure tests pass:
pytest tests/ -v - Format code:
black src/ tests/ - Submit a pull request
Development Workflow
# 1. Clone your fork
git clone https://github.com/YOUR_USERNAME/MyTaskly-mcp.git
cd MyTaskly-mcp
# 2. Create feature branch
git checkout -b feature/my-feature
# 3. Make changes and test
pytest tests/ -v
# 4. Commit with descriptive message
git commit -m "feat: add new MCP tool for task statistics"
# 5. Push and create PR
git push origin feature/my-feature
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
The MIT License allows you to:
- ✅ Use commercially
- ✅ Modify
- ✅ Distribute
- ✅ Private use
📞 Support & Feedback
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: [email protected]
Made with ❤️ by Gabry848 as part of the MyTaskly project
Starring is appreciated! ⭐
No comments yet
Be the first to share your take.