Transport sequence
Negotiate capabilities before calling a tool.
The MCP lifecycle and the CleanedWeb runtime gate are separate checks; both must pass.
- 01InitializeProtocol version
- 02NegotiateTools + resources
- 03AuthorizeKey stays in adapter
- 04InvokeBounded tool input
- 05ReturnResult + receipt
| Concern | REST | MCP |
|---|---|---|
| Discovery | Capabilities endpoint | Initialize + tools |
| Authentication | Bearer header | Trusted adapter |
| Contract | OpenAPI + JSON Schema | Tool schemas |
| Metering | Delivery receipt | Receipt in structured result |
Current status
Machine access is release-gated. Read GET /v1/capabilities and require
machine_access.enabled === true before using API-key authentication or MCP. When
the flag is false, no public MCP or API-key surface should be assumed from this
static guide.
When enabled, the Streamable HTTP endpoint is https://app.cleanedweb.com/mcp. It
uses MCP protocol revision 2025-11-25, JSON-RPC 2.0, stateless JSON responses, and
workspace-scoped Bearer API keys. The same key can call the HTTP property API.
Published tool mapping
The gated server publishes exactly these tools through tools/list:
| MCP tool | Equivalent HTTP operation | Unit behavior |
|---|---|---|
cleanedweb_capabilities |
GET /v1/capabilities |
No delivery charge |
cleanedweb_list_markets |
GET /v1/markets |
No delivery charge |
cleanedweb_count_properties |
POST /v1/properties/count |
No delivery charge |
cleanedweb_search_properties |
POST /v1/properties/search |
Durable metered receipt |
cleanedweb_get_property |
GET /v1/properties/{property_entity_id} |
No delivery charge |
cleanedweb_list_property_changes |
GET /v1/properties/{property_entity_id}/changes |
No delivery charge |
Every tool includes an outputSchema and returns the untouched API result in
structuredContent. Capabilities, markets, count, one-property, and property-change tools are
annotated read-only. Search is intentionally not annotated read-only because it commits a
durable Unit receipt; it is annotated non-destructive, idempotent for an exact request,
and closed-domain. All six tools use openWorldHint: false. Each output schema accepts
the tool's success object or the stable structured error object used when isError is
true, so clients can validate both outcomes.
Keep this first tool surface retrieval-only apart from the metered receipt side effect. Webhook management, account administration, saved-search mutation, and authentication endpoints should not be exposed as agent tools without separate approval and confirmation controls.
Published resources
The server declares resources with listChanged: false. resources/list publishes:
- live runtime capabilities;
property-profile-v2;property-profile-field-catalog-v2;property-event-v1;error-v1.
These JSON resources are annotated for the assistant audience with explicit priority. Clients should read capabilities and the property schema first, then the field catalog for semantics. Resource annotations are hints; schema validation and runtime gates remain the enforcement boundary.
Authentication boundary
The MCP client owns a cw_<environment>_... Bearer key and must keep it out of
prompts, tool arguments, tool results, URLs, traces, and logs. Keys are scoped to one
workspace, have only properties:read, are stored as hashes, and can be revoked.
The full secret is returned only when the key is created.
Every connection is authenticated. If an Origin header is present, it must match
https://app.cleanedweb.com. The shared per-key request limit returns HTTP 429
with Retry-After; do not defeat it by spreading retries across processes.
Tool input example
An adapter can accept the same property-search fields defined by OpenAPI:
{
"market": "LU",
"response_schema": "property-profile-v2",
"deal_type": ["buy"],
"location": "Belair",
"location_place_id": "lux-neighbourhood-belair",
"property_categories": ["apartment"],
"max_price": 1000000,
"min_bedrooms": 2,
"limit": 100,
"max_units": 100,
"idempotency_key": "search-2026-08-04T10:00:00Z"
}
Validate this object against OpenAPI before sending it. Do not add free-form SQL, arbitrary URLs, acquisition controls, or a generic HTTP passthrough to the tool.
Tool output policy
Return the API response without renaming contract fields. Preserve:
property_entity_idfor canonical identity;schema_versionfor validation;snapshot.dataUpdatedAt,projectionGenerationId,availableRecords,returned,has_more, andnext_cursorfor acceptance decisions;sourcesfor provenance.
For conversational use, the adapter may add a compact summary beside the untouched
structured response. It must follow the cursor with the unchanged query when
has_more is true, restart after snapshot_changed, and not claim freshness
when the runtime timestamp is absent or outside policy.
Metering example
Call capabilities before a potentially broad search. When machine access is ready, the runtime publishes the exact delivery rates:
{
"unit_costs": {
"first_delivery": 1,
"unchanged_delivery_within_7_days": 0.1,
"listing_event_within_7_days": 0.25
}
}
cleanedweb_search_properties requires max_units, a positive bounded limit, and
an idempotency_key. Charging, the response receipt, and delivery classification
commit atomically. An exact retry returns the recorded receipt without charging
again. A changed request with the same key returns idempotency_conflict.
Use cleanedweb_count_properties for exact "how many" questions. It accepts the
search filters but no sort, cursor, limit, spend ceiling, or idempotency key. It
returns only the exact total and projection identity, and consumes no delivery
Units. For "more than two bedrooms", send min_bedrooms: 3.
An empty unit_costs object still means machine charging is not ready. Do not
estimate a charge or invoke the search tool in that state.
Error mapping
Map the stable API error object to a tool error without discarding its fields:
{
"schema_version": "error-v1",
"error": {
"code": "invalid_request",
"message": "Request validation failed",
"details": {}
}
}
The adapter may retry only transient availability failures. It should return authentication, entitlement, validation, ambiguity, and not-found errors to the calling agent for a changed plan or user decision.
Standards and further reading