Skip to content
Bloomcount API
Esc
navigateopen⌘Jpreview
On this page

MCP server

Connect an AI agent to one tenant with the same key, the same scopes, and the same errors as the REST API.

The Model Context Protocol endpoint puts this API in front of an AI agent. It speaks the same operations as the REST endpoints, authenticates with the same key, and refuses the same things for the same reasons — an agent connected with a read-only key can read, and nothing else.

https://app.bloomcount.com/api/mcp

Connect

Create a key in Settings → API with only the scopes the agent needs, then point a client at the endpoint with that key in an Authorization header.

claude mcp add --transport http bloomcount \
  https://app.bloomcount.com/api/mcp \
  --header "Authorization: Bearer bloomcount_..."
{
  "mcpServers": {
    "bloomcount": {
      "type": "http",
      "url": "https://app.bloomcount.com/api/mcp",
      "headers": { "Authorization": "Bearer bloomcount_..." }
    }
  }
}
curl https://app.bloomcount.com/api/mcp \
  -H "Authorization: Bearer bloomcount_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Two servers, and which one you want

Bloomcount runs two MCP servers. They do different jobs and it is worth being deliberate about which one an agent connects to — or connecting it to both.

Documentation API
Endpoint docs.bloomcount.com/mcp app.bloomcount.com/api/mcp
Answers with These pages Your tenant’s data
Tools search_docs, get_page, list_pages, get_navigation The 21 below
Authentication None; the docs are public An API key, on every request
Writes Never Whatever the key’s scopes allow

An agent writing an integration wants the documentation server. An agent operating the business — pricing an event, syncing a catalogue — wants this one. An agent doing both wants both, and they do not conflict.

Tools

Twenty-one tools cover all 45 documented operations. They are grouped more coarsely than the endpoints are: one write_supplier rather than a create, an update, an archive and an unarchive, because an agent choosing between four near-identical tools chooses wrong more often than one reading a mode.

PropType
list_products?products:read

Page the catalogue, with free text over names and SKUs.

Typeproducts:read
get_product?products:read

One product with its variants, prices and supplier links.

Typeproducts:read
upsert_products?products:write

Create or update up to 500 products or variants in one call.

Typeproducts:write
list_suppliers?suppliers:read

Active suppliers, with free text over names.

Typesuppliers:read
get_supplier?suppliers:read

One supplier by id, archived ones included.

Typesuppliers:read
write_supplier?suppliers:write

Create, update, archive or unarchive a supplier.

Typesuppliers:write
list_price_lists?priceLists:read

Price lists with their dates and product types.

TypepriceLists:read
get_price_list?priceLists:read

One price list and its entries.

TypepriceLists:read
upsert_price_list?priceLists:write

Create or update a list and its entries together.

TypepriceLists:write
list_tax_groups?taxGroups:read

Tax groups and their rates.

TypetaxGroups:read
upsert_tax_group?taxGroups:write

Create or update a tax group.

TypetaxGroups:write
list_events?events:read

Events newest first, optionally filtered by status, with their totals.

Typeevents:read
get_event?events:read

One event with its groups, lines and pricing.

Typeevents:read
upsert_events?events:write

Create or update event headers in bulk.

Typeevents:write
write_event_groups?events:write

Add, change or remove an event's groups in one call.

Typeevents:write
write_event_items?events:write

Add, change or remove an event's lines; hire dates are availability-checked.

Typeevents:write
list_reference?products:read, venues:read, staff:read

Colours, categories, venues and staff.

Typeproducts:read, venues:read, staff:read
write_reference?products:write, venues:write, staff:write

Create or update any of the same.

Typeproducts:write, venues:write, staff:write
list_webhooks?webhooks:manage

Current subscriptions and their delivery health.

Typewebhooks:manage
subscribe_webhook?webhooks:manage

Subscribe a URL to event changes.

Typewebhooks:manage
delete_resource?the resource's write scope

Delete one record, cascade refusal and all.

Typethe resource's write scope

Each tool call is authorised on its own. A tool the key cannot use fails with missing_scope and names what it would have needed:

{
  "error": "missing_scope",
  "status": 403,
  "scopes_this_tool_may_need": ["webhooks:manage"]
}

What carries over from REST

Everything, deliberately. The MCP server is a translation layer, not a second API with its own rules.

  • Scopes are checked per call, against the same key record.
  • Errors come back verbatim — the same status and the same snake_case code, including the counted ones. A refused delete still says product_on_event_items:14, and that number is the point.
  • The rate limit is 60 requests per minute per key, shared with REST. A busy agent and a busy integration on one key contend for the same budget.
  • fields works on every read tool. Narrowing a projection is usually a better move than paging, and it is much cheaper than fetching everything.
  • idempotencyKey is accepted by the write tools, so a retried call after a dropped connection does not double-write.
  • IDs are the same prefixed, opaque strings the REST API returns, so an ID an agent found through one interface works in the other.

Failure and refusal

A tool that fails returns a normal result with isError: true and the API’s JSON body as its text, rather than a JSON-RPC error. That is the protocol’s intent: the model should read a refusal and decide what to do about it, which it cannot do if the client swallows it as a transport failure. JSON-RPC errors are reserved for what an agent cannot act on — a malformed request, an unknown method.

Destructive tools refuse before they cascade. delete_resource returns 409 with a count of what would go, and only a second call carrying force: true proceeds. Events, venues, staff, colours, categories and webhooks have no force at all.

Protocol notes

  • Transport is a plain HTTP POST returning JSON. There is no SSE stream and no session: the server holds nothing between calls, so there is nothing to resume and nothing to terminate. GET and DELETE return 405.
  • Protocol versions 2025-06-18, 2025-03-26 and 2024-11-05 are accepted; the client’s choice is echoed back when it is one of them.
  • Methods are initialize, ping, tools/list and tools/call. There are no resources or prompts.
  • Batches work. Notifications are accepted and answered with 202.
  • A request with no key returns 401 with a WWW-Authenticate: Bearer header, before anything else is read.

Was this page helpful?