kleinanzeigen-mcp
Read-only access to public kleinanzeigen.de listings through a local browser session: search listings by query with optional location/radius, price range, sort order and multi-page walking, plus retrieval of a single listing's details by id or URL.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@kleinanzeigen-mcpsearch for a used Mac Mini M4 under 500 euros near Berlin"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
kleinanzeigen-mcp
Unofficial project. Not affiliated with, endorsed by, or connected to Kleinanzeigen. "Kleinanzeigen" is used only to describe what the software talks to. This software performs user-directed browser automation on publicly available listings — no account, no login.
A read-only Model Context Protocol server for public kleinanzeigen.de listings. It lets an AI agent search listings and read a single listing through a local browser session.
No AI, no chat UI, no cloud service, no login, no messaging.
Acceptable use
The tool reads public listings, one request at a time, on behalf of a single person. It deliberately does not:
log in, create accounts, or touch any account,
read inboxes, send messages, or manage saved searches,
solve or bypass CAPTCHAs, challenges or access controls,
rotate proxies or spoof fingerprints to evade blocks,
crawl or bulk-export listings.
Every action maps to one user request: one search, one listing. Searches are capped at 10 result pages. You are responsible for complying with the terms of service of any site you access through this software.
Related MCP server: Marketplace Finder MCP Server
Requirements
Node.js >= 20
Install
From npm:
npm install -g @washedguy/kleinanzeigen-mcp
npx patchright install chromiumOr from a checkout:
npm install
npx patchright install chromium
npm run buildThe browser runtime is Patchright,
a drop-in Playwright fork that closes Playwright's automation leaks
(Runtime.enable, navigator.webdriver). If a real Google Chrome is installed it
is used automatically for a more realistic fingerprint; override with
KLEINANZEIGEN_CHANNEL=chrome|msedge|bundled.
Configure the MCP client
The server speaks MCP over stdio.
{
"mcpServers": {
"kleinanzeigen": {
"command": "npx",
"args": ["-y", "@washedguy/kleinanzeigen-mcp"]
}
}
}From a checkout, point at the built entrypoint instead:
{
"mcpServers": {
"kleinanzeigen": {
"command": "node",
"args": ["/path/to/kleinanzeigen-mcp/dist/index.js"]
}
}
}Tools
Tool | Input | Returns |
|
|
|
|
|
|
sort is relevance (default), newest, price_asc or price_desc.
location takes a city or postal code and combines with radiusKm. maxPages
(1–10) walks the numbered result pages and de-duplicates by listing id. Note that
promoted "Top-Anzeigen" are pinned to the top and ignore sorting.
Errors
Failures come back as small, safe payloads — never browser stack traces:
{ "error": "CHALLENGE_REQUIRED", "message": "Kleinanzeigen presented a challenge (e.g. CAPTCHA). Try again later from a normal browser session." }Codes: CHALLENGE_REQUIRED, NAVIGATION_ERROR, LISTING_NOT_FOUND,
RATE_LIMITED, INVALID_INPUT, INTERNAL_ERROR.
Examples
const { results } = await searchListings({ query: "Mac Mini M4", maxPrice: 500, sort: "price_asc" });
const listing = await getListing({ id: results[0].id });How it works
MCP and browser automation are strictly separated: the MCP layer only validates inputs and formats outputs, and never touches the browser.
src/
├── index.ts # stdio entrypoint
├── mcp/ # tools, schemas, response shape
├── kleinanzeigen/ # browser session, page readers, parsing, domain models
└── types/ utils/Search results and listings are parsed from Kleinanzeigen's server-rendered HTML into domain models; raw HTML never reaches the MCP client.
Debugging
kleinanzeigen-mcp-debug # or: npm run debugOpens a visible browser and saves every page (and client-side route change) as
HTML plus an index.jsonl into ./debug-snapshots/. To capture from normal tool
calls instead:
KLEINANZEIGEN_SAVE_HTML=1 npm start
# or: KLEINANZEIGEN_SNAPSHOT_DIR=/tmp/ka-snaps npm run devSnapshots may contain public listing data and are git-ignored — do not commit them.
Development
npm run dev # stdio server with watch mode
npm run verify # typecheck + lint + tests (run before committing)
npm run check # Biome lint/format/import-sort (write)
npm run test # node:test via tsxLinting and formatting use a single dev dependency
(Biome); configuration is in biome.json.
Security
No login, credentials, cookies or tokens: the server only reads public pages.
Sessions are not persisted.
Challenges are never solved or bypassed: the server returns
CHALLENGE_REQUIRED.No proxy rotation, no account creation, no CAPTCHA solving, no bulk scraping.
Logs go to stderr only (stdout is the MCP transport).
Limitations
Read-only, public listings. No account features.
IP reputation is out of scope. If Kleinanzeigen temporarily blocks your IP range, wait it out and reduce request frequency.
Promoted listings appear above the requested sort order.
Available Tools
2 toolsget_listingGet listingARead-only
Open a single Kleinanzeigen listing and return its normalized details. Provide either id or url. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Kleinanzeigen ad id. | |
| url | No | Full listing URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so 'Read-only' largely restates structured data rather than adding it. The description does add that the returned data is 'normalized' and that only one listing is fetched, but says nothing about failure modes, missing ids, or rate limiting.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and resource; every clause carries information (action, target, return, invocation, safety) with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return burden and largely meets it by saying it returns 'normalized details' of one listing. It could be more specific about what fields the normalized payload contains, which is the only real gap for this two-parameter read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds a genuinely useful semantic the schema lacks: the two optional parameters are alternatives ('provide either `id` or `url`'), clarifying that one is required despite neither being marked required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource ('Open a single Kleinanzeigen listing') plus the outcome ('return its normalized details'), which distinguishes it from the plural sibling search_listings implicitly via 'single'. It never names the sibling, so differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'single listing' versus the search sibling, and the 'either `id` or `url`' note signals one way to invoke it. There is no explicit when-to-use/when-not or direct reference to search_listings for the multi-result case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_listingsSearch listingsBRead-only
Search Kleinanzeigen.de for listings and return normalized summaries. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | Sort order. Defaults to relevance. | |
| query | Yes | Search keywords, e.g. "Mac Mini M4". | |
| location | No | Optional location or postal code. | |
| maxPages | No | How many result pages to fetch (1-10, default 1). | |
| maxPrice | No | Maximum price in EUR. | |
| minPrice | No | Minimum price in EUR. | |
| radiusKm | No | Search radius in km. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so 'Read-only' is largely redundant with structured data. The only added value is 'return normalized summaries,' which hints at output shaping but doesn't say what normalization entails or whether results are paginated/capped.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short, front-loaded sentences with the core action first. Slight waste in the trailing 'Read-only,' which repeats the annotation rather than adding new information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of describing return values; 'normalized summaries' is the only signal about result shape and field content. The parameter surface is fully covered by the schema, but the return format and any result caps remain unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all seven parameters (query, location, price bounds, sort enum, radiusKm, maxPages) are already documented in the schema. The description adds no filtering, formatting, or default information beyond it, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (search), the resource (listings), the source (Kleinanzeigen.de), and the return shape (normalized summaries). It does not explicitly distinguish itself from the sibling get_listing, though the search-vs-fetch-detail split is obvious from the names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent can infer this is the entry point for keyword discovery and get_listing is for detail retrieval, but the description never says when to use one over the other or mentions the sibling. No prerequisites or exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.2.0- First observed
get_listing - First observed
search_listings
TDQS
Scored across 2 tools
search_listings and get_listing have clearly distinct purposes: one performs a query and returns multiple summaries, the other retrieves a single listing by id or URL. There is no overlap or risk of misselection.
Both tool names follow a consistent verb_noun snake_case pattern (search_listings, get_listing) and accurately reflect read-only behavior. The convention is predictable and unambiguous.
With only two tools, the surface feels thin for a marketplace MCP. While search and detail retrieval are core, the server lacks ancillary tools that would make it feel well-scoped (e.g., category browsing or seller info).
The core read-only workflow is covered: users can search listings and retrieve full details for a single listing. Minor gaps exist, such as accessing seller profiles or navigating categories, but agents can work around them for basic browsing.
Maintenance
Related MCP Connectors
Search and browse global classifieds across 80 markets. No auth required for read-only access.
Search and discover local community listings, classifieds, services and events.
Search products in nearby stores. Agents can also list items for sale on a user's behalf.
Search Facebook Marketplace, inspect listings and analyze deals. Paid Spottable Pro/Max required.
Related MCP Servers
- FlicenseNot gradedqualityFmaintenanceEnables AI agents to search and retrieve listings from Sweden's largest second-hand marketplaces, Blocket and Tradera. Returns unified data including prices, images, seller information, and direct links to listings.9-
- FlicenseNot gradedqualityDmaintenanceEnables AI agents like claude.ai to search online marketplaces (e.g., Facebook Marketplace) through your own logged-in browser, returning structured listings and details.-
- AlicenseAqualityAmaintenanceEnables AI agents to search and monitor Dutch and Belgian classifieds (Marktplaats and 2dehands) for listings, seller profiles, and categories.832 PyPI4MIT
- AlicenseNot gradedqualityBmaintenanceEnables searching multiple second-hand marketplaces simultaneously from a local command line or AI assistant, providing unified results with pricing insights while respecting each source's terms and robots.txt.AGPL 3.0