Skip to main content
Glama

用于车队遥测的本地 MCP 服务器

CC3067 网络课程项目 1,第 10 组,危地马拉山谷大学。 Fernando Hernández。

一个 MCP(模型上下文协议)服务器,运行在操作员的机器上,将车队的遥测查询作为工具暴露给语言模型调用。借助它,聊天机器人可以回答诸如“P-123BCD 在哪里?”或“这周哪辆车行驶里程最长?”这样的问题,而用户无需打开追踪平台。

该协议完全基于 Python 标准库在 stdio 上从零实现。我没有使用 MCP SDK 或任何处理 JSON-RPC 的库;这是项目的核心要求,我会在协议实现一节中解释。

什么是 MCP

MCP 是一个应用层协议,它标准化了语言模型如何发现和调用外部工具。MCP 服务器发布一个工具列表,每个工具都有名称、描述和参数 JSON 模式。客户端(例如 Claude Desktop)获取该列表,将其展示给模型,当模型决定使用某个工具时,客户端使用模型选择的参数调用它,并将结果返回给模型,让模型用自然语言解释。

从机制上讲,MCP 是基于传输层的 JSON-RPC 2.0。在本项目中,传输层是 stdio:客户端将服务器作为子进程启动,两者通过 stdin 和 stdout 交换以换行符分隔的 JSON 对象。会话以握手开始(initialize → 响应 → notifications/initialized),之后客户端可以调用 tools/listtools/callping

Related MCP server: NL-to-SQL MCP

为什么是车队,为什么是本地

拥有自有车队的公司已经在车辆上安装了 GPS,并拥有追踪平台;数据存在且完整。问题在于访问:如今需要浏览仪表盘、应用筛选器和生成报告,而最了解运营的人往往最不熟悉平台。

服务器按设计在本地运行,这不仅是课程要求:车队的位置会暴露商业路线、客户和作息时间。服务器运行在操作员的机器上,只有每次查询的聚合结果会发送给模型,位置历史永远不会传出。

前置要求

  • Python 3.11 或更高版本

  • git

  • 可选:用于 Google 地理编码和重新生成路线的 Google Maps 密钥(GOOGLE_MAPS_API_KEY)。没有它一切照常工作。

安装

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 秒报告一次,带有 σ ≈ 5 m 的 GPS 噪声,以及我预先知道的事件(长时间停车、超速、信号丢失、进出地理围栏)。

python datos/generador.py

生成 datos/flota.db(SQLite,约 16 万条位置记录和约 1300 个事件),只需几秒钟。默认情况下,数据集在运行时刻结束,因此问题中的“今天”和“昨天”指的是真实日期。要获得可复现的数据集,可以固定结束时刻:

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

最好在工作时间生成(或传入一个工作时间的 --ahora),这样 unidades_detenidas 中会有在途车辆,而不只是熄火的车辆。

路线:离线模式和 API 模式

基础路线以编码折线的形式保存在 datos/rutas/*.json 中(与 Google Directions API 返回的格式相同),以及每条路线的站点。生成器从那里读取它们,不需要网络或密钥

要重新向 Directions API 请求路线(例如,通过编辑 JSON 来更改站点):

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

使用测试客户端运行服务器

服务器本身不是交互式的:它从 stdin 读取 JSON,向 stdout 写入 JSON。为了查看它的运行情况,我编写了 cliente_prueba.py,它作为子进程启动服务器,进行握手,列出工具,并允许调用它们,打印每个消息在双向传输中的原始内容。

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

在交互模式下,输入工具编号,回答其参数,然后查看请求、响应和结果。它还接受 pinglista

服务器也可以手动测试:

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 地理编码,在 "flota" 中添加 "env": {"GOOGLE_MAPS_API_KEY": "..."}

重启 Claude Desktop 后,七个工具就会出现,可以用自然语言提问。数据库在相对于仓库的 datos/flota.db 中查找;可以通过 MCP_FLOTA_DB 变量更改。

工具

工具

回答的问题

参数

返回

posicion_actual

P-123BCD 在哪里?

placa

地址、坐标、速度、航向、发动机状态和最后报告时间

unidades_detenidas

哪些车辆已停止超过 30 分钟?

minutos_minimos(可选,默认 30)

每辆车的车牌、位置、停止时间以及发动机是否开启

resumen_recorrido

给我 P-456DEF 昨天的行程

placafecha

公里数、出发和返回时间、站点(数量、时长、最长的)、最高和平均速度、信号中断

mapa_recorrido

在地图上显示 P-456DEF 昨天的行程

placafecha

带有 OpenStreetMap 轨迹的 PNG 图像、起点、终点、带时长的站点和地理围栏

alertas

这周有超速吗?

tipo(可选)、fecha_iniciofecha_fin

按类型和车辆计数,以及最严重事件的详细信息

verificar_geocerca

P-456DEF 今天进入 CEDIS 了吗?

placanombre_geocercafecha

是否进入,进入和离开时间以及每次访问的停留分钟数

reporte_kilometraje

这个月哪辆车行驶里程最长?

fecha_iniciofecha_fin

按里程排名的车辆,含运营天数和日均里程

日期格式为 AAAA-MM-DD。警报类型:exceso_velocidadparada_prolongadaperdida_senalgeocerca_entradageocerca_salida

合成数据集中定义的地理围栏:CEDIS Zona 12、Bodega Villa Nueva、Bodega Mixco、CD Zona 18、Bodega Carretera a El Salvador 和 Centro Histórico。verificar_geocerca 接受完整名称或部分名称(“cedis”、“mixco”)。

没有任何工具返回原始数据。 15 辆车每 15 秒报告一次,持续 7 天,就是数十万行;将它们发送给模型既不可行也没有必要。每个工具在 SQL 或 pandas 中聚合,并返回计算结果。每个响应的最大行数是 servidor/registro.py 中的常量 MAX_FILAS = 200,并且有一个测试为每个工具验证这一点。

行程地图

mapa_recorrido 是唯一返回文本以外内容的工具:其结果包含两个内容块,一个带有摘要的 text 和一个带有 base64 PNG 的 image,Claude Desktop 直接在聊天中显示。地图使用 matplotlib 绘制;背景瓦片使用 urllib 从 OpenStreetMap 下载,如果没有网络,则在纯色背景上绘制轨迹。

行程地图

问题示例

  • P-123BCD 现在在哪里?

  • 有没有停了超过一个小时的车?

  • 给我 P-456DEF 昨天的行程摘要。

  • 在地图上显示 P-789GHJ 昨天去过哪里。

  • P-234KLM 周一停了几次,最长的一次在哪里?

  • 这周有超速吗?哪辆车最多?

  • 过去七天哪辆车信号丢失了?

  • P-456DEF 昨天进入 CEDIS 了吗?什么时间,待了多久?

  • 这周哪辆车行驶里程最长?

  • 周一到周五整个车队跑了多少公里?

测试

python -m pytest tests -v

两组:

  • tests/test_protocolo.py:正确的握手、在 initialize 之前拒绝方法、格式错误的 JSON → -32700、无效请求 → -32600、不存在的方法 → -32601、无效参数 → -32602、通知不产生响应、响应的 id 与请求的 id 匹配、响应永远不会同时带有 resulterror,以及通过 stdio 实际启动进程并在 EOF 时干净关闭。

  • tests/test_herramientas.py:每个工具针对在临时目录中使用固定种子生成的数据集进行测试,对照生成器故意注入的事件(我留下的停止车辆、长时间停车、信号中断、超速)进行验证,以及业务错误,并确保没有响应超过 MAX_FILAS

协议实现

所有涉及协议的内容都是使用 sysjsonlogging 手工编写的。pandasshapelygeopymatplotlib 是业务逻辑;requests 仅由数据生成器使用。

  • servidor/main.py,传输层。 逐行读取 stdin,将每个响应写入 stdout 并跟 \nflush()。所有日志都输出到 stderr,因为 stdout 是协议通道,多一个字节就会破坏它。在 EOF 时关闭数据库并以代码 0 退出。

  • servidor/jsonrpc.py,JSON-RPC 2.0。 解析和验证每个消息,通过 id 键的存在来区分请求和通知(而不是通过其值,因为 null 是有效的 id),并使用标准代码 -32700-32600-32601-32602-32603 构建响应和错误。

  • servidor/protocolo.py,MCP。 使用状态机(NUEVAINICIALIZANDOLISTA)进行初始化握手:在收到 notifications/initialized 之前,除 initializeping 之外的任何方法都会被拒绝。版本协商:如果客户端请求的版本受支持,我返回该版本;否则返回我支持的最新版本。tools/listtools/callping。我不处理的通知会被静默忽略,因为响应通知会破坏客户端。

  • servidor/registro.py 工具列表及其 inputSchema,并针对它验证参数(类型、requiredenum)。MAX_FILAS 在这里定义。

我决定将 JSON-RPC 与 MCP 分开,因为它们是协议的两个不同层次:JSON-RPC 定义消息的形式,MCP 定义存在哪些方法以及它们的顺序。将它们分开让我能够测试没有会话时的消息验证,以及没有 stdin 时的状态机。

我最注意的区别在于 tools/call:如果工具不存在或参数不符合模式,那就是协议错误,并以 JSON-RPC error 返回,错误码为 -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