Skip to main content
Glama

Partle Marketplace MCP Server

Model Context Protocol server for the Partle marketplace โ€” let your AI shop here: search products and stores, get prices and purchase links, or ask it to add a listing for you, all without leaving your assistant.

Live product and store coverage is available through the get_stats tool. Public catalogue reads need no auth. Writes and private inventory reads need OAuth or a pk_โ€ฆ API key.

Two ways to run it

Point your MCP client at:

https://partle.rubenayla.xyz/mcp/

That's it. Streamable HTTP transport, MCP spec 2025-06-18. Per-client install instructions: /documentation/mcp-setup/.

Local stdio (for clients that prefer installable servers, or for Glama / Smithery scoring)

pip install partle-mcp
partle-mcp

Or with uvx (no install):

uvx partle-mcp

Or with Docker:

docker run --rm -i ghcr.io/rubenayla/partle-mcp

The stdio package proxies to the public REST API at https://partle.rubenayla.xyz, so you don't need a database or local backend.

Claude Desktop / Claude Code (stdio)

{
  "mcpServers": {
    "partle": {
      "command": "uvx",
      "args": ["partle-mcp"]
    }
  }
}

Related MCP server: Google Maps Places MCP

Tools (20 total)

Read (no auth)

Tool

Purpose

search_products

Search the catalog by name, price range, tags, store. Supports cross-language semantic search.

get_product

Full record for one product by ID.

search_stores

Search/list stores by name or address.

get_store

Full record for one store by ID.

get_stats

Platform-wide totals.

search_wanted

Browse public buy requests at /wanted โ€” things people are looking to buy but haven't found. Cross-reference against search_products to offer matches.

Write (authenticated)

Two ways to authenticate, in preference order:

  1. OAuth (recommended) โ€” when you add Partle as a custom connector in claude.ai or any MCP client that supports OAuth, the client walks you through a one-click consent screen and attaches a bearer token automatically. Scopes: products:read, products:write, inventory:read, inventory:write. Revoke at /account โ†’ Connected apps. RFC 9728 metadata at /.well-known/oauth-protected-resource; RFC 7591 dynamic client registration at /oauth/register.

  2. API key (fallback) โ€” pass an api_key parameter to any write tool. Generate at /account โ†’ API Keys. Use this when your client doesn't support OAuth (raw scripts, programmatic agents).

Products โ€” public catalog listings.

Tool

Purpose

create_product

Add a new listing. Set verified=false when an AI is proposing on behalf of an unconfirmed human.

update_product

Edit a listing you own.

delete_product

Remove a listing you own.

upload_product_image

Attach an image (base64 or URL).

delete_product_image

Remove an image from a product.

get_my_products

List products you've created.

The remote HTTP server also offers get_upload_url (re-fetches a signed upload URL for an existing product). Not exposed in this stdio package โ€” use the remote server if you need it.

Inventory โ€” private workshop tracking (owned / wanted / for_sale / sold / discarded). Private to the owner; does not appear on the public /wanted feed.

Tool

Purpose

get_my_inventory

List your inventory items. Filterable by status, project, free text.

add_inventory_item

Add a row in any lifecycle state.

update_inventory_item

Patch any field.

delete_inventory_item

Permanently remove a row.

mark_for_sale

Convenience: flip an owned item to for_sale and set an asking price.

mark_sold

Convenience: flip a for_sale item to sold.

Buy requests โ€” public demand-side posts on /wanted. Independent of personal inventory.

Tool

Purpose

create_buy_request

Post a public buy request (name, description, quantity, optional max_price and contact).

Feedback

Tool

Purpose

submit_feedback

Send freeform feedback about your integration experience.

Public REST API

Same data, also reachable as plain HTTP for clients without MCP support:

  • GET /v1/public/products?q=cerrojo&limit=10 โ€” search products

  • GET /v1/public/stores?q=Madrid&limit=10 โ€” search stores

  • GET /v1/public/wanted?q=bolt&limit=10 โ€” list open public buy requests

  • GET /v1/public/stats โ€” platform totals

  • POST /v1/public/feedback โ€” submit feedback

Base URL: https://partle.rubenayla.xyz. Rate-limited to 100 req/hour per IP.

Full docs: /documentation/ ยท OpenAPI: /openapi.json ยท Discovery: /.well-known/mcp.json.

Example

You: "Use Partle to find a drill under โ‚ฌ50."

Claude: (calls search_products(query="drill", max_price=50))

Returns Blackspur 13pc High Speed Drill Bit Set at โ‚ฌ4.99 (Lenehans, IE), Flotec Drill Pump 225 GPH at โ‚ฌ17.14 (Kooyman Megastore, NL), and a few more โ€” each with a partle_url to view the listing.

More examples in the setup guide.

License

Apache-2.0 โ€” see LICENSE.

Available Tools

18 tools
add_inventory_itemAInspect

Add an item to the caller's personal inventory. Requires an API key.

One creation tool covers all lifecycle states โ€” set status to match the user's intent: "I bought" โ†’ owned, "I want" โ†’ wanted, "I'm selling" โ†’ for_sale. Either product_id or name must be set. Not idempotent.

Args: api_key: Partle API key (prefix pk_). name: Freeform name for items not yet linked to a Partle product. product_id: Link to a canonical Partle product. status: Lifecycle. Default owned. quantity: How many. Fractional ok. Default 1. notes: Freeform multi-line text โ€” the dumping ground for anything not modeled as a column: extra URLs, comments, where stored, condition narrative, purpose, source, history, log entries. Markdown is fine. Put extra URLs here, not in another field. acquisition_price: What you paid. acquisition_currency: Currency of acquisition_price. purchased_at: ISO date (YYYY-MM-DD). asking_price: For status=for_sale. asking_currency: Currency of asking_price. condition: Free string โ€” typical: new, like_new, good, fair, poor. external_link: Primary click-through URL only (source listing, vendor page, manufacturer page). Exactly one. Additional URLs go in notes as markdown links. external_id: Stable identifier from the source system, used as a dedup key. Per-user unique when set โ€” same external_id can't appear twice for one user. Format is up to you (e.g. aliexpress:1005004714348221, amazon:order/.../line/1, content hash). Leave null for handwritten items. project: Tag for grouping.

Returns: The created inventory row.

Inputs: api_key (required), name, product_id, status, +11 more.

create_productAInspect

Create a new product listing on Partle. Requires an API key.

Use this when the user wants to add an item for sale. Each call creates a new record โ€” never call twice with identical input expecting only one record (it is not idempotent). For updates to existing products, use update_product.

Args: api_key: Partle API key, prefix pk_. Generate at https://partle.rubenayla.xyz/account. name: Product name. Required, 1โ€“200 chars. description: Long-form product description. Optional. price: Price in whole currency units, not cents. e.g. 15.99 means โ‚ฌ15.99. Max 100000. Omit for "ask the seller". currency: Currency symbol. Defaults to โ‚ฌ. Use $, ยฃ, etc. url: Link to the merchant's product page. Optional but recommended. store_id: ID of the store this product belongs to. Omit for a personal listing not tied to any store.

Returns: The created product record including its new id and canonical partle_url. Share partle_url with the user.

Inputs: api_key (required), name (required), description, price, +3 more.

delete_inventory_itemA
DestructiveIdempotent
Inspect

Permanently delete an inventory row. Caller must own it.

Args: api_key: Partle API key (prefix pk_). item_id: ID of the row to delete.

Returns: {"deleted": True, "id": item_id} on success.

Inputs: api_key (required), item_id (required).

delete_productA
DestructiveIdempotent
Inspect

Permanently delete a product listing and all its images. Destructive.

Use only when the user explicitly asks to remove a listing they own. Cannot be undone โ€” there is no soft-delete or trash bin. Idempotent: deleting a product that no longer exists returns 404, not an error state on your side.

The API key must own the product.

Args: api_key: Partle API key (prefix pk_). product_id: ID of the product to delete. Get from get_my_products.

Returns: {"deleted": product_id} on success.

Inputs: api_key (required), product_id (required).

delete_product_imageA
DestructiveIdempotent
Inspect

Remove a specific image from a product. Destructive, idempotent.

Use when an image was uploaded by mistake or the merchant updated their listing. The product itself is preserved โ€” only the image record and its file are removed. To remove the product entirely use delete_product.

Args: api_key: Partle API key (prefix pk_). product_id: ID of the product the image belongs to. image_id: ID of the image to delete. Visible in the images array of get_product responses.

Returns: {"deleted_image": image_id} on success.

Inputs: api_key (required), product_id (required), image_id (required).

get_my_inventoryA
Read-only
Inspect

List the caller's personal inventory items. Requires an API key.

Use when the user asks "what do I own?", "what's on my wishlist?", "what am I selling?". Pass status to filter; default returns all.

Args: api_key: Partle API key, prefix pk_. Generate at https://partle.rubenayla.xyz/account. status: Lifecycle filter. One of: owned, wanted, for_sale, sold, discarded. Omit for all. product_id: Filter rows linked to a specific Partle product. project: Exact-match filter on project tag. q: Substring search on name + notes. limit: Page size 1โ€“200, default 50. offset: Pagination offset.

Returns: {"items": [...], "count": int} โ€” each item carries id, status, name (or linked product), quantity, prices, etc.

Inputs: api_key (required), status, product_id, project, +3 more.

get_my_productsA
Read-only
Inspect

List products created by the API key's owner. Requires an API key.

Use this when the user asks "what have I listed?" or before bulk operations like updating prices across multiple of their products. Distinct from search_products, which searches the public catalog without owner scoping.

Read-only.

Args: api_key: Partle API key (prefix pk_). limit: Maximum results (1โ€“200, default 50).

Returns: {"result": [Product, โ€ฆ]} โ€” same shape as search_products.

Inputs: api_key (required), limit.

get_productA
Read-only
Inspect

Get the full record for a single product by its numeric ID.

Use this after search_products returns a candidate the user is interested in, when you need fields that aren't in the search summary (full description, all images, expiration, sold status). Don't loop get_product over many search results โ€” re-search with tighter filters instead.

Read-only. No authentication.

Args: product_id: The integer id from a product returned by search_products or shown on a Partle product page URL.

Returns: A single product object with all fields, including the canonical partle_url to share with the user.

Inputs: product_id (required).

get_statsA
Read-only
Inspect

Get top-level Partle platform statistics.

Use this for size questions ("how big is Partle?", "how many stores does Partle cover?"). Returns aggregate counts only โ€” no per-product or per-store data.

Read-only. No authentication. Cheap, but doesn't change often โ€” cache in long-running agents.

Returns: {"total_products": int, "total_stores": int, "last_updated": str, "api_version": str, "description": str}.

Inputs: no named parameters.

get_storeA
Read-only
Inspect

Get the full record for a single store by its numeric ID.

Use this after search_stores to retrieve fields that aren't in the search summary (full address, owner profile, contact details). For a list of products in that store, call search_products(store_id=โ€ฆ) instead โ€” this tool returns store metadata only.

Read-only. No authentication.

Args: store_id: The integer id from a store returned by search_stores.

Returns: A single store object with all fields.

Inputs: store_id (required).

mark_for_saleA
Idempotent
Inspect

Set status=for_sale and listing fields atomically.

Convenience wrapper for "list X for sale at Yโ‚ฌ". Caller must own the item.

Inputs: api_key (required), item_id (required), asking_price (required), asking_currency, +1 more.

mark_soldA
Idempotent
Inspect

Mark an inventory item as sold (status=sold). Caller must own it.

Inputs: api_key (required), item_id (required).

search_productsA
Read-only
Inspect

Search Partle's product catalog by name or description.

Use this when the user asks to find a specific product or browse products matching a query. Prefer this over search_stores when the intent is product-led ("find a drill") rather than store-led ("what stores are near Madrid"). Use get_product afterwards if the user wants full details for one specific result.

Read-only. No authentication. Rate-limited to 100 requests/hour per IP.

Args: query: Free-text search term (e.g. "wireless headphones", "cerrojo FAC", "drill bit"). Required even in semantic mode. min_price: Lower bound on price in EUR. Omit for no lower bound. max_price: Upper bound on price in EUR. Omit for no upper bound. tags: Comma-separated tag filter (e.g. "electronics,bluetooth"). Tags are AND-ed together. store_id: Restrict results to a single store. Use the integer id field from search_stores results. sort_by: One of price_desc, name_asc, newest, oldest. Omit to use the default search-relevance ranking. semantic: When True, runs a vector / cross-language search. Set this when the user's query may not match the listing language โ€” e.g. "drill" in English will also surface "taladro" (Spanish) and "Bohrmaschine" (German). Pure-English catalogs benefit less. limit: Maximum results (1โ€“100, default 20). Larger limits are slower and may exceed the rate budget faster. offset: Skip this many results before returning. Use for pagination (offset += limit on each follow-up call).

Returns: {"result": [Product, โ€ฆ]}. Each product includes id, name, price, currency, url, description, store (id / name / country), images, tags, and a canonical partle_url. Always share partle_url with the user so they can view the listing.

