A comprehensive, modern Python wrapper for the Planning Center API using Pydantic and async/await patterns. This library provides type-safe access to all Planning Center products including People, Services, Check-Ins, Giving, Groups, and Calendar.
- Type-safe with full Pydantic models for all data structures
- Async/await support using httpx for modern Python patterns
- Webhook native with built-in signature verification and event handling
- All Products supported: People, Services, Check-Ins, Giving, Groups, Calendar, Publishing, Webhooks, Organization
- Auto-pagination for seamless handling of large datasets
- Rate limiting with automatic exponential backoff
- Comprehensive error handling with specific exception types
- CLI tools for common operations
- Utility functions for data processing and analysis
- MCP Server for AI assistant integration with 80+ tools including advanced analytics
# Install with uv (recommended)
cd planning-center-api
uv pip install "planning_center_api@."
# Or with pip
cd planning-center-api
pip install .For AI assistant integration:
# Install MCP server
cd planning-center-mcp-server
uv pip install "planning_center_mcp@."
# Or with pip
cd planning-center-mcp-server
pip install .import asyncio
from planning_center_api import PCOClient, PCOProduct
async def main():
async with PCOClient(app_id="your_app_id", secret="your_secret") as client:
# Get all people with emails
people = await client.get_people(include=["emails"])
# Create new person
person = await client.create_person({
"first_name": "John",
"last_name": "Doe"
})
# Auto-paginate through all services
async for service in client.paginate_all(
product=PCOProduct.SERVICES,
resource="services"
):
print(f"Service: {service.attributes.get('title')}")
asyncio.run(main())The library supports both OAuth 2.0 and Personal Access Token authentication:
# OAuth 2.0 (recommended)
client = PCOClient(access_token="your_oauth_token")
# Personal Access Token
client = PCOClient(app_id="your_app_id", secret="your_secret")from fastapi import FastAPI, Request
from planning_center_api import PCOClient, handle_webhook_event
app = FastAPI()
client = PCOClient(webhook_secret="your_secret")
@app.post("/webhook")
async def webhook_handler(request: Request):
payload = await request.body()
signature = request.headers.get("x-pco-signature")
async def person_created(webhook_payload):
print(f"New person: {webhook_payload.resource.attributes}")
await handle_webhook_event(
client=client,
payload=payload.decode(),
signature=signature,
event_handlers={"people.created": person_created}
)
return {"status": "success"}Main client for Planning Center API operations.
async with PCOClient(
app_id="your_app_id",
secret="your_secret",
access_token="your_token", # Alternative to app_id/secret
webhook_secret="your_webhook_secret"
) as client:
# Use client here# Get resources
people = await client.get(PCOProduct.PEOPLE, "people")
person = await client.get(PCOProduct.PEOPLE, "people", "person_id")
# Create resources
new_person = await client.create(PCOProduct.PEOPLE, "people", {
"first_name": "John",
"last_name": "Doe"
})
# Update resources
updated_person = await client.update(
PCOProduct.PEOPLE, "people", "person_id", {
"phone": "555-123-4567"
}
)
# Delete resources
success = await client.delete(PCOProduct.PEOPLE, "people", "person_id")# Auto-paginate through all resources
async for person in client.paginate_all(
product=PCOProduct.PEOPLE,
resource="people",
per_page=25
):
print(person.get_full_name())# Get people
people = await client.get_people(per_page=50, include=["emails", "phone_numbers"])
person = await client.get_person("person_id", include=["emails"])
# Search and filter
results = await client.search_people("john")
email_results = await client.get_people_by_email("[email protected]")
active_people = await client.get_active_people()
# Create and update
person = await client.create_person({
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]"
})
updated = await client.update_person("person_id", {"phone": "555-123-4567"})# Get services and plans
services = await client.get_services(per_page=25)
service = await client.get_service("service_id")
plans = await client.get_plans(service_id="service_id")
plan = await client.get_plan("plan_id")The library includes a comprehensive CLI tool:
# Get people
pco-cli get --product people --resource people --per-page 10
# Search people
pco-cli search-people --query "john" --output table
# Create a person
pco-cli create --product people --resource people --data '{"first_name": "John", "last_name": "Doe"}'
# Paginate through all services
pco-cli paginate --product services --resource services --output csv
# Find by email
pco-cli find-by-email --email "[email protected]"The repository includes a comprehensive Model Context Protocol (MCP) server that exposes all major Planning Center APIs as tools for AI assistants like Claude, Cursor, and other MCP-compatible clients.
- Comprehensive Coverage: 80+ read-only tools across 9 Planning Center products
- Native MCP Integration: Built using the official MCP protocol for seamless AI assistant integration
- Read-only operations for data safety
- Mock server included for testing without API credentials
- Claude Desktop ready with pre-configured setup
- Advanced filtering and pagination support
- Advanced Analytics: 10+ specialized analytics tools for data-driven insights
- Event attendee filtering for enhanced event management
get_people,get_person,get_person_addresses,get_person_emails,get_person_phones,get_person_background_checks,get_field_definitions,get_forms,get_form,get_campuses,get_campus
get_services,get_service,get_plans,get_plan,get_songs,get_song,get_arrangements,get_arrangement,get_keys,get_key,get_teams,get_team,get_team_positions,get_team_position
get_registrations,get_registration,get_attendees,get_attendee,get_event_attendees
get_donations,get_donation,get_funds,get_fund,get_batches,get_batch,get_pledges,get_pledge,get_pledge_campaigns,get_pledge_campaign,get_recurring_donations,get_recurring_donation
get_groups,get_group,get_group_events,get_group_event,get_group_memberships,get_group_membership,get_group_types,get_group_type
get_calendar_events,get_calendar_event
get_check_in_events,get_check_in_event,get_locations,get_location
get_channels,get_channel,get_episodes,get_episode
get_webhook_subscriptions,get_webhook_subscription
get_connected_applications,get_connected_application,get_oauth_applications,get_oauth_application
Perfect for testing and development:
# Navigate to MCP server directory
cd planning-center-mcp-server
# Run the mock server
uv run python mcp_mock_server_comprehensive.py
# Or use the batch file
run_comprehensive_server.batFor production use with real Planning Center data:
# Set up environment variables
cp env.example .env
# Edit .env with your Planning Center API credentials
# Run the real server
uv run python mcp_server_fixed.py
# Or use the batch file
run_real_server.batThe servers are pre-configured for Claude Desktop integration:
- Edit your Claude Desktop config:
%APPDATA%\Claude\claude_desktop_config.json - Add server configuration (already done if you followed the setup)
- Restart Claude Desktop
- Start asking questions about Planning Center data!
- Mock Server:
planning-center-mock(no credentials needed) - Real Server:
planning-center-api(requires API credentials)
Once configured, you can ask Claude questions like:
- "Show me all active people in our database"
- "Get the attendees for Summer Camp 2024"
- "Find all donations from last month"
- "List all groups and their members"
- "Show me upcoming calendar events"
- 14+ tools covering the most commonly used endpoints
- Realistic fake data with proper relationships between entities
- No authentication required for testing
- Same API structure as the real server
- MCP integration for AI assistant testing
For detailed MCP server documentation, see planning-center-mcp-server/README.md.
Set environment variables or use a config file:
export PCO_APP_ID="your_app_id"
export PCO_SECRET="your_secret"
# or
export PCO_ACCESS_TOKEN="your_token"Or create a config.json file:
{
"app_id": "your_app_id",
"secret": "your_secret",
"timeout": 30.0,
"max_retries": 3
}The library provides specific exception types for different error scenarios:
from planning_center_api.exceptions import (
PCOError,
PCOAuthenticationError,
PCOPermissionError,
PCONotFoundError,
PCOValidationError,
PCORateLimitError,
PCOServerError
)
try:
person = await client.get_person("invalid_id")
except PCONotFoundError:
print("Person not found")
except PCOAuthenticationError:
print("Authentication failed")
except PCORateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after}")
except PCOError as e:
print(f"API error: {e.message}")All data is returned as Pydantic models with type safety:
# Resource models
person = await client.get_person("person_id")
print(person.get_first_name()) # Type-safe access
print(person.get_email())
print(person.get_full_name())
# Collection models
people = await client.get_people()
print(len(people)) # Collection length
for person in people: # Iterable
print(person.get_full_name())
# Access included resources
person = await client.get_person("person_id", include=["emails"])
emails = person.get_relationship_data("emails")The library automatically handles rate limiting with exponential backoff:
# Rate limiting is handled automatically
# You can configure it in PCOConfig
config = PCOConfig(
rate_limit_requests=100, # Requests per window
rate_limit_window=60, # Window in seconds
max_retries=3, # Max retry attempts
backoff_factor=2.0 # Exponential backoff factor
)# Run tests
cd planning-center-api
pytest
# Run with coverage
pytest --cov=planning_center_api
# Run specific test file
pytest tests/test_client.pyCheck the planning-center-api/examples/ directory for comprehensive examples:
basic_usage.py- Basic API operationswebhook_server.py- FastAPI webhook serverdata_export.py- Data export and analysisadvanced_usage.py- Advanced patterns and utilities
# Clone the repository
git clone <repository-url>
cd planningcenter-wrapper
# Install development dependencies
cd planning-center-api
uv sync --group dev
# Run linting
uv run ruff check --fix planning_center_api/
# Run tests
uv run pytestplanningcenter-wrapper/
βββ planning-center-api/ # Core API package
β βββ planning_center_api/ # Source code
β βββ examples/ # Usage examples
β βββ tests/ # Test suite
β βββ docs/ # Documentation
β βββ pyproject.toml # Package configuration
βββ planning-center-mcp-server/ # Comprehensive MCP server for AI assistants
β βββ planning_center_mcp/ # MCP server source code
β βββ mcp_server_fixed.py # Real server with 65+ tools
β βββ mcp_mock_server_comprehensive.py # Mock server for testing
β βββ run_real_server.bat # Batch file for real server
β βββ run_comprehensive_server.bat # Batch file for mock server
β βββ README.md # Comprehensive MCP server documentation
β βββ COMPREHENSIVE_API_COVERAGE.md # Complete API coverage documentation
β βββ CLAUDE_DESKTOP_SETUP.md # Claude Desktop setup guide
β βββ QUICKSTART.md # Quick start guide
β βββ pyproject.toml # MCP server configuration
βββ _apis/ # API documentation
βββ README.md # This file
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Check the examples directory
- Review the API documentation
- MCP Server Documentation:
- Open an issue for bugs or feature requests