Skip to main content

Authentication

Every request to the MCP server (except the health check) must carry a valid MCP token. A token is bound to a single account and user, and every query the agent runs is automatically scoped to that account.

Experimental — tokens available on request

The MCP server is experimental and MCP tokens are issued on request. Contact Smily to have a token created.

Obtaining a token

MCP tokens are issued on request. When you ask for one, specify which flavor you need (see Token types & account selection below):

  • a token pinned to a single account (the common case), or
  • a token that can operate across several accounts, choosing the active one per request (early access — currently limited to a small number of users; see below).

A token looks like this:

mcp_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p
Copy it immediately — it is shown only once

The plaintext token is displayed only at the moment it is created. Smily stores only a hash of it (SHA-256) plus a short mcp_… prefix for display, and the original value can never be recovered. If you lose it, request a new one.

Tokens may optionally have an expiry. An expired or revoked token is rejected with an Unauthorized error.

Token types & account selection

Every token is one of two types, which differ only in how the active account for a request is determined.

Token typeAccounts it can reachHow the active account is chosen
Single-accountexactly one accountImplicit — nothing to specify.
Multi-accounta defined set of accountsSelected per request (see below).

Single-account tokens

The common case. The token is bound to one account, and every tool call operates on it. You don't specify an account — it's implicit. You can ignore the rest of this section.

Multi-account tokens

Limited early availability

Multi-account tokens are in an early-access phase and are being made available to a small number of users first. They are not yet open to everyone — broader availability will follow. If you think you need one, get in touch.

A multi-account token can operate across several accounts — the set of accounts it is authorized for. Because more than one account is reachable, every request must say which account to act on. A multi-account token has no default account: a tool call that doesn't pin one fails with an Invalid params error (account_id is required for this token).

You pin the active account in one of three ways. They are tried in this order, first match wins:

  1. JSON-RPC _meta on the call's params, under the key bookingsync.com/account-id:

    {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
    "name": "api_v3_list",
    "arguments": { "resource": "bookings" },
    "_meta": { "bookingsync.com/account-id": 1234 }
    }
    }
  2. The account_id tool argument on a tools/call (simplest for most clients — it's a normal tool argument, see Tools):

    {
    "name": "api_v3_list",
    "arguments": { "resource": "bookings", "account_id": 1234 }
    }
  3. The X-BookingSync-Account-ID HTTP header — a request-wide fallback applied to every call in the request when neither of the above is present:

    X-BookingSync-Account-ID: 1234

The value is the numeric account id. If you pin an account the token isn't authorized for, the call fails with account_id … is not authorized for this token.

Choosing a method

_meta and account_id are per-call, so an agent can switch accounts between calls within one session. The header is convenient when every call in a session targets the same account. For single-account tokens these inputs are simply ignored (and a mismatching value is rejected).

Presenting the token

The server accepts the token from three sources. When more than one is present, the highest priority wins:

PrioritySourceHow to send
1Authorization header (preferred)Authorization: Bearer mcp_…
2X-MCP-Token header (legacy)X-MCP-Token: mcp_…
3token URL query parameterhttps://www.bookingsync.com/mcp?token=mcp_…

1. Authorization header (preferred)

This is the recommended method and what most MCP clients support natively.

curl -X POST https://www.bookingsync.com/mcp \
-H "Authorization: Bearer mcp_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}'

2. X-MCP-Token header (legacy)

Still accepted for backwards compatibility; prefer Authorization: Bearer for new integrations.

curl -X POST https://www.bookingsync.com/mcp \
-H "X-MCP-Token: mcp_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p" \
-H "Content-Type: application/json" \
-d '{ ... }'

3. Token in the URL (for header-less clients)

Some MCP clients — notably Claude Cowork and other "add a connector by URL" experiences — can only be configured with a URL and cannot attach a custom Authorization header. For those, put the token in the token query parameter:

https://www.bookingsync.com/mcp?token=mcp_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p
Prefer headers when you can

A token in a URL leaks more easily than one in a header — URLs end up in browser history, proxy logs, and crash traces. Smily mitigates this by redacting the token parameter from its own application logs and error-tracking, but you should still prefer the Authorization header whenever your client supports it. Treat a URL that contains a token as a secret.

Access scoping

A token can only ever reach the accounts it is authorized for — one account for a single-account token, or its defined set for a multi-account token. Every tool call is scoped to the account it targets:

  • api_v3_list / api_v3_get only ever return records belonging to the active account.
  • A multi-account token cannot reach an account outside its authorized set: pinning an unauthorized account_id is rejected with an Invalid params error.

Combined with the read-only nature of the tools, this keeps the blast radius tightly bounded.

Rate limiting

Each token is limited to 1,000 requests per hour. The server returns standard rate-limit headers on every response:

HeaderMeaning
X-RateLimit-LimitThe hourly request ceiling (1000).
X-RateLimit-RemainingRequests left in the current window.
X-RateLimit-ResetUnix timestamp when the window resets.
Retry-AfterSeconds to wait before retrying (only when throttled).

When the limit is exceeded, the server responds with HTTP 429 Too Many Requests and a JSON-RPC error with code -32029:

{
"jsonrpc": "2.0",
"id": null,
"error": { "code": -32029, "message": "Rate limit exceeded. Retry after 1543s." }
}

Revoking access

To cut off an agent immediately, revoke the token (or let it expire). Any active MCP session created with that token stops working on its next request, because the session re-checks the token's validity. See Protocol & transport → Sessions for session lifecycle details.