All Articles
Technical 5 min read

Implementation Prompt for AI

Task: Build an MCP task manager with agentic patterns

Core Requirements:

  • MCP server using Python mcp library
  • SQLite database with projects and tasks tables
  • Four main tools: create_project, create_task, analyze_tasks, get_task_graph
  • Tasks support: title, description, project_id, priority (low/medium/high/urgent), status (pending/in_progress/completed), dependencies (list of task IDs)

Key Implementation Details:

  1. Database Schema:
projects: id, name, description, created_at
tasks: id, title, description, project_id, priority, status, depends_on (JSON array), created_at
  1. Agentic Tool - create_task:
  • Parameters: title, description, project_id (optional), priority (default “medium”), depends_on (list)
  • Store dependencies as JSON string
  • Return task_id on success
  1. Agentic Tool - analyze_tasks:
  • Takes list of task descriptions
  • Groups by common keywords (length > 4)
  • Suggests projects when 2+ tasks share keywords
  • Returns JSON with suggested_projects, task_relationships, priority_recommendations
  1. Priority Inference Logic:
  • “urgent”/“asap”/“critical” → urgent priority
  • “important”/“security”/“bug” → high priority
  • “later”/“eventually” → low priority
  • Default → medium priority
  1. MCP Server Setup:
  • Use Server("task-manager") from mcp.server
  • Decorate tools with @app.tool()
  • Run with app.run_stdio()
  1. Claude Desktop Integration: Add to config JSON:
{
  "mcpServers": {
    "task-manager": {
      "command": "python",
      "args": ["/path/to/run_server.py"]
    }
  }
}

Expected Agent Behavior: When user says “Build API, write tests, deploy”, agent should:

  1. Create project if tasks are related
  2. Create tasks with dependencies (tests depend on API, deploy depends on tests)
  3. Set appropriate priorities based on context
  4. Return structured task graph

Use this specification to implement the complete system.

The Model Context Protocol (MCP) is revolutionizing how we build AI-powered tools by providing a standardized way for LLMs to interact with external systems. In this guide, we’ll build a sophisticated task management system that uses agentic patterns to automatically organize, prioritize, and manage tasks intelligently.

What is MCP?

Model Context Protocol is an open protocol that enables seamless integration between LLM applications and external data sources. Instead of building custom integrations for every tool, MCP provides a universal interface that any LLM can use to access your tools and data.

Why MCP Matters

MCP servers act as bridges between AI assistants (like Claude) and your applications. They expose tools, resources, and prompts that LLMs can discover and use automatically.

Architecture Overview

Our task manager will implement the following agentic pattern:

# High-level architecture
Task Input → Agent Analysis → Project Assignment → Task Creation → Dependency Resolution

Key Components

  1. MCP Server: Exposes task management tools to the LLM
  2. Agent Layer: Analyzes tasks and determines optimal project structure
  3. Task Engine: Manages task lifecycle and dependencies
  4. Storage Layer: Persists tasks and projects

Setting Up the MCP Server

First, let’s install the required dependencies:

pip install mcp anthropic-sdk pydantic sqlite-utils
Development Environment

Use a virtual environment to isolate dependencies. I recommend uv for fast Python package management.

Creating the Server Foundation

# task_manager_mcp.py
from mcp.server import Server
from mcp.types import Tool, TextContent
from pydantic import BaseModel
from typing import List, Optional
import sqlite3
import json
from datetime import datetime

# Data models
class Task(BaseModel):
    id: Optional[int] = None
    title: str
    description: str
    project_id: Optional[int] = None
    priority: str = "medium"  # low, medium, high, urgent
    status: str = "pending"   # pending, in_progress, completed
    depends_on: List[int] = []
    created_at: Optional[str] = None

class Project(BaseModel):
    id: Optional[int] = None
    name: str
    description: str
    created_at: Optional[str] = None

# Initialize MCP server
app = Server("task-manager")

# Database setup
def init_db():
    conn = sqlite3.connect('tasks.db')
    c = conn.cursor()

    c.execute('''CREATE TABLE IF NOT EXISTS projects
                 (id INTEGER PRIMARY KEY, name TEXT, description TEXT,
                  created_at TEXT)''')

    c.execute('''CREATE TABLE IF NOT EXISTS tasks
                 (id INTEGER PRIMARY KEY, title TEXT, description TEXT,
                  project_id INTEGER, priority TEXT, status TEXT,
                  depends_on TEXT, created_at TEXT,
                  FOREIGN KEY (project_id) REFERENCES projects (id))''')

    conn.commit()
    conn.close()

init_db()

Implementing Agentic Tools

Now let’s create the tools that enable agentic behavior:

1. Create Project Tool

@app.tool()
async def create_project(name: str, description: str) -> str:
    """
    Create a new project to organize related tasks.
    The agent uses this when detecting multiple related tasks.
    """
    conn = sqlite3.connect('tasks.db')
    c = conn.cursor()

    created_at = datetime.now().isoformat()
    c.execute(
        "INSERT INTO projects (name, description, created_at) VALUES (?, ?, ?)",
        (name, description, created_at)
    )

    project_id = c.lastrowid
    conn.commit()
    conn.close()

    return json.dumps({
        "success": True,
        "project_id": project_id,
        "message": f"Created project '{name}' with ID {project_id}"
    })

2. Create Task with Dependencies

@app.tool()
async def create_task(
    title: str,
    description: str,
    project_id: Optional[int] = None,
    priority: str = "medium",
    depends_on: List[int] = None
) -> str:
    """
    Create a new task. Supports dependency tracking.
    Agent automatically infers priority and dependencies.
    """
    conn = sqlite3.connect('tasks.db')
    c = conn.cursor()

    created_at = datetime.now().isoformat()
    depends_on_json = json.dumps(depends_on or [])

    c.execute(
        """INSERT INTO tasks
           (title, description, project_id, priority, status, depends_on, created_at)
           VALUES (?, ?, ?, ?, ?, ?, ?)""",
        (title, description, project_id, priority, "pending", depends_on_json, created_at)
    )

    task_id = c.lastrowid
    conn.commit()
    conn.close()

    return json.dumps({
        "success": True,
        "task_id": task_id,
        "message": f"Created task '{title}' with ID {task_id}"
    })

3. Intelligent Task Analysis

@app.tool()
async def analyze_tasks(task_descriptions: List[str]) -> str:
    """
    Analyze a list of task descriptions and suggest optimal structure.
    This is the core agentic function that determines project grouping.
    """
    # This tool returns analysis that helps the LLM organize tasks
    # In practice, you might use embeddings or classification here

    analysis = {
        "suggested_projects": [],
        "task_relationships": [],
        "priority_recommendations": []
    }

    # Simple heuristic: group by common keywords
    keywords = {}
    for idx, desc in enumerate(task_descriptions):
        words = desc.lower().split()
        for word in words:
            if len(word) > 4:  # Ignore short words
                if word not in keywords:
                    keywords[word] = []
                keywords[word].append(idx)

    # Find common themes
    for keyword, task_indices in keywords.items():
        if len(task_indices) >= 2:
            analysis["suggested_projects"].append({
                "theme": keyword.capitalize(),
                "tasks": task_indices,
                "reasoning": f"Tasks {task_indices} share the theme '{keyword}'"
            })

    return json.dumps(analysis, indent=2)
Production Considerations

In production, use proper embeddings (OpenAI, Cohere) or a classification model for better task grouping. This example uses simple keyword matching for demonstration.

4. Get Task Dependencies

@app.tool()
async def get_task_graph(project_id: Optional[int] = None) -> str:
    """
    Get task dependency graph for visualization and planning.
    Helps identify blockers and critical path.
    """
    conn = sqlite3.connect('tasks.db')
    c = conn.cursor()

    if project_id:
        c.execute("SELECT * FROM tasks WHERE project_id = ?", (project_id,))
    else:
        c.execute("SELECT * FROM tasks")

    tasks = c.fetchall()
    conn.close()

    graph = {
        "nodes": [],
        "edges": []
    }

    for task in tasks:
        task_id, title, desc, proj_id, priority, status, deps, created = task
        graph["nodes"].append({
            "id": task_id,
            "title": title,
            "priority": priority,
            "status": status
        })

        # Parse dependencies
        if deps:
            depends_on = json.loads(deps)
            for dep_id in depends_on:
                graph["edges"].append({
                    "from": dep_id,
                    "to": task_id
                })

    return json.dumps(graph, indent=2)

Running the Server

Create a runner script:

# run_server.py
import asyncio
from task_manager_mcp import app

async def main():
    async with app.run_stdio():
        await app.serve()

if __name__ == "__main__":
    asyncio.run(main())

Start the server:

python run_server.py

Using with Claude Desktop

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "task-manager": {
      "command": "python",
      "args": ["/path/to/run_server.py"]
    }
  }
}

Agentic Usage Examples

Now you can interact with Claude naturally:

Example 1: Simple Task Creation

You: I need to build a new API, write tests, and deploy it

Claude: I'll help organize this. Let me create a project and tasks with dependencies...
[Creates "API Development" project]
[Creates tasks: 1. Build API, 2. Write tests (depends on 1), 3. Deploy (depends on 2)]

Example 2: Complex Project

You: Create tasks for:
- Research user authentication methods
- Implement OAuth2 flow
- Add rate limiting
- Write API documentation
- Set up monitoring
- Create user dashboard

Claude: I've analyzed these tasks and identified two distinct projects...
[Creates "Backend Infrastructure" project for auth, rate limiting, monitoring]
[Creates "Frontend Development" project for dashboard]
[Automatically sets dependencies and priorities]

Advanced: Smart Priority Detection

Enhance the agent with priority inference:

@app.tool()
async def infer_priority(title: str, description: str, context: str) -> str:
    """
    Use LLM to infer task priority based on context and keywords.
    """
    # Keywords that indicate urgency
    urgent_keywords = ["urgent", "asap", "critical", "immediately", "hotfix"]
    high_keywords = ["important", "soon", "security", "bug", "broken"]

    text = f"{title} {description} {context}".lower()

    if any(kw in text for kw in urgent_keywords):
        return "urgent"
    elif any(kw in text for kw in high_keywords):
        return "high"
    elif "later" in text or "eventually" in text:
        return "low"
    else:
        return "medium"

Testing the System

Create a test suite:

# test_task_manager.py
import pytest
import asyncio
from task_manager_mcp import create_project, create_task, analyze_tasks

@pytest.mark.asyncio
async def test_create_project():
    result = await create_project("Test Project", "A test project")
    data = json.loads(result)
    assert data["success"] is True
    assert "project_id" in data

@pytest.mark.asyncio
async def test_task_dependencies():
    # Create project
    proj = await create_project("Dev", "Development tasks")
    proj_data = json.loads(proj)
    proj_id = proj_data["project_id"]

    # Create tasks with dependencies
    task1 = await create_task("Setup", "Setup environment", proj_id)
    task1_id = json.loads(task1)["task_id"]

    task2 = await create_task(
        "Build",
        "Build feature",
        proj_id,
        depends_on=[task1_id]
    )

    # Verify dependency
    task2_data = json.loads(task2)
    assert task2_data["success"] is True

Production Deployment

For production use:

Deployment Checklist
  1. Add authentication and rate limiting
  2. Use PostgreSQL instead of SQLite
  3. Implement proper error handling and logging
  4. Add webhooks for task status changes
  5. Create backup and recovery procedures
  6. Set up monitoring and alerting

Docker Deployment

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "run_server.py"]

Conclusion

You’ve now built a fully functional MCP task manager with agentic capabilities! The agent can:

  • ✅ Automatically group related tasks into projects
  • ✅ Infer task priorities from context
  • ✅ Manage complex dependency graphs
  • ✅ Provide intelligent task analysis

This foundation can be extended with features like:

  • Time tracking and estimates
  • Team member assignment
  • Recurring tasks
  • Integration with calendars and notification systems
  • Advanced AI analysis using RAG or fine-tuned models

References

  1. Model Context Protocol Documentation Official MCP specification and implementation guide
  2. Anthropic MCP Python SDK Python SDK for building MCP servers
  3. Building Agentic Systems - Anthropic Best practices for designing agentic AI workflows
  4. Claude Desktop MCP Configuration How to integrate MCP servers with Claude Desktop
  5. SQLite JSON Functions SQLite documentation for handling JSON data types
HT

Written by Hisham Tariq

Backend Engineer & AI Researcher passionate about building secure, intelligent systems at the intersection of cybersecurity and artificial intelligence. Specializing in Python, FastAPI, and machine learning.