Bird MCP Server
Provides tools for creating and managing Anki flashcards, decks, and statistics.
Provides tools for managing calendar events, listing calendars, and finding free time slots.
Provides tools for creating, reading, updating, and deleting notes in an Obsidian vault.
Provides tools for managing tasks, projects, labels, and comments in Todoist.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Bird MCP ServerCreate a high-priority task in Todoist to finish project report by Friday"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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
Related MCP server: Todoist MCP Server
Quick Reference
# 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-mcpFeatures
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 (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:
Go to Todoist Integrations
Scroll to "API token" section
Copy your API token
AnkiConnect Setup (Optional):
Open Anki
Go to Tools → Add-ons → Get Add-ons
Enter code:
2055492159Restart Anki
AnkiConnect will run on
http://localhost:8765by default
Google Calendar Setup (Optional): See the Google Calendar Setup Guide section below for detailed OAuth2 configuration instructions.
2. Set Up Environment Variables
Create a .env file in the project root:
# 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.jsonInstallation & 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
# 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 uvInstall Dependencies
# Install all dependencies (including the package itself)
uv sync
# Or install in editable mode
uv pip install -e .Run the Server
# 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.pyThe mcp dev command will start the MCP Inspector on http://localhost:6274 for testing and debugging.
Option 2: Using pip
Create Virtual Environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activateInstall Dependencies
pip install -r requirements.txt
pip install -e .Run the Server
python -m bird_mcp.serverOption 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
# 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 downMounting 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:
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 containerThen update your .env:
# .env
OBSIDIAN_VAULT_PATH=/app/vault # This matches the container pathNote: The host.docker.internal hostname allows the Docker container to connect to AnkiConnect running on your host machine.
Build and Run with Docker Directly
# 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:6274Using Docker with Claude Desktop
To use the Dockerized MCP server with Claude Desktop, configure it in your claude_desktop_config.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 fileBuilding the Package
Method 1: With uv (Recommended)
uv is a fast Python package installer and resolver that provides better dependency management and faster builds.
# 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 (
.pycfiles)All source modules from
src/bird_mcp/Package metadata from
pyproject.tomlDependencies list
Method 2: With pip and setuptools
# 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 buildInstalling from Source
Install from Local Directory
# 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/birdInstall from Git Repository
# 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@mainInstall from Built Wheel
# 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.whlPublishing to PyPI (Future)
When ready to publish to PyPI for public distribution:
# 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-mcpVerifying Installation
After installing the package, verify it's working:
# 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
# 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.txtSyncing Dependencies
# 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 --upgradeMCP 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.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
Configuration (using Python directly):
{
"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):
{
"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):
{
"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
# 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.serverVerify Connection
# List all configured MCP servers
claude mcp list
# You should see:
# bird-personal-assistant: python -m bird_mcp.server - ✓ ConnectedEnvironment Variables for Claude Code
Claude Code will use the .env file in your project directory. Ensure it's properly configured:
# 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/vaultImportant: 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:
# 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:
# Remove the MCP server
claude mcp remove bird-personal-assistantDevelopment
Project Architecture
The Bird MCP server is built using a modular architecture:
Core Components:
server.py - Main MCP server
Registers all tools via
@mcp.tool()decoratorsInitializes integrations with environment variables
Handles tool execution and error responses
Provides health check endpoint
todoist_tools.py - Todoist Integration
Uses official
todoist-api-pythonlibraryAsync/await pattern with
asyncio.to_thread()for sync API callsHandles ResultsPaginator nested list structures
11 tools for task management and analytics
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
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
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
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}responsesAsync/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 fileDevelopment Setup
# 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.serverAdding 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:
"""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:
# 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:
# 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:
# 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:
uv add package-nameFor pip:
pip install package-name
# Then update requirements.txt
pip freeze > requirements.txtOr manually add to pyproject.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:
# .env.example
MY_SERVICE_API_KEY=your_api_key_here7. Test Your Tool
# Start the MCP server with inspector
uv run mcp dev src/bird_mcp/server.py
# Or run directly
uv run python -m bird_mcp.serverOpen 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
# Install dev dependencies
uv pip install -e ".[dev]"
# Run tests
pytest
# With coverage
pytest --cov=src/bird_mcp --cov-report=htmlCode Formatting
# 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:
# Start server with inspector
uv run mcp dev src/bird_mcp/server.py
# Or with Docker
docker-compose --profile dev up bird-mcp-devThen 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
Go to Google Cloud Console
Click "Select a project" at the top, then "New Project"
Enter a project name (e.g., "Bird MCP Calendar")
Click "Create"
Step 2: Enable Google Calendar API
In your Google Cloud project, go to "APIs & Services" > "Library"
Search for "Google Calendar API"
Click on "Google Calendar API"
Click "Enable"
Step 3: Configure OAuth Consent Screen
Go to "APIs & Services" > "OAuth consent screen"
Select "External" user type (unless you have a Google Workspace)
Click "Create"
Fill in the required fields:
App name: "Bird MCP Server"
User support email: Your email
Developer contact information: Your email
Click "Save and Continue"
On the "Scopes" page, click "Add or Remove Scopes"
Add the Google Calendar API scope:
Filter for "Google Calendar API"
Select
https://www.googleapis.com/auth/calendar
Click "Update" then "Save and Continue"
On "Test users", add your Google account email
Click "Save and Continue"
Step 4: Create OAuth2 Credentials
Go to "APIs & Services" > "Credentials"
Click "+ Create Credentials" > "OAuth client ID"
Select "Desktop app" as the application type
Enter a name (e.g., "Bird MCP Desktop")
Click "Create"
Click "Download JSON" to download your credentials file
Save the file as
credentials.jsonin a secure location
Step 5: Configure Environment Variables
Update your .env file with the path to your credentials:
# Google Calendar Integration
GOOGLE_CALENDAR_CREDENTIALS_PATH=/absolute/path/to/credentials.json
# Optional: Custom token storage location
# GOOGLE_CALENDAR_TOKEN_PATH=/path/to/token.pickleImportant: 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:
Start the MCP server:
python -m bird_mcp.serverA browser window will open automatically asking you to sign in to Google
Sign in with the Google account you added as a test user
Grant the requested permissions (Calendar access)
You'll see a success message in your browser
The authentication token will be saved automatically to
~/.bird_mcp/google_calendar_token.pickleFuture requests will use this saved token (no browser required)
Token Management
Token Location: By default, tokens are saved to
~/.bird_mcp/google_calendar_token.pickleToken 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
Troubleshooting Google Calendar
"Credentials file not found"
Verify
GOOGLE_CALENDAR_CREDENTIALS_PATHpoints to the correct fileUse absolute paths:
/Users/username/credentials.jsonnot~/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.pickleRestart 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
Credentials File: Keep
credentials.jsonsecure - it contains your OAuth2 client secretToken File: The token file contains access to your calendar - keep it secure
Scopes: The integration only requests calendar access, not other Google services
Test Users: In development, only accounts added as test users can authenticate
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:
# 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-mcpNote: The first time you run with Docker, the OAuth flow may not work automatically. You'll need to:
Run the authentication on your host machine first (outside Docker)
Then use Docker with the saved token file
Troubleshooting
Server Won't Start
Symptoms: Server fails to start or crashes immediately
Solutions:
Check environment variables
# Ensure .env file exists ls -la .env # Check TODOIST_API_TOKEN is set cat .env | grep TODOIST_API_TOKENCheck Python version
# Requires Python 3.10+ python --versionCheck dependencies
# With uv uv sync # With pip pip install -r requirements.txtCheck logs
# Run server directly to see errors python -m bird_mcp.server # Look for error messages in outputVerify package installation
# 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:
Verify server is configured
# List configured servers claude mcp list # Should show: bird-personal-assistant: python -m bird_mcp.server - ✓ ConnectedCheck you're in the project directory
# The server needs to find .env file pwd # Should show /path/to/bird ls .env # Should existTest server manually
# Run server to check for errors python -m bird_mcp.server # Should see initialization logs: # INFO - Initializing Todoist integration... # INFO - Todoist integration initialized successfullyRe-add the server
# Remove and re-add claude mcp remove bird-personal-assistant claude mcp add --transport stdio --scope local bird-personal-assistant -- python -m bird_mcp.serverCheck environment variables are accessible
# 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:
Verify MCP configuration file location
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
Check JSON syntax
# Validate JSON syntax cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | python -m json.toolVerify Python path
# Check which Python is being used which python # Use absolute path in config if needed /full/path/to/python -m bird_mcp.serverCheck environment variables in config
Ensure
TODOIST_API_TOKENis set in theenvsectionUse absolute paths for
OBSIDIAN_VAULT_PATH
Restart Claude Desktop
Completely quit Claude Desktop (not just close window)
Reopen and check server status
MCP Client Can't Connect
Verify server is running: Test with
python -m bird_mcp.serverdirectlyCheck MCP configuration: Ensure the command and args are correct in your MCP settings
Check environment variables: Ensure they're set in the MCP configuration or
.envfileCheck Python path: Ensure the package is installed (
pip install -e .oruv pip install -e .)
Docker Issues
Symptoms: Docker container won't start or crashes
Solutions:
Port conflicts (development mode only)
# Check if ports are in use lsof -i :6274 lsof -i :6277 # Kill process using port if needed kill -9 <PID>Environment variables
# Ensure .env file exists ls -la .env # Check format (no quotes around values) cat .envBuild cache issues
# Rebuild without cache docker-compose build --no-cache # Or with docker directly docker build --no-cache -t bird-mcp .Volume mount issues (for Obsidian)
# 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:rwView container logs
# 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:
Verify API token
# Get new token from https://todoist.com/app/settings/integrations/developer # Update .env file with new tokenCheck API rate limits
Todoist has rate limits (varies by plan)
Wait a few minutes and try again
Test token manually
# 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:
Verify AnkiConnect is installed
# Open Anki → Tools → Add-ons # Should see "AnkiConnect" in the list # Code: 2055492159Check Anki is running
# Anki must be open for AnkiConnect to work # Start Anki applicationVerify port
# Test connection curl http://localhost:8765 # Should return AnkiConnect API infoCheck firewall
Some firewalls block localhost connections
Allow connections to port 8765
Test with Docker
# Use host.docker.internal instead of localhost # Already configured in docker-compose.ymlUse health check
# 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:
Verify vault path
# Check path exists ls -la /path/to/obsidian/vault # Update .env OBSIDIAN_VAULT_PATH=/absolute/path/to/vaultCheck path is absolute
# Correct: /Users/username/obsidian_vault # Wrong: ~/obsidian_vault # Wrong: ../obsidian_vaultVerify permissions
# Check read/write permissions ls -ld /path/to/obsidian/vault # Should show drwxr-xr-x or similarDocker vault mounting
Ensure volume is mounted in docker-compose.yml
Use absolute paths for host directory
Set
OBSIDIAN_VAULT_PATH=/app/vaultinside container
Common Error Messages
"ModuleNotFoundError: No module named 'bird_mcp'"
Solution: Install package with
pip install -e .oruv pip install -e .
"Todoist integration disabled"
Solution: Set
TODOIST_API_TOKENin.envfile
"AnkiConnect error: Connection refused"
Solution: Start Anki application
"Vault path does not exist"
Solution: Check
OBSIDIAN_VAULT_PATHis 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:
Check the logs
# Run with verbose output python -m bird_mcp.server 2>&1 | tee server.logTest with health check
# In Claude Code, ask: "Run a health check on the MCP server"Report issues
GitHub Issues: Create an issue
Include logs, error messages, and your setup (OS, Python version, etc.)
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tamdogood/bird'
If you have feedback or need assistance with the MCP directory API, please join our Discord server