The OnceHub MCP Server provides a standardized way for AI models and agents to interact directly with your OnceHub scheduling API. Rather than sending users a booking link and asking them to schedule manually, an AI Agent can retrieve availability and schedule meetings on the user’s behalf using MCP tools, through a natural language flow.
This solution enables external AI Agents to access OnceHub scheduling APIs within AI-driven workflows using the standardized Model Context Protocol (MCP) remote server.
Compatible with: VS Code Copilot, Claude Desktop, OpenAI, and any MCP-compatible AI client.
- Features
- Quick Start
- Architecture
- Tools
- Client Configuration
- Installation
- Testing
- Production Deployment
- Contributing
- License
- 🔌 MCP Protocol Support - Works with any MCP-compatible AI client
- 📅 Time Slot Retrieval - Fetch available booking slots from OnceHub booking calendars
- 🗓️ Meeting Scheduling - Automatically schedule meetings with guest information
- 🔐 Secure Authentication - API key-based authentication via headers
- 🧪 Well Tested - 92% code coverage with comprehensive unit tests
- 🐳 Docker Ready - Containerized for easy deployment
- 📝 AI-Friendly Prompts - Built-in workflow guidance for AI assistants
Get started with the OnceHub MCP Server in your AI client:
Obtain your OnceHub API key from the Authentication documentation.
Create .vscode/mcp.json in your workspace:
{
"servers": {
"oncehub": {
"url": "https://mcp.oncehub.com/sse",
"type": "http",
"headers": {
"authorization": "Bearer YOUR_ONCEHUB_API_KEY"
}
}
}
}Replace YOUR_ONCEHUB_API_KEY with your actual API key.
Ask your AI assistant to:
- "Show me available time slots for calendar BKC-XXXXXXXXXX"
- "Schedule a meeting for tomorrow at 2 PM with John Doe"
✅ Production Server: Our hosted MCP server is available at https://mcp.oncehub.com/sse.
mcp-server/
├── main.py # MCP server with tool definitions
├── models.py # Pydantic data schemas for BookingForm and Location
├── pyproject.toml # Project dependencies and configuration
├── Dockerfile # Docker image configuration
├── .dockerignore # Files to exclude from Docker build
└── README.md # This file
Retrieves available time slots from a booking calendar.
Parameters:
calendar_id(str, required): The booking calendar ID (e.g., 'BKC-XXXXXXXXXX')start_time(str, optional): Filter slots from this datetime in ISO 8601 format (e.g., '2026-02-15T09:00:00Z')end_time(str, optional): Filter slots until this datetime in ISO 8601 format (e.g., '2026-02-28T17:00:00Z')timeout(int, default: 30): Request timeout in seconds
Example Response:
{
"success": true,
"status_code": 200,
"calendar_id": "BKC-XXXXXXXXXX",
"total_slots": 5,
"data": [
{"start_time": "2026-02-10T10:00:00Z", "end_time": "2026-02-10T11:00:00Z"},
{"start_time": "2026-02-10T14:00:00Z", "end_time": "2026-02-10T15:00:00Z"}
]
}Schedules a meeting in a specified time slot. Always call get_booking_time_slots first to ensure the time slot is available.
Parameters:
calendar_id(str, required): ID of the booking calendar (e.g., 'BKC-XXXXXXXXXX')start_time(str, required): The exact start time from an available slot in ISO 8601 formatguest_time_zone(str, required): Guest's timezone in IANA format (e.g., 'America/New_York', 'Europe/London')guest_name(str, required): Guest's full nameguest_email(str, required): Guest's email address for confirmationguest_phone(str, optional): Guest's phone number in E.164 format (e.g., '+15551234567')location_type(str, optional): Meeting mode - 'virtual', 'virtual_static', 'physical', or 'guest_phone'location_value(str, optional): Location details based on type:virtual: Provider name (e.g., 'zoom', 'google_meet', 'microsoft_teams')virtual_static: Use nullphysical: Address ID (e.g., 'ADD-XXXXXXXXXX')guest_phone: Phone number in E.164 format
custom_fields(dict, optional): Custom form fields as key-value pairs (e.g.,{"company": "Acme", "interests": ["Demo"]})timeout(int, default: 30): Request timeout in seconds
Example Response:
{
"success": true,
"status_code": 200,
"booking_id": "BKG-123456789",
"confirmation": {
"guest_name": "John Doe",
"guest_email": "john@example.com",
"scheduled_time": "2026-02-10T10:00:00Z",
"timezone": "America/New_York"
}
}- Python 3.13 or higher
- uv package manager (recommended)
- OnceHub API key - See Authentication documentation to obtain your API key
- OnceHub API endpoint URL (usually
https://api.oncehub.com)
Create a .env file or set these environment variables:
# Required: Your OnceHub API endpoint
ONCEHUB_API_URL=https://api.oncehub.com
# Note: API key is passed via Authorization header from MCP clients
# Do NOT commit API keys to version controlThis MCP server is compatible with VS Code Copilot, Claude Desktop, OpenAI, and other MCP-compatible clients.
Windows (PowerShell):
New-Item -Path ".vscode" -ItemType Directory -Force
New-Item -Path ".vscode\mcp.json" -ItemType File -ForcemacOS/Linux:
mkdir -p .vscode
touch .vscode/mcp.jsonEdit .vscode/mcp.json:
{
"servers": {
"oncehub": {
"url": "http://0.0.0.0:8000/sse",
"type": "http",
"headers": {
"authorization": "Bearer YOUR_ONCEHUB_API_KEY"
}
}
}
}Configuration Options:
url: The MCP server endpoint (change to your server URL if self-hosting)authorization: Your OnceHub API key withBearerprefix- Server name (
oncehub): Can be customized to any identifier
After saving the configuration, reload VS Code to activate the MCP server connection.
Edit your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"oncehub": {
"url": "http://0.0.0.0:8000/sse",
"headers": {
"authorization": "Bearer YOUR_ONCEHUB_API_KEY"
}
}
}
}Restart Claude Desktop after saving.
For other MCP-compatible clients, configure them to connect to:
- Endpoint:
http://0.0.0.0:8000/sse - Protocol: HTTP with Server-Sent Events (SSE)
- Authentication: Bearer token in
Authorizationheader
Security Note: Never commit API keys to version control. Use environment variables or secure secret management for production deployments.
Windows (PowerShell):
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"macOS/Linux:
curl -LsSf https://astral.sh/uv/install.sh | shgit clone https://github.com/scheduleonce/mcp-server.git
cd mcp-serverWindows (PowerShell):
$env:ONCEHUB_API_URL="https://api.oncehub.com"macOS/Linux:
export ONCEHUB_API_URL="https://api.oncehub.com"Or create a .env file:
echo "ONCEHUB_API_URL=https://api.oncehub.com" > .envNote: The API key is passed via the
Authorizationheader from MCP clients (not as an environment variable).
Option 1: Direct execution
uv run main.pyOption 2: Using the script entry point
uv run mcp-serverThe server will start on http://0.0.0.0:8000
Health check:
curl http://localhost:8000/healthConnect to SSE endpoint:
curl http://localhost:8000/ssedocker build -t mcp-server .docker run -p 8000:8000 mcp-serverdocker run -p 8000:8000 \
-e ONCEHUB_API_URL="https://api.oncehub.com" \
mcp-serverCreate docker-compose.yml:
version: '3.8'
services:
mcp-server:
build: .
ports:
- "8000:8000"
environment:
- ONCEHUB_API_URL=https://api.oncehub.com
restart: unless-stoppedThen run:
docker-compose up -dRepresents meeting location details.
Fields:
type(str): Location type ("physical", "virtual", "phone")value(str): Location details (address, URL, phone number)
The server includes comprehensive logging for HTTP requests to OnceHub:
- Outgoing requests (→)
- Response status codes (←)
- Request/response bodies
Logs are output to the console with timestamps and log levels.
GET /health- Health check endpointGET /sse- Server-Sent Events endpoint for MCP protocol communication
uv pip install fastmcp pydantic httpxuv pip install -e ".[test]"Edit main.py and change log_level parameter:
asyncio.run(mcp.run_sse_async(host="0.0.0.0", port=8000, log_level="debug"))Available log levels: "debug", "info", "warning", "error", "critical"
The project includes comprehensive unit tests for all tools and functions.
# Install test dependencies
uv pip install pytest pytest-asyncio pytest-cov pytest-mockRun all tests:
uv run pytestRun tests with coverage report:
uv run pytest --cov=. --cov-report=html --cov-report=termRun specific test file:
uv run pytest test_tools.pyRun specific test class:
uv run pytest test_tools.py::TestGetBookingTimeSlotsRun specific test:
uv run pytest test_tools.py::TestGetBookingTimeSlots::test_get_time_slots_successRun with verbose output:
uv run pytest -vRun and stop on first failure:
uv run pytest -xAfter running tests with coverage, open the HTML report:
# Windows
start htmlcov/index.html
# macOS
open htmlcov/index.html
# Linux
xdg-open htmlcov/index.htmltest_tools.py- Unit tests for all tool functionsTestGetApiKeyFromContext- Tests for API key extractionTestGetBookingTimeSlots- Tests for time slot retrievalTestScheduleMeeting- Tests for meeting scheduling
All tests use mocking to avoid actual API calls and ensure fast, reliable test execution.
-
API Key Management
- Never commit API keys to version control
- Use environment variables or secret management systems
- Rotate API keys regularly
-
Network Security
- Use HTTPS in production (add reverse proxy like nginx)
- Implement rate limiting to prevent abuse
- Use firewall rules to restrict access
-
Monitoring
- Monitor the
/healthendpoint for availability - Set up logging aggregation (e.g., ELK stack, CloudWatch)
- Track API response times and error rates
- Monitor the
# Build and tag the image
docker build -t oncehub-mcp-server:1.0.0 .
# Run with restart policy
docker run -d \
--name oncehub-mcp \
--restart unless-stopped \
-p 8000:8000 \
-e ONCEHUB_API_URL="https://api.oncehub.com" \
oncehub-mcp-server:1.0.0- AWS: Use ECS, Fargate, or EC2 with Application Load Balancer
- Azure: Deploy to Azure Container Instances or App Service
- GCP: Use Cloud Run or Google Kubernetes Engine
- Default timeout is 30 seconds - adjust based on your needs
- The server uses asyncio for concurrent request handling
- Consider horizontal scaling for high-traffic scenarios
- Use connection pooling for database/cache if added
# Simple health check script
curl -f http://localhost:8000/health || exit 1
# Docker healthcheck (add to Dockerfile)
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1Ensure you're passing the api_key parameter when calling the tools.
Make sure the server is running and accessible on port 8000.
The SSE endpoint requires a GET request, not POST. Use proper MCP client libraries or curl with GET.
Check that logging is properly configured in main.py and the server is running with log_level="info" or "debug".
This project is licensed under the terms of the MIT open source license. Please refer to MIT for the full terms.
- Documentation: OnceHub API Docs
- Issues: GitHub Issues
- MCP Protocol: Model Context Protocol
- Built with FastMCP
- Compatible with the Model Context Protocol
- Powered by OnceHub API
Made by the Oncehub team
