# Fixando public price MCP

> Read-only structured access to the same service price estimates published on Fixando. No account, API key or OAuth is required.

## Connection

- Endpoint: `https://www.fixando.de/mcp`
- Transport: stateless Streamable HTTP, JSON responses.
- Method: POST. GET on the MCP endpoint returns 405.
- Content-Type: `application/json`
- Accept: `application/json, text/event-stream`
- Supported protocol versions: 2025-11-25, 2025-06-18, 2025-03-26.
- No session ID or persistent SSE channel is required.
- Human guide: [/mcp/docs](/mcp/docs)
- Website retrieval guidance: [/llms.txt](/llms.txt)

This reference is for agents with an MCP client. Standard HTTP crawlers can read public HTML price pages and sitemaps; they do not execute MCP tools automatically. The MCP is for public price data, not a general website crawler or access to private marketplace data.

## Protocol sequence

1. POST `initialize` with a supported version, client capabilities and clientInfo.
2. Read the negotiated protocolVersion from the response.
3. Send `notifications/initialized` without an id; successful notifications have HTTP 202 and no body.
4. Send `MCP-Protocol-Version` with the negotiated version on subsequent requests.
5. Call `tools/list` for the current public tool definitions.
6. Call `tools/call` with a tool name and its arguments.

Initialization:

```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"example-agent","version":"1.0"}}}
```

Notification:

```json
{"jsonrpc":"2.0","method":"notifications/initialized"}
```

Tool discovery:

```json
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
```

## Price retrieval workflow

1. Use `get_markets` to discover supported market codes, languages, currencies and endpoints. Do not assume every country has price data.
2. Use `search_price_categories` to discover root, parent or service price-page candidates for the selected market. Queries match the selected language. Do not invent category IDs or page slugs.
3. For a location-specific query, use `search_price_locations`. A municipality's cc ID is scoped to its dd district; retain both IDs. dd=0 means no district restriction for location discovery.
4. Use `get_prices` with a returned canonical page URL, or with site_code, catid and optional dd/cc. A URL cannot be combined with category/location IDs. A URL and optional explicit market/language must agree.
5. For search pagination, pass next_offset as the next offset and keep the same filters. Stop when next_offset is null. Fetch only the pages needed for the query; do not enumerate every category/location combination without a reason.
6. Cite the canonical url returned by get_prices as the public source.

Market discovery:

```json
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_markets","arguments":{}}}
```

Example service search in Portugal:

```json
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"search_price_categories","arguments":{"site_code":"pt","query":"limpeza","limit":5}}}
```

When a canonical public price-page URL is already known, get_prices can resolve it directly; a prior search is not required.

## Interpret and cite the response

Successful tools return structuredContent plus the same JSON serialized in a text content block. Price lookups include status, resolved market/language, currency, canonical url, category, location and a prices array.

- Preserve the currency and billing_type_id/unit. Do not compare per-hour and per-project amounts as if they were the same unit.
- minimum, central and maximum are the rounded values published on the website.
- central_statistic is median for request-based calculations and mean for legacy data.
- range_statistic is p10_p90 for request-based calculations and legacy_range for legacy data. Do not describe P10-P90 as a measured minimum/maximum or a guaranteed quote.
- date identifies the published logical snapshot, including unchanged records carried forward by incremental publication. It is not an individual quote date or an invented fixed observation window.
- source contains the actual category and geographic IDs used. fallback=true means the selected reference has a broader scope than requested. Disclose that scope when relevant.
- status=no_data with an empty prices array is a valid page without sufficient public prices. Do not invent missing numbers or interpret no_data as a zero price.
- Estimates are indicative, not binding quotes. Raw quotes and admin-only statistics are unavailable.

## Limits and retry behaviour

- Search page size: 20 by default, maximum 50.
- Request limit: 120 per client IP per minute, shared across tools and markets.
- HTTP 429: wait for Retry-After before retrying. Do not change IPs or markets to evade the limit.
- HTTP 503: temporary unavailability. Back off; do not retry in a tight loop.
- JSON-RPC errors describe protocol problems. isError=true describes a failed tool call; use its message to correct arguments.
- Save X-Request-ID for diagnostics. Access metadata is recorded in a dedicated log; full response payloads are not retained.
- Respect robots directives and access controls when retrieving linked HTML pages. This documentation does not grant access to private pages.

## Current public tool schemas

The definitions below are generated from the same registry used by tools/list. tools/list is authoritative if a previously fetched copy of this document differs.

```json
[
    {
        "name": "get_markets",
        "description": "List supported Fixando price markets, currencies, languages and MCP endpoints. Start here to select a site_code.",
        "inputSchema": {
            "type": "object",
            "properties": {},
            "required": [],
            "additionalProperties": false
        },
        "annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false
        }
    },
    {
        "name": "search_price_categories",
        "description": "Find root, parent and service price-page candidates by name, optionally for a location. Includes noindex and geographic fallback pages. Use get_prices to check price availability; discovery does not guarantee data.",
        "inputSchema": {
            "type": "object",
            "properties": {
                "site_code": {
                    "type": "string",
                    "description": "Market code returned by get_markets, for example pt or de.",
                    "maxLength": 3
                },
                "lang": {
                    "type": "string",
                    "description": "Supported market language; defaults to the market language.",
                    "maxLength": 10
                },
                "query": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Optional case-insensitive name search."
                },
                "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50
                },
                "offset": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000
                },
                "kind": {
                    "type": "string",
                    "maxLength": 7,
                    "enum": [
                        "root",
                        "parent",
                        "service"
                    ],
                    "description": "Optional category hierarchy level."
                },
                "dd": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "District ID from search_price_locations; 0 means national."
                },
                "cc": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Municipality ID from search_price_locations; requires its district dd."
                }
            },
            "required": [
                "site_code"
            ],
            "additionalProperties": false
        },
        "annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false
        }
    },
    {
        "name": "search_price_locations",
        "description": "Find districts and municipalities in one market. Use returned dd/cc IDs with get_prices or search_price_categories. Optionally restrict municipalities to dd.",
        "inputSchema": {
            "type": "object",
            "properties": {
                "site_code": {
                    "type": "string",
                    "description": "Market code returned by get_markets, for example pt or de.",
                    "maxLength": 3
                },
                "lang": {
                    "type": "string",
                    "description": "Supported market language; defaults to the market language.",
                    "maxLength": 10
                },
                "query": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "Optional case-insensitive name search."
                },
                "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50
                },
                "offset": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000
                },
                "dd": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "District ID from search_price_locations; 0 means national."
                }
            },
            "required": [
                "site_code"
            ],
            "additionalProperties": false
        },
        "annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false
        }
    },
    {
        "name": "get_prices",
        "description": "Read the same current prices published on a Fixando price page. Supply an absolute HTTPS price-page url OR site_code with catid and optional dd/cc; do not mix URL and IDs. Returns rounded values, currency, billing unit, median/mean semantics, source scope and fallback. A valid page without sufficient data returns no_data. No raw quotes or admin-only statistics.",
        "inputSchema": {
            "type": "object",
            "properties": {
                "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "description": "Absolute HTTPS Fixando price-page URL; never fetched remotely."
                },
                "site_code": {
                    "type": "string",
                    "description": "Market code returned by get_markets, for example pt or de.",
                    "maxLength": 3
                },
                "lang": {
                    "type": "string",
                    "description": "Supported market language; defaults to the market language.",
                    "maxLength": 10
                },
                "catid": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Root, parent or service category ID from search_price_categories."
                },
                "dd": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "District ID from search_price_locations; 0 means national."
                },
                "cc": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Municipality ID from search_price_locations; requires its district dd."
                }
            },
            "required": [],
            "additionalProperties": false,
            "oneOf": [
                {
                    "required": [
                        "url"
                    ],
                    "not": {
                        "anyOf": [
                            {
                                "required": [
                                    "catid"
                                ]
                            },
                            {
                                "required": [
                                    "dd"
                                ]
                            },
                            {
                                "required": [
                                    "cc"
                                ]
                            }
                        ]
                    }
                },
                {
                    "required": [
                        "site_code",
                        "catid"
                    ],
                    "not": {
                        "required": [
                            "url"
                        ]
                    }
                }
            ]
        },
        "annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false
        }
    }
]
```
