Skip to main content
Glama

Subito Monitoring

Checks License: MIT

A single-user, open source Subito.it search and watch service: autonomous polling, SQLite state and delivery queue, direct Telegram notifications, and eight MCP tools for Hermes or any MCP client. No LLM, dashboard, external database or Vinted runtime. MIT licensed; the monitoring core is adapted from Vinted Monitoring with attribution.

Integration status (2026-11-03): limited live validation passed. The production provider now uses ordinary system curl, which succeeded on macOS and in the Linux container. Page 2, all four orders, Motori, Immobili, valid empty results and a narrow Market silent baseline/rescan were checked against actual Subito responses. Chrome also confirmed page 2 and the site's real ordering URL. No Telegram message was sent; long-running availability is not guaranteed. See verification.

Subito's terms prohibit automated extraction without permission. Network access is disabled by default (SM_UPSTREAM_ENABLED=false). Obtain appropriate permission before enabling it; this switch does not grant permission or bypass a block. 401/403/challenges persistently suspend access until an administrator investigates.

Quick start with Docker

Public image: ghcr.io/alexxanddr/subito-monitoring:latest, Linux amd64/arm64. Use a version or commit tag for a repeatable deployment; see publishing. The image includes Python, curl and CA certificates. Chrome is not required.

git clone https://github.com/Alexxanddr/subito-monitoring.git
cd subito-monitoring
cp .env.example .env
# Edit .env privately before starting:
# - replace SM_HTTP_TOKEN with a random secret of at least 32 characters;
# - set both Telegram variables for watches, or leave both unset for search only;
# - set SM_UPSTREAM_ENABLED=true only after reviewing Subito access permission.
chmod 600 .env
docker compose pull
docker compose up -d --no-build
curl --fail http://127.0.0.1:8000/health/ready

The example bearer value is intentionally invalid: startup refuses the unchanged placeholder. Compose binds HTTP to loopback on port 8000 and mounts a persistent named volume at /data. Never use docker compose down -v on real state. Set actual service DNS in SM_ALLOWED_HOSTS before connecting remote MCPHub. Every MCP call requires the bearer token; health probes contain booleans only. Readiness proves the polling task is running, not that Subito scans are fresh.

Related MCP server: Avito Monitor MCP

Local installation and development

Python 3.12–3.14, system curl >=8.4, and a local filesystem with POSIX locks are required (Linux/macOS). On Debian/Ubuntu install curl and ca-certificates; macOS ships curl, which can be checked with curl --version.

uv sync --frozen --no-editable --extra dev
uv run --no-sync subito-monitoring

The default transport is MCP stdio, state is data/monitor.sqlite3, and Subito network access is off. Inject environment settings through your supervisor/client; the local CLI does not automatically load .env. Stdio owns the database until stdin closes. For Hermes-independent monitoring use supervised HTTP or Compose. Do not run a second stdio owner alongside the HTTP service on the same database.

To build the image locally instead of pulling the published image:

docker compose up --build -d

See all environment variables and MCP examples and backup, restore, upgrades and troubleshooting.

MCP tools

Tool

Effect

search_items

Immediate one native page; no watch, state baseline or Telegram send

create_watch

Persistent query, silent initial complete baseline

list_watches

Queries, baseline, errors and last successful scan

update_watch

Replace query or change name/interval; query change resets baseline

pause_watch / resume_watch

Change polling; queued deliveries remain

delete_watch

Delete watch; retain global history and queued deliveries

monitoring_status

Freshness, incomplete coverage, suspension and delivery backlog

“Show the 10 newest ThinkCentre i5 under EUR 150” → search_items:

{"query":{"text":"ThinkCentre i5","section":"market","max_price":"150","order":"newest_first"},"limit":10,"page":1}

“Monitor ThinkCentre i5 under EUR 150 every five minutes” → create_watch:

{"name":"ThinkCentre i5","query":{"text":"ThinkCentre i5","section":"market","max_price":"150","order":"newest_first"},"interval_seconds":300}

Watches default to 600 seconds, validated 60–604800. Supported query orders: newest_first, relevance, price_low_to_high, price_high_to_low; watches require newest_first. Text searches Italy sale listings. section selects market, motori or immobili; default all combines known supported categories and excludes Lavoro, including jobs, services and work equipment. marketplace: IT is the legacy country field, not a Subito section. Motori/Immobili use the observed category paths; Market/all are filtered locally by the first-party category catalog. Motori/Immobili and a narrow Market query have limited live validation. relevance is available for Market/all, not Motori/Immobili. Price filtering is local: missing prices are excluded when a range is set. Native pages contain at most 30 ordinary listings; promoted gallery listings are intentionally excluded. A limit of 1–30 truncates the current native page, and incrementing page skips its unused remainder. Sparse price matches can return fewer than requested. No individual subcategory, location, radius, time filters, photos or price-drop alerts in this version.

Reliability and operations

Baseline and associations commit atomically only after reaching an explicit last page within the scan budget and checking the first page for newly arrived IDs. Failures never advance state. IDs are the numeric listing ID validated against its URN and URL; there is no maximum-ID/timestamp heuristic. Global ID/destination history suppresses reposted IDs across overlapping watches; a different ID is new. Baseline records are distinguished from successfully sent messages. Pending sends survive restart, pause, edits and deletion. A crash after Telegram accepted a message but before the SQLite commit can duplicate it: delivery is at least once.

A mutable paginated site is not an exhaustive snapshot. The default scan budget is five native pages plus a first-page check; broad searches may never complete a baseline. Narrow the text query. Downtime can lose ads that disappear before a successful scan; no timestamp recovery window is promised. Process health does not prove scan freshness or Telegram delivery.

Build and check

uv run --no-sync pytest -q
uv run --no-sync ruff check .
uv run --no-sync ruff format --check .
docker build -t subito-monitoring:test .
python3 scripts/container_check.py

Pull requests run offline tests, lint, a full-history secret scan, a locked-dependency export check, and container/volume verification. Pushes to master additionally build and test native amd64 and arm64 images before publishing the multi-platform latest and sha-<commit> tags. Release tags publish versioned images only after the same checks; version tags must match pyproject.toml. CI never contacts Subito or Telegram and needs no personal registry token.

See publishing and release procedure, verification evidence, and dependency license inventory. This project is unaffiliated with Subito. No cluster, MCPHub or Hermes installation is implied by a public image; those are separate administrator operations.

Available Tools

8 tools
create_watchB

Create persistent polling independent of Hermes; silent initial complete baseline.

Telegram destination is administrator configured. New IDs only, not price drops. Polling defaults to 600 seconds. Watch queries must use newest_first.

Inputs: name (required), query (required), interval_seconds.

delete_watchC

Delete a watch and its seen IDs; retain global deduplication and queued deliveries.

Inputs: watch_id (required).

list_watchesB

List persistent searches, baseline state, scan freshness and errors. No credentials.

Inputs: no named parameters.

monitoring_statusC

Authenticated scan freshness, errors and persistent Telegram backlog.

Inputs: no named parameters.

pause_watchC

Pause scans; previously queued notifications still deliver.

Inputs: watch_id (required).

resume_watchC

Resume scans with existing baseline, bounded recovery and ID deduplication.

Inputs: watch_id (required).

search_itemsA

Immediate one-page Italy/EUR search, no watch or Telegram message.

Set section to market, motori or immobili; all (default) excludes Lavoro. Market is filtered locally; Motori/Immobili use category paths. Set order explicitly for the desired ranking (default newest_first). Newest is ordering, not a time filter. Page results can move or repeat. No reliable listing timestamp, exhaustive coverage, or price-drop detection.

Inputs: query (required), page, limit.

update_watchA

Replace the entire query, or change interval/name. Filter changes reset a silent baseline.

Existing queued notifications are retained. No price-drop or time filter support.

Inputs: watch_id (required), name, query, interval_seconds.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 8 tools

    Disambiguation4/5

    list_watches and monitoring_status both report freshness/errors, creating some overlap, though one is explicitly unauthenticated and the other is authenticated with Telegram backlog. search_items is clearly immediate versus persistent watches, and pause/resume/update/delete are distinct lifecycle actions.

    Naming Consistency4/5

    Seven of eight tools follow a clear verb_noun pattern: list_watches, pause_watch, search_items, create_watch, update_watch, resume_watch, delete_watch. monitoring_status breaks the verb pattern as a noun phrase, but the overall convention remains readable and predictable.

    Tool Count5/5

    Eight tools is well-scoped for this domain, covering the full watch lifecycle, status inspection, and an immediate search path. Each tool has a clear role without obvious bloat.

    Completeness4/5

    The surface covers create/list/update/delete plus pause/resume and status for persistent searches, and list_watches exposes baseline and freshness state. A dedicated get_watch by ID is absent, but it is a minor gap agents can work around via list_watches.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      An MCP server that connects to a Telegram group chat, persists messages to a local SQLite database, and exposes tools to search, retrieve, and send messages via SSE.
      -
    • F
      license
      Not graded
      quality
      D
      maintenance
      A remote MCP server that searches Avito for new classified ads, filtering by price and returning only previously unseen listings. Designed for scheduled monitoring via ChatGPT tasks.
      -
    • F
      license
      A
      quality
      C
      maintenance
      Local SQLite archive and MCP search service for the Telegram channel @markettwits, enabling users to query asset-specific twits by instrument and time range.
      1
      -