Inputs: query (required), min_price, max_price, tags, +5 more.

search_storesA
Read-only
Inspect

Search or list stores in the Partle marketplace.

Use this when the user asks store-led questions ("what hardware shops are in Madrid?") rather than product-led ones (use search_products for that). Pass no query to browse the whole catalog.

Read-only. No authentication. Rate-limited to 100 requests/hour per IP.

Args: query: Free-text search over store name and address. Omit to list all stores in default order. limit: Maximum results (1โ€“50, default 20).

Returns: {"result": [Store, โ€ฆ]}. Each store includes id, name, address, country, lat/lon (when geocoded), homepage, and type. Pass id to search_products(store_id=โ€ฆ) to filter the product catalog by that store.

Inputs: query, limit.

submit_feedbackAInspect

Send freeform feedback about your experience using Partle.

Use this when you encounter a confusing tool description, a broken response, missing data, or anything you'd want the maintainers to know. Especially valuable for AI agents โ€” your feedback becomes a signal we use to tune the API.

Not idempotent (each call adds a record). Don't loop. No PII required.

Args: feedback: Freeform text up to 5000 characters. Be specific โ€” name the tool, the input that was confusing, and what you expected.

Returns: The created feedback record with timestamp.

Inputs: feedback (required).

update_inventory_itemA
Idempotent
Inspect

Patch an inventory item. Only provided fields change. Idempotent.

Caller must own the item (404 otherwise โ€” the API doesn't leak existence). For lifecycle changes, see mark_for_sale and mark_sold for ergonomic wrappers.

Inputs: api_key (required), item_id (required), name, product_id, +12 more.

update_productA
Idempotent
Inspect

Update fields on an existing product. Requires an API key.

Only fields you pass are changed; omitted fields are preserved. Idempotent โ€” calling twice with the same input yields the same final state. For creating a new listing, use create_product instead.

The API key must own the product. Trying to update someone else's product returns a 403/404.

Args: api_key: Partle API key (prefix pk_). product_id: ID of the product to update. Get from create_product's return value, get_my_products, or search_products. name: New product name. Omit to leave unchanged. description: New description. Omit to leave unchanged. price: New price in whole currency units (e.g. 15.99 = โ‚ฌ15.99). currency: New currency symbol. url: New merchant URL.

Returns: The updated product record (full, not just the changed fields).

Inputs: api_key (required), product_id (required), name, description, +3 more.

upload_product_imageA
DestructiveIdempotent
Inspect

Attach an image to an existing product. Provide exactly one of image_base64 (with content_type) or image_url.

Use this after create_product returns a product ID. For replacing a previously-uploaded image, delete the old one with delete_product_image first. Marked destructive because subsequent edits to the image set are visible publicly.

Args: api_key: Partle API key (prefix pk_). product_id: ID of the product to attach the image to. image_base64: Raw image data, base64-encoded. When set, content_type is required (e.g. image/jpeg). content_type: MIME type of the base64 payload. Required with image_base64. One of: image/jpeg, image/png, image/gif, image/webp. image_url: URL the server should fetch the image from. Use this when the image is already hosted somewhere public โ€” saves base64 overhead.

Returns: The created ProductImage record with its id (use for deletion) and storage path.

Inputs: api_key (required), product_id (required), image_base64, content_type, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelogโ€ฆ

    TDQS

    A4.2/5.0

    Scored across 18 tools

    Disambiguation4/5

    Most tools have distinct purposes, especially between inventory and product management. However, add_inventory_item and update_inventory_item could be confused at first glance, though descriptions clarify. The mark_for_sale and mark_sold wrappers add convenience without significant ambiguity.

    Naming Consistency4/5

    Naming follows a consistent verb_noun snake_case pattern (e.g., create_product, delete_inventory_item). Minor inconsistency: mark_for_sale vs. mark_sold (different verb forms) and get_my_inventory vs. get_my_products, but these are clear and predictable.

    Tool Count4/5

    18 tools cover inventory, product, store, search, and feedbackโ€”a broad but coherent scope. While the number is slightly high, each tool serves a distinct need, and there are no redundant ones.

    Completeness4/5

    The tool set covers full CRUD for inventory and products, plus search, stats, and feedback. Missing features like image reordering or store creation are reasonable omissions given the platform's focus. No critical gaps for core workflows.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers