#
tokens: 2931/50000 5/5 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── coding_todo.py
├── minimal_server.py
├── README.md
└── requirements.txt
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so
*.dylib

# Distribution / packaging
.Python
env/
venv/
.venv
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written into a _MEIPASS folder, but if PyInstaller
#  creates a self-extracting executable, it will use a temp folder instead.
_MEIPASS/
_MEI*/

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mypy
.mypy_cache/
.dmypy.json
dmypy.sock

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# General ignores
tmp/
temp/
*.tmp
*.log
*.DS_Store

# MCP directory
mcp/

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Coding Todo Server

This MCP server provides tools and resources for managing a coding project's todo list.

## Overview

This server allows you to:

- View the current todo list
- View details of specific todo items
- Add new todo items
- Update the status of todo items
- Delete todo items
- Update todo item details

## Resources

- `todo://list`:  Provides a list of all todo items with their status, title, priority and tags.
- `todo://item/{todo_id}`: Provides detailed information about a specific todo item, including status, priority, creation date, project, tags, and description.

## Tools

- `add_todo`: Adds a new todo item to the list.
    - Arguments:
        - `title`: Title of the todo item (required)
        - `description`: Detailed description of the todo item (required)
        - `project`: Project name (optional)
        - `priority`: Priority from 1 (lowest) to 5 (highest) (optional, default: 1)
        - `tags`: List of tags related to the todo (optional)

- `update_todo_status`: Updates the status of an existing todo item.
    - Arguments:
        - `id`: The ID of the todo item to update (required)
        - `status`: New status (pending/in_progress/completed) (required)

- `delete_todo`: Deletes a todo item from the list.
    - Arguments:
        - `id`: The ID of the todo item to delete (required)

- `update_todo`: Updates the details of an existing todo item.
    - Arguments:
        - `id`: The ID of the todo item to update (required)
        - `title`: New title (optional)
        - `description`: New description (optional)
        - `project`: New project name (optional)
        - `priority`: New priority from 1 (lowest) to 5 (highest) (optional)
        - `tags`: New list of tags (optional)

## Installation

Before running the server, you need to install the required Python packages. You can do this using pip:

```bash
pip install -r requirements.txt
```

## Usage

To run the server, execute the `coding_todo.py` script.

```bash
python coding_todo.py
```

This will start the MCP server, making its tools and resources available to MCP clients.

```

--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------

```
mcp-sdk
pydantic

```

--------------------------------------------------------------------------------
/minimal_server.py:
--------------------------------------------------------------------------------

```python
#!/usr/bin/env python
import asyncio
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("minimal-server")

@mcp.tool()
def hello_world() -> str:
    """A simple hello world tool"""
    return "Hello, world from minimal MCP server!"

if __name__ == "__main__":
    print("Starting MCP server...")
    mcp.run()

```

--------------------------------------------------------------------------------
/coding_todo.py:
--------------------------------------------------------------------------------

```python
import asyncio
from datetime import datetime
from enum import Enum
from typing import Dict, List, Optional

from mcp.server.fastmcp import FastMCP, Context
from pydantic import BaseModel

# Todo status enum
class TodoStatus(str, Enum):
    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"

# Todo model with coding project specific fields
class Todo(BaseModel):
    id: str
    title: str
    description: str
    status: TodoStatus = TodoStatus.PENDING
    created_at: datetime = datetime.now()
    updated_at: Optional[datetime] = None
    project: Optional[str] = None
    priority: int = 1  # 1 (lowest) to 5 (highest)
    tags: List[str] = []

# Store todos in memory
todos: Dict[str, Todo] = {}

# Create an MCP server using FastMCP
mcp = FastMCP("coding-todo-server")

# Resource to list all todos
@mcp.resource("todo://list")
def get_todo_list() -> str:
    """List of all coding project todos"""
    if not todos:
        return "No todos found."
    
    result = "# Coding Project Todos\n\n"
    for todo_id, todo in todos.items():
        status_marker = "[ ]" if todo.status != TodoStatus.COMPLETED else "[x]"
        result += f"{status_marker} **{todo.title}** (ID: {todo_id}, Priority: {todo.priority})\n"
        if todo.tags:
            result += f"   Tags: {', '.join(todo.tags)}\n"
    return result

# Resource to view a specific todo
@mcp.resource("todo://item/{todo_id}")
def get_todo_item(todo_id: str) -> str:
    """Get details of a specific todo item"""
    if todo_id not in todos:
        raise ValueError(f"Todo not found: {todo_id}")
    
    todo = todos[todo_id]
    result = f"# Todo: {todo.title}\n\n"
    result += f"**Status:** {todo.status.value}\n"
    result += f"**Priority:** {todo.priority}/5\n"
    result += f"**Created:** {todo.created_at.strftime('%Y-%m-%d %H:%M')}\n"
    if todo.updated_at:
        result += f"**Updated:** {todo.updated_at.strftime('%Y-%m-%d %H:%M')}\n"
    if todo.project:
        result += f"**Project:** {todo.project}\n"
    if todo.tags:
        result += f"**Tags:** {', '.join(todo.tags)}\n"
    result += f"\n**Description:**\n{todo.description}\n"
    return result

# Prompt to summarize todos
@mcp.prompt()
def summarize_todos(status: str = "pending", project: str = None) -> str:
    """Creates a summary of todos with optional filtering
    
    Args:
        status: Filter by status (pending/in_progress/completed/all)
        project: Filter by project name
    """
    filtered_todos = list(todos.values())
    if status != "all":
        filtered_todos = [t for t in filtered_todos if t.status.value == status]
    if project:
        filtered_todos = [t for t in filtered_todos if t.project == project]
    
    status_text = f"{status} " if status != "all" else ""
    project_text = f"for project {project} " if project else ""
    
    return f"""Here are the current {status_text}todos {project_text}to summarize:

{chr(10).join(f"- {t.title} (Priority: {t.priority}): {t.description}" for t in filtered_todos)}

Please provide a concise summary of these todos and suggest an approach to tackle them efficiently."""

# Prompt to suggest which todo to tackle next
@mcp.prompt()
def suggest_next_todo() -> str:
    """Suggests which todo to tackle next based on priority and status"""
    pending_todos = [t for t in todos.values() if t.status != TodoStatus.COMPLETED]
    
    if not pending_todos:
        return "There are no pending todos. Would you like suggestions for new coding tasks to add?"
    
    # Sort by priority (highest first)
    sorted_todos = sorted(pending_todos, key=lambda t: (-t.priority, t.created_at))
    
    return f"""Here are the current pending todos in order of priority:

{chr(10).join(f"- {t.title} (Priority: {t.priority}, Status: {t.status.value}): {t.description}" for t in sorted_todos)}

Based on these todos, which one should I tackle next and why? Please provide a brief recommendation."""

# Tool to add a new todo
@mcp.tool()
def add_todo(title: str, description: str, project: str = None, priority: int = 1, tags: List[str] = None) -> str:
    """Add a new todo item
    
    Args:
        title: Title of the todo item
        description: Detailed description of the todo item
        project: Project name (optional)
        priority: Priority from 1 (lowest) to 5 (highest)
        tags: List of tags related to the todo
    """
    # Generate a new todo ID
    todo_id = f"todo{len(todos) + 1}"
    
    new_todo = Todo(
        id=todo_id,
        title=title,
        description=description,
        project=project,
        priority=priority,
        tags=tags or [],
    )
    
    todos[todo_id] = new_todo
    
    return f"Added todo '{title}' with ID: {todo_id}"

# Tool to update the status of a todo
@mcp.tool()
def update_todo_status(id: str, status: str) -> str:
    """Update the status of a todo item
    
    Args:
        id: The ID of the todo item
        status: New status (pending/in_progress/completed)
    """
    if id not in todos:
        raise ValueError(f"Todo not found: {id}")
    
    try:
        todos[id].status = TodoStatus(status)
        todos[id].updated_at = datetime.now()
    except ValueError:
        raise ValueError(f"Invalid status: {status}. Must be one of: pending, in_progress, completed")
    
    return f"Updated todo '{todos[id].title}' status to {status}"

# Tool to delete a todo
@mcp.tool()
def delete_todo(id: str) -> str:
    """Delete a todo item
    
    Args:
        id: The ID of the todo item to delete
    """
    if id not in todos:
        raise ValueError(f"Todo not found: {id}")
    
    title = todos[id].title
    del todos[id]
    
    return f"Deleted todo '{title}' (ID: {id})"

# Tool to update a todo's details
@mcp.tool()
def update_todo(id: str, title: str = None, description: str = None, project: str = None, 
               priority: int = None, tags: List[str] = None) -> str:
    """Update a todo item's details
    
    Args:
        id: The ID of the todo item
        title: New title (optional)
        description: New description (optional)
        project: New project name (optional)
        priority: New priority from 1 (lowest) to 5 (highest) (optional)
        tags: New list of tags (optional)
    """
    if id not in todos:
        raise ValueError(f"Todo not found: {id}")
    
    todo = todos[id]
    
    if title is not None:
        todo.title = title
    
    if description is not None:
        todo.description = description
    
    if project is not None:
        todo.project = project
    
    if priority is not None:
        if not 1 <= priority <= 5:
            raise ValueError("Priority must be between 1 and 5")
        todo.priority = priority
    
    if tags is not None:
        todo.tags = tags
    
    # Update the timestamp
    todo.updated_at = datetime.now()
    
    return f"Updated todo '{todo.title}' (ID: {id})"

# Initialize with example todos
def initialize_example_todos():
    example_todos = [
        Todo(
            id="todo1",
            title="Implement user authentication",
            description="Add JWT-based authentication to the API endpoints",
            priority=4,
            project="Backend API",
            tags=["backend", "security"],
        ),
        Todo(
            id="todo2",
            title="Fix CSS responsiveness",
            description="The dashboard layout breaks on mobile devices",
            priority=3,
            project="Frontend UI",
            tags=["frontend", "css", "bugfix"],
        ),
        Todo(
            id="todo3",
            title="Write unit tests",
            description="Create tests for the new data processing module",
            priority=2,
            project="Backend API",
            tags=["testing", "quality"],
        ),
    ]
    
    for todo in example_todos:
        todos[todo.id] = todo

# Initialize and run server
if __name__ == "__main__":
    initialize_example_todos()
    mcp.run()
```