Skip to content

MCP Server

WebCalendar includes a Model Context Protocol (MCP) server that enables AI assistants to interact with calendar data.

Table of Contents

Overview

The MCP server (mcp.php) exposes calendar operations as tools that AI assistants can call. It supports both local (STDIO) and remote (HTTP) transport, allowing integration with desktop AI apps, CLI tools, and web-based AI services.

Requirements

  • WebCalendar v1.9.13 or later
  • PHP 8.2+
  • Nothing to install for the SDK: it ships in includes/classes/mcp-sdk/ with every release zip and Docker image
  • MCP_SERVER_ENABLED set to Y in admin settings

Setup

1. Enable in Admin Settings

Log in as an admin, go to Admin > System Settings, open the MCP Server tab, and set:

  • MCP Server enabled (MCP_SERVER_ENABLED) = Yes
  • MCP Write Access (MCP_WRITE_ACCESS) = Yes, only if assistants should be able to add, change or delete events. See Write Access.
  • MCP Rate Limit (MCP_RATE_LIMIT) = max requests per hour per user

2. Generate an API Token

Each user generates their own token:

  1. Go to Preferences (pref.php).
  2. Next to MCP API Token, click Generate New Token.
  3. Copy the token straight away. It is shown once and never again.

The token is generated server-side and only its SHA-256 hash is stored, in the cal_api_token column of webcal_user, so neither WebCalendar nor a database backup can show it to you later. If it is lost, generate a new one, which replaces the old. To revoke access, click Clear Token.

The same Preferences tab shows the MCP Endpoint URL and a sample agent configuration.

3. Configure Your AI Assistant

See Client Configuration Examples below for specific applications.

Authentication

The MCP server accepts tokens via multiple methods (checked in order):

Method Transport Example
MCP_TOKEN env var STDIO MCP_TOKEN=abc123 php mcp.php
X-MCP-Token header HTTP X-MCP-Token: abc123
Authorization: Bearer header HTTP Authorization: Bearer abc123
?token= query parameter HTTP mcp.php?token=abc123

The token is looked up in webcal_user.cal_api_token to identify the user. All operations execute as that user with their permissions.

Available Tools

list_events

List events within a date range.

Parameter Type Required Description
start_date string Yes Start date (YYYYMMDD)
end_date string Yes End date (YYYYMMDD)

get_user_info

Get information about the authenticated user.

Parameters: None

Returns: Login, name, email.

search_events

Search events by keyword.

Parameter Type Required Description
keyword string Yes Search term
limit integer No Max results (default 50)

add_event

Create a new non-repeating event.

Parameter Type Required Description
name string Yes Event title
date string Yes Event date (YYYYMMDD)
description string No Event description
location string No Event location
time string No Start time (HHMMSS), or -1 for an untimed event
duration integer No Duration in minutes

Returns: Created event ID.

add_recurring_event

Create a repeating event from an RFC 5545 recurrence rule.

Parameter Type Required Description
name string Yes Event title
date string Yes Date of the first occurrence (YYYYMMDD)
rrule string Yes Recurrence rule, e.g. FREQ=WEEKLY;BYDAY=MO
time string No Start time (HHMMSS), or -1 for an untimed event
duration integer No Duration in minutes
description string No Event description
location string No Event location

Returns: Created event ID.

update_event

Change fields of an event. Only the event's creator may update it, and only the fields given are altered.

Parameter Type Required Description
event_id integer Yes Event to update
name string No New title
date string No New date (YYYYMMDD)
time string No New start time (HHMMSS), or -1 for untimed
duration integer No New duration in minutes
description string No New description
location string No New location

Returns: Confirmation of what changed.

delete_event

Delete an event. Only the event's creator may delete it.

Parameter Type Required Description
event_id integer Yes Event to delete

get_availability

List the user's busy time blocks in a date range, for finding a free slot without reading event details. Times are GMT.

Parameter Type Required Description
start_date string Yes Range start (YYYYMMDD)
end_date string Yes Range end (YYYYMMDD)

Returns: Busy blocks with their start times and durations.

check_conflicts

Check whether a proposed slot overlaps any existing timed event, before creating one. Times are GMT.

Parameter Type Required Description
date string Yes Proposed date (YYYYMMDD)
time string Yes Proposed start time (HHMMSS)
duration integer Yes Proposed duration in minutes

Returns: Any overlapping events. Untimed and all-day events are not considered, since they do not occupy a slot.

Write Access

add_event, add_recurring_event, update_event and delete_event all refuse unless MCP Write Access is enabled in Admin > Settings (MCP_WRITE_ACCESS). It is off by default, so a freshly configured server is read-only and an assistant cannot change a calendar until an administrator allows it.

The read tools -- list_events, search_events and get_user_info -- are unaffected by that setting.

Transport Modes

STDIO (Local)

The AI assistant launches php mcp.php as a subprocess and communicates via stdin/stdout using JSON-RPC. Best for desktop apps and CLI tools running on the same machine as WebCalendar.

