Skip to main content
Glama
milano-mobility-mcp

milano-mobility-mcp

by bsab

Milano Mobility MCP

MVP Python funzionante del Nodo Mobilità & Restrizioni: quattro tool MCP stdio per ridurre l'asimmetria informativa su Area B, Area C, MoVe-In e antismog a Milano. Urbanistica esclusa.

Non è un'autorizzazione alla circolazione né consulenza legale. Verificare sempre le disposizioni delle autorità e la propria situazione prima di viaggiare. Nessuna garanzia contro sanzioni.

Cosa funziona davvero

Tool

Supporto nel MVP

check_vehicle_access

Profilo, data e perimetro validati; attualmente sempre non_determinabile, con motivazioni e riferimenti. Nessun divieto abilitato: fonti comunali non verificabili nella consultazione.

get_active_smog_level

Adapter non live: livello, territorio del provvedimento, validità e ultima verifica sconosciuti. Riferimenti ufficiali per verifica esterna.

query_movein_allowance

Calcolo esatto Decimal sui tre valori dichiarati dall'utente. Non legge il saldo personale né determina la soglia normativa.

get_daily_costs

Attualmente sempre non_determinabile: tariffa, totale e scadenza null, non zero. Nessuna tariffa verificata vigente e quindi nessuna abilitata.

SDK ufficiale mcp, modelli Pydantic, Python 3.11+. Nessuna richiesta di rete effettuata dai tool. Risposte con structuredContent e contenuto JSON testuale MCP.

Esiti e prove

  • decision: consentito, vietato, non_determinabile. Questa versione non emette mai consentito: la copertura complessiva è incompleta.

  • Il motore supporta vietato per un divieto ordinario documentato sul profilo dichiarato, condizionato all'assenza di deroghe applicabili dichiarata dall'utente. Questo ramo è esercitato da fixture sintetiche nei test, non da regole distribuite nel catalogo attuale.

  • Un divieto verificato prevale su componenti sconosciute, tutte visibili in assessments.

  • Per budget/costi, decision resta non_determinabile rispetto alla circolazione; calculation_status distingue calcolato, documentato, non_determinabile.

  • Input: user_unverified. Il motore richiede official_public per fonti operative; record synthetic_test o non verificati non sostengono regole. I source_checks restituiti sono riferimenti documentali (reference_only), non prove di regole applicabili.

  • Fonti mancanti, scadute, consultate nel futuro o fuori copertura non producono divieti documentati, costi certi o autorizzazioni. Sconosciuto non significa nessun blocco, ticket gratuito o deroga garantita.

Related MCP server: ECRVSP Documentos: Baixar Veículo

Quickstart

Accesso al repository privato necessario. Nessun token applicativo, account MoVe-In o credenziale da inserire nel progetto.

Windows / PowerShell

gh repo clone bsab/milano-mobility-mcp
Set-Location milano-mobility-mcp
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e '.[test]'
.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe -m milano_mobility_mcp

Entry point alternativo: .\.venv\Scripts\milano-mobility-mcp.exe.

Linux / macOS

gh repo clone bsab/milano-mobility-mcp
cd milano-mobility-mcp
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[test]'
.venv/bin/python -m pytest -q
.venv/bin/python -m milano_mobility_mcp

Entry point alternativo: .venv/bin/milano-mobility-mcp.

Il processo attende messaggi MCP su stdin: non è una REPL né un server HTTP. Nessun banner su stdout; arresto manuale con Ctrl+C. Normalmente lo avvia il client MCP. Installazione senza pytest: pip install -e . con l'interprete dell'ambiente.

Configurazione client MCP

Usare l'interprete assoluto del virtualenv, non python dipendente dal PATH. Sostituire il percorso d'esempio con quello reale. Il package installato non dipende dalla directory corrente del client.

Windows:

{
  "mcpServers": {
    "milano-mobility": {
      "command": "C:\\progetti\\milano-mobility-mcp\\.venv\\Scripts\\python.exe",
      "args": ["-m", "milano_mobility_mcp"]
    }
  }
}

Linux/macOS:

{
  "mcpServers": {
    "milano-mobility": {
      "command": "/home/utente/milano-mobility-mcp/.venv/bin/python",
      "args": ["-m", "milano_mobility_mcp"]
    }
  }
}

