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.
list_products?products:read
Page the catalogue, with free text over names and SKUs.
products:readget_product?products:read
One product with its variants, prices and supplier links.
products:readupsert_products?products:write
Create or update up to 500 products or variants in one call.
products:writelist_suppliers?suppliers:read
Active suppliers, with free text over names.
suppliers:readget_supplier?suppliers:read
One supplier by id, archived ones included.
suppliers:readwrite_supplier?suppliers:write
Create, update, archive or unarchive a supplier.
suppliers:writelist_price_lists?priceLists:read
Price lists with their dates and product types.
priceLists:readget_price_list?priceLists:read
One price list and its entries.
priceLists:readupsert_price_list?priceLists:write
Create or update a list and its entries together.
priceLists:writelist_tax_groups?taxGroups:read
Tax groups and their rates.
taxGroups:readupsert_tax_group?taxGroups:write
Create or update a tax group.
taxGroups:writelist_events?events:read
Events newest first, optionally filtered by status, with their totals.
events:readget_event?events:read
One event with its groups, lines and pricing.
events:readupsert_events?events:write
Create or update event headers in bulk.
events:writewrite_event_groups?events:write
Add, change or remove an event's groups in one call.
events:writewrite_event_items?events:write
Add, change or remove an event's lines; hire dates are availability-checked.
events:writelist_reference?products:read, venues:read, staff:read
Colours, categories, venues and staff.
products:read, venues:read, staff:readwrite_reference?products:write, venues:write, staff:write
Create or update any of the same.
products:write, venues:write, staff:writelist_webhooks?webhooks:manage
Current subscriptions and their delivery health.
webhooks:managesubscribe_webhook?webhooks:manage
Subscribe a URL to event changes.
webhooks:managedelete_resource?the resource's write scope
Delete one record, cascade refusal and all.
the resource's write scopeEach 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.
fieldsworks on every read tool. Narrowing a projection is usually a better move than paging, and it is much cheaper than fetching everything.idempotencyKeyis 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.
GETandDELETEreturn405. - Protocol versions
2025-06-18,2025-03-26and2024-11-05are accepted; the client’s choice is echoed back when it is one of them. - Methods are
initialize,ping,tools/listandtools/call. There are no resources or prompts. - Batches work. Notifications are accepted and answered with
202. - A request with no key returns
401with aWWW-Authenticate: Bearerheader, before anything else is read.