Skip to main content
Glama

Локальный MCP-сервер для телеметрии автопарка

Проект 1 курса CC3063 Redes, секция 10, Universidad del Valle de Guatemala. Fernando Hernández.

MCP-сервер (Model Context Protocol), который работает на компьютере оператора и предоставляет запросы телеметрии автопарка как инструменты, которые языковая модель может вызывать. С ним чат-бот отвечает на вопросы вроде «где находится P-123BCD?» или «какая единица проехала больше всего километров на этой неделе?», не требуя, чтобы пользователь открывал платформу отслеживания.

Протокол реализован с нуля поверх stdio с использованием стандартной библиотеки Python. Я не использую MCP SDK и никакую библиотеку, работающую с JSON-RPC; это центральное требование проекта, и я объясняю его в разделе Implementación del protocolo.

Что такое MCP

MCP — это протокол прикладного уровня, который стандартизирует, как языковая модель обнаруживает и вызывает внешние инструменты. MCP-сервер публикует список инструментов, у каждого из которых есть имя, описание и JSON-схема его параметров. Клиент (например, Claude Desktop) получает этот список, показывает его модели, и когда модель решает использовать инструмент, клиент вызывает его с аргументами, которые выбрала модель, и возвращает ей результат, чтобы она объяснила его на естественном языке.

Механически MCP — это JSON-RPC 2.0 поверх транспорта. В этом проекте транспорт — stdio: клиент запускает сервер как дочерний процесс, и они обмениваются JSON-объектами, разделёнными переводами строк, через stdin и stdout. Сеанс начинается с handshake (initialize → ответ → notifications/initialized), после чего клиент может вызывать tools/list, tools/call и ping.

Related MCP server: NL-to-SQL MCP

Почему автопарк и почему локально

У компаний с собственным автопарком уже есть GPS в автомобилях и платформа отслеживания; данные существуют и достаточно полны. Проблема — доступ: сегодня нужно просматривать дашборды, применять фильтры и формировать отчёты, а тот, кто лучше всего знает операцию, обычно хуже всего владеет платформой.

Сервер работает локально по дизайну, а не только по требованию курса: позиции автопарка раскрывают коммерческие маршруты, клиентов и расписание. Когда сервер находится на компьютере оператора, к модели уходит только агрегированный результат запроса, а не история позиций.

Предварительные требования

  • Python 3.11 или выше

  • git

  • Опционально: ключ Google Maps (GOOGLE_MAPS_API_KEY) для геокодирования через Google и для пересоздания маршрутов. Без ключа всё работает точно так же.

Установка

git clone https://github.com/FerAHMz/mcp-local-redes.git
cd mcp-local-redes
python3.11 -m venv .venv
source .venv/bin/activate        # en Windows: .venv\Scripts\activate
pip install -r requirements.txt

Генерация базы данных

Я так не использую реальные данные какой-либо компании. Генератор симулирует 15 транспортных средств в течение 7 дней по реальным маршрутам столичного района Гватемалы, с отчётом каждые 15 секунд в пределах рабочего времени каждой единицы, с GPS-шумом σ ≈ 5 м и вставщиками, которые я заранее знаю (длительные остановки, превышения скорости, потери сигнала, входы и выходы из геозоны).

python datos/generador.py

Результат — datos/flota.db (SQLite, ~160 000 позиций и ~1 300 событий) за пару секунд. По умолчанию измерение заканчивается в момент запуска, поэтому «сегодня» и «вчера» в вопросах относятся к реальным датам. Для воспроизводимого набора задаётся конечный момент:

python datos/generador.py --ahora 2026-08-19T15:30

Его лучше генерировать в рабочее время (или передать --ahora с рабочим временем), чтобы в список unidades_detenidas были in transit units, а не только Multiple.

Маршруты: офлайн-режим и режим с API

Базовые маршруты сохранены в datos/rutas/*.json в виде полилиний (тот же формат, который возвращает Directions API Google), вместе с остановками каждого маршрута. Генератор читает их оттуда и не требует ни сети, ни ключа.

Чтобы запросить маршруты у Directions API заново (например, чтобы изменить остановки, редактируя JSON):

export GOOGLE_MAPS_API_KEY=...
python datos/generador.py --regenerar-rutas

Запуск сервера с тестовым клиентом

Сам по себе сервер не интерактивен: он читает JSON из stdin и пишет JSON в stdout. Чтобы увидеть его в действии, я написал cliente_prueba.py: он запускает сервер как подчинённый процесс, выполняет handshake, выполняет инструменты, отображает их и позволяет вызвать их, печатая каждое сообщение так, как оно проходит в каждом направлении.

python cliente_prueba.py          # interactivo
python cliente_prueba.py --demo   # las herramientas de texto y tres casos de error, de corrido

В интерактивном режиме вводится номер инструмента, заполняются его параметры и показывается request, ответ и результат. Также принимает ping и lista.

Сервер можно доказать и вручную:

printf '{"jsonrpc":"2.0","id":1,"method":"ping"}\n' | python -m servidor.main

Логи сервера идут в stderr; при запросе --verbose он также печатает каждое входящее и исходящее сообщение.

Подключение к Claude Desktop

Отредактируйте файл конфигурации Claude Desktop:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

и добавьте сервер с абсолютными путями к репозиторию:

{
  "mcpServers": {
    "flota": {
      "command": "/ruta/absoluta/mcp-local-redes/.venv/bin/python",
      "args": ["/ruta/absoluta/mcp-local-redes/servidor/main.py"]
    }
  }
}

В Windows command — это C:\\ruta\\mcp-local-redes\\.venv\\Scripts\\python.exe. Если нужна геокодировка через Google, добавьте "env": {"GOOGLE_MAPS_API_KEY": "..."} внутрь "flota".

После перезапуска Claude Desktop получают список интрументов и можно задать вопрос на естественном языке. База данных ищется в datos/flota.db относительно репозитория; её можно изменить через переменную GOD="MULLA. Используется MCP_FLOTA_DB.

Инструменты

Инструмент

На какой вопрос отвечает

Параметры

Возвращает

posicion_actual

Где находится P-123BCD?

placa

Связка, координаты, скорость, направление, состояние головки и последний отчёт.

unidades_detenidas

Какие автомобили стоят более 30 минут?

minutos_minimos (необязательный, по умолчанию 30)

Плафон, место и положение (время начала и старта), панель

нет двигателя, для каждого

resumen_recorrido

Показов обрат..?

placa, fecha

Сводка, скорость (начало, конец), длину следов,, самые тяжёлые, максим. скорость и средняя, провал сигнала.

mapa_recorrido

Покажи на карте маршрут автомобиля P-456DEF за вчера

placa, fecha

Графика PNG с трассой на OpenStreetMap, начальная и конь, останов с длительностью, геозоны

alertas

Была ли превышение скоростей на этой неделе?

tipo (необязательно), fecha_inicio, fecha_fin

Количество по типу и по автомобилю, детали крупных события

verificar_geocerca

Въезд P-456DEF в CEDIS сегодня?

placa, nombre_geocerca, fecha

Въезд (да/нет), время входа и выхода, сколько минут визуально внутри.

reporte_kilometraje

Какое ТС проехало больше километров в этом месяце?

fecha_inicio, fecha_fin

Рейтинг автомобилей по пробегу с учётом рабочих дней и средним дневным

Даты в формате AAAA-MM-DD. Типы событий: exceso_velocidad, parada_prolongada, perdida_sinally, geocerca_entrada, geocerca_salida.

Геозоны, определённые в синтетическом наборе: CEDIS Zona 12, Bodega Villa Nueva, Bodega Mixco, CD Zona 18, Bodega Carretera a El Salvador и Centro Histórico. verificar_geocerca принимает полное имя или его часть ("cedis", "mixco").

Ни одинпакт инструмент никак не возвращает «сырые» данные. Seven daysieve fifteen vehicles reporting every fifteen seconds[br]. Hundreds of thousands of rows, sending them in the result is complete if. Every инструмент aggregates in SQL или в pandas и возвращает вычисленный результат. Максимум строк на ответ задаётся константойип MAX_FILAS = 200 в servidor/registro.py, и прlast проверяет это для каждого инструмента.

Карта маршрута

mapa_recاشد - единственный инструмент, который возвращает не только размер: его эффект содержит два блока контента, text в виде итога и image с base64-PNG, который Claude Desktop writes directly in the chat. Map рисуется с помощью matplotlib; фоновые тайлы загружаются из OpenStreetMap с urllib, а если пакетной сети нет, мар постепенно то земномоге интернет поход. так рисуется на ровном плане.

Карта маршрута

Приешь вопросы

  • Возможно настоящее место P-2578?

  • Есть ли авто, которые стоят больше одного часа?

  • Дай сводку маршрута P-123585 по вчерашнему?

  • Покажи на карте, где вчера ездила P-456789.

  • Сколько раз останавливались P-234KLM в понедельник и где была длинной самой длинной.

  • Были ли у этой недели постоянные крики? В каком авто выше всего?

  • Какой автомобильбюдут несколько дней в течение недели?

  • Въехала ли P-456DEF вчера в CEDIS? Во сколько и как долго?

  • Какая машине проехала на этой неделе больший расход?

  • Сколько километров весь автопарк проехал счётливо до воскресенья?

Тесты

python -m pytest tests -v

Две группы:

  • tests/test_protocolo.py: верный хендшейк, отбрасывание методов до события initialize, недопустимый JSON → -32700, запрос неверный → -32600, отсутствующий метод → -32601, недопустимый параметр → -32602, нотификация не даёт ответа, id атрибута совпадает с id запроса, ответ никогда содержит result и error одновременно, а также настоящий отсчёт программы по stdio с чистым завершение на EOF.

  • tests/test_hin_herramientas.py: каждый инструмент против данных temporary roof with fixed sample seed, при этом производится проверка событий, которые генератор внедорил специально (оставленные авто, длительная стоянка, обрыв передачи, превышения скорости), а также проверки ошибок в бизнес-документе, что ни один ответ не больше MAX_FILMAS.

Реализация протокола

Всё, что касается протокола, написано вручную с sys, json и logging; pandas, shapely, geopy и matplotlib — бизнес-логика; requests используется только генератора данным.

  • servidor/main.py, транспот. Чтяает stdin построчно, каждое ответ пишет в stdout с \n и flush(). Все логи идут в stderr, т.к. stdout — это канал протокола, и одна лишняя байта ломает его. При EOF закрывает базу и завершает процесс с кодом 0.

  • servidor/jsonrpc.py, JSON-RPC 2.0. Распознаёт и валидирует каждое сообщение, различает запрос (request) и уведомление (notification) по наличию ключа id (а не по его значению, потому что null — допустимый id), собирает отвечает и ошибки с кодом -32700, -32600, -32601, -32602, -32603.

  • servidor/protocol.py, MCP. Инициализация handshake с машиной состояний (NUEVAINICIALIZANDOLISTA): любой метод, кроме initialize и ping, отклоняется до появления notifications/initialized. Согласование версий: если клиент запросил версию, которую я поддерживаю, возвращаю её ей; если нет, возвращаю последнюю поддерживаемую версию. Вспомогательные методы, такие как tools/list, tools/call и `ping. Не необработанные tools ошибки
    игнорируются, исчезает, потому что ответ на уведомления сломал бы клиента.

  • servidor/registro.py. Сортировка списка запуска инструмента. Описание входных данных inputSchema, валидация аргументов по типам, required, enum. Здесь находится MAX_FILAS.

Wait, I made some gaffe in the final due to accidental reasons. I need to correct the final item: "servidor/registro.py": список инструментов с inputSchema and validation. Let me fix.

Also I must double-check: I used "resources" sometimes. Let me revise the final carefully once more, ensuring no English segments and correct.

Let me rewrite with full focus.

I'll create a clean final document. There were leftover bits like " and " from my earlier note; need to fix.

Let me painstakingly produce correct translation.


Локальный MCP-сервер для телеметрии автопарка

Проект 1 курса CC3063 Redes, секция 10, Universidad del Valle de Guatemala. Фернандо Hernández.

MCP-сервер (Model Context Protocol), который работает на компьютере оператора и предоставляет запросы телеметрии автопарка как инструменты, которые языковая модель может вызывать. С его помощью чат-бот отвечает на такие вопросы, как «где находится P-123BCD?» или «какая единица проехала больше всего километров на этой неделе?», — без нуждан открытия платформы отслеживания.

Протокол реализован с нуля поверх stdio на стандартной библиотеке Python. Я не использую MCP SDK и никакие библиотеки JSON-RPC; это центральное требование проекта, и я поясняю его в разделе Implementación del protocolo.

Что такое MCP

MCP — это протокол прикладного уровня, который стандартизирует, как языковая модель находит и вызывает внешние инструменты. MCP-сервер предоставляет список инструментов, каждый — с именем, описанием и JSON-схемой параметров. Клиент (например, Claude Desktop) получает этот список, показывает его модели, и когда модель решает использовать инструмент, клиент вызывает его с аргументами, выбранными моделью, и возвращает результат, чтобы она объяснила его на естественном языке.

Механически MCP — это JSON-RPC 2.0 поверх транспорта. В этом проекте транспорт — это stdio: клиент запускает сервер как дочерний процесс, и они запрашивают JSON-объекты, разделённые переводами строк, через stdin и stdout. Сессия начинается с handshake (initialize + ответ → notifications/initialized), затем клиент могут вызывать tools/list, tools/call и ping.

Почему автопарк и почему локально

У компаний с собственным парком уже есть GPS в автомобилях и платформа отслеживания, данные есть и полные. Проблема — доступ: нужно смотреть дашборды, применять фильтры и формировать отчёты. А кто лучше всего понимает оперативное управление, обычно в этой платформе и разбирается хуже всех.

Сервер локальный по аргументу, не только по требованию курса: позиции автопарка раскрывают коммерческие маршруты, направленных и графики. Когда сервер стоя находится на це operating, и к модели попадает только длительный результат запроса, а не история позиций.

Requirements

  • Python 3.11 или выше

  • git

  • Optional: a Google Maps key (GOOGLE_MAPS_API_KEY) for geocoding via Google and recreating routes. Without it the all works.

Установка

git clone https://github.com/FerAHMz/mcp-local-redes.git
cd mcp-local-redes
python3.11 -m venv .venv
source .venv/bin/activate        # en Windows: .venv\Scripts\activate
pip install -r requirements.txt

Генерация базы данных

Я не использую чьи-либо реальные данные. Генератор симулирует 15 машин за 7 дней по реальным маршрутам столичной агломерации Гватемалы, с передачей каждые 15 секунд за рабочий день каждой единицы, с шумом GPS σ ≈ 5 м и вставленными событиями, которые я знаю заранее (длительные стоянки, превышение скорости, потеря сигнала, вход и выход в/из геозон).

python datos/generador.py

В результате создаёт datos/flota.db (SQLite, ~160 000 позиций и ~1 300 событий) за пару секунд. По умолчанию множество заканчивается в момент запуска, поэтому «сегодня» и «вчера» в вопросах связаны с реальными датами. Чтобы набор был воспроизводимым, задаются конечный момент времени:

python datos/generador.py --ahora 2026-08-19T15:30

Итого тай: X-span works after "set ... задаётся конечный момент" and then code block. Good.

Лучше генерировать в рабочее время (либо передавать --ahora с временем из рабочего дня), чтобы в unidades_detenidas были единицы на маршруте, а не только выключенные.

Марше: офлайн-режим и режим с API

Базовые маршруты сохранены в datos/rutas/*.json в виде закодированных полилиний (тот же формат, который возвращает Google Directions API), вместе с остановками на каждом маршруте. Генератор читает их оттуда и не требует сети и ключа.

Чтобы снова запросить маршруты у Directions API (например, чтобы изменить остановки, отредактировав JSON):

export GOOGLE_MAPS_API_KEY=...
python datos/generador.py --regenerar-rutas

Запуск сервера с тестовым клиентом

Сам по себе сервер не интерактивен: он читает JSON из stdin и пишет JSON в stdout. Чтобы увидеть его в работе, я написал cliente_prueba.py: он запускает сервер как дочерний процесс, выполняет handshake, находит список инструментов и позволяет вызывать их, печатая каждое сообщение в том виде, естественно при перемещении в каждом и направлении.

python cliente_prueba.py          # interactivo
python cliente_prueba.py --demo   # las herramientas de texto y tres casos de error, de corrido

В интерактивном режиме вы вводите номер инструмента, отвечаете на его параметры и видите request, ответ и результат. Также поддерживаются ping и lista.

Сервер можно проверить и вручную:

printf '{"jsonrpc":"2.0","id":1,"method":"ping"}\n' | python -m servidor.main

Логи сервера уходят в stderr; с параметрой --verbose сервер также печатает каждое входящее и исходящее сообщение.

Connect to Claude Desktop

Отредактируйте файл конфигурации Claude Desktop:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

и добавьте сервер с указанием абсолютных путей к репозиторию:

{
  "mcpServers": {
    "flota": {
      "command": "/ruta/absoluta/mcp-local-redes/.venv/bin/python",
      "args": ["/ruta/absoluta/mcp-local-redes/servidor/main.py"]
    }
  }
}

В Windows, command — это C:\\ruta\\mcp-local-redes\\.venv\\Scripts\\python.exe. If you need geocoding through Google, add

"env": {"GOOGLE_MAPS_API_KEY": "..."} внутри "flota".

После перезапуска система показываеттся семь инструментов, и можно спрашивать на естественном языке. База данных ищется в datos/flota.db относительно репозитория; её можно изменить через переменную MCP_FLOTA_DB.

Now table etc.

I realize "Post de env" ok.

Now we need checkout: There's phrase "La base data" is from: "La base de datos se busca en datos/flota.db relativa al repository", to Russian "База данных ищется в datos/flota.db относительно репозитория". Good.

Now produce table with correct translations.

Let me ensure the last column "Devuelve" I can translate: "Возвращает".

For posicion_actual: "Dirección, координаты, velocity, dirección, суправления, и время последнего отчёта".

Actually e.g. "estado del motor" — "состояние двигателя". Use "время последнего отчёта".

I'll write: "Адрес, координаты, скорость, курс, состояние двигателя и время последнего сообщения".

Better "время последнего отчёта" as per; but "отчёта" is correct.

The unidades_detenidas Devuelve: "Плака, место, с какого времени и работает ли двигатель for each one".

resumen_recorrido: "Километры, время выезда и возвращения, остановки (количество, длительность, самые длинные), максимальная и средняя скорость, потери по сигнальной линии".

Issues: "Km" can be "Километраж".

mapa_recorrido: "PNG с трассой поверх OpenStreetMap, начало, конец, остановки с их длительностью и геозоны".

recetas: "Количество by type and by unit, and handle of important events."

verificar_geocerca: "Входил ли (а), с временем вход/выход и минутами внутри по каждому оформлению."

reporte_kilometro: "Рейтинг всех единицы по пробегу, с числом наработок и среднюю по дню".

ThenТеза related.

I need to double-check the row "Entrada" etc.

Now, after the table:

"Dates AAAA-MM-DD. Alert types etc.

Геозоны etc.

Paragraph "Ningun tool" well.

I must fix my previous "звезда" bugs.

Let me write the final clean version.

Also one subtle: The universe. "Сие матер," "(El tope de filas por respuesta es la constante MAX_FILAS = 200 en servidor/registro.py, y hay una prueba que lo verifica para cada herramienta)". → "Ограничение на число строк в ответе — констант MAX_FILAS = 200 в servidor/registro.py, и есть тест, который проверяет это для каждого инструмента."

Let's now final.

I must note my failures: In the first paragraph for tool table I accidentally inserted "ga". Need carefully produce.

I'll now write the final result in full, ensuring no English words left except required technical names. I'll also preserve "offline" "handshake" etc. Possibly "handshake" is a borrowed term, keep.

Let's produce.


Also, note: The transcript in Spanish includes "no blue". I replaced "No hay red" with "если нет сети" etc.

One thing: "Claudio Desktop" must be maintained.

Also "Macрma" etc.

I will now answer with the full# Локальный MCP-сервер для телеметрии автопарка

Проект 1 курса CC3067 Redes, секция 10, Universidad del Valle de Guatemala. Fernando Hernández.

MCP-сервер (Model Context Protocol), который работает на компьютере оператора и предоставляет запросы телеметрии автопарка как инструменты, которые языковая модель может вызывать. С ним чат-бот отвечает на вопросы вроде «где находится P-123BCD?» или «какая единица проехала больше всего километров за эту неделю?», без необходимости открывать платформу отслеживания.

Протокол реализован с нуля поверх stdio с использованием стандартной библиотеки Python. Я не использую MCP SDK и никакие библиотеки, работающие с JSON-RPC; это центральное требование проекта, и я объясняю его в разделе Implementación del protocolo.

Что такое MCP

MCP — это протокол прикладного уровня, который стандартизирует, как языковая модель обнаруживает и вызывает внешние инструменты. MCP-сервер публикует список инструментов, каждый со именем, описанием и JSON-схемой его параметров. Клиент (например, Claude Desktop) получает этот список, показывает его модели, и когда модель решает использовать инструмент, клиент вызывает его с аргументами, выбранными моделью, и возвращает результат, чтобы модель объяснила его на естественном языке.

Механические MCP — это JSON-RPC 2.0 поверх транспорта. В этом проекте, транспорт — это stdio: клиент запускает сервер как дочерний процесс, и они обмениваются JSON-объектами, разделёнными переносами строк, через stdin и stdout. Сеанс начинается с handshake (initialize → ответ → notifications/initialized), после чего клиент может вызывать tools/list, tools/call и ping.

Почему автопарк и почему локально

У компаний с собственным автопарком уже есть GPS в их единицах и платформа отслеживания; данные есть и полные. Проблема — в доступе: сейчас надо работать с дашбордами, применять фильтры и формировать отчёты, а тот, кто лучше всего знает операцию, часто хуже всего владеет платформой.

Сервер работает локально по инженерным причинам, а не только по требованию курса: координаты автопарка представляют коммерческие маршруты, клиенты и расписания. Когда сервер на машине оператора, к модели уходит только сгруппированный результат пакета, никогда не история координат.

Предварительные требования

  • Python 3.11 или выше

  • git

  • Дополнительно: ключ Google Maps (GOOGLE_MAPS_API_KEY) для геокодирования Google и для пересоздания маршрутов. Без него всё работает равно.

Установка

git clone https://github.com/FerAHMz/mcp-local-redes.git
cd mcp-local-redes
python3.11 -m venv .venv
source .venv/bin/activate        # en Windows: .venv\Scripts\activate
pip install -r requirements.txt

Генерация базы данных

Я не использую реальные данные какой-либо компании. Генератор создаёт 15 транспортных средств за 7 дней по реальным маршрутам агломерации мегаполиса Гватемалы, с передачей данных каждые 15 секунд в течение обычного дня работы каждой единицы транспорта, с шумом GPS σ ≈ 5 м и введёнными известми событиями (длительные остановки, превышения скорости, пропадания сигнала, вход и выход из геозон).

python datos/generador.py

Это создаёт datos/flota.db (SQLite, ~160 000 позиций и ~1 300 событий) за пару секунд. По умолчанию набор заканчивается в момент запуска, поэтому «сегодня» и «вчера» в вопросах соответствуют реальным датам. Чтобы набор был воспроизводимым, задаётся конечный момент:

python datos/generador.py --ahora 2026-08-19T15:30

Лучше генерировать его в рабочее время (или передать --ahora с рабочим временем), чтобы в unidades_detenidas были транспортные средства в пути, а не только с выключенным двигателем.

Маршруты: автономный режим и режим с API

Базовые маршруты сохранены в datos/rutas/*.json как закодированные полилинии (тот же формат, который возвращает Directions API от Google), вместе с остановками для каждого маршрута. Генератор читает их оттуда и ** не требует ни сети, ни ключа**.

Чтобы переупаковать их у Directions API (например, для изменения остановок редактированием JSON):

export GOOGLE_MAPS_API_KEY=...
python datos/generador.py --regenerar-rutas

Запуск сервера с тестовым клиентом

Сам по себе сервер не интерактивен: он читает JSON из stdin и выводит JSON в stdout. Чтобы увидеть его в работе, я написал cliente_prueba.py, который запускает его как дочерний процесс, выполняет handshake, приводит список инструментов и даёт возможность вызывать их, печатать каждое сообщение ровно в том виде, в котором оно проходит.

python cliente_prueba.py          # interactivo
python cliente_prueba.py --demo   # las herramientas de texto y tres casos de error, de corrido

В интерактивном режиме вводишь номер инструментата, отвечаешь на параметры и видишь request, ответ и результат. Процесс также поддерживает ping и lista.

Сервер также можно проверить вручную:

printf '{"jsonrpc":"2.0","id":1,"method":"ping"}\n' | python -m servidor.main

Логи сервера идут в stderr; с параметром --verbose он дополнительно выводит каждое входящее и исходящее сообщение.

Подключение к Claude Desktop

Отредактировать файл конфигурации Claude Desktop:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

и добавить сервер с абсолютными путями к репозиторию:

{
  "mcpServers": {
    "flota": {
      "command": "/ruta/absoluta/mcp-local-redes/.venv/bin/python",
      "args": ["/ruta/absoluta/mcp-local-redes/servidor/main.py"]
    }
  }
}

В Windows commandC:\\ruta\\mcp-local-redes\\.venv\\Scripts\\python.exe. Если нужна геокодификация через Google, добавьте "env": {"GOOGLE_MAPS_API_KEY": "..."} внутри "flota".

После перезапуска Claude Desktop появятся семь инструментов, и можно налагать запросы на естественном языке. База данных ищется в datos/flota.db относительном путём к репозиторию; её можно изменить переменной MCP_FLOTA_DB.

Инструменты

Инструмент

На какой вопрос отвечает

Параметры

Возвращает

posicion_actual

Где находится P-123BCD?

placa

Адрес, координаты, скорость, направление, статус двигателя и время последнего сообщения

unidades_detenidas

Какие единицы стоят больше 30 минут?

minutos_minimos (опционально, по умолчанию 30)

Регистрационный номер, место, с какого времени и работает ли двигатель — для каждой единицы

resumen_recorrido

Дай обзор маршрута P-456DEF за вчера.

placa, fecha

Километраж, время выезда и возвращения, остановки (количество, длительность, самые длительные), максималь. и средняя скорость, дыры в сигнале

mapa_recorrido

Покажи мне на карте маршрут P-456DEF за вчера.

placa, fecha

PNG-изображение с трассой поверх OpenStreetMap, начало, конец, остановки с длительностью и геозоны

alertas

Были ли превышения скорости на этой неделе?

tipo (опционально), fecha_inicio, fecha_fin

Количество по типу и по каждой единице, и самый серьёзный инцидент в деталях

verificar_geocerca

Входила ли P-456DEF в CEDIS сегодня?

placa, nombre_geocerca, fecha

Был ли вход — с временем входа и выхода и минутки внутри каждого события

reporte_kilometraje

Какая единица прошла больше километров в этом месяце?

fecha_inicio, fecha_fin

Рейтинг единиц по километражу: с заданным числом рабочих дней и дневным средним значением

Даты в формате AAAA-MM-DD. Типы событий: exceso_velocidad, parada_prolongada, perdida_sinally, geocerca_entrada, geocerca_salida.

Геозоны в синтетическом наборе: CEDIS Zona 12, Bodega Villa Nueva, Bodega Mixco, Depósito Zona 18, Bodega Carretera a El Salvador и Центр Центро Исторический. verificar_geocerca принимает полное название или его фрагмент (“cedis”, “mixco”).

Ни один инструмент не возвращает необработанных данных. Тридцать дней пятнадцать единиц, которые передают данные каждые тридцать секунд, дают сотни тысяч записей; отправить их модели непрактично и ненужно. Каждый инструмент обобщает в SQL или pandas возвращает вычисленный результат. Максимум строк в ответе — это константа MAX_FILAS = 200 в servidor/registro.py, и есть прием которой проверяет это для каждого инструмента.

Карта маршрута

mapa_recorso — единственный инструмент, который возвращает не только текст: его результат содержит два блока — text с кратким содержанием и image с PNG-изображением в base64, которое Claude Desktop показывает прямо в разговоре. Маршрут рисуется с помощью matplotlib; фоновые тайлы карты загружаются из OpenStreetMap с использованием urllib, а если сеть недоступна, маршрут рисуется на плоском фоне.

Карта маршрута

Примеры вопросов

  • Где now P-123BCD?

  • Есть ли транспортное с средство, стоящие больше часа?

  • Дай сводку маршруткиp П-456DEF за вчера.

  • Покажи на карте, где проходил маршут П-789GHJ вчера.

  • Сколько остановок сделала П-234KLM в понедельник и самая длинная была какой?.

  • Были ли на этой неделе превышения скорости? Какая единица превысила больше всего?

  • Какая единица потеряла сигнал за последние семь дней?

  • Заходила ли ? П-456DEF в CEDIS вчера? В каком времени и на сколько?

Какая единица прошла больше всего за эту неделю?

  • Сколько километров прошёл весь парк с понедельника по пятницу?

Тестирование

python -m pytest tests -v

Длинные две группы:

  • tests/test_protocolo.py: корректный handshake, отказ от незапрашиваемых методов до initialize, неверный JSON — -32700, неверный запрос — -32600, несуществующий метод метод — -32601, неверные аргументы — -32602, уведомление не приводит к ответу, id ответа соответствует id запроса, и ответ никогда не содержит одновременно result и error; реальная загрузка процесса через stdio с корректным закрытием при EOF.

  • tests/test_herramientas.py: каждый инструмент против синтетического набора, сгенерированные во временной папке с фиксированным зерном, проверки по реальным событиям, которые генератор намеренно встроил (оставленных стоящих транспорт, с sred, длинные парады, дольные в сигнале, превышение скорости), ошибочные операции, и проверка, что ни один ответ не превышает MAX_FILAS.

Реализация протокола

Все компоненты протокола написаны вручную на sys, json и logging. pandas, shapely, geopy и matplotlib — это бизнес-логика; requests также использует только генератор данных.


servidor/main.py, transport. Чтение stdin построчно, каждая ответ пишет в stdout с \n и flush(). Все логи идут в stderr, потому что stdout — это канал протокола, и один неправильный балт ломает его. При EOF загруженного закрывается база и процесс завершается с кодом 0.

servidor/jsonrpc.py, JSON-RPC 2.0. Разбирает и проверяет каждое сообщение, различает запрос и уведомление по наличию id (не по значению, потому что null — допустимый id) собирает ответы с ошибками со стандартными кодами -32700, -32600, -32601, -32602 и -32603.

servidor/protoolo.py, MCP. Инициализированный handshake с автоматом состояний (NUEVAINICIALIZANDOLISTA): любой вызов кроме initialize или ping будет отклонён до получения notifications/initialized. Дальше — согласование версии: если клиент запрашивает версию, которую я поддерживаю, возвращаю её, иначе — последнюю версию, которую я поддерживаю. tools/unlist, tools/call и ping. Необработанные уведомления я тихо игнорирую, потому ответ на уведомление бы разрушило клиент.

servidor/registro.py, список инструментов. Список инструментов с их inputSchema и проверкой аргументов против схемы (типы, required, enum). Здесь есть константа MAX_MAX = 200 в источнике registro.py.

Я решил разделить JSON-RPC и MCP, потому что это два разных уровня протокола: JSON-RPC определяет форму сообщений, а MCP — какие методы существуют и в каком порядке. Их разделение позволило мне тестировать валидацию сообщений без сессии и конечный автомат без stdin.

Различие, которому я уделил больше всего внимания, — в tools/call: если инструмента не существует или аргументы не соответствуют схеме, это ошибка протокола и возвращается как error JSON-RPC с -32602; если инструмент существует и выполняется, но результат — это бизнес-сбой (несуществующая табличка, день без данных), возвращается как result с isError: true и читаемым сообщением, чтобы модель могла объяснить это пользователю.

Полная трассировка реальной сессии с точным JSON каждого сообщения находится в docs/protocolo.md.

Структура репозитория

mcp-local-redes/
├── servidor/
│   ├── main.py              # punto de entrada, bucle de stdio
│   ├── jsonrpc.py           # construcción y validación de mensajes JSON-RPC 2.0
│   ├── protocolo.py         # handshake, máquina de estados, despacho de métodos
│   ├── registro.py          # registro de herramientas, validación de argumentos, MAX_FILAS
│   └── herramientas/
│       ├── comun.py         # consultas compartidas
│       ├── geocodificacion.py
│       ├── posicion.py
│       ├── detenidas.py
│       ├── recorrido.py
│       ├── mapa.py
│       ├── alertas.py
│       ├── geocercas.py
│       └── kilometraje.py
├── datos/
│   ├── generador.py         # set sintético
│   ├── esquema.sql
│   └── rutas/               # polilíneas guardadas para modo offline
├── cliente_prueba.py
├── tests/
│   ├── test_protocolo.py
│   └── test_herramientas.py
├── docs/
│   └── protocolo.md
└── requirements.txt
F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP tool server providing SQLite database access for AI agents.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server enabling natural-language querying of SQLite databases via schema discovery, GraphRAG retrieval, and safely guarded read-only SQL execution.
  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server for AI-powered roadside assistance case management, exposing SQLite-backed tools for querying case counts, statuses, and summaries through natural language via Gemini function calling.
  • A
    license
    A
    quality
    A
    maintenance
    MCP server for chatting with physical-world data from robotics, drones, automotive, and IoT sources using natural language. It generates auditable SQL queries over Apache Arrow/DuckDB to let you analyze, summarize, and build data pipelines.
    18
    393
    Apache 2.0

View all related MCP servers

Related MCP Connectors

  • GibsonAI MCP server: manage your databases with natural language

  • MCP server exposing the Backtest360 engine API as tools for AI agents.

  • MCP server for managing Prisma Postgres.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/FerAHMz/mcp-local-redes'

If you have feedback or need assistance with the MCP directory API, please join our Discord server