La posizione del file di configurazione dipende dal client. Nessuna variabile segreta richiesta. Non abilitare log degli argomenti nel client se contengono dati personali: il server non registra input e non accetta targhe.

Esempi dei quattro tool

Argomenti MCP sempre nella forma {"request": {...}}. Risposte sotto come estratti; motivazioni e metadati completi vengono restituiti.

1. Profilo veicolo esplicito

check_vehicle_access:

{
  "request": {
    "vehicle": {
      "category": "M1", "fuel": "elettrico", "euro_class": null,
      "exemptions": "da_verificare", "resident_in_milan": true
    },
    "at": "2026-09-08T12:00:00+02:00",
    "area": "area_b",
    "inside_area_confirmed_by_user": true,
    "destination": "Destinazione dichiarata in Area B, non geocodificata"
  }
}

Risultato decision: "non_determinabile", anche per elettrico: restano situazione personale, geografia e misure non coperte. Residenza non significa esenzione. exemptions: "nessuna_applicabile_dichiarata" è solo una dichiarazione; usare da_verificare se accessi gratuiti, deroghe o MoVe-In potrebbero essere applicabili.

Obbligatori: categoria, alimentazione, classe Euro (null esplicito ammesso solo per elettrico), stato deroghe, area e conferma perimetro. Valori enumerati esposti da list_tools; categorie/alimentazioni non coperte non vengono assimilate ad altre.

Data/ora ISO 8601 con offset di Europe/Rome: +01:00 in inverno, +02:00 in estate. Date naive, offset errati, ore locali inesistenti e timestamp numerici rifiutati. Le due occorrenze dell'ora ambigua autunnale si distinguono con l'offset. Nessun divieto prospettico per istanti futuri. Nessuna geocodifica di civici, confini, itinerari o verifica varchi/telecamere.

2. Antismog: sconosciuto non è livello zero

get_active_smog_level:

{"request": {"territory": "Comune di Milano"}}

Risposta: decision: "non_determinabile", active_level: null, authority_status: "non_verificato", authoritative_territory: null, valid_from: null, valid_until: null, last_checked: null, freshness: "missing".

evaluated_at è l'ora della chiamata, non la consultazione di un bollettino. Il territorio richiesto non è presentato come ambito di un provvedimento. Le misurazioni ARPA non provano attivazione/revoca; il MVP non converte PM10 in uno stato amministrativo.

3. MoVe-In: solo aritmetica dichiarata

query_movein_allowance:

{"request": {"km_percorsi": "100.1", "soglia_annuale": "100.4", "distanza_viaggio": "0.2"}}

Estratto:

{
  "decision": "non_determinabile", "calculation_status": "calcolato",
  "input_provenance": "user_unverified",
  "km_residui": "0.3", "km_eccedenti": "0",
  "viaggio_nel_budget_dichiarato": true,
  "km_residui_dopo_viaggio": "0.1", "km_eccedenti_dopo_viaggio": "0",
  "authenticated_balance": false
}

Numeri dimostrativi, non soglie normative. Decimal serializzati come stringhe: preferirle anche negli input. Ammessi 0–1.000.000.000 km, massimo sei decimali (limiti tecnici). Negativi, NaN, infiniti e booleani rifiutati. Sopra soglia il residuo è zero, l'eccedenza esplicita e neppure un viaggio nullo rientra nel budget. Nessun saldo autenticato, rinnovo, soglia spettante o autorizzazione dedotti.

4. Costi non coperti

get_daily_costs:

{"request": {"area": "area_b", "on_date": "2026-09-08", "tariff": "ordinaria"}}

Risposta: calculation_status: "non_determinabile", ordinary_ticket_eur: null, total_due_eur: null, activation_deadline_exclusive: null. Non afferma che Area B sia a pagamento: non è calcolato un costo totale per quell'area.

Anche per Area C il risultato attuale è sconosciuto: prove mancanti. Il motore è predisposto per tariffa ordinaria/scadenza solo con fonte verificata per la data; nessuna tariffa reale è abilitata. Tariffe agevolate/sconosciute non diventano ordinarie. Totale dovuto sempre null: non si verifica l'obbligo individuale. Il campo scadenza esclusiva, quando sarà supportato, indica attivazione prima di quell'istante, non una scadenza universale di pagamento.

Fonti, aggiornamento e limiti

Registro fonti: URL, consultazione, regole, periodo e limiti. Catalogo in src/milano_mobility_mcp/sources.py, incluso nel package; nessun aggiornamento automatico o parametro client per sovrascrivere fonti/orologio.

Consultazione dei riferimenti: 8 settembre 2026; nessuna data operativa coperta da regole/tariffe distribuite. Le pagine comunali necessarie hanno restituito HTTP 403; InfoAria soltanto una shell JavaScript. Le pagine Regione/ARPA leggibili documentano cautele e ruoli, non un bollettino attivo. Il motore impone alle future fonti operative una freschezza massima di 24 ore, non una scadenza normativa. Un timestamp nuovo non basta: occorre verifica documentale e temporale. Nessun calendario generale di festivi/sospensioni. Il calcolo MoVe-In è già utilizzabile senza queste fonti mancanti.

Non supportati: storico completo, regole future, tutte le classi/categorie, deroghe e accessi residui, targa, importo personale dovuto, geocodifica, API varchi, funzionamento telecamere, saldo privato MoVe-In, antismog live, pagamento o scraping autenticato. Nessun deploy/acquisto. Repository privato, nessuna licenza aggiunta.

Test e sviluppo

.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe -m pytest -q tests\test_mcp_integration.py
.\.venv\Scripts\python.exe -m pip check

Su Unix usare .venv/bin/python e separatori /. Test offline deterministici: calcoli, input invalidi, timezone/DST, confini, fonti mancanti/scadute/periodi, divieto con unknown, costi sconosciuti non zero. Lo smoke avvia veri processi da modulo ed entry point, usa il client SDK per initialize, list_tools, call_tool sui quattro tool, verifica JSON strutturato e sopravvivenza agli input invalidi. CI Windows/Linux, Python 3.11/3.13.

Validazione locale dell'8 settembre 2026: Python 3.13.14, SDK mcp 1.30.0; python -m pytest -q 122 passati, inclusi due smoke stdio reali; python -m pip check senza problemi. Wheel costruita con python -m pip wheel . --no-deps --wheel-dir <directory-artifact> e verificata per package, fonti ed entry point, senza fixture di test. La matrice CI è configurata separatamente: questi risultati locali non attestano da soli gli altri sistemi/interpreti.

Architettura: models.py contratti; catalog.py provenienza/tempo; sources.py snapshot; service.py valutazioni con clock interno; adapters.py indisponibilità antismog; server.py stdio. Nessun log applicativo degli input; stdout solo protocollo MCP.

Prossimi passi: roadmap.

Available Tools

4 tools
check_vehicle_accessD
Read-onlyIdempotent

Profilo/perimetro dichiarati, ora Europe/Rome: nessun divieto abilitato nel catalogo attuale.

Inputs: request (required). Returns: area, reasons, decision, assessments, +6 more

get_active_smog_levelB
Read-onlyIdempotent

Stato antismog: adapter non live, restituisce onestamente livello e validità sconosciuti.

Inputs: request (required). Returns: reasons, decision, authority, freshness, +10 more

get_daily_costsC
Read-onlyIdempotent

Nessuna tariffa/scadenza abilitata nel catalogo attuale: importi null, mai zero implicito.

Inputs: request (required). Returns: area, on_date, reasons, currency, +8 more

query_movein_allowanceA
Read-onlyIdempotent

Sottrae km dichiarati con Decimal; NON saldo autenticato né autorizzazione alla circolazione.

Inputs: request (required). Returns: rule, reasons, decision, km_residui, +11 more

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    C2.5/5.0

    Scored across 4 tools

    Disambiguation4/5

    Each tool targets a different mobility concept—vehicle access, Move-In allowance, smog level, and daily costs—so an agent can generally select correctly. The only mild ambiguity is between check_vehicle_access and query_movein_allowance, since both concern circulation restrictions.

    Naming Consistency3/5

    All names use snake_case and a verb-like prefix, but the verbs are inconsistent: check, query, get, get. This is readable but does not follow a single uniform verb_noun convention.

    Tool Count4/5

    Four tools is on the lean side but reasonable for a focused Milan mobility server. The count is not bloated, though the domain could justify a few more tools if live functionality were present.

    Completeness2/5

    The tools cover four distinct query areas, but the descriptions repeatedly admit to non-live adapters, empty catalogs, and non-authenticated data. This leaves obvious gaps for agents needing real smog levels, actual Move-In balances, enabled restrictions, or applicable fees.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers