# HODDS (remote · hodds.ai)

Find software, SaaS and APIs for a need in a sourced catalogue organised by business process.

- Trust score: 68/100 (medium)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- remote · `hodds.ai`: 68/100 (this document), [markdown](https://verifymcp.io/servers/ai-hodds-hodds/hodds.md), [page](https://verifymcp.io/servers/ai-hodds-hodds/hodds)

## Channel facts

- Endpoint: `https://hodds.ai/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `0.4.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Endpoint Security**: 63/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation check failed: no authorisation is required to call this server, and it exposes a tool marked destructive (unwatch_need).
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 64/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 3274 tokens (~155/item across 21 items; 21 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 33/100
  - Stability observed for 10 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 85/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 47% of tool parameters carry a description.
  - Structured output schemas are declared (90% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 22 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

## Install

### How do I install the HODDS MCP server?

HODDS is a hosted endpoint at https://hodds.ai/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add --transport http ai-hodds-hodds 'https://hodds.ai/mcp'
```

### Cursor

```json
{
  "mcpServers": {
    "ai-hodds-hodds": {
      "url": "https://hodds.ai/mcp"
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "ai-hodds-hodds": {
      "type": "http",
      "url": "https://hodds.ai/mcp"
    }
  }
}
```

### Codex

```toml
[mcp_servers.ai-hodds-hodds]
url = "https://hodds.ai/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ai-hodds-hodds": {
      "type": "remote",
      "url": "https://hodds.ai/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ai-hodds-hodds --url 'https://hodds.ai/mcp' --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  ai-hodds-hodds:
    url: "https://hodds.ai/mcp"
```

### Netclaw

```json
{
  "McpServers": {
    "ai-hodds-hodds": {
      "Transport": "http",
      "Url": "https://hodds.ai/mcp"
    }
  }
}
```

### Vellum

```bash
assistant mcp add ai-hodds-hodds -t streamable-http -u 'https://hodds.ai/mcp'
```

### Other

```json
{
  "mcpServers": {
    "ai-hodds-hodds": {
      "type": "http",
      "url": "https://hodds.ai/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-04 (score 68, +1)

No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-11-02 (score 67, +1)

No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-31 (score 66, +1)

No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-30 (score 65, 0)

- [security] Tool “cancel_plan” rewrote its description, which is the text the model reads
- [security] Tool “get_plan” rewrote its description, which is the text the model reads
- [security] Tool “watch_need” rewrote its description, which is the text the model reads
- [functional] Server version: 0.6.0 → 0.7.0
- [cosmetic] “watch_need” added an optional parameter “target”

### 2026-10-29 (score 65, 0)

- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “cancel_plan” rewrote its description, which is the text the model reads
- [security] Tool “get_plan” rewrote its description, which is the text the model reads
- [security] Tool “watch_need” rewrote its description, which is the text the model reads
- [functional] Server version: 0.5.0 → 0.6.0

### 2026-10-28 (score 65, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-27 (score 64, 0)

- [security] Tool “cancel_plan” rewrote its description, which is the text the model reads
- [security] Tool “get_plan” rewrote its description, which is the text the model reads
- [functional regression] Tool coverage: 100% → 90%
- [functional regression] Schema quality: 2826 → 3188
- [functional regression] Tool coverage: 59% → 48%
- [functional improvement] Stability: unverified → 0.03
- [functional] Server version: 0.4.0 → 0.5.0
- [functional] New tool “read_choice”
- [functional] New tool “watch_choice”

### 2026-10-26 (score 64)

First indexed and scored.

## MCP tools (21)

### `search_solutions` (~287 tokens)

Search software for a need

Searches the HODDS catalogue of software, SaaS, APIs and online services, organised by business process, for records that match a need written in English or French (for example "transcribe my meetings" or "automatiser mes workflows"). Returns a request_id, a status and up to `limit` options; each option has an id, a label, a short description and source URLs (provenance). Ranking combines lexical matching on record names, keywords and processes with semantic similarity (multilingual embeddings on Cloudflare Workers AI), or lexical matching alone when the semantic part is unavailable; ownership or sponsorship never changes it. Confidence is always UNKNOWN: records are non-attested facts taken from publishers' public pages. Status NO_MATCH with an empty option list means that no record matches the need closely enough, or that the need belongs to a process with no record yet; results are never padded. Read-only.

Input parameters:

- `lang` (string): Language of option descriptions: "en" (default) or "fr".
- `limit` (integer): Maximum number of options to return (1-50, default 10).
- `need` (string, required): The need in natural language, English or French: the task to get done.
- `process` (string): Optional process id that restricts the search (ids from list_processes, e.g. "automate-workflows").

Output parameters:

- `options` (array)
- `request_id` (string)
- `status`

### `get_solution` (~127 tokens)

Get a catalogue record

Returns one HODDS catalogue record by id (an option id returned by search_solutions): name, homepage, summary in English and French, processes (the first is primary), keywords, pricing models without amounts (empty means unknown) with the pricing page, interfaces (public API, MCP server, self-hosting: yes, no or unknown), markets, publisher, dated sources and status. Status non_attested means the publisher has not confirmed the record; unknown values are stated as unknown. Read-only.

Input parameters:

- `id` (string, required): Solution id, e.g. "n8n".

Output parameters:

- `added_on` (string)
- `data_portability` (object): Documented export formats (lowercase) and catalogue ids of solutions the publisher documents an import from. Omitted, empty or without source = unknown.
- `data_residency` (array): Regions where the publisher documents that customer data is stored: EU or ISO 3166-1 alpha-2 codes. Omitted or empty = unknown.
- `founder_link` (string): Declared link between the HODDS founder and the solution. Never affects ranking.
- `hodds_status` (object): HODDS review status, distinct from status (publisher attestation). approved = reviewed by HODDS on checked_on, shown as "Approved by HODDS"; not_yet = listed, not reviewed yet, shown as "Not yet appr…
- `id` (string): Stable slug, unique in the catalogue. Equals the file name without .json.
- `interfaces` (object)
- `keywords` (array): Lowercase search terms in English and French describing what the solution does. Never another product's name. (scripts/catalogue.mjs checks lowercase for every script.)
- `markets` (array): ISO 3166-1 alpha-2 codes where the documented offer applies, or global. Omitted = not documented.
- `name` (string)
- `open_source`: Whether the solution is published under an open-source licence. Omitted = unknown.
- `pricing` (object)
- `processes` (array): Process ids from catalogue/processes.json (checked by scripts/catalogue.mjs). processes[0] is the primary process and decides the folder catalogue/solutions/<group>/.
- `publisher` (string)
- `sources` (array): Official pages actually read to write this record.
- `status`: Publisher attestation. non_attested: the publisher has not attested this record. withdrawn is a reserved value for solutions that left the portfolio; no record carries it yet. Corrections: see /contr…
- `summary` (object): Factual description taken from the official source. No superlatives, no comparisons, no unverifiable claims.
- `url` (string): Official homepage.
- `version` (object): Current version as published by the publisher. source = the publisher's official page that states it.
- `withdrawn_on` (string): Day the solution left the portfolio. Allowed only when status is withdrawn.

### `list_processes` (~70 tokens)

List processes

Returns the HODDS process taxonomy: groups (for example "Run the business") and processes (for example "invoice-and-get-paid"), with English and French labels and the number of catalogue records per process. A process id is accepted as the `process` filter of search_solutions. Read-only.

Output parameters:

- `catalogue_version` (string)
- `groups` (array)
- `processes` (array)
- `solution_count` (integer): Number of solutions in the catalogue.

### `send_feedback` (~184 tokens)

Report an outcome

Stores a declarative outcome report for an option returned by search_solutions: outcome YES (the option met the need), PARTLY or NO, with the request_id and the option id exactly as returned. It is the only HODDS tool that writes data without a token; the watch tools (watch_need and the others) write only with an organisation token. The report is stored as an unverified caller statement and never changes ranking by itself; the same report sent twice is stored once. When feedback storage is unavailable on the deployment, the tool returns an error and stores nothing.

Input parameters:

- `option_id` (string, required): id of the option being reported.
- `outcome` (string, required): YES: the option met the need. PARTLY: in part. NO: it did not.
- `request_id` (string, required): request_id returned by search_solutions (req_...).

Output parameters:

- `status`

### `watch_need` (~397 tokens)

Watch a need

Watches a need; CATEGORY follows a process. Optional target selects one product and capability_ids (empty = whole product), counted once. Targeted alerts report documented changes, conditions and unknowns, not a guarantee of suitability. Initially not_computed; rules produce challenger/switch brief; alerts on following calls. Unknown constraints stay uninterpreted. prepaid-v1: payment_required (402), draft_id, watch_status DRAFT, destination /my/plan. Legacy: free_watch_used (409, Checkout). plan_ending (409) refuses new watches. Errors: _meta["ai.hodds/error"]. Search is free. Price: €2 excl. VAT at the start of each monthly period covers the first 4 counted watches; initial basket extras: €0.50 each now; later extras: €0.50 excl. VAT at period end, never charged twice. A person accepts the summary at destination. Legacy rights stay unchanged. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `alert_budget` (integer): Alerts per calendar month (1-20, default 5); beyond, one DIGEST per day.
- `context` (object)
- `current_choice` (string): Active catalogue id; any process accepted.
- `current_choice_name` (string|null): Free name instead of id; exact unique matches resolve, others stay unlinked.
- `delivery` (object)
- `lang` (string): Language of the summary: "en" or "fr".
- `level` (string): NEED (default when need is given) or CATEGORY (process required, no need).
- `need` (string): The need in natural language, English or French (absent for a CATEGORY watch).
- `process` (string): Process id (from list_processes); deduced from the need when absent.
- `target` (object)

Output parameters:

- `alert_budget` (integer)
- `alerts` (array): The 50 most recent alerts, unacknowledged first (200 with all=true).
- `baseline_request_id` (string|null): Search request_id that deduced process; null if process supplied.
- `challenger` (object|null)
- `challenger_reason`
- `constraints` (array)
- `created_at` (string)
- `current_choice` (string|null)
- `current_choice_name` (string|null): Unlinked name.
- `duplicate` (boolean): Opening: existing active watch reused.
- `last_review_at` (string|null)
- `level`
- `need` (string|null): Natural-language need; absent/null for CATEGORY.
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `plan` (string): FREE: legacy only; prepaid-v1: PAID. Organisation entitlement: GET /api/plan. No drafts.
- `process` (string)
- `quiet_since` (string)
- `rules_version` (string): Public computation rules identifier; see /rules/.
- `status`: payment_required returns a DRAFT error, never ACTIVE success.
- `summary` (string): One English/French sentence, per request.
- `target` (object)
- `watch_id` (string)

### `get_watch` (~126 tokens)

Read a watch

Returns one watch of the organisation: constraints, solution in place, challenger with its switch brief and HODDS status, challenger_reason when there is none, and the 50 most recent alerts, unacknowledged first (all: true for 200). Reading does not acknowledge. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `all` (boolean): true: the 200 most recent alerts.
- `watch_id` (string, required): Watch id returned by watch_need or list_watches (w_...).

Output parameters:

- `alert_budget` (integer)
- `alerts` (array): The 50 most recent alerts, unacknowledged first (200 with all=true).
- `baseline_request_id` (string|null): Search request_id that deduced process; null if process supplied.
- `challenger` (object|null)
- `challenger_reason`
- `constraints` (array)
- `created_at` (string)
- `current_choice` (string|null)
- `current_choice_name` (string|null): Unlinked name.
- `duplicate` (boolean): Opening: existing active watch reused.
- `last_review_at` (string|null)
- `level`
- `need` (string|null): Natural-language need; absent/null for CATEGORY.
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `plan` (string): FREE: legacy only; prepaid-v1: PAID. Organisation entitlement: GET /api/plan. No drafts.
- `process` (string)
- `quiet_since` (string)
- `rules_version` (string): Public computation rules identifier; see /rules/.
- `status`: payment_required returns a DRAFT error, never ACTIVE success.
- `summary` (string): One English/French sentence, per request.
- `target` (object)
- `watch_id` (string)

### `list_watches` (~80 tokens)

List watches

Lists the watches of the organisation with their challenger and number of pending alerts; include_closed adds the watches closed in the last 30 days. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `include_closed` (boolean): true: include watches closed in the last 30 days.

Output parameters:

- `count` (integer)
- `free_watch_used` (boolean): Historical free-watch indicator; false grants no prepaid right. See GET /api/plan.offer_version.
- `offer_version` (string)
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `summary` (string): One sentence in English, or in French when the request was in French.
- `watches` (array)

### `set_current_choice` (~111 tokens)

Change the solution in place

Sets a solution by id or free name (any process), null clears. Returns the watch; challenger recomputed later. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `current_choice` (string|null): Catalogue id, or null.
- `current_choice_name` (string|null): Free name instead of id, or null.
- `watch_id` (string, required): Watch id returned by watch_need or list_watches (w_...).

Output parameters:

- `alert_budget` (integer)
- `alerts` (array): The 50 most recent alerts, unacknowledged first (200 with all=true).
- `baseline_request_id` (string|null): Search request_id that deduced process; null if process supplied.
- `challenger` (object|null)
- `challenger_reason`
- `constraints` (array)
- `created_at` (string)
- `current_choice` (string|null)
- `current_choice_name` (string|null): Unlinked name.
- `duplicate` (boolean): Opening: existing active watch reused.
- `last_review_at` (string|null)
- `level`
- `need` (string|null): Natural-language need; absent/null for CATEGORY.
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `plan` (string): FREE: legacy only; prepaid-v1: PAID. Organisation entitlement: GET /api/plan. No drafts.
- `process` (string)
- `quiet_since` (string)
- `rules_version` (string): Public computation rules identifier; see /rules/.
- `status`: payment_required returns a DRAFT error, never ACTIVE success.
- `summary` (string): One English/French sentence, per request.
- `target` (object)
- `watch_id` (string)

### `ack_alerts` (~132 tokens)

Acknowledge alerts

Acknowledges alerts of one watch (alert_ids, or all: true for every alert of this watch); the only call that empties the pending delivery. Returns the number acknowledged and the number remaining for the organisation; a replay changes nothing. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `alert_ids` (array): Alert ids (a_...).
- `all` (boolean): true: every alert of this watch.
- `watch_id` (string, required): Watch id returned by watch_need or list_watches (w_...).

Output parameters:

- `acked` (integer): Alerts acknowledged by this call.
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `remaining` (integer): Unacknowledged alerts left for the organisation.
- `summary` (string): One sentence in English, or in French when the request was in French.

### `rate_alert` (~114 tokens)

Rate an alert

Marks one alert relevant or not_relevant, with an optional note of at most 500 characters. It never changes ranking. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `alert_id` (string, required): Alert id (a_...).
- `note` (string): Optional note.
- `rating` (string, required): relevant or not_relevant.
- `watch_id` (string, required): Watch id returned by watch_need or list_watches (w_...).

Output parameters:

- `alert_id` (string)
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `rating`
- `summary` (string): One sentence in English, or in French when the request was in French.

### `unwatch_need` (~74 tokens)

Close a watch

Closes a watch; its need, constraints and alerts are erased 30 days after closing. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `watch_id` (string, required): Watch id returned by watch_need or list_watches (w_...).

Output parameters:

- `closed_at` (string)
- `deleted_on` (string)
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `status`
- `summary` (string): One sentence in English, or in French when the request was in French.
- `watch_id` (string)

### `get_creator_plan` (~103 tokens)

Read the creator plan

Returns the demand data subscription of the organisation of the token: plan NONE or SUBSCRIBED, subscribed processes, pending removals, the coming invoice, payment provider and invoices. €10 excl. VAT per process per month, invoiced by VORAN, paid through Stripe; no effect on ranking. Contract 0.3.1. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Output parameters:

- `billing` (object|null)
- `currency`
- `ends_on` (string|null)
- `invoiced_by`
- `invoices` (array)
- `next_invoice` (object|null)
- `payment` (object|null)
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `pending_removals` (array)
- `plan`
- `price_per_process_month`
- `processes` (array)
- `ranking_effect`
- `since` (string|null)
- `summary` (string): One sentence in English, or in French when the request was in French (or in the language of the organisation).
- `unit`

### `set_creator_processes` (~148 tokens)

Set the subscribed processes

Replaces the list of subscribed processes. Without an active subscription the result has status 402 and a Stripe Checkout destination for a person to open. With one, an addition through this tool also answers status 402 with the Plan page as destination: nothing is charged here, only the page charges, after a person confirms it. Removals apply at once and the removed processes stay readable until the end of the paid period. An empty list is refused (empty_selection): use cancel_creator_plan. Contract 0.3.1. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `processes` (array, required)

### `list_gaps` (~114 tokens)

Read the demand data of a process

Returns, for a subscribed process, the gaps formulated by HODDS and the client aggregates above the anonymity threshold (watched needs, organisations watching, NO_MATCH, current choices, constraints, challengers delivered, GAP_RESOLVED). No need text, no organisation, no agent. Contract 0.3.1. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Input parameters:

- `process` (string, required): Process id of /catalogue/processes.json.

Output parameters:

- `aggregates` (object)
- `as_of` (string)
- `gaps` (array)
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `process` (string): Process id of /catalogue/processes.json.
- `rules_version` (string)
- `summary` (string): One sentence in English, or in French when the request was in French (or in the language of the organisation).

### `cancel_creator_plan` (~69 tokens)

Stop the creator plan

Stops the subscription at the end of the paid period. Listings, claims, declarations and ranking are unchanged; the coarse demand table stays free. Contract 0.3.1. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Output parameters:

- `ends_on` (string)
- `listings`
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `plan`
- `summary` (string): One sentence in English, or in French when the request was in French (or in the language of the organisation).
- `then`

### `get_plan` (~204 tokens)

Read the My ways plan

Returns the plan of the organisation of the token: FREE, PAID, PAST_DUE, ENDING or ENDED; watched solutions billed in the current Stripe period, offer_version, invoice and payment proof. initial_basket, when present, gives the account's selected needs, exact upfront quote and activation status; its destination is for a human, not agent payment. prepaid-v1: €2 excl. VAT at the start of each monthly period covers the first 4 counted watches; initial basket extras: €0.50 each now; later extras: €0.50 excl. VAT at period end, never charged twice. Legacy rights keep the free unit and arrears until voluntary conversion. VORAN invoices through Stripe. Each watch identity counts once per period, even if closed, regardless of agent. Contract 0.7.0. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Output parameters:

- `amount_due_estimate` (string|null): Excl. VAT at next boundary: prepaid overage_due_estimate + next_period_minimum (no repeated current minimum); legacy max(2.00, watches_billed × 0.50) in arrears. Null outside paid plan; unknown taxes…
- `billing` (object|null): Name and country of the Stripe customer, as entered at Stripe.
- `billing_reconciliation` (object): Present when earlier prepaid usage has no confirmed delivery and can no longer be retried automatically. Unknown does not mean unbilled: reconcile the original identifiers with Stripe before any fina…
- `currency`
- `ends_on` (string|null): Last day of the plan when it is ENDING, or PAST_DUE with its stop asked; null otherwise.
- `initial_basket` (object): Current initial basket owned by the token's account, from the same snapshot as the human Plan. Absent without a current selection: expired PREPARED/EXPIRED and fully activated PAID history are exclud…
- `initial_payment_confirmed` (boolean): Applicable full initial payment confirmed server-side for accepted amount, offer and identities. Not return/card/active flag/zero invoice. Check version and period.
- `invoiced_by`
- `invoices` (array)
- `minimum_covers`: Prepaid covers first 4 counted watches. Legacy counts paid watches only, excluding its free watch.
- `monthly_minimum`: €2 excl. VAT per period, even empty: prepaid at start; legacy in arrears.
- `next_invoice` (object|null): Stripe period end and excl. VAT estimate: ended-period overage + next minimum for prepaid; null outside paid plan.
- `next_period_minimum`: Active prepaid: 2.00 excl. VAT for renewal, 0.00 if ending at boundary; null otherwise.
- `offer_version`: Server-assigned; legacy rights retained until voluntary conversion. Clients cannot select legacy.
- `overage_due_estimate` (string|null): Active prepaid, excl. VAT at period end: first period max(0,M-max(4,N))×0.50; later max(0,M-4)×0.50. N=initial paid basket, M=counted identities. Null otherwise.
- `payment` (object|null): The payment method lives at Stripe; no digit of it is stored or returned.
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `plan`: Technical state, not entitlement: check version, first payment and period. FREE right only for legacy. PAST_DUE: renewal retries. ENDING: existing prepaid watches to boundary, no new ones. ENDED: no…
- `price_per_watch_month`
- `since` (string|null): First day of the paid plan; null outside PAID, PAST_DUE and ENDING.
- `summary` (string): One English/French sentence, per request or organisation language.
- `unit`
- `upfront_amount` (string): Excl. VAT, identical on human Plan/API/MCP: current unpaid initial_basket amount max(2.00,N×0.50); otherwise 2.00 before new prepaid with no selection, or 0.00 if already paid or legacy. A paid unres…
- `watches` (array)
- `watches_billed` (integer): Prepaid identities counted once if active at start or activated in [start,end). Closed exactly at start excluded; later closure restores no unit. Legacy excludes free watch, retaining prior period ru…
- `watches_total` (integer): watches[] count: active and closed within 30 days.

### `cancel_plan` (~88 tokens)

Stop the My ways plan

Stops the subscription at period end; new paid watches are refused immediately. Then paid watches close and remain readable 30 days. No renewal minimum. Agent tokens and legacy free rights are unchanged. Without a paid plan the tool answers not_paid. Contract 0.7.0. Needs an organisation token (Authorization: Bearer hodds_...); without it the tool returns the error token_required.

Output parameters:

- `ends_on` (string)
- `pending` (object): Delivery on the next call: alerts that wait for this organisation. Absent when there is nothing to deliver. Only ack_alerts empties it.
- `plan`
- `readable_until` (string)
- `summary` (string): One English/French sentence, per request or organisation language.
- `then`

### `compare_solutions` (~156 tokens)

Compare solutions for a need

Compare 2–3 catalogue IDs by required capabilities, offer, context and dated sources. Unknown/stale/conflict stay explicit; unknown price is never zero. Discover IDs at /api/capabilities and details at /api/solutions/{id}/specification. Costs require all assumptions. Large result: repeat arguments with view; restart on 409. Public read, no billing/business writes; one call per POST.

Input parameters:

- `context` (object)
- `cost_scenario`
- `criteria` (array)
- `locale` (string)
- `priority`
- `priority_required` (boolean)
- `requirements` (array)
- `solution_ids` (array, required)
- `view` (object)

### `find_comparable_solutions` (~152 tokens)

Find alternatives for a priority

Find alternatives by required priority, optionally relative to one solution. IDs/context: /api/capabilities. A match satisfies every requirement in one configuration. Evaluates the whole pilot before limit, separating match/unresolved/mismatch and stating catalogue coverage, not market coverage. Large result: repeat arguments with view; restart on 409. Public read, no billing/business writes; one call per POST.

Input parameters:

- `context` (object)
- `cost_scenario`
- `criteria` (array)
- `limit` (integer)
- `locale` (string)
- `priority` (object, required)
- `reference_id`
- `requirements` (array)
- `view` (object)

### `read_choice` (~212 tokens)

Read a software choice

Public read: capabilities discovers IDs and context vocabulary; candidates finds IDs for a priority; compare compares 2–3 IDs; specification reads one dossier. Same operation/input with representation detail, transport.resume and reference reads a snapshot field or page. On 409 restart summary. No account or writes. Sources, unknowns and dated limits remain explicit. Read the single JSON content.text Outcome (no structuredContent). Candidate priority operators by discovered value_type: boolean equals true only; quantity (integer) or amount ({minor,currency,tax_basis}) equals, at_least, at_most; set equals, or contains with a nonempty array; enum equals a member of enum_values. Text is not a candidate priority. Use the request schema for required keys and vocabularies for values; comparison_rule does not define priority operators or imply superiority.

Input parameters:

- `input` (object)
- `operation` (string, required)
- `reference` (object)
- `representation` (string)
- `resume` (object)

### `watch_choice` (~136 tokens)

Document a watched software choice

Requires a Bearer token and an existing owned NEED watch. bind explicitly attaches a canonical comparison request at expected_revision (optional explicit reset_baseline); review checks the current accepted documentary build; get reads the retained state and events with after/limit (1–50). No new watch, purchase or notification. A conflict requires an explicit caller decision; no automatic retry or reset.

Input parameters:

- `after` (integer)
- `expected_revision` (integer)
- `limit` (integer)
- `operation` (string, required)
- `request` (object)
- `reset_baseline` (boolean)
- `watch_id` (string, required)

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/ai-hodds-hodds/hodds#diagnostics

## Score history

- 2026-11-05: 68
- 2026-11-04: 68
- 2026-11-03: 67
- 2026-11-02: 67
- 2026-11-01: 66
- 2026-10-31: 66
- 2026-10-30: 65
- 2026-10-29: 65
- 2026-10-28: 65
- 2026-10-27: 64
- 2026-10-26: 64

## Common questions

### What is the HODDS MCP server?

HODDS is an MCP server listed in the public MCP registry as ai.hodds/hodds. Find software, SaaS and APIs for a need in a sourced catalogue organised by business process. This page covers its hosted endpoint (https://hodds.ai/mcp).

### Is the HODDS MCP server safe to use?

HODDS scores 68 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the HODDS MCP server expose?

HODDS exposes 21 tools: search_solutions, get_solution, list_processes, send_feedback, watch_need, and 16 more. Their descriptions and schemas cost roughly 3,084 tokens of context every time the server is loaded.

### Does the HODDS MCP server require authentication?

No. We connected to HODDS without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.

### Is the HODDS MCP server still maintained?

HODDS is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- Remote endpoint: https://hodds.ai/mcp
- Website: https://hodds.ai/connect/
- Changelog RSS feed: https://verifymcp.io/servers/ai-hodds-hodds/hodds.xml
- Changelog JSON feed: https://verifymcp.io/servers/ai-hodds-hodds/hodds.json
- HTML version of this page: https://verifymcp.io/servers/ai-hodds-hodds/hodds
