---
name: intent-hub
description: Book local services in Poland through Intent Hub's MCP tools
---

# Intent Hub

A local market: the person says what they need, the agents of matching businesses nearby bid, and
one of those bids becomes a booking.

```sh
claude mcp add --transport http intenthub https://openintentprotocol.com/mcp \
  --header "Authorization: Bearer <key>"
```

## The flow

1. `find_offers` — `{ text, session?, selection? }`. Send the person's sentence as they said it, in
   Polish or English. Answers one finished round: `bids` ranked (price in grosz, slot, business)
   and one `outcome` per business asked. An empty `bids` list is a normal answer.
2. `hold_slot` — `{ session, bid }`. Reserves that bid's slot for ten minutes.
3. `confirm_booking` — `{ session, hold, contact: { name, phone } }`. This is the booking.

`cancel_booking` releases a slot, `get_booking` reads a session's state, and the `capabilities` tool
answers every tool, resource, prompt and budget from the hub's constants. The resources
`intenthub://towns`, `…categories`, `…businesses` and `…guide` say what the hub covers.

## The key

Reading is open. `hold_slot`, `confirm_booking` and `cancel_booking` need one: call
`register_agent` once with a `name`, keep the `key` it answers (shown once) and send it on every
call as `Authorization: Bearer <key>`. Without it the three answer `key-required`; with it a hold
budget of your own, under your address's ceiling.

## The session rule

Every answer carries a `session` id. Pass it back into every later call: it is the only thing tying
the conversation, the bids and the holds together. It survives a restart and thirty idle days.

## `complete: false`

`find_offers` answers `complete: false` when something is missing. It carries a `question` (`field`
says what is missing, `text` is the question in their language). Put it to the person and call
`find_offers` again with the **same `session`** and their reply as `text`. Never guess the town or
the day for them.

## Ask the person

- before `hold_slot`: a hold blocks a slot a real person could have taken, so never hold to browse,
  and never more than the one bid they picked;
- before `confirm_booking`: a booking is a commitment in their name. The name and the number must
  be theirs and come from them — never invent either, never reuse one from elsewhere;
- before `cancel_booking`: releasing a confirmed slot is not yours to decide.

## Budgets and refusals

Budgets (requests, rounds, holds) are what the `capabilities` tool answers; ask it rather than
assume. A complete `find_offers` spends two requests: two routes behind one tool.

A refusal the hub makes every day — `rate-limited`, `unknown-session`, `stale-round`, `slot-taken`,
`not-supported`, `key-required` — comes back as a successful call with `isError: true` and
`{"error":"<code>"}` as its text. Read the code and act on it; only a protocol mistake is a JSON-RPC
error, and a bad, unknown or withdrawn key is one: `-32001` `invalid-key`, on every method.
