Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Connect AI agents to the Planning Center MCP server

Vendor MCP
Open markdown

The Planning Center MCP connector routes your AI agent's tool calls to Planning Center's own MCP server through Scalekit. Each user signs in to Planning Center once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 65 tools.

Tools
65
What they doRead · write · destructive
62 · 3 · 062 read3 write0 destructive
Users sign in with
OAuth app
Scalekit's or your own

Setup

  1. Install the SDK

    Terminal window
    npm install @scalekit-sdk/node dotenv
  2. Set your credentials

    Add your Scalekit credentials to your .env file. Find values in app.scalekit.com > Developers > API Credentials.

    .env
    SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
    SCALEKIT_CLIENT_ID=<your-client-id>
    SCALEKIT_CLIENT_SECRET=<your-client-secret>
  3. Create the Planning Center MCP connection

    In AgentKit > Connections, create a Planning Center MCP connection. The name you give it is the connection_name your code passes. See Configure connections.

    Scalekit credentials are available for Planning Center MCP server, so you don't need to register an OAuth app.

  4. Authorize a user and make your first call

    quickstart.mts
    import { ScalekitClient } from '@scalekit-sdk/node'
    import 'dotenv/config'
    import { createInterface } from 'node:readline/promises'
    const scalekit = new ScalekitClient(
    process.env.SCALEKIT_ENVIRONMENT_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET,
    )
    const actions = scalekit.actions
    const connector = 'planningcentermcp'
    const identifier = 'user_123'
    // Generate an authorization link for the user
    const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
    console.log('Authorize Planning Center MCP:', link)
    const rl = createInterface({ input: process.stdin, output: process.stdout })
    await rl.question('Press Enter after authorizing...')
    rl.close()
    // Make your first call
    const result = await actions.executeTool({
    connector,
    identifier,
    toolName: 'planningcentermcp_calendar_calendars',
    toolInput: {},
    })
    console.log(result)
    Terminal window
    npx tsx quickstart.mts

    Each user signs in once. See Authorize a user for the full flow and statuses.

Tools

Pass the exact name to execute_tool
Try in PlaygroundRequest a tool
  • planningcentermcp_calendar_calendarsList the calendars configured in Planning Center Calendar (e.g.Read-only

    CalendarCalendars

    List the calendars configured in Planning Center Calendar (e.g. "Youth Ministry", "Staff", "Worship"). Calendars partition an organization's events by ministry or context. Use this tool to see which calendars exist, resolve a calendar name to its id, or look up a calendar's description, color, or default status. This tool returns the full list of calendars; there is no server-side filtering by name or any other attribute. Organizations have only a small handful of calendars, so retrieve them all and match the one you want by name client-side.

    Inputs

    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of name-name
    output_fieldsarray
    Specify which fields to include in the response.
  • planningcentermcp_calendar_conflictsRead booking conflicts in Planning Center Calendar — situations where two events have overlapping resource requests for the same room or piece of equipment.Read-only

    CalendarConflicts

    Read booking conflicts in Planning Center Calendar — situations where two events have overlapping resource requests for the same room or piece of equipment. A conflict carries the contested `resource`, the `winner` event once staff have picked one, and `resolved_at` when the conflict has been settled. Use `filter: ["unresolved"]` to answer "what's overbooked right now" — that's the operationally interesting set, and it inherently scopes to conflicts on upcoming events (past-only conflicts drop out). `filter: ["resolved"]` returns conflicts that have been settled. The `resource` relationship id chains to the calendar_resources tool; the `winner` event id chains to calendar_events. Both are surfaced as JSON:API relationship linkages on every response.

    Inputs

    filterarray
    Restrict to "unresolved" (currently overbooked, scoped to upcoming events) or "resolved" (settled).
    includearray
    Specify which relationships to include in the response.
    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of resolved_at-resolved_at
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10
  • planningcentermcp_calendar_event_instancesSearch specific occurrences of events in Planning Center Calendar — the "what is happening at this date and time" surface.Read-only

    CalendarEventInstances

    Search specific occurrences of events in Planning Center Calendar — the "what is happening at this date and time" surface. An event instance is one occurrence of a parent event: a single Wednesday of a weekly Bible Study, next Sunday's service, or the one date of a one-off event. Recurring instances expose `recurrence` and `compact_recurrence_description` for human-readable patterns. Prefer this tool over `calendar_events` when the question is about specific dates or times ("what's happening next Sunday?", "when does the youth retreat happen?", "the next four Wednesdays of Bible Study"). Use `calendar_events` instead when the question is about the parent event template regardless of when it occurs. For questions about one particular event, resolve it with `calendar_events` and pass its id as `event_id` — more reliable than an `event_name` substring match when several events share a word. Pair it with `filter: ["future"]` for "when does this happen next?". Use `filter: ["future"]` for upcoming instances without computing a date filter yourself. Filter by name via `event_name` (a phrase-substring match — pass a bare substring like "bible study"; wildcards are not supported), by kind, by date range, by tag, or by calendar. To filter by tag, call `calendar_tags` to resolve a tag name to a tag id, then pass `tag_ids` here to narrow to that ministry, audience, or category. To filter by calendar, call `calendar_calendars` to resolve a calendar name to a calendar id, then pass `calendar_ids` here. `description`, `image_url`, and `kind` are heavier fields (rich HTML, image URL, event kind) and are only returned when you list them explicitly in `output_fields`.

    Inputs

    calendar_idsarray
    Filter instances by calendar ids. A single id is the common case. Passing multiple ids returns instances on ANY of those calendars (a union) — `[worship_id, youth_id]` returns instances on either calendar. Resolve calendar names to ids via `calendar_calendars`.
    created_at_endstring
    Latest created at to include (inclusive), as YYYY-MM-DD.
    created_at_startstring
    Earliest created at to include (inclusive), as YYYY-MM-DD. Pair with created_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    ends_at_endstring
    Latest ends at to include (inclusive), as YYYY-MM-DD.
    ends_at_startstring
    Earliest ends at to include (inclusive), as YYYY-MM-DD. Pair with ends_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    event_idstring
    Limit to occurrences of this event, resolved via the calendar_events tool. Prefer this over event_name whenever you already know which event you mean. Only the "future" filter value is supported when scoped to an event; the approval-status filter values cannot be combined with event_id.
    event_namestring
    Filter instances by name (defaults to the parent event's name; can be overridden per instance). Phrase-substring match — pass a bare substring like "bible study"; wildcards are not supported.
    filterarray
    Named filter scopes. Use ["future"] to return only instances that have not yet ended. Approval-status scopes filter by each instance's booking status: "approved" also includes shared instances, "pending" also includes unresolved conflicts, and "rejected" also includes lost instances. The approval-status scopes are not available when event_id is supplied.
    includearray
    Specify which relationships to include in the response.
    kindstring
    Filter instances by their parent event's kind: "standard" for normal events, "blockout" for blockouts.one of standardblockout
    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of created_at-created_atupdated_at-updated_atstarts_at-starts_atends_at-ends_at
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10
    starts_at_endstring
    Latest starts at to include (inclusive), as YYYY-MM-DD.
    starts_at_startstring
    Earliest starts at to include (inclusive), as YYYY-MM-DD. Pair with starts_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    tag_idsarray
    Filter instances by tag ids. A single id is the common case. When you pass multiple ids, upstream composes them as OR within a tag group and AND across tag groups (ungrouped tags each count as their own group) — so `[youth_ministry_id, sunday_service_id]` returns instances tagged with BOTH, not either. Resolve tag names via `calendar_tags`.
    updated_at_endstring
    Latest updated at to include (inclusive), as YYYY-MM-DD.
    updated_at_startstring
    Earliest updated at to include (inclusive), as YYYY-MM-DD. Pair with updated_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
  • planningcentermcp_calendar_eventsSearch events in Planning Center Calendar.Read-only

    CalendarEvents

    Search events in Planning Center Calendar. Calendar is the organization-wide event discovery surface and absorbs events originating in Services, Groups, and Registrations — a Sunday service plan, a small group meeting, and an event signup all appear here alongside Calendar-native events. Use this tool to find events across products: by name, approval status, Church Center visibility, feed, created/updated date, or the `future` named scope for upcoming events. Two views of the same record are simultaneously true: an event surfaced here may also be the source-of-truth for a product-native tool. When the user wants product-specific detail — a Services plan's order of service, a Registrations signup's attendees, a Group's roster — chain into `services_plans`, `registrations_signups`, or `groups_events` after discovering the event here. This tool doesn't surface which calendar an event belongs to — no calendar field or include here. To work by calendar, resolve the calendar id with `calendar_calendars` and pass it to `calendar_event_instances` as `calendar_ids`. That returns one row per occurrence, so dedupe on the `event` relationship id to count events.

    Inputs

    approval_statusstring
    Filter by approval status: 'A' approved, 'P' pending, 'R' rejected.one of APR
    created_at_endstring
    Latest created at to include (inclusive), as YYYY-MM-DD.
    created_at_startstring
    Earliest created at to include (inclusive), as YYYY-MM-DD. Pair with created_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    featuredboolean
    Filter by whether the event is featured on Church Center.
    feed_idstring
    Filter events by the feed they belong to (e.g. the Services, Groups, or Registrations feed that absorbs them into Calendar).
    filterarray
    Use ["future"] to return only events that have not yet ended, excluding past events.
    includearray
    Specify which relationships to include in the response.
    link_onlyboolean
    Filter by whether the event is published to Church Center through a direct link only.
    namestring
    Filter events by name. Matches exactly unless you include a '%' wildcard for partial matches.
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10
    updated_at_endstring
    Latest updated at to include (inclusive), as YYYY-MM-DD.
    updated_at_startstring
    Earliest updated at to include (inclusive), as YYYY-MM-DD. Pair with updated_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    visible_in_church_centerboolean
    Filter by whether the event's Church Center visibility is Published (true) or Hidden (false).
  • planningcentermcp_calendar_resource_bookingsSearch resource bookings in Planning Center Calendar — a successful reservation of a room or piece of equipment for an event, over a start/end time range.Read-only

    CalendarResourceBookings

    Search resource bookings in Planning Center Calendar — a successful reservation of a room or piece of equipment for an event, over a start/end time range. Use this tool to answer "what's booked?" questions, e.g. whether a room is reserved during a time window, or what's reserved for a particular event or occurrence. Provide `resource_id` (resolved via `calendar_resources`) to scope to a single room or resource, `event_id` (resolved via `calendar_events`) to scope to a single event's bookings, or `event_instance_id` (resolved via `calendar_event_instances`) to scope to one specific occurrence — provide at most one of the three. Omit all three to search bookings across the whole organization. Recurring events (weekly services, ongoing classes) attach their bookings to the individual event instance rather than the parent event, so prefer `event_instance_id` for "what's booked for this Sunday/this occurrence?" questions. Use the `event_resource_request` include to identify what was reserved and its approval status; chain into `calendar_events` for richer event detail — this tool does not include the full event record. A booking is a successful reservation, distinct from a scheduling conflict (overlapping reservations awaiting staff resolution) — for "what's overbooked?" questions, use `calendar_conflicts` instead.

    Inputs

    approval_statusstring
    Limit to bookings with this approval status. This is a single value, not a list — use a compound value such as "approved_pending" to match multiple statuses in one call, since the API ORs statuses within a single value but ANDs separate filter values. Cannot be combined with event_id or event_instance_id (neither route supports approval-status scopes).one of approvedpendingrejectedapproved_pendingapproved_rejectedpending_rejectedapproved_pending_rejected
    ends_at_endstring
    Latest ends at to include (inclusive), as YYYY-MM-DD.
    ends_at_startstring
    Earliest ends at to include (inclusive), as YYYY-MM-DD. Pair with ends_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    event_idstring
    Limit to bookings for this event, resolved via the calendar_events tool. Provide at most one of resource_id/event_id/event_instance_id. Only the "future" filter value is supported when scoped to an event; approval_status cannot be combined with event_id.
    event_instance_idstring
    Limit to bookings for this specific occurrence of an event, resolved via the calendar_event_instances tool. Provide at most one of resource_id/event_id/event_instance_id. Prefer this over event_id for recurring events — their bookings attach to the instance, not the parent event. Only the "future" filter value is supported when scoped to an event instance; approval_status cannot be combined with event_instance_id.
    filterarray
    Use ["future"] to limit to bookings that haven't ended yet.
    includearray
    Specify which relationships to include in the response.
    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of created_at-created_atends_at-ends_atstarts_at-starts_atupdated_at-updated_at
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10
    resource_idstring
    Limit to bookings of this room or resource, resolved via the calendar_resources tool. Provide at most one of resource_id/event_id/event_instance_id.
    starts_at_endstring
    Latest starts at to include (inclusive), as YYYY-MM-DD.
    starts_at_startstring
    Earliest starts at to include (inclusive), as YYYY-MM-DD. Pair with starts_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
  • planningcentermcp_calendar_resourcesSearch rooms and equipment available for booking in Planning Center Calendar.Read-only

    CalendarResources

    Search rooms and equipment available for booking in Planning Center Calendar. A "resource" is either a physical space (kind='Room') or an item of equipment (kind='Resource'). Each resource carries a `path_name` in the output showing its folder location (e.g. "Main Campus/Sanctuary"); path-based filtering isn't supported server-side, but you can scope to a specific folder via `resource_folder_id` (chain from `include: resource_folder`). Use this tool when the question is about *space or equipment booking* — "what rooms can we book?", "list all our A/V equipment", "which resources do we have?". If instead the question is about *check-in setup* (where kids get dropped off, which station a family checks in at), that's a Check-Ins locations concept and belongs to a separate Check-Ins tool. Resource ids returned here chain forward to Calendar tools that answer "is this resource booked at time X."

    Inputs

    created_at_endstring
    Latest created at to include (inclusive), as YYYY-MM-DD.
    created_at_startstring
    Earliest created at to include (inclusive), as YYYY-MM-DD. Pair with created_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    filterarray
    Use ["rooms"] for rooms only or ["resources"] for equipment only. Named scopes on the organization endpoint; equivalent to `kind=Room` / `kind=Resource`.
    idsarray
    Specific resource IDs to retrieve
    includearray
    Specify which relationships to include in the response.
    kindstring
    Filter by kind: 'Room' for physical bookable spaces, 'Resource' for equipment.one of RoomResource
    namestring
    Filter resources by name. Matches exactly unless you include a '%' wildcard for partial matches.
    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of created_at-created_atexpires_at-expires_atname-nameupdated_at-updated_at
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10
    resource_folder_idstring
    Filter to resources in a specific folder. Chain from a prior response's `include: resource_folder` linkage, or from a folder id you already have.
    updated_at_endstring
    Latest updated at to include (inclusive), as YYYY-MM-DD.
    updated_at_startstring
    Earliest updated at to include (inclusive), as YYYY-MM-DD. Pair with updated_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
  • planningcentermcp_calendar_tagsRead tags used to organize events in Planning Center Calendar.Read-only

    CalendarTags

    Read tags used to organize events in Planning Center Calendar. Tags are the vocabulary an organization uses to categorize events by ministry, audience, or context (e.g. "Youth Ministry", "All-Church"). Use this tool to resolve a tag name to a tag id, browse the available tags, or find tags within a specific tag group. Tag ids chain forward to `calendar_event_instances` via its `tag_ids` filter for server-side filtering of event instances by tag. Server-side filtering of `calendar_events` by tag id is not supported; use the `tags` include on `calendar_events` if you need tag data alongside events. Include `tag_group` to see how tags are grouped (e.g. "Audience", "Ministry"); the "Individual Tags" bucket in the UI corresponds to tags with no tag group and can be filtered via `filter: "individual"`. To list the tag groups themselves, call this tool with `include: ["tag_group"]` and dedupe the `tag_group` relationships client-side.

    Inputs

    church_center_categoryboolean
    Filter by whether the tag is used as a Church Center category.
    created_at_endstring
    Latest created at to include (inclusive), as YYYY-MM-DD.
    created_at_startstring
    Earliest created at to include (inclusive), as YYYY-MM-DD. Pair with created_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    filterstring
    Use "individual" to return only tags with no tag group (the "Individual Tags" bucket in the UI).one of individual
    idstring
    Filter to a specific tag by its ID.
    includearray
    Specify which relationships to include in the response.
    namestring
    Filter tags by name. Exact match unless you include a '%' wildcard for partial matches.
    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of name-nameposition-position
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10
    tag_group_idstring
    Filter to tags belonging to a specific tag group.
    updated_at_endstring
    Latest updated at to include (inclusive), as YYYY-MM-DD.
    updated_at_startstring
    Earliest updated at to include (inclusive), as YYYY-MM-DD. Pair with updated_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
  • planningcentermcp_check_ins_check_insSearch individual check-in records — one row per person per event session, showing who checked in to which event, when, where, and whether they were checked out.Read-only

    CheckInsCheckIns

    Search individual check-in records — one row per person per event session, showing who checked in to which event, when, where, and whether they were checked out. Use for attendance questions where individual identity matters (e.g. "who checked in to the 9am service last Sunday", "did the Smith family check in this morning"). Each record covers regular attendees, guests, or volunteers; filter by event, person, date, or check-in category. `checked_out_at` is ambiguous when null: it can mean the person hasn't been picked up yet, OR that the org doesn't record check-outs at all (many don't — they only badge people in). Report what the data shows and surface the ambiguity rather than asserting someone wasn't picked up. Use `include=checked_out_by` to surface the picker-upper when it was recorded. `security_code`, `medical_notes`, `emergency_contact_name`, and `emergency_contact_phone_number` are stripped from every response before it reaches you — the upstream API exposes them to admins, but this tool removes them on both the primary check-in record and any included resources. Sibling tools to disambiguate: - `check_ins_check_ins` (this tool) — one row per person per event session. Use for "who" and "how many" when individual identity matters. - `check_ins_headcounts` — pre-aggregated totals by event/category. Use for "how many" when only the count matters and no PII is needed (and the org actually recorded headcounts). - `services_plans` — planning-side schedules (who's scheduled to play / on the rotation), NOT attendance. To find check-ins for a Registrations signup, follow the chain: `registrations_signups` returns a signup id → pass that as `registration_event_id` on `check_ins_events` → take the resulting Check-Ins event's id → pass it as `event_id` here. The reverse direction (a Check-Ins event back to its source signup) is not exposed.

    Inputs

    account_center_person_idinteger
    Limit to check-ins for a specific person. Pass a value returned by `people_search`. Note: one-time-guest check-ins have no person id and are excluded by this filter.
    created_at_endstring
    Latest created at to include (inclusive), as YYYY-MM-DD.
    created_at_startstring
    Earliest created at to include (inclusive), as YYYY-MM-DD. Pair with created_at_end; set both to the same day to match a single date, or pass just one side for an open-ended range.
    event_idinteger
    Limit to check-ins for a specific Check-Ins event. Pass a value returned by `check_ins_events`.
    filterstring
    Limit to a check-in category: regular, guest, volunteer, attendee (regular + guest combined), first_time, one_time_guest, not_one_time_guest, checked_out, or not_checked_out.one of regularguestvolunteerattendeefirst_timeone_time_guestnot_one_time_guestchecked_outnot_checked_out
    includearray
    Specify which relationships to include in the response.
    location_idsarray
    Limit to check-ins at specific locations. Pass values returned by `check_ins_locations`.
    order_bystring
    Sort results by field. Use '-' prefix for descending order.one of first_name-first_namelast_name-last_namenumber-numbercreated_at-created_atupdated_at-updated_atchecked_out_at-checked_out_at
    output_fieldsarray
    Specify which fields to include in the response.
    page_afterstring
    Pagination token from previous response's next_page_token field
    per_pageinteger
    Maximum number of results to returndefault 10