{"$schema":"https://verifymcp.io/schemas/trust-report.json","schemaVersion":1,"license":{"name":"CC BY-NC 4.0","url":"https://creativecommons.org/licenses/by-nc/4.0/"},"generatedAt":"2026-11-05T17:00:39.394Z","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp","markdownUrl":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp.md","server":{"slug":"lukabudik-alza-mcp","name":"io.github.lukabudik/alza-mcp","registryName":"io.github.lukabudik/alza-mcp","description":"Unofficial MCP server for Alza.cz: catalog search plus token-guarded account and checkout.","registryStatus":"active","deletedAt":null,"statusMessage":null,"liveness":"live","publisher":{"class":"unknown","claimed":false}},"component":{"slug":"alza-mcp","type":"npm","identifier":"alza-mcp","withdrawn":false,"url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp","version":"0.5.0","transport":"stdio","scoredAt":"2026-11-05T09:51:54.912Z"},"score":{"total":79,"tier":"medium","status":"scored","weekDelta":3,"history":[{"date":"2026-11-05","total":79},{"date":"2026-11-04","total":79},{"date":"2026-11-03","total":78},{"date":"2026-11-02","total":78},{"date":"2026-11-01","total":77},{"date":"2026-10-31","total":77},{"date":"2026-10-30","total":76},{"date":"2026-10-29","total":76},{"date":"2026-10-28","total":75},{"date":"2026-10-27","total":75},{"date":"2026-10-26","total":74},{"date":"2026-10-25","total":74},{"date":"2026-10-24","total":73},{"date":"2026-10-23","total":78},{"date":"2026-10-22","total":77},{"date":"2026-10-21","total":74},{"date":"2026-10-20","total":74},{"date":"2026-10-19","total":74},{"date":"2026-10-18","total":74},{"date":"2026-10-17","total":74},{"date":"2026-10-16","total":74},{"date":"2026-10-15","total":74},{"date":"2026-10-14","total":42},{"date":"2026-10-13","total":42},{"date":"2026-10-12","total":42},{"date":"2026-10-11","total":42}]},"categories":[{"name":"Supply Chain Security","score":75,"verdict":"fail","reasons":["No malware found by supply-chain analysis.","CVE check failed: a known high-severity CVE affects zod 3.25.76, a direct dependency. A fixed version is available.","Declares code that runs automatically (postinstall) and that we could not recognise. It may be perfectly ordinary, but we have not established what it does.","32 of 117 dependencies flagged as unhealthy (1 deprecated)."],"codes":[{"code":"supplychain.malware_clean","args":{}},{"code":"cve.direct","args":{"package":"zod","version":"3.25.76","severity":"high"}},{"code":"installscript.unreviewed","args":{"hooks":"postinstall"}},{"code":"dephealth.assessed","args":{"deps":"117","unhealthy":"32","deprecated":"1"}}]},{"name":"Provenance & Transparency","score":74,"verdict":"fail","reasons":["Repository check failed: the declared repository URL redirects; it must resolve directly.","Cryptographically verified build provenance (signed, bound to lukabudik/alza-mcp).","Clear OSI-approved license (MIT).","Actively maintained (last published 28 days ago).","Publishes a security disclosure policy (SECURITY.md)."],"codes":[{"code":"provenance.repo_redirected","args":{}},{"code":"provenance.verified","args":{"repo":"lukabudik/alza-mcp"}},{"code":"license.osi","args":{"spdx":"MIT"}},{"code":"maintenance.recent","args":{"age_days":"28"}},{"code":"disclosure.present","args":{}}]},{"name":"Schema Quality & AI Usability","score":77,"verdict":"fail","reasons":["100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).","AI-judged instruction clarity (excellent).","Context-footprint check failed: tool/resource definitions use about 6228 tokens (~346/item across 18 items; 18 tools + 0 resources), over budget; trim descriptions and params.","Usage-examples check failed: none of the tools include examples."],"codes":[{"code":"schema.descriptions","args":{"pct":"100"}},{"code":"schema.ai_quality","args":{"band":"excellent"}},{"code":"schema.footprint_heavy","args":{"avg":"346","items":"18","tools":"18","tokens":"6228","resources":"0"}},{"code":"schema.examples_absent","args":{}}]},{"name":"Stability & Change Management","score":70,"verdict":"partial","reasons":["Stability observed for 21 of 30 days with no destabilising changes; credit accrues until the full window elapses."],"codes":[{"code":"stability.building_history","args":{"days":"21"}}]},{"name":"Tool Coverage","score":100,"verdict":"pass","reasons":["100% of tools have a non-trivial description (not blank, and not just the tool's name).","100% of tool parameters carry a description.","Structured output schemas are declared (100% of tools); any adoption earns full credit."],"codes":[{"code":"toolquality.descriptions","args":{"pct":"100"}},{"code":"toolquality.param_docs","args":{"pct":"100"}},{"code":"toolquality.output_present","args":{"pct":"100"}}]},{"name":"Tool Safety","score":100,"verdict":"pass","reasons":["No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.","We read all 18 captured tool definition(s), and no name or description among them implies an irreversible operation.","An AI judge read all 19 captured unit(s) of tool text and found none that tries to manipulate the model reading it."],"codes":[{"code":"toolsafety.injection_clean","args":{}},{"code":"toolsafety.destructive_none","args":{"tools":"18"}},{"code":"toolsafety.manipulation_clean","args":{"units":"19","judged":"19"}}]},{"name":"Capabilities","score":100,"verdict":"pass","reasons":["Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28."],"codes":[{"code":"protocol.supported","args":{"latest":"2026-07-28","version":"2025-11-25"}}]}],"inconclusive":[],"malware":[],"components":[{"slug":"alza-mcp","type":"npm","identifier":"alza-mcp","withdrawn":false,"score":79,"current":true,"url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp","markdownUrl":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp.md"}],"facts":[{"label":"Registry","value":"npm"},{"label":"Package","value":"alza-mcp"},{"label":"Version","value":"0.5.0"},{"label":"Transport","value":"stdio"}],"install":{"available":true,"bundleSha256":null},"tools":[{"name":"search_products","title":"Search Alza products","description":"Search the Alza.cz catalog by keyword. Use this for product discovery — finding what's available, comparing options, or starting research. Returns a list with product code, name, price, stock (from the card's purchase CTA), and rating. To get full details for one product, follow up with `get_product`. Price filters (`min_price`/`max_price`, rejected when inverted) and sorts are applied client-side to the top ~72 ranked candidates, so a narrow window can return fewer items than exist; `pageSize` is the real number of cards per Alza page (~24, not your `limit`) and `hasMore` says whether further pages exist. Sorting: Alza's search page ignores server-side sort, so price-asc / price-desc / rating scan up to ~72 top-ranked candidates (3 pages) and sort them client-side — `candidatesScanned` reports how many were scanned; for an absolute price floor also pass `max_price`. `in_stock: true` keeps only products with a live purchase CTA. Brand/attribute filtering: call `list_category_filters({category_id})` for real ids, then pass `producer_ids` and/or `filters` with `category_id`. This switches to Alza's own filtered category page, so `query` is ignored and results match what the website shows; a filter Alza doesn't honour returns an error rather than unfiltered results. Slider facets (screen size, refresh rate, brightness, weight, …) filter by `{param_id, min?, max?}` range; the applied ranges come back in `appliedRanges`. `min_screen_inches`/`max_screen_inches` use the category's real diagonal slider when `category_id` is given, and a product-name size heuristic otherwise. For attributes Alza has no facet for, compare shortlisted candidates with `get_product`'s `params`. Read-only.","inputs":[{"name":"category_id","type":"integer","required":false,"description":"Restrict the search to a specific category id. Use list_categories to discover ids."},{"name":"filters","type":"array","required":false,"description":"Attribute filter selections from `list_category_filters` (`filterable: true` groups only; never guess ids). Requires `category_id`. Combines with `producer_ids`. Two forms: `{param_id, value_id}` for…"},{"name":"in_stock","type":"boolean","required":false,"description":"If true, keep only products purchasable right now (card shows a 'Do košíku'/'Vybrat variantu' (alza.sk: 'Do košíka'/'Vybrať variant') purchase CTA; cards with a 'Hlídat'/'Strážiť' watch button are ex…"},{"name":"limit","type":"integer","required":false,"description":"Maximum number of results to return. Default 20, max 50."},{"name":"max_price","type":"number","required":false,"description":"Maximum price in the locale's currency. Products whose price could not be read are excluded. Must not be below `min_price`. Applied client-side to the scanned candidates (up to ~72 top-ranked results…"},{"name":"max_screen_inches","type":"number","required":false,"description":"Maximum screen diagonal in inches. See `min_screen_inches` for when this is a server-side filter vs a name-based fallback."},{"name":"min_price","type":"number","required":false,"description":"Minimum price in the locale's currency. Products whose price could not be read are excluded. Must not exceed `max_price`. Applied client-side to the scanned candidates (up to ~72 top-ranked results o…"},{"name":"min_screen_inches","type":"number","required":false,"description":"Minimum screen diagonal in inches, for display products (monitors, TVs, laptops). With `category_id` (and a category that has a diagonal slider) this is Alza's own server-side diagonal filter (live-v…"},{"name":"page","type":"integer","required":false,"description":"1-indexed result page (1-50) (follows Alza's rendered pagination). Only pages Alza actually renders are reachable — a page beyond the rendered set returns no results rather than repeating page 1. Pag…"},{"name":"producer_ids","type":"array","required":false,"description":"Filter by ONE brand id (an array of at most one — Alza has no multi-brand category URL; to compare brands call once per brand) — get real ids from `list_category_filters`'s `brands`. Requires `catego…"},{"name":"query","type":"string","required":true,"description":"Search keywords. Required. Example: 'iPhone 15 Pro', 'PlayStation 5', 'gaming mouse Logitech'."},{"name":"sort","type":"string","required":false,"description":"Sort order, default 'relevance'. Alza's search page ignores server-side sort parameters, so price (asc/desc) and rating sorts gather candidates from up to 3 result pages (~72 items — the top of Alza'…"}],"outputs":[{"name":"appliedRanges","type":"array","required":false,"description":null},{"name":"candidatesScanned","type":"number","required":false,"description":null},{"name":"hasMore","type":"boolean","required":false,"description":null},{"name":"nextPage","type":"number","required":false,"description":null},{"name":"page","type":"number","required":true,"description":null},{"name":"pageSize","type":"number","required":true,"description":"Cards per rendered Alza result page (the real page capacity), not the requested limit."},{"name":"products","type":"array","required":true,"description":null},{"name":"query","type":"string","required":true,"description":null},{"name":"total","type":"number","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":1279},{"name":"get_product","title":"Get product details","description":"Fetch details for a single product by its Alza code (the `code` from `search_products`, e.g. 'WEXOA002B0' — not the numeric id): name, price (with the original price when discounted), availability, rating, brand, category, primary image, URL, and the spec table when the product page carries one (up to 30 rows, merged from both the DOM spec table and the JSON-LD `additionalProperty` list some page templates use instead — fixed 2026-09-27 after a product with only the latter returned no params at all). Use after `search_products` to compare shortlisted candidates in depth, and to get the canonical URL to show the user. For reviews use `get_product_reviews`; for the complete spec sheet (parameterGroups) use `mobile_read` with operation=`router_product` and product_id = the numeric `d########` id from the product URL. Sourced from the product page's JSON-LD schema, so values are accurate and stable. Read-only.","inputs":[{"name":"code","type":"string","required":true,"description":"Alza product code, e.g. 'WEXOA002B0'. This is the canonical identifier returned by `search_products` (the `code` field). Not the numeric id."}],"outputs":[{"name":"product","type":"object","required":true,"description":"Scraped product detail (JSON-LD sourced; stable fields listed, rest passthrough)."}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":266},{"name":"compare_products","title":"Compare products side by side","description":"Fetch 2–6 products by their Alza codes (the `code` from `search_products`) and return one aligned comparison table: a column per product, rows for price, availability, rating and brand, then every spec row present in any of them (exact spec-name matching; a product missing a row shows —). Use instead of calling `get_product` repeatedly when the user asks which of several candidates is better. A code that fails to load is reported in its own column (`ok: false`, `error`) while the others still compare. Pages load at most two at a time, so 6 products take roughly 15–30 s on a cold cache. Optional `summarize: true` adds a short verdict generated by your client's LLM via MCP sampling, grounded only in the table (skipped, not an error, when sampling is unsupported). Read-only.","inputs":[{"name":"codes","type":"array","required":true,"description":"2–6 Alza product codes to compare side by side, e.g. ['WEXOA002B0', 'JA190b1']. These are the `code` values from `search_products` (not numeric ids). Duplicates (same code, any letter case) are colla…"},{"name":"summarize","type":"boolean","required":false,"description":"Opt-in: also ask your own client LLM (MCP sampling) for a short verdict grounded only in the table. Ignored with `summary.status: \"unavailable\"` when the client does not support sampling — the table…"}],"outputs":[{"name":"duplicatesIgnored","type":"array","required":false,"description":null},{"name":"products","type":"array","required":true,"description":null},{"name":"rows","type":"array","required":true,"description":null},{"name":"summary","type":"object","required":false,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":323},{"name":"get_product_reviews","title":"Get product reviews","description":"Fetch reviews for a single product by its Alza code: the aggregate rating and review count plus up to `limit` individual reviews (author as Alza displays it, date, rating, body, pros/cons) from Alza's reviews API, newest first. `reviewCount` is the product page's aggregate; the reviews list can contain more items than it, apparently because the API also returns reviews from other storefronts (Slovak-language reviews have been seen; the API has no market field to confirm it) — the response text says so when that happens. Use after `get_product` when the user wants real-world feedback before deciding. If the reviews API is unavailable you receive the aggregate only (empty `reviews` array) — in that case rely on the rating/count. Do not use for the aggregate rating alone when you already have it from `search_products`/`get_product`. Read-only.","inputs":[{"name":"code","type":"string","required":true,"description":"Alza product code, e.g. 'WEXOA002B0'. Same as the `code` from `search_products`."},{"name":"limit","type":"integer","required":false,"description":"Maximum number of individual reviews to include. Default 10, max 50."}],"outputs":[{"name":"code","type":"string","required":true,"description":null},{"name":"ratingAverage","type":"number","required":false,"description":null},{"name":"reviewCount","type":"number","required":false,"description":null},{"name":"reviews","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":250},{"name":"recommend_alternatives","title":"Recommend alternative products","description":"Find alternatives to one product (\"something like this but cheaper / better / same brand\"). Candidate pool = Alza's own alternatives list for the product (mobile API, keyed by the numeric commodity id taken from the product URL); if that list is empty, or nothing in it survives the mode filter, falls back to a same-category `search_products` (`poolSource` says which was used). Heuristics: `cheaper` = strictly lower price, cheapest first; `same-brand` = brand match (source brand vs. the candidate's name), then rating desc, price asc; `better-specs` = rating >= source rating (unrated dropped), then rating desc, price asc — it ranks by customer rating, it does not compare spec tables, so shortlist then compare with `get_product` `params`. The source product is always excluded. Read-only.","inputs":[{"name":"code","type":"string","required":true,"description":"Alza product code of the product to find alternatives for, e.g. 'RI054b5'. Same as the `code` from `search_products`."},{"name":"limit","type":"integer","required":false,"description":"Maximum number of alternatives to return. Default 5, max 20."},{"name":"mode","type":"string","required":false,"description":"Ranking mode. 'cheaper': strictly lower price than the source, cheapest first. 'same-brand': same brand as the source, best rating first then lower price. 'better-specs': rated at least as high as th…"}],"outputs":[{"name":"alternatives","type":"array","required":true,"description":null},{"name":"candidatesConsidered","type":"number","required":true,"description":null},{"name":"mode","type":"string","required":false,"description":null},{"name":"poolSource","type":"string","required":true,"description":null},{"name":"source","type":"object","required":true,"description":"Scraped product detail (JSON-LD sourced; stable fields listed, rest passthrough)."}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":331},{"name":"find_pickup_points","title":"Find AlzaBox lockers and Alza showrooms","description":"Find AlzaBox parcel lockers and AlzaShop showrooms near a Czech/Slovak postal code: name, address, GPS, distance and opening hours, sorted nearest first. The postal code is geocoded with the public OpenStreetMap Nominatim service (nominatim.openstreetmap.org): the normalised code and the country are sent to that third party, not to Alza. Use when the user asks where the nearest AlzaBox or Alza store is, or where they could pick up an order. No cart or login needed. Lockers come from Alza's public locker map and are cached; each has a `parcelShopId`. Locker hours vary (many are nonstop, mall lockers follow mall hours) and are looked up for the first 10 lockers returned. Important: a standalone locker list can't tell whether a given product fits. Alza excludes large items (observed: 34\"+ monitors) from the whole AlzaBox network and routes them to a few oversized-item pickup points. To check a specific product, add it to the cart and read `delivery_options` (or `web_pickup_places`, which is cart-scoped). Read-only. Example: `find_pickup_points({postal_code: '500 02', types: ['alzabox'], limit: 5})`","inputs":[{"name":"limit","type":"integer","required":false,"description":"Maximum number of pickup points to return. Default 10."},{"name":"postal_code","type":"string","required":true,"description":"Czech or Slovak 5-digit postal code. Examples: '110 00', '11000', '602 00'. One optional space is tolerated; blank or malformed values are rejected."},{"name":"radius_km","type":"number","required":false,"description":"Search radius in kilometres. Default 15 km."},{"name":"types","type":"array","required":false,"description":"Restrict to specific pickup-point types. 'alzabox' = self-service AlzaBox parcel lockers (live list from Alza's public locker map, no cart needed). 'branch' = brick-and-mortar AlzaShop showrooms with…"}],"outputs":[{"name":"points","type":"array","required":true,"description":null},{"name":"warnings","type":"array","required":false,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":439},{"name":"list_category_filters","title":"List a category's filters","description":"List the brands and attribute filters (facets) Alza defines for a category, with real ids and product counts. The attribute set differs per category (laptops have CPU/RAM facets, monitors have panel/resolution facets, …). Pass `brands[].valueId` to `search_products` as `producer_ids` (brand filtering works in every category), and `filterable: true` groups' `param_id`/`value_id` pairs as `filters`. Checkbox values are only honoured when Alza has an SEO landing page for that exact value (HDMI ports, for example); many others, notably panel type and resolution on monitors, are redirected to the unfiltered category (live 2026-10-07), and `filterable: true` does not predict which. When one isn't honoured, `search_products` returns an error rather than unfiltered results; drop that filter and compare candidates with `get_product`'s `params` instead. Slider groups (`filterMode: \"range\"` — screen size, refresh rate, brightness, weight, port counts, …) filter by `{param_id, min?, max?}` in `search_products`'s `filters`, with min/max in the facet's own units as given by `values[].value` (e.g. millimetres for a monitor diagonal, inches for a TV diagonal; live-verified 2026-10-06). `filterable: false` groups are informational only. Call this before using `producer_ids`/`filters` — never guess ids. Read-only.","inputs":[{"name":"category_id","type":"integer","required":true,"description":"Category id to read attribute filters for (from `list_categories` or `search_products`'s results)."}],"outputs":[{"name":"brands","type":"array","required":true,"description":null},{"name":"category_id","type":"number","required":true,"description":null},{"name":"groups","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":358},{"name":"list_categories","title":"List Alza categories","description":"Browse the Alza category tree one level at a time. Useful for narrowing a product search — find the right category id, then pass it to `search_products` as `category_id`. Without arguments, returns top-level categories.","inputs":[{"name":"parent_id","type":"integer","required":false,"description":"Parent category id. Omit to list top-level categories. Pass an id from a previous result to drill down."}],"outputs":[{"name":"categories","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":84},{"name":"get_deals","title":"Find discounted Alza products","description":"Find currently discounted products on Alza.cz, with current price, original price, savings and a discount % COMPUTED from the observed prices (never from marketing badges). Alza has no 'sale' facet or product-grid sale page, so this scans category listing pages (up to 3 pages ≈ 72 cards for a given `category_id`; page 1 of five popular categories when omitted) for cards showing a crossed-out original price or an 'Ušetříte' savings amount — it covers a bounded sample, not Alza's whole sale inventory (`candidatesScanned` says how many cards were checked). Czech store only (alza.cz price-box wording); errors on other locales. Prices are the shelf price, not code/AlzaPlus+ coupon prices. Read-only.","inputs":[{"name":"category_id","type":"integer","required":false,"description":"Leaf category id to scan for discounts (from `list_categories`/`search_products`; top-level hub categories such as 'Počítače a notebooky' have no product grid and return nothing). Omit to scan the fi…"},{"name":"limit","type":"integer","required":false,"description":"Maximum deals to return, best discount first. Default 20, max 50."},{"name":"min_discount_percent","type":"number","required":false,"description":"Keep only products whose computed discount is at least this many percent. Default 0 (any discount)."}],"outputs":[{"name":"candidatesScanned","type":"number","required":true,"description":null},{"name":"categoryIds","type":"array","required":true,"description":null},{"name":"deals","type":"array","required":true,"description":null},{"name":"total","type":"number","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":294},{"name":"autocomplete","title":"Alza search suggestions","description":"Cheap search-box suggestions (plain HTTP, no page render): suggested query phrases plus matching categories, brands and products with ids/codes. Use it to refine a messy Czech query before a full `search_products` — pass a category `id` as `category_id`, or a product code to `get_product`.","inputs":[{"name":"limit","type":"integer","required":false,"description":"Max entries per section (suggested phrases, categories, products, brands, articles). Default 5, max 10."},{"name":"query","type":"string","required":true,"description":"Partial or full search text, e.g. \"čistič kol\" or \"iphone\". Czech diacritics are fine."}],"outputs":[{"name":"articles","type":"array","required":true,"description":null},{"name":"brands","type":"array","required":true,"description":null},{"name":"categories","type":"array","required":true,"description":null},{"name":"products","type":"array","required":true,"description":null},{"name":"query","type":"string","required":true,"description":null},{"name":"suggestions","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":132},{"name":"auth_discovery","title":"Read Alza OAuth discovery","description":"Read the live OpenID Connect discovery document that the Alza mobile app uses (issuer, authorization endpoint, token endpoint). Use only when debugging the OAuth flow or verifying which identity endpoints Alza exposes before calling `auth_start`. Do not use for everyday shopping — it returns a configuration document, not account data, and changes nothing. Read-only; no credentials are ever sent.","inputs":[],"outputs":[{"name":"authorization_endpoint","type":"string","required":false,"description":null},{"name":"code_challenge_methods_supported","type":"array","required":false,"description":null},{"name":"grant_types_supported","type":"array","required":false,"description":null},{"name":"issuer","type":"string","required":false,"description":null},{"name":"jwks_uri","type":"string","required":false,"description":null},{"name":"token_endpoint","type":"string","required":false,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":84},{"name":"auth_start","title":"Start Alza mobile API OAuth","description":"Start an OAuth 2.0 PKCE sign-in for the Alza mobile API: returns an authorization URL plus a state value. Use when `account_status` reports no loaded token, or when account tools start failing with authentication errors. Flow: open the returned authorization URL in a browser, sign in to Alza, the app redirects to `alza://identity?code=...&state=...` — then call `auth_exchange` with that redirect URL (or its code and this state). Desktop browsers cannot open the `alza://` scheme, so the page appears to stall and after ~40 s shows \"Při přihlášení došlo k chybě.\" — that message is a client-side timer, not a failed sign-in. Tell the user to open DevTools before signing in (Network tab with \"Preserve log\" on) and copy the `alza://identity?code=...` URL from the redirect's `Location` header, or from the Console error about failing to launch `alza://`. The code is short-lived, so exchange it promptly. This call only creates a local PKCE session: the user's credentials never enter the MCP and nothing changes on Alza's side. Do not call it repeatedly for one sign-in — each call supersedes the previous state.","inputs":[],"outputs":[{"name":"authorizationUrl","type":"string","required":true,"description":null},{"name":"state","type":"string","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":276},{"name":"auth_exchange","title":"Exchange Alza OAuth code","description":"Complete the OAuth 2.0 PKCE sign-in: exchange the authorization code for mobile API tokens and load them into this server. Use immediately after the user finishes the `auth_start` flow in the browser. Pass the whole `alza://identity?code=...&state=...` redirect URL as `code` (state is then read from it), or the bare `code` plus `state` — never a password and never a refresh token here. Fails if the state does not match a pending `auth_start` session (start over from `auth_start` in that case). Side effect: replaces the token set currently loaded in this process; afterwards account tools such as `cart`, `profile`, and `order` are authenticated.","inputs":[{"name":"code","type":"string","required":true,"description":"Authorization code from the `alza://identity` redirect (the `code` query parameter), or the full redirect URL."},{"name":"state","type":"string","required":false,"description":"State value returned by `auth_start`; must match the pending PKCE session exactly. Optional when `code` is the full redirect URL."}],"outputs":[{"name":"data","type":null,"required":false,"description":null},{"name":"err","type":"number|string|null","required":false,"description":null},{"name":"msg","type":"string|null","required":false,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":226},{"name":"prepare_mutation","title":"Prepare an Alza mutation","description":"Start a two-step mutation by returning a one-time confirmation token bound to exactly one action. This call itself sends nothing to Alza. Use it before the high-impact typed mutations — `register` (action `register`), `address_upsert` (`address_create` or `address_edit`), `address_delete` (`address_delete`), `pay_after_order` (`after_order_payment`), `web_place_order` (`web_place_order`), `web_pay_after_order` (`web_after_order_payment`), `cancel_order` (`cancel_order`), `review_submit` (`review_submit`), `subscription_activate` (`subscription_activate`), `subscription_update_installment` (`subscription_update_installment`), `upload_attachment` (`attachment_upload`), `watchdog_set` (`watchdog_set`), `watchdog_delete` (`watchdog_delete`) — and before any low-risk `mutate_list` action (`create`, `rename`, `delete`, `add`, `remove`, `move`, `set_country`, `set_isic`, `add_gift`, `add_order_service`, `send_feedback`, `submit_discussion`, `rate_discussion`, `coupon_add`, `coupon_remove`, `basket_update`, `basket_unlock`, `gdpr_export`). Pass `payload`: exactly the arguments you will send to that tool, all except `confirmation_token` (for `mutate_list`, the object you will pass as its `payload`). The token is bound to the action and to that payload — a call with different arguments is refused and spends the token. Pass the returned token as `confirmation_token` on the matching call; the token is single-use — the first call that presents it spends it, even if that call fails, so prepare a new one to retry — and it expires 5 minutes after it is issued (`expiresAt`). Each action has its own pending token: preparing the same action again replaces its earlier token, tokens prepared for other actions stay valid. Do not use for read-only tools, and not for `add_to_cart` (which is a low-risk cart write that needs no token).","inputs":[{"name":"action","type":"string","required":true,"description":"Which mutation you are about to perform; the token will only be accepted by that action's tool."},{"name":"payload","type":"object","required":true,"description":"The exact arguments of the mutation call, without `confirmation_token` — e.g. cancel_order: {order_id, part_id, hash, reason}; mutate_list coupon_add: {coupon: \"CODE\"}. Show these to the user when as…"}],"outputs":[{"name":"action","type":"string","required":true,"description":null},{"name":"confirmationToken","type":"string","required":true,"description":null},{"name":"expiresAt","type":"string","required":true,"description":null},{"name":"payloadBound","type":"boolean","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":540},{"name":"account_status","title":"Check mobile API auth status","description":"Report whether a mobile API access token is loaded in this server process, and when it expires (`expiresAt`, `expired`) if that is known. An expired token is refreshed automatically before the next account call when a refresh token is loaded. Use as a first check before account-scoped tools (`cart`, `profile`, `order`, `add_to_cart`), or to diagnose \"not authenticated\" failures. If no token is loaded, run `auth_start`, have the user complete the browser sign-in, then `auth_exchange`. Read-only; no network call.","inputs":[],"outputs":[{"name":"apiBaseUrl","type":"string","required":true,"description":null},{"name":"authenticated","type":"boolean","required":true,"description":null},{"name":"expired","type":"boolean","required":false,"description":null},{"name":"expiresAt","type":"string","required":false,"description":null},{"name":"visitorId","type":"string","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":122},{"name":"list_toolsets","title":"List available toolsets","description":"List every toolset this server groups its tools into: id, title, description, member tool names, and whether it's currently enabled. Only `catalog` and `auth` are enabled by default to keep the visible tool list small — use `set_toolset` to turn on the group a task actually needs (e.g. `basket_and_checkout` before placing an order). Call this first if you're unsure which toolset covers what you need. Read-only, no network call.","inputs":[],"outputs":[{"name":"toolsets","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":106},{"name":"set_toolset","title":"Enable or disable a toolset","description":"Enable or disable every tool in one toolset (or `all` for every toolset) at once, so only the tools relevant to the current task are visible. Call `list_toolsets` first to see the available ids. Changing this fires the standard MCP tools-list-changed notification. No Alza-side effect — this only changes which tools this MCP server currently exposes to you.","inputs":[{"name":"enabled","type":"boolean","required":true,"description":"true to enable, false to disable."},{"name":"id","type":"string","required":true,"description":"Toolset id from `list_toolsets`, or \"all\"."}],"outputs":[{"name":"enabled","type":"boolean","required":true,"description":null},{"name":"id","type":"string","required":true,"description":null},{"name":"tools_affected","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":120},{"name":"report_issue","title":"Draft a GitHub issue about alza-mcp","description":"Draft a bug report or feature request for the alza-mcp project (github.com/lukabudik/alza-mcp). Use it when a tool fails unexpectedly, returns data that is clearly wrong, Alza changed something and a tool broke, or the user needs something no tool can do. Not for the user's own mistakes (invalid arguments, a product that doesn't exist) or for problems with an Alza order — those go to Alza support. This tool files nothing: it returns a redacted Markdown draft with version and environment details and this session's recent tool errors, a `gh` command to search for duplicates, a `gh issue create` command, and a prefilled new-issue link. Then: show the user the title and body and ask before filing, since it is posted publicly from their GitHub account. If they agree and you can run shell commands with an authenticated GitHub CLI, run `gh_search_command` first and, if nothing matches, `gh_create_command`; otherwise give them `new_issue_url`.","inputs":[{"name":"category","type":"string","required":true,"description":"bug = alza-mcp misbehaves; alza_change = Alza changed a page/endpoint and a tool broke; feature_request = something the tools can't do yet; docs = wrong or missing documentation."},{"name":"expected","type":"string","required":false,"description":"What you expected instead."},{"name":"include_recent_errors","type":"boolean","required":false,"description":"Attach this session's last 5 tool errors (redacted). Default true."},{"name":"steps","type":"array","required":false,"description":"Steps to reproduce: tool calls with their arguments, in order."},{"name":"title","type":"string","required":true,"description":"One-line summary, e.g. \"get_product returns no specs for PSU pages\"."},{"name":"tool","type":"string","required":false,"description":"The alza-mcp tool involved, e.g. \"search_products\"."},{"name":"what_happened","type":"string","required":true,"description":"What went wrong, including the exact error text. No personal data: credentials, emails, phone numbers and account ids are redacted automatically, but leave out names and addresses."}],"outputs":[{"name":"body","type":"string","required":true,"description":"Markdown issue body, already redacted."},{"name":"gh_create_command","type":"string","required":true,"description":"Files the issue with the GitHub CLI from the user's account (body passed via heredoc)."},{"name":"gh_search_command","type":"string","required":true,"description":"Run first to look for an existing issue about the same problem."},{"name":"labels","type":"array","required":true,"description":null},{"name":"new_issue_url","type":"string","required":true,"description":"Prefilled GitHub new-issue page, for agents without a shell or `gh`."},{"name":"recent_errors_included","type":"integer","required":true,"description":null},{"name":"redactions","type":"integer","required":true,"description":"How many credential / personal-data matches were replaced."},{"name":"repo","type":"string","required":true,"description":null},{"name":"title","type":"string","required":true,"description":null},{"name":"url_body_truncated","type":"boolean","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":411}],"toolsTruncatedAtCapture":false,"diagnostics":{"capturedAt":"2026-11-05T09:51:54.000Z","track":"package","endpoint":null,"declaredUrl":null,"truncated":false,"tls":null,"dnssec":null,"auth":null,"httpsRedirect":null,"transports":[],"provenance":{"outcome":"verified","label":"Verified","reason":"verified","reasonLabel":"Verified","discovery":"attestation_endpoint","discoveryLabel":"Registry attestation endpoint","sourceRepo":null,"attestationSkipped":null,"attestationSkippedLabel":null},"installScripts":[{"hook":"postinstall","tier":"unreviewed"}],"installScriptsTotal":null,"vulnerabilities":[{"id":"GHSA-mrhx-c7xc-m3w5","cve":"CVE-2023-54404","severity":"high","fixAvailable":true}],"vulnerabilitiesTotal":1,"dependencies":{"nodes":117,"partial":false,"deprecated":1,"stale":32,"noRepo":null}},"mismatches":[],"changelog":{"trackingSince":"2026-10-11","recent":[{"id":"chg_01a1a5fe-327a-7d23-9d4d-f0a0b2ca6976","kind":"score.total_changed","summary":"Trust score (78 → 79)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-11-04","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a1a5fe-327a-7d23-9d4d-f0a0b2ca6976"},{"id":"chg_01a19bab-c68f-75de-a585-a1c28bfcabb7","kind":"score.total_changed","summary":"Trust score (77 → 78)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-11-02","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a19bab-c68f-75de-a585-a1c28bfcabb7"},{"id":"chg_01a19164-3ffc-7bcf-91a0-a60ede8d2008","kind":"check.reverified","summary":"Security disclosure (unverified → pass)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-31","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a19164-3ffc-7bcf-91a0-a60ede8d2008"},{"id":"chg_01a19164-3ffd-7cd0-9822-5a15472cc1ac","kind":"score.total_changed","summary":"Trust score (76 → 77)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-31","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a19164-3ffd-7cd0-9822-5a15472cc1ac"},{"id":"chg_01a18c70-6930-7af8-9515-564f8951bb83","kind":"check.unverifiable","summary":"Security disclosure (pass → unverified)","materiality":"functional","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-30","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a18c70-6930-7af8-9515-564f8951bb83"},{"id":"chg_01a18706-b0e7-77b8-849c-f47b3c5508e8","kind":"score.total_changed","summary":"Trust score (75 → 76)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-29","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a18706-b0e7-77b8-849c-f47b3c5508e8"},{"id":"chg_01a17cb6-c445-79aa-a367-4de12dd0485f","kind":"score.total_changed","summary":"Trust score (74 → 75)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-27","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a17cb6-c445-79aa-a367-4de12dd0485f"},{"id":"chg_01a17269-d32d-7352-a6b4-dfb5cb32e954","kind":"score.total_changed","summary":"Trust score (73 → 74)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-25","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a17269-d32d-7352-a6b4-dfb5cb32e954"},{"id":"chg_01a16d46-cafd-7512-9005-a955da48bb62","kind":"advisory.identified","summary":"CVE-2023-54404 affects this package (high)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-24","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a16d46-cafd-7512-9005-a955da48bb62"},{"id":"chg_01a16d46-cafe-7eb1-ac54-f5f2a65d4c59","kind":"check.verdict","summary":"Known CVEs (pass → fail)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-24","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a16d46-cafe-7eb1-ac54-f5f2a65d4c59"},{"id":"chg_01a16d46-caff-74ed-93ff-43a5f36d0cea","kind":"score.total_changed","summary":"Trust score (78 → 73)","materiality":"functional","direction":"regression","scoreDelta":-5,"occurredOn":"2026-10-24","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a16d46-caff-74ed-93ff-43a5f36d0cea"},{"id":"chg_01a1681e-6506-78cc-a9cd-4d00f9961003","kind":"score.total_changed","summary":"Trust score (77 → 78)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-23","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a1681e-6506-78cc-a9cd-4d00f9961003"},{"id":"chg_01a1630a-076b-7705-98e7-8f1a9b6883e7","kind":"check.reverified","summary":"Stability (unverified → 0.23)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-22","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a1630a-076b-7705-98e7-8f1a9b6883e7"},{"id":"chg_01a1630a-076c-7909-b218-61690f2cb33b","kind":"score.total_changed","summary":"Trust score (74 → 77)","materiality":"functional","direction":"improvement","scoreDelta":3,"occurredOn":"2026-10-22","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a1630a-076c-7909-b218-61690f2cb33b"},{"id":"chg_01a13d11-4739-7539-a237-997e930a6826","kind":"check.reverified","summary":"Injection markers (unverified → pass)","materiality":"security","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-15","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a13d11-4739-7539-a237-997e930a6826"},{"id":"chg_01a13d11-473b-71db-b8cf-451abcca1b65","kind":"check.appeared","summary":"First check of Judged manipulation (pass)","materiality":"security","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-15","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a13d11-473b-71db-b8cf-451abcca1b65"},{"id":"chg_01a13d11-473b-7692-beb9-319cddb4b722","kind":"check.reason","summary":"Stability (Stability not yet verified: not enough scan history yet (needs a 30-day window).)","materiality":"security","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-15","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a13d11-473b-7692-beb9-319cddb4b722"},{"id":"chg_01a13d11-473c-7991-841e-c2abede561e3","kind":"check.reverified","summary":"Tool coverage (unverified → 100)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-15","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a13d11-473c-7991-841e-c2abede561e3"},{"id":"chg_01a13d11-473d-7103-be0e-504674541202","kind":"check.reverified","summary":"Schema quality (unverified → 100)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-15","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a13d11-473d-7103-be0e-504674541202"},{"id":"chg_01a13d11-473d-7a4d-9783-f5bc74c36ee5","kind":"check.reverified","summary":"MCP protocol (unverified → pass)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-15","url":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp#chg-chg_01a13d11-473d-7a4d-9783-f5bc74c36ee5"}],"truncated":true,"feedUrl":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp/changelog.json"},"links":{"html":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp","markdown":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp.md","changelogJson":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp/changelog.json","changelogRss":"https://verifymcp.io/servers/lukabudik-alza-mcp/alza-mcp.xml","external":[{"label":"npm package","href":"https://www.npmjs.com/package/alza-mcp"},{"label":"Socket report","href":"https://socket.dev/npm/package/alza-mcp"}]}}