Connect an AI assistant
MCP server v1.1 · Last updated: September 21, 2026
Wedding Harmony exposes a Model Context Protocol (MCP) server, so an AI assistant — Claude, ChatGPT, Muse, OpenClaw or anything else that speaks MCP — can read a couple's wedding plan and add to it on their behalf: who is coming, what is due, what is left in the budget.
The tools mirror what the app already offers Siri and the Shortcuts app. There is no separate developer account: a couple creates a key inside the app and pastes it into their assistant.
Endpoint
| URL | https://www.weddingharmonyapp.com/mcpAlso reachable directly at https://europe-west1-weddingplanner-an.cloudfunctions.net/mcp; the www address is the one OAuth metadata names as the resource. |
|---|---|
| Transport | MCP Streamable HTTP, stateless. One JSON-RPC 2.0 message per POST, one JSON body back.
No sessions, no server-initiated streams: GET and DELETE return 405. |
| Protocol versions | 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05.
initialize echoes the client's version when supported, otherwise answers with
2025-06-18. |
| Capabilities | tools only. resources/list and prompts/list return empty
lists. |
| Region | Google Cloud europe-west1 (Belgium). Wedding data is stored in the EU. |
| OpenAPI | None. The server describes its tools through tools/list, with a JSON Schema per tool. |
Authentication
Every request carries a bearer token:
Authorization: Bearer …
Two ways to get one. Assistants that support OAuth (claude.ai, ChatGPT, Muse) use the sign-in flow and never see a key; anything that lets the user paste a token (Claude Code, MCP Inspector, scripts) can use a connector key.
OAuth 2.1 with PKCE (recommended)
Standard MCP authorization. The client discovers the server through
/.well-known/oauth-protected-resource/mcp and
/.well-known/oauth-authorization-server, registers itself dynamically, and sends the user to
/oauth/authorize. Nothing to configure by hand.
| Issuer | https://www.weddingharmonyapp.com |
|---|---|
| Authorization | GET /oauth/authorize — response_type=code, PKCE S256 required, resource optional (RFC 8707) |
| Token | POST /oauth/token — authorization_code and refresh_token; form-encoded or JSON |
| Registration | POST /oauth/register — RFC 7591; public clients (token_endpoint_auth_method: none) and client_secret_basic / client_secret_post |
| Revocation | POST /oauth/revoke — RFC 7009; revoking either token ends the connection |
| Scope | wedding (the only one; requests for openid / offline_access are tolerated) |
| Tokens | Access tokens live 1 hour, refresh tokens 180 days and rotate on every use |
| Redirect URIs | https, loopback http://localhost / 127.0.0.1 (any port) or a private scheme; exact match otherwise |
How the user approves. The couple's identity lives in the app (Sign in with Apple), so the authorization page does not ask for a password. It shows an 8-character code and asks the user to open Wedding Harmony › Settings › AI Assistants › Approve a connection and type it (or tap the Open in Harmony button on the same phone). Once approved, the page redirects back to the client with the authorization code. The code on the page is valid for 10 minutes; the authorization code for 5.
Every approved connection appears in the app's key list under the assistant's registered
client_name, and the couple can revoke it there at any time.
Connector keys
A connector key starts with wh_ and is created by the couple in the app under
Settings › AI Assistants › Create key. It is shown exactly once; the server stores only its
SHA-256 hash. Keys never expire until revoked.
- Keys belong to a person, not to a wedding. A key opens exactly the weddings that person owns or collaborates on — normally one.
- Creating a key or approving a connection requires a signed-in account (Sign in with Apple). Anonymous accounts are asked to sign in first.
- Up to 10 live keys per account. One key per assistant is the recommended pattern.
- Keys and approvals are currently done on iOS; Android is planned.
Firebase ID tokens
For testing, a Firebase Authentication ID token for the same project is accepted in place of a key. It expires after an hour and is meant for developers working on the apps, not for connectors.
A missing, unknown, expired or revoked token gets 401 with
WWW-Authenticate: Bearer … resource_metadata="…", which is what starts the OAuth flow in a
compliant client.
Quick start
Assistants with a "custom connector" or "MCP server" setting only need the URL; OAuth-capable ones will take the user through the approval page on their own. With a connector key, from a terminal:
MCP=https://www.weddingharmonyapp.com/mcp
KEY=wh_your_key_here
# 1. Handshake
curl -s -X POST $MCP \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-06-18","capabilities":{},
"clientInfo":{"name":"curl","version":"0"}}}'
# 2. What can it do?
curl -s -X POST $MCP \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# 3. Ask about the wedding
curl -s -X POST $MCP \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"get_wedding_overview","arguments":{}}}'
Every tool result carries a human-readable content[0].text and a machine-readable
structuredContent object with the same facts:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [{ "type": "text",
"text": "Anna & Tom are getting married in 120 days (2027-01-19) at Schloss Hof.\nGuests: 2 of 6 people attending (4 guest records).\nTasks: 2 open, 1 done.\nBudget: 10,000 EUR planned/spent of 25,000 EUR; 15,000 EUR left." }],
"structuredContent": {
"partnerNames": ["Anna", "Tom"], "date": "2027-01-19", "daysUntil": 120,
"venueName": "Schloss Hof", "currencyCode": "EUR",
"guests": { "records": 4, "people": 6, "attendingPeople": 2 },
"tasks": { "open": 2, "completed": 1 },
"budget": { "total": 25000, "spent": 10000, "remaining": 15000 }
}
}
}
Notifications (messages without an id) are acknowledged with 202 and no body.
A JSON array of messages is answered with an array.
Tools
Every tool except list_weddings accepts an optional weddingId. Leave it out to use
the couple's active wedding. Money is in the wedding's currencyCode; dates are ISO 8601.
Headcounts count people: a guest record, its unnamed plus-one and its children.
Read
| Tool | Returns | Arguments |
|---|---|---|
list_weddings | Weddings the account can open, active one flagged. | — |
get_wedding_overview | Names, date and countdown, venue, currency, headline guest / task / budget counts. Start here. | — |
get_rsvp_summary | People attending, declined, maybe, pending; children; invitations sent. | — |
list_guests | Guest records with RSVP, contact, plus-one, children, dietary needs, group, table. | status, search, group, limit |
list_tasks | Checklist tasks, soonest due first, overdue flagged. | status (open · completed · all), category, dueWithinDays, limit |
get_budget_summary | Total, planned or spent, paid vs to pay, remaining, per-category breakdown. | — |
list_budget_entries | Individual entries, largest first. | category, unpaidOnly, limit |
list_vendors | Vendors with category, booking status, contact, cost, deposit, contract. | status, category |
list_music | Songs per wedding moment, chosen pick starred, do-not-play list. | moment |
get_timeline | Day-of running order, every timeline with its entries. | — |
get_seating_summary | Tables with capacity and seated guests; attending guests without a seat. | — |
Write
| Tool | Does | Arguments |
|---|---|---|
add_guest | Adds one person to the guest list. | firstName*, lastName, rsvpStatus, email, phone, group, role, hasPlusOne, plusOneName, isChild, dietaryRestrictions, allergies, mealChoice, tags, notes |
set_guest_rsvp | Sets a guest's RSVP by id or name; lists candidates when a name is ambiguous. | status*, guestId or name |
add_task | Adds a checklist task. | title*, description, category, priority, dueDate, notes |
complete_task | Ticks a task off, or reopens it with completed: false. | taskId or title, completed |
add_budget_entry | Adds an expense as an estimate and/or actual cost. | title*, estimatedCost or actualCost*, category, isPaid, paidDate, vendorName, notes |
add_vendor | Adds a vendor or supplier. | name*, category, status, contactName, email, phone, website, address, totalCost, contractSigned, notes |
add_song | Adds a song to a moment; isSelected makes it the pick. | title*, moment*, artist, customMomentName, isSelected, notes |
* required. Enum values (RSVP statuses, categories, priorities, vendor statuses, music
moments) are listed in each tool's inputSchema from tools/list. Write tools carry
MCP annotations (readOnlyHint: false, destructiveHint: false); nothing here deletes
data.
Access & limits
- Account: a free Wedding Harmony account with at least one wedding, on iOS or Android. Approving a connection or creating a key needs Sign in with Apple; the connector itself works for any wedding that account can open.
- Plan: every tool is available on the free plan. Premium features inside the app (seating canvas, exports) do not change what the connector can do.
- Rate limit: 60 requests per minute per account. Over the limit you get
429withRetry-After: 60. - Keys: up to 10 live keys per account.
- Payments: none. The connector does not sell or unlock anything.
- Regions: available worldwide; data is processed and stored in the EU.
Errors
| HTTP | Meaning |
|---|---|
401 | Missing, unknown, expired or revoked token. WWW-Authenticate: Bearer carries resource_metadata so an OAuth client can start the flow. |
405 | GET or DELETE: the server is stateless, POST JSON-RPC only. |
429 | Rate limit; wait for Retry-After. |
400 | Body is not JSON, or empty. |
200 + error | JSON-RPC errors: -32601 unknown method, -32602 unknown tool or bad params, -32600 malformed request. |
200 + isError | Tool-level problems the assistant should relay or fix: an ambiguous guest name (with candidates), an invalid enum value, a date that doesn't parse, no wedding on the account. |
Data & privacy
An assistant sees exactly what the couple sees in the app for the weddings their account can open: guest names and contact details, RSVP answers, dietary needs, tasks, budget entries, vendors, songs, timeline and seating. Nothing about other users, and nothing the couple could not open themselves.
- Wedding Harmony does not send data to your assistant on its own. Every read and write happens because the assistant called a tool with the couple's key.
- What the assistant does with the data is governed by the assistant provider's terms, not ours. Couples should connect assistants they trust with their guests' details.
- Keys are stored hashed. Revoking one on the AI Assistants screen ends access at once.
- Writes are attributed inside the app the same way manual edits are; songs added through a connector are marked as added by "AI assistant".
See the Privacy Policy and Terms of Service for the full picture of how wedding data is handled.
Support
Email: adaskososik@gmail.com
Reports of a tool behaving unexpectedly are welcome; include the tools/call request and the
response, minus your key.