Bird MCP Server
by tamdogood
README.md
# Bird MCP Server
A personal assistant MCP (Model Context Protocol) server that integrates with Todoist, Anki, and Obsidian to help you learn, organize, and stay productive. Built with Python and FastMCP, fully packaged with `uv` and Docker-compatible.
## Table of Contents
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Installation & Running](#installation--running)
- [Option 1: Using uv](#option-1-using-uv-recommended)
- [Option 2: Using pip](#option-2-using-pip)
- [Option 3: Using Docker](#option-3-using-docker)
- [Packaging](#packaging)
- [MCP Client Configuration](#mcp-client-configuration)
- [Claude Desktop / Cursor](#claude-desktop--cursor-configuration)
- [Claude Code (CLI)](#claude-code-configuration)
- [Development](#development)
- [Available Tools](#available-tools)
- [Troubleshooting](#troubleshooting)
## Quick Reference
```bash
# Quick start with uv
uv venv && source .venv/bin/activate
uv pip install -e .
cp .env.example .env # Edit with your API tokens
python -m bird_mcp.server
# Add to Claude Code
claude mcp add --transport stdio --scope local bird-personal-assistant -- python -m bird_mcp.server
# Build Docker image
docker build -t bird-mcp .
# Run with Docker
docker run -i --rm --env-file .env bird-mcp
```
## Features
### Currently Implemented
**Todoist Integration (11 tools):**
- Create tasks with descriptions, due dates, priorities, and labels
- Retrieve and filter tasks by project, label, or custom filters
- Complete, update, and delete tasks
- Add and retrieve comments on tasks
- Analyze task statistics (priority distribution, project breakdown, due dates)
- List all projects, labels, and sections
**Anki Integration (14 tools):**
- Create and manage decks
- Create basic flashcards (front/back)
- Create cloze deletion cards
- Get comprehensive statistics (per deck and overall)
- Update deck configuration (daily limits)
- Find notes with Anki search syntax
- Suspend/unsuspend cards
- Get note types and detailed note information
- Update and delete notes
**Obsidian Integration (8 tools):**
- Create, read, update, and delete notes
- Search notes by content, folder, or tag
- List notes in vault or specific folders
- Get or create daily notes
- Get vault statistics
**Google Calendar Integration (10 tools):**
- List all available calendars
- Create, update, and delete calendar events
- Get events within time ranges (today, upcoming, custom)
- Find free time slots for scheduling
- Quick add events using natural language
- Block study time for learning workflows
**Health Check:**
- Monitor connectivity and status of all integrated services
## Prerequisites
- Python 3.10 or higher
- [uv](https://github.com/astral-sh/uv) (recommended) or pip
- Docker (optional, for containerized deployment)
- Todoist account and API token
- Anki with AnkiConnect add-on (optional, for Anki features)
- Obsidian vault (optional, for Obsidian features)
- Google Calendar with OAuth2 credentials (optional, for Google Calendar features)
## Quick Start
### 1. Get Your API Tokens
**Todoist API Token:**
1. Go to [Todoist Integrations](https://todoist.com/app/settings/integrations/developer)
2. Scroll to "API token" section
3. Copy your API token
**AnkiConnect Setup (Optional):**
1. Open Anki
2. Go to Tools → Add-ons → Get Add-ons
3. Enter code: `2055492159`
4. Restart Anki
5. AnkiConnect will run on `http://localhost:8765` by default
**Google Calendar Setup (Optional):**
See the [Google Calendar Setup Guide](#google-calendar-setup) section below for detailed OAuth2 configuration instructions.
### 2. Set Up Environment Variables
Create a `.env` file in the project root:
```bash
# Required
TODOIST_API_TOKEN=your_todoist_token_here
# Optional
ANKI_CONNECT_URL=http://localhost:8765
OBSIDIAN_VAULT_PATH=/path/to/your/obsidian/vault
GOOGLE_CALENDAR_CREDENTIALS_PATH=/path/to/credentials.json
```
## Installation & Running
### Option 1: Using uv (Recommended)
`uv` is a fast Python package installer and resolver. The project is fully configured to work with `uv`.
#### Install uv
```bash
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or with pip
pip install uv
```
#### Install Dependencies
```bash
# Install all dependencies (including the package itself)
uv sync
# Or install in editable mode
uv pip install -e .
```
#### Run the Server
```bash
# Direct execution
uv run python -m bird_mcp.server
# Or using mcp CLI (for development with inspector)
uv run mcp dev src/bird_mcp/server.py
```
The `mcp dev` command will start the MCP Inspector on `http://localhost:6274` for testing and debugging.
### Option 2: Using pip
#### Create Virtual Environment
```bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
#### Install Dependencies
```bash
pip install -r requirements.txt
pip install -e .
```
#### Run the Server
```bash
python -m bird_mcp.server
```
### Option 3: Using Docker
**Important for Obsidian Integration:** If you want to use Obsidian features with Docker, you'll need to mount your vault as a volume (see below).
#### Build and Run with Docker Compose
```bash
# 1. Create .env file with your configuration
cp .env.example .env
# 2. Edit .env and configure:
# - TODOIST_API_TOKEN (required)
# - ANKI_CONNECT_URL (optional, default: http://host.docker.internal:8765)
# - OBSIDIAN_VAULT_PATH (optional, for Obsidian integration)
# 3. Build and start the production container
docker-compose up -d
# Or start the development container with MCP Inspector
docker-compose --profile dev up -d bird-mcp-dev
# View logs
docker-compose logs -f
# Stop the container
docker-compose down
```
#### Mounting Obsidian Vault (Required for Obsidian Integration)
If you want to use Obsidian features, you need to mount your vault into the container. Edit `docker-compose.yml`:
```yaml
services:
bird-mcp:
# ... existing configuration
volumes:
# Mount your Obsidian vault (read-write access)
- /path/to/your/obsidian/vault:/app/vault:rw
environment:
- TODOIST_API_TOKEN=${TODOIST_API_TOKEN}
- ANKI_CONNECT_URL=${ANKI_CONNECT_URL:-http://host.docker.internal:8765}
- OBSIDIAN_VAULT_PATH=/app/vault # Path inside container
```
Then update your `.env`:
```bash
# .env
OBSIDIAN_VAULT_PATH=/app/vault # This matches the container path
```
**Note:** The `host.docker.internal` hostname allows the Docker container to connect to AnkiConnect running on your host machine.
#### Build and Run with Docker Directly
```bash
# Build production image
docker build -t bird-mcp .
# Run production container (basic, no Obsidian)
docker run -d --name bird-mcp --env-file .env bird-mcp
# Run with Obsidian vault mounted
docker run -d --name bird-mcp \
--env-file .env \
-v /path/to/your/obsidian/vault:/app/vault:rw \
-e OBSIDIAN_VAULT_PATH=/app/vault \
bird-mcp
# Build development image (with MCP Inspector)
docker build -f Dockerfile.dev -t bird-mcp-dev .
# Run development container with all features
docker run -d --name bird-mcp-dev \
--env-file .env \
-p 6274:6274 -p 6277:6277 \
-v /path/to/your/obsidian/vault:/app/vault:rw \
-e OBSIDIAN_VAULT_PATH=/app/vault \
bird-mcp-dev
# Access MCP Inspector at http://localhost:6274
```
#### Using Docker with Claude Desktop
To use the Dockerized MCP server with Claude Desktop, configure it in your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"bird": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--env-file",
"/absolute/path/to/bird/.env",
"-v",
"/absolute/path/to/obsidian/vault:/app/vault:rw",
"bird-mcp"
]
}
}
}
```
**Important:** Use absolute paths for `--env-file` and volume mounts.
## Packaging
The project is properly configured for packaging with both `uv` and standard Python tools, following PEP 621 standards.
### Package Structure
The project uses a `src` layout for better packaging practices:
```
bird/
├── src/
│ └── bird_mcp/
│ ├── __init__.py # Package initialization with version
│ ├── server.py # Main MCP server with tool registrations
│ ├── todoist_tools.py # Todoist API integration (11 tools)
│ ├── anki_tools.py # AnkiConnect API integration (14 tools)
│ ├── obsidian_tools.py # Obsidian vault integration (8 tools)
│ ├── google_calendar_tools.py # Google Calendar API integration (10 tools)
│ └── utils.py # Error handling and retry decorators
├── pyproject.toml # PEP 621 package configuration
├── requirements.txt # Dependencies list (for pip)
├── uv.lock # Locked dependencies (for uv reproducibility)
├── .dockerignore # Files excluded from Docker builds
├── Dockerfile # Production Docker image (uses uv)
├── Dockerfile.dev # Development Docker image (with MCP Inspector)
├── docker-compose.yml # Multi-service Docker configuration
├── .env.example # Example environment variables
└── README.md # This file
```
### Building the Package
#### Method 1: With uv (Recommended)
`uv` is a fast Python package installer and resolver that provides better dependency management and faster builds.
```bash
# Install the package in editable mode (for development)
uv pip install -e .
# This allows you to modify source code and see changes immediately
# The package is installed but points to your source directory
# Build distribution packages
uv build
# This creates two distribution formats:
# - dist/bird_mcp-0.1.0.tar.gz (source distribution)
# - dist/bird_mcp-0.1.0-py3-none-any.whl (wheel - faster to install)
```
**What's in the wheel?**
- Compiled bytecode (`.pyc` files)
- All source modules from `src/bird_mcp/`
- Package metadata from `pyproject.toml`
- Dependencies list
#### Method 2: With pip and setuptools
```bash
# Install the package in editable mode
pip install -e .
# Install build tool
pip install build
# Build distribution packages
python -m build
# This creates the same dist/ files as uv build
```
### Installing from Source
#### Install from Local Directory
```bash
# For development (editable install - changes reflect immediately)
cd /path/to/bird
pip install -e .
# For production (regular install - creates a copy)
pip install /path/to/bird
# With uv
uv pip install -e /path/to/bird
```
#### Install from Git Repository
```bash
# Direct from git (requires git URL)
pip install git+https://github.com/yourusername/bird.git
# With uv
uv pip install git+https://github.com/yourusername/bird.git
# Specific branch or tag
pip install git+https://github.com/yourusername/bird.git@main
```
#### Install from Built Wheel
```bash
# After building with 'uv build' or 'python -m build'
pip install dist/bird_mcp-0.1.0-py3-none-any.whl
# With uv
uv pip install dist/bird_mcp-0.1.0-py3-none-any.whl
```
### Publishing to PyPI (Future)
When ready to publish to PyPI for public distribution:
```bash
# 1. Ensure version is updated in pyproject.toml
# 2. Build fresh distribution packages
uv build
# 3. Check the distribution
twine check dist/*
# 4. Upload to TestPyPI first (for testing)
uv publish --publish-url https://test.pypi.org/legacy/
# 5. Test installation from TestPyPI
pip install -i https://test.pypi.org/simple/ bird-mcp
# 6. If everything works, publish to real PyPI
uv publish
# Users can then install with:
# pip install bird-mcp
```
### Verifying Installation
After installing the package, verify it's working:
```bash
# Check package is installed
pip list | grep bird-mcp
# Check version
python -c "import bird_mcp; print(bird_mcp.__version__)"
# Run the MCP server
python -m bird_mcp.server
# You should see:
# INFO - Initializing Todoist integration...
# INFO - Todoist integration initialized successfully
# ...
```
### Dependency Management
The project uses multiple dependency files for different tools:
- **pyproject.toml**: Source of truth for dependencies (PEP 621)
- **requirements.txt**: Generated from pyproject.toml for pip users
- **uv.lock**: Lock file for reproducible builds with uv
#### Updating Dependencies
```bash
# With uv (recommended - updates uv.lock automatically)
uv add package-name
uv add --dev package-name # for dev dependencies
# With pip (requires manual updates)
# 1. Edit pyproject.toml dependencies list
# 2. Reinstall
pip install -e .
# 3. Update requirements.txt
pip freeze > requirements.txt
```
#### Syncing Dependencies
```bash
# Install exact versions from uv.lock (reproducible)
uv sync --frozen
# Update all dependencies to latest compatible versions
uv sync
# Update a specific package
uv add package-name --upgrade
```
## MCP Client Configuration
### Claude Desktop / Cursor Configuration
To use this MCP server with Claude Desktop or Cursor, add the following to your MCP settings file:
**Location:**
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux**: `~/.config/Claude/claude_desktop_config.json`
**Configuration (using Python directly):**
```json
{
"mcpServers": {
"bird": {
"command": "python",
"args": ["-m", "bird_mcp.server"],
"env": {
"TODOIST_API_TOKEN": "your_token_here",
"ANKI_CONNECT_URL": "http://localhost:8765",
"OBSIDIAN_VAULT_PATH": "/path/to/vault"
}
}
}
}
```
**Configuration (using uv):**
```json
{
"mcpServers": {
"bird": {
"command": "uv",
"args": ["run", "python", "-m", "bird_mcp.server"],
"env": {
"TODOIST_API_TOKEN": "your_token_here",
"ANKI_CONNECT_URL": "http://localhost:8765",
"OBSIDIAN_VAULT_PATH": "/path/to/vault"
}
}
}
}
```
**Configuration (using Docker):**
```json
{
"mcpServers": {
"bird": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--env-file",
"/path/to/.env",
"bird-mcp"
]
}
}
}
```
**Note:** After updating the configuration file, restart Claude Desktop or Cursor for changes to take effect.
### Claude Code Configuration
To use this MCP server with Claude Code (the CLI tool), use the `claude mcp add` command:
#### Quick Setup
```bash
# Add the server to Claude Code with local scope
claude mcp add --transport stdio --scope local bird-personal-assistant -- python -m bird_mcp.server
# Or with uv
claude mcp add --transport stdio --scope local bird-personal-assistant -- uv run python -m bird_mcp.server
```
#### Verify Connection
```bash
# List all configured MCP servers
claude mcp list
# You should see:
# bird-personal-assistant: python -m bird_mcp.server - ✓ Connected
```
#### Environment Variables for Claude Code
Claude Code will use the `.env` file in your project directory. Ensure it's properly configured:
```bash
# Navigate to your project directory
cd /path/to/bird
# Create .env from example
cp .env.example .env
# Edit .env with your credentials
# Required:
TODOIST_API_TOKEN=your_token_here
# Optional:
ANKI_CONNECT_URL=http://localhost:8765
OBSIDIAN_VAULT_PATH=/path/to/your/obsidian/vault
```
**Important:** Make sure you're in the project directory when running `claude` commands, or the server won't be able to find the `.env` file.
#### Testing the Integration
Once configured, you can test the server with Claude Code:
```bash
# Start a conversation
claude
# Try a command like:
"Check the health of my MCP server"
"Create a Todoist task named 'Test from Claude Code'"
"Show me my Obsidian vault statistics"
```
#### Removing the Server
If you need to remove the server from Claude Code:
```bash
# Remove the MCP server
claude mcp remove bird-personal-assistant
```
## Development
### Project Architecture
The Bird MCP server is built using a modular architecture:
**Core Components:**
1. **server.py** - Main MCP server
- Registers all tools via `@mcp.tool()` decorators
- Initializes integrations with environment variables
- Handles tool execution and error responses
- Provides health check endpoint
2. **todoist_tools.py** - Todoist Integration
- Uses official `todoist-api-python` library
- Async/await pattern with `asyncio.to_thread()` for sync API calls
- Handles ResultsPaginator nested list structures
- 11 tools for task management and analytics
3. **anki_tools.py** - AnkiConnect Integration
- HTTP API client for AnkiConnect (port 8765)
- Note type validation before card creation
- Supports basic cards, cloze deletions, and card management
- 14 tools for flashcard operations
4. **obsidian_tools.py** - Obsidian Integration
- Filesystem-based vault access (no API required)
- YAML frontmatter parsing and generation
- Daily notes integration
- 8 tools for note management
5. **google_calendar_tools.py** - Google Calendar Integration
- OAuth2 authentication with Google Calendar API v3
- Automatic token refresh and persistence
- Natural language event creation (Quick Add)
- Free slot finding and study time blocking
- 10 tools for calendar management
6. **utils.py** - Shared Utilities
- Error handling decorators for consistent responses
- Retry logic with exponential backoff
- BaseIntegration abstract class for future integrations
**Design Patterns:**
- **Optional Integration Pattern**: Services gracefully degrade if not configured
- **Error Handling**: Consistent `{"success": bool, "error": str}` responses
- **Async/Await**: Non-blocking operations for external API calls
- **Environment-based Config**: All secrets via environment variables
### Project Structure
```
bird/
├── src/
│ └── bird_mcp/
│ ├── __init__.py # Package initialization with version
│ ├── server.py # Main MCP server (44 tools total)
│ ├── todoist_tools.py # Todoist API integration (11 tools)
│ ├── anki_tools.py # AnkiConnect API integration (14 tools)
│ ├── obsidian_tools.py # Obsidian vault integration (8 tools)
│ ├── google_calendar_tools.py # Google Calendar API integration (10 tools)
│ └── utils.py # Error handling and retry decorators
├── Dockerfile # Production Docker image (uses uv)
├── Dockerfile.dev # Development Docker image (uses uv)
├── docker-compose.yml # Docker Compose configuration
├── .dockerignore # Files excluded from Docker builds
├── pyproject.toml # Package configuration (PEP 621)
├── requirements.txt # Dependencies list
├── uv.lock # Locked dependencies (uv)
├── .env.example # Example environment variables
└── README.md # This file
```
### Development Setup
```bash
# Clone the repository
git clone https://github.com/yourusername/bird.git
cd bird
# Create virtual environment with uv (recommended)
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Or with Python's venv
python -m venv venv
source venv/bin/activate
# Install dependencies in editable mode
uv pip install -e ".[dev]"
# Or with pip
pip install -e ".[dev]"
# Set up environment variables
cp .env.example .env
# Edit .env with your API tokens
# Run the server
python -m bird_mcp.server
```
### Adding New MCP Tools
To add a new MCP tool to the server, follow these steps:
#### 1. Create or Update Tool Implementation
Create a new tool class in a separate file (e.g., `src/bird_mcp/my_service_tools.py`) or add methods to an existing tool class:
```python
"""My Service integration tools."""
from typing import Any
import httpx
class MyServiceTools:
"""Tools for interacting with My Service API."""
def __init__(self, api_key: str):
self.api_key = api_key
self.client = httpx.AsyncClient()
async def do_something(self, param: str) -> dict[str, Any]:
"""Do something with the service.
Args:
param: Some parameter
Returns:
Dictionary with success status and result/error
"""
try:
# Your implementation here
response = await self.client.get(
"https://api.example.com/endpoint",
headers={"Authorization": f"Bearer {self.api_key}"},
params={"param": param}
)
response.raise_for_status()
return {"success": True, "data": response.json()}
except Exception as e:
return {"success": False, "error": str(e)}
```
#### 2. Initialize the Tool in server.py
Add initialization code in `src/bird_mcp/server.py`:
```python
# At the top with other imports
from bird_mcp.my_service_tools import MyServiceTools
# In the initialization section (around line 40-67)
my_service_key = os.getenv("MY_SERVICE_API_KEY")
my_service = None
if my_service_key:
try:
logger.info("Initializing My Service integration...")
my_service = MyServiceTools(my_service_key)
logger.info("My Service integration initialized successfully")
except Exception as e:
logger.warning(f"My Service integration disabled: {e}")
else:
logger.info("My Service integration disabled (MY_SERVICE_API_KEY not set)")
```
#### 3. Register the Tool with MCP
Add tool registration functions in `src/bird_mcp/server.py`:
```python
# My Service Tools
@mcp.tool()
async def my_service_do_something(param: str) -> dict[str, Any]:
"""Do something with My Service.
Args:
param: Some parameter description
Returns:
Dictionary with success status and result
"""
if not my_service:
return {"success": False, "error": "My Service integration not configured"}
return await my_service.do_something(param=param)
```
#### 4. Add Health Check (Optional)
Update the `health_check` tool to include your new service:
```python
# In the health_check function (around line 73-148)
# Check My Service
if my_service:
try:
logger.info("Performing My Service health check...")
result = await my_service.do_something("test")
results["services"]["my_service"] = {
"status": "connected" if result["success"] else "error",
"message": (
"Successfully connected to My Service"
if result["success"]
else result.get("error")
),
}
except Exception as e:
logger.error(f"My Service health check failed: {e}")
results["services"]["my_service"] = {"status": "error", "message": str(e)}
else:
results["services"]["my_service"] = {
"status": "disabled",
"message": "My Service integration not configured (set MY_SERVICE_API_KEY)",
}
```
#### 5. Update Dependencies (if needed)
If your new tool requires additional dependencies:
**For uv:**
```bash
uv add package-name
```
**For pip:**
```bash
pip install package-name
# Then update requirements.txt
pip freeze > requirements.txt
```
Or manually add to `pyproject.toml`:
```toml
dependencies = [
# ... existing dependencies
"package-name>=1.0.0",
]
```
#### 6. Update Environment Variables
Add your new service's API key to `.env.example` and document it:
```bash
# .env.example
MY_SERVICE_API_KEY=your_api_key_here
```
#### 7. Test Your Tool
```bash
# Start the MCP server with inspector
uv run mcp dev src/bird_mcp/server.py
# Or run directly
uv run python -m bird_mcp.server
```
Open `http://localhost:6274` (if using `mcp dev`) to test your tool in the MCP Inspector.
#### 8. Update Documentation
- Add your new tool to the "Available Tools" section in this README
- Update the features list at the top
- Document any new environment variables
### Running Tests
```bash
# Install dev dependencies
uv pip install -e ".[dev]"
# Run tests
pytest
# With coverage
pytest --cov=src/bird_mcp --cov-report=html
```
### Code Formatting
```bash
# Format code with black
black src/
# Lint code with ruff
ruff check src/
# Auto-fix linting issues
ruff check --fix src/
```
### Development with MCP Inspector
The MCP Inspector is a web-based tool for testing and debugging MCP servers:
```bash
# Start server with inspector
uv run mcp dev src/bird_mcp/server.py
# Or with Docker
docker-compose --profile dev up bird-mcp-dev
```
Then open `http://localhost:6274` in your browser. You'll need the authentication token shown in the terminal output.
## Available Tools
### Health Check (1 tool)
- **health_check**: Check the health and connectivity of all integrated services (Todoist, Anki, Obsidian, Google Calendar)
### Todoist Tools (11 tools)
- **todoist_create_task**: Create a new task with optional description, project, due date, priority, and labels
- **todoist_get_tasks**: Retrieve tasks with optional filters (project, label)
- **todoist_complete_task**: Mark a task as completed
- **todoist_update_task**: Update task content, description, due date, priority, or labels
- **todoist_delete_task**: Permanently delete a task
- **todoist_analyze_stats**: Get comprehensive statistics about your tasks
- **todoist_get_projects**: List all your Todoist projects
- **todoist_get_labels**: Get all available Todoist labels
- **todoist_get_sections**: Get sections, optionally filtered by project
- **todoist_get_comments**: Get all comments for a task
- **todoist_add_comment**: Add a comment to a task
### Anki Tools (14 tools)
- **anki_create_deck**: Create a new deck in Anki
- **anki_get_decks**: Get all Anki decks with their IDs
- **anki_create_note**: Create a basic flashcard with front and back
- **anki_create_cloze_note**: Create a cloze deletion card (e.g., "{{c1::Paris}} is the capital of {{c2::France}}")
- **anki_get_deck_stats**: Get statistics for a specific deck (card counts, due cards, etc.)
- **anki_get_all_stats**: Get comprehensive statistics across all decks
- **anki_update_deck_config**: Update deck settings (new cards per day, reviews per day)
- **anki_find_notes**: Find notes using Anki search syntax (e.g., "deck:French tag:verb")
- **anki_suspend_cards**: Suspend cards to prevent them from appearing in reviews
- **anki_unsuspend_cards**: Unsuspend cards to allow them to appear in reviews again
- **anki_get_note_types**: Get all available note types (models) in Anki
- **anki_update_note**: Update an existing Anki note's fields and tags
- **anki_get_note_info**: Get detailed information about specific notes
- **anki_delete_notes**: Permanently delete notes from Anki
### Obsidian Tools (8 tools)
- **obsidian_create_note**: Create a new note in Obsidian vault with optional folder, tags, and frontmatter
- **obsidian_read_note**: Read a note from Obsidian vault by path
- **obsidian_update_note**: Update an existing note (replace or append content, update frontmatter)
- **obsidian_delete_note**: Delete a note from Obsidian vault
- **obsidian_search_notes**: Search notes by content, folder, or tag
- **obsidian_list_notes**: List all notes in vault or specific folder
- **obsidian_get_daily_note**: Get or create daily note for a specific date
- **obsidian_get_vault_stats**: Get statistics about the Obsidian vault (total notes, size, folder distribution)
### Google Calendar Tools (10 tools)
- **google_calendar_list_calendars**: List all available Google Calendars with IDs, names, and access roles
- **google_calendar_create_event**: Create a new calendar event with title, time, description, location, and attendees
- **google_calendar_get_events**: Get events within a specified time range
- **google_calendar_update_event**: Update an existing calendar event (title, time, description, location)
- **google_calendar_delete_event**: Delete a calendar event
- **google_calendar_find_free_slots**: Find available time slots in the calendar for scheduling
- **google_calendar_quick_add**: Create an event using natural language (e.g., "Lunch with John tomorrow at 12pm")
- **google_calendar_get_today_events**: Get all events for today
- **google_calendar_get_upcoming_events**: Get upcoming events for the next N days
- **google_calendar_block_study_time**: Create a study block event for learning workflows (integrates with Anki/Obsidian)
## Google Calendar Setup
The Google Calendar integration requires OAuth2 authentication. Follow these steps to set it up:
### Step 1: Create a Google Cloud Project
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Click "Select a project" at the top, then "New Project"
3. Enter a project name (e.g., "Bird MCP Calendar")
4. Click "Create"
### Step 2: Enable Google Calendar API
1. In your Google Cloud project, go to "APIs & Services" > "Library"
2. Search for "Google Calendar API"
3. Click on "Google Calendar API"
4. Click "Enable"
### Step 3: Configure OAuth Consent Screen
1. Go to "APIs & Services" > "OAuth consent screen"
2. Select "External" user type (unless you have a Google Workspace)
3. Click "Create"
4. Fill in the required fields:
- App name: "Bird MCP Server"
- User support email: Your email
- Developer contact information: Your email
5. Click "Save and Continue"
6. On the "Scopes" page, click "Add or Remove Scopes"
7. Add the Google Calendar API scope:
- Filter for "Google Calendar API"
- Select `https://www.googleapis.com/auth/calendar`
8. Click "Update" then "Save and Continue"
9. On "Test users", add your Google account email
10. Click "Save and Continue"
### Step 4: Create OAuth2 Credentials
1. Go to "APIs & Services" > "Credentials"
2. Click "+ Create Credentials" > "OAuth client ID"
3. Select "Desktop app" as the application type
4. Enter a name (e.g., "Bird MCP Desktop")
5. Click "Create"
6. Click "Download JSON" to download your credentials file
7. Save the file as `credentials.json` in a secure location
### Step 5: Configure Environment Variables
Update your `.env` file with the path to your credentials:
```bash
# Google Calendar Integration
GOOGLE_CALENDAR_CREDENTIALS_PATH=/absolute/path/to/credentials.json
# Optional: Custom token storage location
# GOOGLE_CALENDAR_TOKEN_PATH=/path/to/token.pickle
```
**Important:** Use absolute paths, not relative paths like `~/` or `./`
### Step 6: Initial Authentication
The first time you use the Google Calendar integration, you'll need to authenticate:
1. Start the MCP server:
```bash
python -m bird_mcp.server
```
2. A browser window will open automatically asking you to sign in to Google
3. Sign in with the Google account you added as a test user
4. Grant the requested permissions (Calendar access)
5. You'll see a success message in your browser
6. The authentication token will be saved automatically to `~/.bird_mcp/google_calendar_token.pickle`
7. Future requests will use this saved token (no browser required)
### Token Management
- **Token Location**: By default, tokens are saved to `~/.bird_mcp/google_calendar_token.pickle`
- **Token Refresh**: Tokens are automatically refreshed when they expire
- **Revoke Access**: To revoke access, delete the token file and remove the app from your [Google Account permissions](https://myaccount.google.com/permissions)
### Troubleshooting Google Calendar
**"Credentials file not found"**
- Verify `GOOGLE_CALENDAR_CREDENTIALS_PATH` points to the correct file
- Use absolute paths: `/Users/username/credentials.json` not `~/credentials.json`
**"Access blocked: This app's request is invalid"**
- Make sure you added your email as a test user in OAuth consent screen
- Verify the Google Calendar API is enabled in your project
**"Invalid grant" or "Token has been expired or revoked"**
- Delete the token file: `rm ~/.bird_mcp/google_calendar_token.pickle`
- Restart the server to re-authenticate
**Browser doesn't open during authentication**
- Check the terminal output for the authentication URL
- Copy and paste the URL into your browser manually
- Follow the authentication steps in the browser
### Security Considerations
1. **Credentials File**: Keep `credentials.json` secure - it contains your OAuth2 client secret
2. **Token File**: The token file contains access to your calendar - keep it secure
3. **Scopes**: The integration only requests calendar access, not other Google services
4. **Test Users**: In development, only accounts added as test users can authenticate
5. **Publishing**: To allow any Google account, you'll need to verify your app (not required for personal use)
### Using with Docker
When using Docker, you need to mount both the credentials and token files:
```bash
# Create directory for credentials
mkdir -p ~/.bird_mcp
# Copy credentials file
cp /path/to/credentials.json ~/.bird_mcp/
# Run with Docker, mounting the credentials directory
docker run -i --rm \
--env-file .env \
-v ~/.bird_mcp:/root/.bird_mcp:rw \
-e GOOGLE_CALENDAR_CREDENTIALS_PATH=/root/.bird_mcp/credentials.json \
-e GOOGLE_CALENDAR_TOKEN_PATH=/root/.bird_mcp/google_calendar_token.pickle \
bird-mcp
```
**Note**: The first time you run with Docker, the OAuth flow may not work automatically. You'll need to:
1. Run the authentication on your host machine first (outside Docker)
2. Then use Docker with the saved token file
## Troubleshooting
### Server Won't Start
**Symptoms:** Server fails to start or crashes immediately
**Solutions:**
1. **Check environment variables**
```bash
# Ensure .env file exists
ls -la .env
# Check TODOIST_API_TOKEN is set
cat .env | grep TODOIST_API_TOKEN
```
2. **Check Python version**
```bash
# Requires Python 3.10+
python --version
```
3. **Check dependencies**
```bash
# With uv
uv sync
# With pip
pip install -r requirements.txt
```
4. **Check logs**
```bash
# Run server directly to see errors
python -m bird_mcp.server
# Look for error messages in output
```
5. **Verify package installation**
```bash
# Check if package is installed
pip list | grep bird-mcp
# Reinstall if missing
pip install -e .
```
### Claude Code Issues
**Symptoms:** Claude Code can't find or connect to the MCP server
**Solutions:**
1. **Verify server is configured**
```bash
# List configured servers
claude mcp list
# Should show: bird-personal-assistant: python -m bird_mcp.server - ✓ Connected
```
2. **Check you're in the project directory**
```bash
# The server needs to find .env file
pwd # Should show /path/to/bird
ls .env # Should exist
```
3. **Test server manually**
```bash
# Run server to check for errors
python -m bird_mcp.server
# Should see initialization logs:
# INFO - Initializing Todoist integration...
# INFO - Todoist integration initialized successfully
```
4. **Re-add the server**
```bash
# Remove and re-add
claude mcp remove bird-personal-assistant
claude mcp add --transport stdio --scope local bird-personal-assistant -- python -m bird_mcp.server
```
5. **Check environment variables are accessible**
```bash
# Print environment variable (should show your token)
echo $TODOIST_API_TOKEN
# If empty, source .env
export $(cat .env | xargs)
```
### Claude Desktop / Cursor Connection Issues
**Symptoms:** Claude Desktop shows server as disconnected or tools don't appear
**Solutions:**
1. **Verify MCP configuration file location**
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`
2. **Check JSON syntax**
```bash
# Validate JSON syntax
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | python -m json.tool
```
3. **Verify Python path**
```bash
# Check which Python is being used
which python
# Use absolute path in config if needed
/full/path/to/python -m bird_mcp.server
```
4. **Check environment variables in config**
- Ensure `TODOIST_API_TOKEN` is set in the `env` section
- Use absolute paths for `OBSIDIAN_VAULT_PATH`
5. **Restart Claude Desktop**
- Completely quit Claude Desktop (not just close window)
- Reopen and check server status
### MCP Client Can't Connect
1. **Verify server is running**: Test with `python -m bird_mcp.server` directly
2. **Check MCP configuration**: Ensure the command and args are correct in your MCP settings
3. **Check environment variables**: Ensure they're set in the MCP configuration or `.env` file
4. **Check Python path**: Ensure the package is installed (`pip install -e .` or `uv pip install -e .`)
### Docker Issues
**Symptoms:** Docker container won't start or crashes
**Solutions:**
1. **Port conflicts** (development mode only)
```bash
# Check if ports are in use
lsof -i :6274
lsof -i :6277
# Kill process using port if needed
kill -9 <PID>
```
2. **Environment variables**
```bash
# Ensure .env file exists
ls -la .env
# Check format (no quotes around values)
cat .env
```
3. **Build cache issues**
```bash
# Rebuild without cache
docker-compose build --no-cache
# Or with docker directly
docker build --no-cache -t bird-mcp .
```
4. **Volume mount issues** (for Obsidian)
```bash
# Check vault path exists
ls -la /path/to/obsidian/vault
# Ensure path is absolute in docker-compose.yml
# Correct: /Users/username/obsidian_vault:/app/vault:rw
# Wrong: ~/obsidian_vault:/app/vault:rw
```
5. **View container logs**
```bash
# With docker-compose
docker-compose logs -f bird-mcp
# With docker
docker logs bird-mcp
```
### Todoist API Issues
**Symptoms:** Todoist tools return errors or fail
**Solutions:**
1. **Verify API token**
```bash
# Get new token from https://todoist.com/app/settings/integrations/developer
# Update .env file with new token
```
2. **Check API rate limits**
- Todoist has rate limits (varies by plan)
- Wait a few minutes and try again
3. **Test token manually**
```bash
# Test with curl
curl https://api.todoist.com/rest/v2/projects \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
```
### AnkiConnect Issues
**Symptoms:** Anki tools fail or return connection errors
**Solutions:**
1. **Verify AnkiConnect is installed**
```bash
# Open Anki → Tools → Add-ons
# Should see "AnkiConnect" in the list
# Code: 2055492159
```
2. **Check Anki is running**
```bash
# Anki must be open for AnkiConnect to work
# Start Anki application
```
3. **Verify port**
```bash
# Test connection
curl http://localhost:8765
# Should return AnkiConnect API info
```
4. **Check firewall**
- Some firewalls block localhost connections
- Allow connections to port 8765
5. **Test with Docker**
```bash
# Use host.docker.internal instead of localhost
# Already configured in docker-compose.yml
```
6. **Use health check**
```bash
# Run health check to test all services
# In Claude Code:
"Check the health of my MCP server"
```
### Obsidian Integration Issues
**Symptoms:** Obsidian tools return "vault not found" errors
**Solutions:**
1. **Verify vault path**
```bash
# Check path exists
ls -la /path/to/obsidian/vault
# Update .env
OBSIDIAN_VAULT_PATH=/absolute/path/to/vault
```
2. **Check path is absolute**
```bash
# Correct: /Users/username/obsidian_vault
# Wrong: ~/obsidian_vault
# Wrong: ../obsidian_vault
```
3. **Verify permissions**
```bash
# Check read/write permissions
ls -ld /path/to/obsidian/vault
# Should show drwxr-xr-x or similar
```
4. **Docker vault mounting**
- Ensure volume is mounted in docker-compose.yml
- Use absolute paths for host directory
- Set `OBSIDIAN_VAULT_PATH=/app/vault` inside container
### Common Error Messages
**"ModuleNotFoundError: No module named 'bird_mcp'"**
- Solution: Install package with `pip install -e .` or `uv pip install -e .`
**"Todoist integration disabled"**
- Solution: Set `TODOIST_API_TOKEN` in `.env` file
**"AnkiConnect error: Connection refused"**
- Solution: Start Anki application
**"Vault path does not exist"**
- Solution: Check `OBSIDIAN_VAULT_PATH` is correct absolute path
**"'list' object has no attribute 'id'"**
- This was a bug in earlier versions, ensure you're on latest code
### Getting Help
If you're still experiencing issues:
1. **Check the logs**
```bash
# Run with verbose output
python -m bird_mcp.server 2>&1 | tee server.log
```
2. **Test with health check**
```bash
# In Claude Code, ask:
"Run a health check on the MCP server"
```
3. **Report issues**
- GitHub Issues: [Create an issue](https://github.com/yourusername/bird/issues)
- Include logs, error messages, and your setup (OS, Python version, etc.)
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues