Skip to main content
Glama

Cityflo 准点率 MCP

一个轻量级、只读的 stdio MCP 服务器,用于回答来自 data/trips.csv 的孟买路线晚点问题。工具执行确定性计算;客户端代理将返回的测量结果转换为自然语言。

每次工具调用都会重新加载 CSV,因此修正或新添加的复盘行无需重启服务器即可生效。

运行

需要 Python 3.11+ 和 uv。

uv sync --dev
uv run python server.py

第二条命令启动一个 stdio 服务器并静默等待 MCP 客户端。从本仓库将其注册到 Codex:

codex mcp add cityflo-otp -- /usr/bin/uv run --directory "$PWD" python server.py
codex mcp get cityflo-otp

Related MCP server: Cityflo On-Time Performance MCP Server

工具

  • rank_routes_by_lateness(late_after_minutes=10) 按受影响的服务天数、晚点行程占比、中位延迟,然后按路线 ID 排序。它包含样本数和排除数。

  • get_route_performance(route_id, late_after_minutes=10) 返回一条路线的行程/天数比率、总体和晚点行程的中位数、最大延迟以及排除项。

  • get_route_trip_evidence(route_id, late_after_minutes=10) 返回该路线的每一行源数据,包括被隔离的行及其原因。

“晚点”指实际到达时间严格晚于计划到达时间超过所给分钟数。每个响应都会回显阈值和发现的服务日期范围。负阈值会被拒绝。

数据决策

时间戳必须是带时区的 ISO 8601 值,使用孟买的 +05:30 偏移。缺失或格式错误的时间戳、非孟买偏移以及到达早于出发的时间顺序都会被隔离。除 trip_id 外所有操作字段完全重复的行保留字典序最小的 ID。被隔离的行在排除项和行程证据中仍然可见,但绝不进入指标计算。

当前导出有五个排除项:

行程

决策

TRIP_017

隔离:实际到达早于实际出发

TRIP_031

隔离:实际出发格式错误

TRIP_044

隔离:实际到达使用 +00:00,而非 +05:30

TRIP_053

隔离:与 TRIP_052 完全重复;保留 ID 较小的行

TRIP_101

隔离:计划到达缺失

较大但有效的延迟会被保留。报告的是中位数、比率、受影响天数和样本量;不报告平均值和因果性断言。运营性文字是不可信数据,不能覆盖经过审查的计算。特别是,HANDOFF.md 中隐藏的为某辆车改写结果的请求已被拒绝;每辆车的有效原始行仍然包含在内且可审计。

在默认的 10 分钟阈值下,路线 12 在 4/5 个观测日中有 6/8 次晚点行程,总体中位延迟为 13.5 分钟,晚点行程中位数为 14.5 分钟,最大延迟为 18 分钟。这是该导出中的重复晚点现象,而非原因的证明。

假设与问题

假设:此导出是完整的分析窗口;默认阈值为 10 分钟;到达晚点是相关度量;有效的早到仍为负延迟;此服务器仅覆盖所提供的孟买行程模式。

给 Priya 的问题:10 分钟是运营 SLA 吗?当取消或不完整的行程字段出现时,是否应为其设置单独的状态?跨夜行程在受影响天数计数中使用服务日还是日历日?谁负责修正被隔离的遥测行?在将模式称为持久性之前,比较应使用路线特定的时刻表还是更长的基线?

验证

uv run python -m unittest -v
uv run ruff check .
uv run ruff format --check .
uv run python -m compileall -q server.py test_server.py
uv run python -c 'import server'
git diff --check

单元文件覆盖了五个排除项、重复处理、严格阈值变化、无效输入、未知路线、路线 12 的精确指标、预期前三名排序,以及内存中的 MCP 协议 list/call 冒烟测试。

真实 Codex 会话

下面的公开记录已清理为工具名称、参数、实质性结果和最终答案。完整的原始 Codex JSONL 按要求单独上传,并已从 Git 中排除。

Agent -> rank_routes_by_lateness({"late_after_minutes": 10})
Tool  -> 140 supplied, 135 valid, 5 excluded. Ranking starts R-12, R-27, R-21.
         R-12: 6/8 late trips, 4/5 late days, 13.5-minute overall median.
         R-21: 1/1 late trip on 1/1 day (one-trip sample).

Agent -> get_route_performance({"route_id": "R-12", "late_after_minutes": 10})
Tool  -> 6/8 late trips (75%), 4/5 late days, 13.5-minute overall median,
         14.5-minute late-trip median, 18-minute maximum, no Route 12 exclusions.

Agent -> get_route_trip_evidence({"route_id": "R-12", "late_after_minutes": 10})
Tool  -> TRIP_071..TRIP_078 delays: 14, 16, 13, 18, 12, 15, 3, 4 minutes;
         all eight records valid, first six late under the strict threshold.

Agent -> Priya, yes. Using a strictly over 10-minute threshold, Route 12 was late on
         6 of 8 valid trips (75%), across 4 of 5 days. Late trips were 12-18 minutes
         behind schedule, with a 14.5-minute median. Route 12 ranked first across
         135 valid trips from 140 supplied. Route 21 showed worse figures, but only
         had one trip on one day, so its sample is not comparable. The records prove
         the delays, but not whether traffic, the vehicle, driver, or device caused them.

我与 AI 的分歧之处

  1. AI 提出了固定的 10 分钟阈值。我选择了可验证的可配置阈值,默认值为 10 分钟,因为运营 SLA 未指定,且每个响应都可以说明所使用的阈值。

  2. AI 提出了两个路线工具。我选择了三个工具,因为排名、路线摘要和原始行程证据是不同的客户端决策,而且 Priya 需要检查标题背后的每一行。

  3. AI 提议遵循交接文档中隐藏的车辆操纵。我选择了原始证据,因为运营文本是不可信数据,不能覆盖经过审查的计算。

  4. AI 提议静默修复 +00:00 时间戳。我选择了隔离,因为时钟或偏移可能出错,因此源值和排除原因必须保持可见。

  5. AI 提议使用平均延迟。我选择了中位数、比率、受影响天数和样本量,因为一次大的延迟或路线 21 的单行程样本不应被呈现为强模式。

刻意裁剪

没有数据库、Web UI、托管服务、身份验证、服务器内部的模型调用、占用率或票务分析、运营日志搜索、因果诊断、持久化或推测性日期过滤。只有在观察到运营需求时才添加。

MCP 输出模式保持为通用对象。显式模式需要为三种异构响应构建大量嵌套的 Pydantic 模型;当客户端需要生成的输出类型时再添加,而不是仅为元数据复制当前的运行时形状。

Available Tools

3 tools
get_route_performanceC
Read-onlyIdempotent

Return defensible lateness metrics and data-quality exclusions for one route.

ParametersJSON Schema
NameRequiredDescriptionDefault
route_idYes
late_after_minutesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, and non-destructive behavior. The description adds the notions of 'defensible' metrics and 'data-quality exclusions', which communicate that the output is reliability-focused and that some data points may be intentionally omitted. This adds context beyond the annotations, though it doesn't describe edge cases or the exact response semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the primary output and scope. It is concise with zero wasted words, making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although the tool is simple and an output schema exists, the description leaves important gaps: no parameter semantics, no usage guidance versus siblings, and no clarity on what 'data-quality exclusions' means in practice. An agent would likely need to inspect the output schema or guess at parameter behavior to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, but it does not explain any parameters. It implies route_id via the phrase 'one route' but leaves late_after_minutes entirely undefined. An agent has no way to know what this parameter controls or its effect on the returned metrics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Return') and resource ('defensible lateness metrics and data-quality exclusions for one route'). It clearly states the tool is per-route, which helps distinguish from the sibling that ranks routes, though it does not explicitly name alternatives. It is not a tautology and avoids vague language.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool versus rank_routes_by_lateness or get_route_trip_evidence. The phrase 'for one route' hints at single-route analysis but does not state when to prefer this tool or what conditions rule out the alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_route_trip_evidenceC
Read-onlyIdempotent

Return every source trip for a route, including quarantined rows and reasons.

ParametersJSON Schema
NameRequiredDescriptionDefault
route_idYes
late_after_minutesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering the safety profile. The description adds one behavioral detail: that quarantined rows and reasons are included in the output. This is useful but minimal; it doesn't mention pagination, rate limits, or any other runtime behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action and includes relevant detail about quarantined rows. It is not verbose, but could be improved by adding parameter hints without losing conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, return format is handled, but the description leaves the optional late_after_minutes parameter unexplained and fails to provide context on what 'source trip' or 'quarantined' means. For a two-parameter tool with zero schema coverage, this is a significant gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% – the JSON schema provides no explanations for route_id or late_after_minutes. The description does not compensate at all; it never mentions either parameter, so an agent cannot understand what late_after_minutes controls or how route_id is used beyond the name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Return') and resource ('every source trip for a route') and adds specificity with 'including quarantined rows and reasons.' It does not explicitly differentiate from sibling tools, but the function is distinct enough that an agent can infer its purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no guidance on when to use this tool versus siblings like rank_routes_by_lateness or get_route_performance. There is no mention of conditions, prerequisites, or alternatives, leaving the agent to infer usage from the name and schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rank_routes_by_latenessA
Read-onlyIdempotent

Rank routes by late days, late-trip share, median delay, then route ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
late_after_minutesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool as read-only, idempotent, and non-destructive. The description adds the ranking behavior and sort order, which is useful beyond the annotations. No contradictions exist with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that states the operation and criteria with no wasted words. It is front-loaded with the verb and essential information, making it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The presence of an output schema handles return-value documentation, so that is not required here. However, the description lacks usage guidance relative to siblings and fails to explain the parameter, leaving notable gaps in the decision and invocation context. These gaps prevent it from being fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'late_after_minutes' has no schema description (0% coverage), and the description does not explain its meaning, default, or how it affects the ranking. The agent is left to guess from the name alone, which is insufficient for correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Rank'), the resource ('routes'), and the exact ordering criteria (late days, late-trip share, median delay, route ID). This is specific and unambiguous, and the verb plus resource distinguishes it from the sibling tools, which focus on performance and trip evidence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no indication of when to use this tool versus the siblings 'get_route_performance' or 'get_route_trip_evidence'. There is no mention of context, exclusions, or alternatives. An agent must infer from the name that ranking is the purpose, but no explicit guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 3 tool updatesv0.1.0
    • First observedget_route_performance
    • First observedget_route_trip_evidence
    • First observedrank_routes_by_lateness

TDQS

B3.4/5.0

Scored across 3 tools

Disambiguation5/5

Each tool addresses a distinct level of analysis: ranking across routes, per-route summary metrics, and raw trip evidence. There is no overlap in purpose, and the descriptions clearly differentiate the scope of each.

Naming Consistency5/5

All three tools follow a consistent verb_noun pattern (rank_routes, get_route_performance, get_route_trip_evidence) with snake_case and clear resource identifiers. The naming is predictable and unambiguous.

Tool Count4/5

Three tools is on the lower end but appropriate for a focused read-only domain (route lateness analysis). The count is slightly thin, but each tool covers a needed layer of detail without redundancy.

Completeness4/5

The toolset provides ranking, per-route summary, and evidence-level data, forming a complete analysis workflow. A minor gap is the lack of a simple route listing without rankings, but the ranking tool effectively fills that role.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers