Skip to main content
Glama
frankwiersma

tweakers-aanbod-mcp

by frankwiersma

tweakers-aanbod-mcp

MCP server for Tweakers Vraag & Aanbod, the Dutch second-hand marketplace for electronics. It lets Claude (or any MCP client) search listings in a category, filter on price, condition, seller type and distance, and open a single advertisement.

"Find laptops between €300 and €550 within 30 km of Utrecht, nearest first, and open the best one."

For new products and shop prices, see rleroi/tweakers-mcp (Pricewatch). This server covers the second-hand side.

Install

Needs uv (brew install uv).

Claude Code

claude mcp add tweakers-aanbod -- uvx --from git+https://github.com/frankwiersma/tweakers-aanbod-mcp tweakers-aanbod-mcp

Claude Desktop: add this to ~/Library/Application Support/Claude/claude_desktop_config.json (Windows: %APPDATA%\Claude\claude_desktop_config.json) and restart Claude Desktop. Desktop does not use your shell PATH, so use the absolute path from which uvx:

{
  "mcpServers": {
    "tweakers-aanbod": {
      "command": "/absolute/path/to/uvx",
      "args": ["--from", "git+https://github.com/frankwiersma/tweakers-aanbod-mcp", "tweakers-aanbod-mcp"]
    }
  }
}

Related MCP server: marktplaats-mcp

Tools

Tool

What it does

list_categories(contains)

The ~220 Vraag & Aanbod categories with their slugs (laptops, videokaarten, ...)

search_listings(category, ...)

One page (~40 listings) of a category: title, price, date, seller rating, city, distance

get_listing(listing_id)

The full advertisement: description, condition, warranty, age, delivery, payment, photos, seller

search_listings filters on Tweakers' side, so a narrow search costs one request:

Argument

Example

Notes

keyword

"thinkpad t14"

min_price, max_price

300, 550

Euros

near, max_distance_km

"Utrecht", 30

Place name or full Dutch postcode (3521DT). Each listing then carries distance_km.

conditions

["new", "good"]

new, good, visibly_used, defective

seller_type

"business"

private or business

min_seller_rating

4

1 to 5 stars

sort

"price_low"

newest, oldest, price_low, price_high, nearest, best_rated

page

2

include_wanted

true

Also return "gevraagd" posts

How it works

It reads the same public pages a browser does: the category listing at /<category>/aanbod/ (with the query parameters of its filter form) and the advertisement at /aanbod/<id>/. It stays out of the paths that robots.txt disallows (/aanbod/zoeken, /ajax, ...), which is why every search needs a category.

Requests go out one at a time, at least two seconds apart. Tweakers rate limits busy IPs; when that happens the tool returns a clear error and you can retry after a minute. Nothing is cached to disk or stored.

Caveats

  • Unofficial and not affiliated with Tweakers. It parses HTML, which can change at any time.

  • Listings include seller nicknames and locations as Tweakers shows them. Tweakers' terms do not allow collecting other members' personal data systematically, so use this for your own searches, not for building datasets.

  • Tweakers ignores a place name it cannot resolve. The tool detects that and returns an error instead of unfiltered results.

  • An old listing id still opens; check posted_at.

Development

git clone https://github.com/frankwiersma/tweakers-aanbod-mcp && cd tweakers-aanbod-mcp
uv sync
uv run pytest                # offline, against fixtures in tests/fixtures
uv run tweakers-aanbod-mcp   # stdio server

MIT licensed.

Available Tools

3 tools
get_listingA
Read-only

Open one advertisement: full description, condition, warranty, age, delivery and payment options, photos, and the seller's location, rating and history. Old ids still resolve, so check posted_at.

NameRequiredDescriptionDefault
listing_idYesThe `id` from search_listings, or the number in /aanbod/<id>/.

Output Schema

NameRequiredDescription
idYes
ageYes
urlYes
titleYes
viewsYes
imagesYes
sellerYes
paymentYes
deliveryYesHow the item changes hands, e.g. 'ophalen en (pakket)post nationaal'.
warrantyYes
conditionYes
posted_atYes
price_eurYes
price_textYes
descriptionYes
pricewatch_urlYesLinked Pricewatch product, if the seller picked one.
shipping_costsYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the description needn't restate safety. It adds genuinely non-obvious behavior: legacy ids still resolve, meaning the returned record may be stale and `posted_at` should be inspected — a caveat an agent could not derive from the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the action and the returned payload, with the staleness caveat placed last where it belongs. No filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so enumerating return fields is a bonus rather than a necessity, and the stale-id behavior is covered. What's missing is only edge-case handling (invalid/removed ids, how precise the seller location is) — minor for a single-record fetch.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and already explains where listing_id comes from (search_listings `id` or the /aanbod/<id>/ number), so the baseline is 3. The description adds the extra semantic that an id need not be current, which changes how an agent should interpret and validate the argument.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Open one advertisement") and enumerates exactly what the record contains — description, condition, warranty, delivery/payment, photos, seller info. The singular "one" implicitly contrasts with search_listings, but no sibling is named, so an agent must infer the split.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: this is the detail fetch for an item found via search_listings, and the id-source hint lives in the schema rather than the description. The closing note about old ids is a data-freshness caveat rather than explicit when/when-not guidance or a named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_categoriesA
Read-only

List Vraag & Aanbod categories (about 220, e.g. laptops, videokaarten, cameras).

NameRequiredDescriptionDefault
containsNoCase-insensitive text to match in slug or name.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds useful context about result volume (~220 entries) and the domain of category values, but says nothing about ordering, pagination, or how the 'contains' filter narrows the set.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the verb and resource, and every clause earns its place by adding cardinality and concrete examples. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values needn't be explained, and the single parameter is fully covered by the schema. The remaining gap is minor: it doesn't say what happens with large unfiltered results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the single 'contains' parameter is fully documented in the schema as a case-insensitive slug/name match. The description contributes nothing about the filter (e.g. that omitting it returns the full ~220 list), so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List Vraag & Aanbod categories') and adds cardinality (~220) plus concrete examples (laptops, videokaarten, cameras), so an agent knows exactly what comes back. It does not explicitly contrast with search_listings or get_listing, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

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 lookup to call before filtering listings by category, but the description never says when to use it versus search_listings or get_listing. 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.

search_listingsA
Read-only

Search one Vraag & Aanbod category. Filtering happens on Tweakers' side, so narrow filters cost no extra requests. Returns about 40 listings per page with price, seller rating and city.

NameRequiredDescriptionDefault
nearNoPlace name ('Utrecht') or full Dutch postcode ('3521DT'). Adds the distance to each listing. A 4-digit postcode alone may resolve to Belgium.
pageNoResult page; each page holds about 40 listings.
sortNonewest
keywordNoWords that must appear in the listing.
categoryYesCategory slug from list_categories, e.g. 'laptops'.
max_priceNoMaximum asking price in euros.
min_priceNoMinimum asking price in euros.
conditionsNoKeep only these conditions.
seller_typeNoPrivate sellers or businesses only.
include_wantedNoAlso return 'gevraagd' (wanted) posts.
max_distance_kmNoOnly listings within this distance of `near`.
min_seller_ratingNoMinimum seller rating, 1 to 5 stars.

Output Schema

NameRequiredDescription
urlYes
pageYes
pagesYes
totalYes
listingsYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, and the description adds useful behavior beyond that: filtering is server-side, narrow filters do not cost extra requests, and each page returns about 40 listings with price, seller rating and city. It does not cover auth, rate limits, or edge-case behavior, but it goes meaningfully beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three tight sentences with the category-scoping constraint and filtering-cost caveat front-loaded. Every sentence adds useful information without repeating the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 12 parameters, 92% schema coverage, annotations, and an output schema, the description only needs to supply high-value context. It does so by noting server-side filtering, page size, and returned listing fields. The main remaining gap is sibling routing, but the essential search behavior is covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 92%, so the schema already documents nearly all parameters. The description adds the page size and server-side filtering context, but it does not add parameter-specific semantics beyond what the schema provides, making 3 the appropriate baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Search') and resource ('listings') constrained to one category, so the core purpose is clear. It does not explicitly distinguish itself from the sibling tools list_categories or get_listing, though the category-scoped search framing helps.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies usage by saying to search one category and notes that narrow filters cost no extra requests, which encourages precise filtering. However, it does not explicitly say when to use this versus list_categories or get_listing, nor does it state any exclusions or prerequisites.

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.

  1. 3 tool updatesv0.1.0
    • First observedget_listing
    • First observedlist_categories
    • First observedsearch_listings

TDQS

A4/5.0

Scored across 3 tools

Disambiguation5/5

The three tools form a clear funnel: browse categories, search within a category, then open a specific listing. Each has a distinct resource and action, with no overlapping purposes. An agent can easily select the right tool.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: list_categories, search_listings, get_listing. There are no mixed conventions or vague verbs.

Tool Count5/5

Three tools are exactly enough for a read-only marketplace browsing server: one for category discovery, one for search, and one for detail retrieval. No tool feels redundant or missing within that narrow scope.

Completeness4/5

The core browse-search-detail workflow is fully covered, including categories, listings, and rich detail such as seller history. Minor gaps exist, such as no explicit cross-category search or pagination control, but agents can work around them via the documented search behavior.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server for interacting with Bazos.cz, Bazos.sk, Bazos.at, and Bazos.pl. Supports searching ads, retrieving ad details, and fetching user ratings.
    3
    113 npm
    4
    AGPL 3.0
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to search and monitor Dutch and Belgian classifieds (Marktplaats and 2dehands) for listings, seller profiles, and categories.
    8
    63 PyPI
    4
    MIT