MCP_TOKEN=your-token php mcp.php

HTTP (Remote)

The MCP server accepts HTTP POST requests with JSON-RPC payloads. This allows AI services running anywhere to access your calendar.

curl -X POST https://yourserver.com/webcalendar/mcp.php \
  -H "Content-Type: application/json" \
  -H "X-MCP-Token: your-token" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"get_user_info","arguments":{}},"id":1}'

Accessing mcp.php via GET in a browser displays a status page confirming the server is running.

Client Configuration Examples

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent config file on your platform:

{
  "mcpServers": {
    "webcalendar": {
      "command": "php",
      "args": ["/path/to/webcalendar/mcp.php"],
      "env": {
        "MCP_TOKEN": "your-api-token"
      }
    }
  }
}

Restart Claude Desktop after saving. The calendar tools will appear in Claude's tool list.

Claude Code (CLI)

Add to your project's .mcp.json or ~/.claude/mcp.json:

{
  "mcpServers": {
    "webcalendar": {
      "command": "php",
      "args": ["/path/to/webcalendar/mcp.php"],
      "env": {
        "MCP_TOKEN": "your-api-token"
      }
    }
  }
}

HTTP Client (Remote Access)

For AI services that support HTTP-based MCP servers:

{
  "mcpServers": {
    "webcalendar": {
      "url": "https://yourserver.com/webcalendar/mcp.php",
      "headers": {
        "X-MCP-Token": "your-api-token"
      }
    }
  }
}

Alternative using Bearer authentication:

{
  "mcpServers": {
    "webcalendar": {
      "url": "https://yourserver.com/webcalendar/mcp.php",
      "headers": {
        "Authorization": "Bearer your-api-token"
      }
    }
  }
}

Note: Some Apache configurations strip the Authorization header. If Bearer auth doesn't work, use X-MCP-Token instead.

Custom Integration

Any application that speaks MCP can integrate. The server implements the standard MCP JSON-RPC protocol. For STDIO, launch php mcp.php as a subprocess with MCP_TOKEN in the environment. For HTTP, POST JSON-RPC messages to mcp.php.

CORS Configuration

For HTTP transport from browser-based clients, configure allowed origins in webcal_config:

Setting Description
MCP_CORS_ORIGINS Allowed origins (* for any, or specific domain)

The server returns appropriate Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers headers, and handles OPTIONS preflight requests.

Admin Settings

Setting Description Default
MCP_SERVER_ENABLED Y to enable, N to disable N
MCP_WRITE_ACCESS Y to allow the four write tools N
MCP_RATE_LIMIT Max requests per hour per user 100
MCP_CORS_ORIGINS Allowed CORS origins for HTTP transport —

Use Cases

Personal Productivity

Ask your AI assistant natural-language questions about your calendar:

  • "What meetings do I have tomorrow?"
  • "Find all events with 'review' in the title"
  • "Add a dentist appointment next Tuesday at 3pm for 1 hour"
  • "What's on my calendar for the rest of this week?"

Team Coordination

If the AI has access to multiple users' tokens (or a shared calendar):

  • "What events are on the team calendar next week?"
  • "Schedule a standup meeting for tomorrow at 9am"
  • "Search for all offsite events this quarter"

Automated Workflows

Use the HTTP transport to integrate calendar operations into scripts and automation:

# List this week's events from a shell script
curl -s -X POST https://cal.example.com/webcalendar/mcp.php \
  -H "Content-Type: application/json" \
  -H "X-MCP-Token: $MCP_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "list_events",
      "arguments": {
        "start_date": "'$(date +%Y%m%d)'",
        "end_date": "'$(date -d "+7 days" +%Y%m%d)'"
      }
    },
    "id": 1
  }'

Daily Briefing

Combine with an AI assistant to generate a morning summary:

  • "Give me a briefing of today's events with locations and times"
  • "Are there any scheduling conflicts this week?"

Troubleshooting

"API token required" error

  • Verify a token is set: Preferences shows (token set) next to MCP API Token. If you no longer have the token itself, generate a new one.
  • For STDIO: ensure MCP_TOKEN is in the environment.
  • For HTTP: check the header is being sent (X-MCP-Token or Authorization: Bearer).

"MCP server is not enabled" error

An admin must set MCP Server enabled to Yes under Admin > System Settings > MCP Server.

Apache strips Authorization header

Some Apache configurations (especially with CGI/FPM) strip the Authorization header. Workarounds:

  1. Use X-MCP-Token header instead (recommended).
  2. Add to .htaccess:
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
    

Rate limiting

If you receive rate limit errors, ask an admin to increase MCP_RATE_LIMIT in System Settings, or reduce request frequency.

No events returned

  • Verify the token user has events in the requested date range.
  • Check that dates use YYYYMMDD format (e.g., 20260401).
  • The token user's permissions determine what events are visible.