Skip to content
Conduit

mcp server

mcp-electronicmarkets-tr

High-performance Rust MCP server for real-time price and stock search across Turkish electronics markets.

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 26, 2026

Electronic Markets TR — MCP Server (Rust)

A lightweight Model Context Protocol server that searches Turkish electronics e-commerce sites in parallel and returns normalized product, price (TRY) and stock data for AI agents.

Purpose

Give LLM agents one tool to compare prices and stock across Turkish electronics markets, without loading pages or scraping HTML themselves. The server returns raw page-one search hits; ranking and relevance judgment stay with the agent.

Supported markets

MarketMethod
RobotistanServer-rendered search page (/arama?q=)
RobocomboTicimax storefront JSON API
Direnc.netT-Soft v5 search page (data-toggle attributes)
Robo90T-Soft AJAX product loader
CeriyanWooCommerce product search (/?s=&post_type=product)

Architecture

src/
  domain/        Product, Price/Money (kurus-backed integer), StockStatus, Market, SearchQuery
  parsing.rs     Turkish price/stock text parsing (pure functions, no I/O)
  http.rs        Shared reqwest client: pooling, timeouts, bounded retry
  scrapers/      One independent module per market (fetch + site-specific parser)
  search.rs      Concurrent orchestration: all 5 markets in parallel, per-market timeout,
                 partial results on failure
  pipeline.rs    Stock filter + URL-canonicalization dedup (pure functions)
  mcp_service.rs rmcp tool server + shared search execution
  main.rs        stdio entry point

Design notes:

  • Money: kurus (1/100 TRY) stored as i64; no floating point anywhere near prices. A missing price is Price::Unavailable, distinct from zero.
  • Concurrency: all markets are queried concurrently (bounded by the static market count). A 20 s per-market timeout turns a slow site into a per-market error without affecting other markets.
  • Errors: typed (HttpError, ScrapeError); market failures are reported in the response payload (marketErrors) instead of failing the whole search.

Setup

Requires Rust 1.85+ (edition 2024).

cargo build --release

Configuration

Environment variables:

  • RUST_LOG — log filter (default: no logs on stdout; logs go to stderr, e.g. RUST_LOG=warn)

HTTP behavior (timeouts, retries, pool size) is configured in src/http.rs::HttpClientConfig with sensible defaults: 5 s connect timeout, 15 s request timeout, 1 retry for transient failures (5xx/timeout/network) only.

MCP usage

Register in an MCP client (e.g. Claude Desktop):

{
  "mcpServers": {
    "electronic-markets-tr": {
      "command": "/absolute/path/to/mcp-electronicmarkets-tr/target/release/mcp-electronicmarkets-tr"
    }
  }
}

Tool: search_products

ArgumentTypeDefaultDescription
querystring—Product name or keywords (1–128 chars)
only_in_stockbooleantrueReturn only products currently in stock

Response (JSON):

{
  "query": "esp32",
  "onlyInStock": true,
  "resultCount": 5,
  "products": [
    {
      "market": "robotistan",
      "name": "ESP32-CAM ...",
      "price": { "available": { "kurus": 92320 } },
      "stockStatus": "in_stock",
      "url": "https://www.robotistan.com/..."
    }
  ],
  "marketErrors": []
}

Development

cargo check          # fast type check
cargo test           # unit + fixture + MCP protocol tests (offline)
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --check

Testing

  • Unit tests (src/): Turkish price parsing, stock text parsing, URL building, filtering, deduplication, query validation.
  • Fixture tests (tests/scraper_fixtures.rs, tests/robocombo_fixture.rs): real HTML/JSON captured from the live sites; parser output verified against live-observed counts (e.g. Ceriyan esp32 -> 10 products, 5 in stock / 5 out of stock). Includes malformed-HTML and missing-field safety tests.
  • MCP protocol tests (tests/mcp_protocol.rs): full rmcp handshake over an in-memory duplex transport — tool registration, input schema shape, invalid-parameter rejection.

Live smoke testing

Hits the real sites; ignored by default so cargo test stays offline:

cargo test --test live_smoke -- --ignored --nocapture

Verifies all five markets with three queries: arduino uno, esp32, 220 ohm resistor. Each market is reported independently; one failing market does not hide others' results.

Performance comparison (concurrent vs sequential search) can be run with:

cargo run --release --example perf_search

Measured on a residential connection (2026-09-10): concurrent 2.4 s vs sequential 7.4 s for esp32 (~3.1x speedup); results vary with per-site latency. Working set during a search: ~14 MB.

Release build

cargo build --release
# binary: target/release/mcp-electronicmarkets-tr

Adding a new scraper

  1. Add a variant to Market (src/domain/market.rs) and include it in Market::ALL.
  2. Create src/scrapers/<market>.rs with pub async fn search(http: &HttpClient, query: &SearchQuery) plus a pure pub fn parse_search_page(&str) -> Vec<Product>.
  3. Wire the variant in search.rs::scrape_market.
  4. Capture a real fixture (e.g. curl -A "Mozilla/..." <search-url> > tests/fixtures/<market>_search.html) and add a fixture test.
  5. Verify with live smoke tests before shipping.
↑↓ navigate openesc close