Skip to main content
Glama

Ticket Fighter

An MCP server that automates parking ticket detection, evidence gathering, and dispute preparation across multiple US cities. Runs fully in the cloud via the @ticket_fighter MMP bot or locally as a stdio MCP server.

MMP Bot

DM @ticket_fighter on MMP to use Ticket Fighter through any AI assistant. The bot runs on Railway and handles everything headlessly.

Landing page: tf.mmp.chat

Commands:

  • add ABC1234 NY nyc — Monitor a plate

  • check — Scan for tickets now

  • analyze 1234567 nyc — Evidence & defense strategy

  • dispute 1234567 nyc — Generate dispute

  • submit 1234567 nyc — Submit to city portal

  • status 1234567 nyc — Check outcome

  • gmail — Connect Gmail for decision tracking

  • help — Show all commands

Bot source: /ticket-fighter-bot

Related MCP server: MCP Job Application Tracker & Resume Customizer

Supported Cities (24)

Open Data API (no browser needed)

City

API

Fallback

NYC

NYC Open Data (SODA nc67-uf89)

CityPay scraper if data >30 days stale

San Francisco

SF Open Data (SODA ab4h-6ztd)

eTIMS scraper if data >30 days stale

Chicago

CHIPAY JSON API (ticket # lookups)

Browser scraper for plate searches (hCaptcha)

No CAPTCHA (fully automatable)

City

Platform

Dispute Method

Boston

RMC Pay

Online/mail/video appeal

Miami

RMC Pay

Via Miami Parking Authority

Charlotte

RMC Pay

3-tier appeal

Denver

RMC Pay

Via portal

Dallas

RMC Pay

Via portal

Raleigh

RMC Pay

Via portal

Orlando

CPC

Notarized appeal form (PDF)

Baltimore

Custom

Phone/in-person (410-396-3000)

Atlanta

DS Payments

Duncan appeal portal (14-day deadline)

San Diego

DS Payments

Duncan appeal portal

Detroit

DS Payments

Duncan appeal portal

Pittsburgh

DS Payments

Duncan appeal portal

Milwaukee

DS Payments

Duncan appeal portal

Sacramento

DS Payments

Duncan appeal portal

New Orleans

DS Payments

Duncan appeal portal

CAPTCHA (auto-solved via 2Captcha, or user solves in browser)

City

Platform

CAPTCHA Type

Dispute Method

NYC

CityPay

reCAPTCHA v2

HBW online hearing

Chicago

CHIPAY

hCaptcha

eHearing

Washington DC

eTIMS

Custom image

DC DMV online

San Francisco

eTIMS

Custom image

SFMTA citations

Detroit (eTIMS)

eTIMS

Custom image

Via portal

Cleveland

eTIMS

Custom image

Via portal

Columbus

eTIMS

Custom image

Via portal

Oakland

eTIMS

Custom image

Via portal

Santa Monica

eTIMS

Custom image

Via portal

Platform adapters (add new cities with one line of config)

  • RMC Pay — 50+ US cities use this platform. Add any with: createRmcPayAdapter({ cityId, displayName, subdomain })

  • DS Payments — 25+ cities. Add with: createDsPaymentsAdapter({ cityId, displayName, citySlug, appealSlug })

  • eTIMS — 10+ major cities. Add with: createEtimsAdapter({ cityId, displayName, cityPath, subdomain })

Cloud Operation

Ticket Fighter runs fully headless in the cloud with these env vars:

Var

Purpose

CAPTCHA_API_KEY

2Captcha API key — auto-solves reCAPTCHA v2 (NYC) and hCaptcha (Chicago)

GOOGLE_CLIENT_ID

Google OAuth client ID — enables Gmail API for decision tracking

GOOGLE_CLIENT_SECRET

Google OAuth client secret

GOOGLE_REDIRECT_URI

OAuth callback URL (e.g. https://tf.mmp.chat/auth/gmail/callback)

Without these, the tools fall back to headed browser mode (local use only).

ChatGPT App

Ticket Fighter includes a widget UI for ChatGPT. All tools render inline results — a dashboard for check_tickets, detail views for analyze_ticket, dispute previews, and status badges.

To rebuild the widget: cd app && npm install && npm run build

Setup

npm install
npx playwright install chromium
cd app && npm install && npm run build && cd ..
npm run build

Claude Code (.mcp.json)

{
  "mcpServers": {
    "ticket-fighter": {
      "command": "node",
      "args": ["/path/to/ticket-fighter/dist/index.js"]
    }
  }
}

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "ticket-fighter": {
      "command": "node",
      "args": ["/path/to/ticket-fighter/dist/index.js"]
    }
  }
}

Tools

manage_plates

Add, remove, or list saved license plates.

check_tickets

Scan city portals for open violations on your saved plates.

analyze_ticket

Gather evidence for a specific ticket: details, Street View imagery, registration cross-references, applicable traffic rules, common defenses, and past dispute history.

generate_dispute

Format dispute arguments into city-specific structure. Returns a preview — does not submit.

submit_dispute

Submit a previewed dispute. Requires explicit confirmation.

check_status

Check dispute status via city portal or Gmail search for decision emails.

setup_gmail

Connect Gmail for decision email monitoring. With Google OAuth configured, returns an authorization URL. Without it, opens a browser for manual login.

Scripts (NYC submission helpers)

NYC's submit_dispute MCP tool intentionally throws — DOF submissions require the user in the loop (evidence upload, personal info, penalty-of-perjury attestation). Two scripts in scripts/ handle the flow:

fetch-summons-citypay.mjs <violation>...

Launches a headed Chromium, walks through CityPay's "Search by Parking Violation" tab for each violation, saves the officer's summons image and CityPay results page to ~/.ticket-fighter/decisions/. User solves any reCAPTCHA; script auto-detects solve (token present OR form navigation) and continues.

node scripts/fetch-summons-citypay.mjs 9270466449 4051701815 8998315609

submit-dispute-nyc.mjs <violation>

Polling-fill for NYC DOF's "Dispute by Web" form. Opens https://www.nyc.gov/site/finance/vehicles/dispute-web.page; user clicks "Dispute by Web" (opens a new tab); script watches all tabs and iframes in the context; every 3 seconds it fills any form field it recognizes (name, address, city, zip, email, plate, violation #, argument textarea) and attaches evidence files to any input[type=file]. Stops at the final Review/Submit page — user reviews and clicks submit manually.

Configure at the top of the script:

  • RESPONDENT — name, address, email

  • EVIDENCE — map of violation # → array of file paths

  • Dispute argument text is loaded from ~/.ticket-fighter/decisions/dispute-<violation>.txt

node scripts/submit-dispute-nyc.mjs 9270466449

DOF-accepted file types: PDF, JPG/JPEG, TIFF, BMP, GIF. Not PNG — convert with sips -s format jpeg in.png --out out.jpg before listing in EVIDENCE.

Adding a New City

If the city uses RMC Pay (check if {cityname}.rmcpay.com loads their portal):

  1. Add one line to src/adapters/rmcpay-cities.ts: export const myAdapter = createRmcPayAdapter({ cityId: "mycity", displayName: "My City", subdomain: "mycitysubdomain" });

  2. Register in src/index.ts

  3. Build and test

For other platforms:

  1. Create src/adapters/yourcity.ts implementing the CityAdapter interface

  2. Create src/codes/yourcity-codes.json with violation codes and defenses

  3. Register the adapter in src/index.ts

  4. Build and test

License

MIT

Available Tools

8 tools
analyze_ticketA
Read-only

Gather evidence for a specific violation: ticket details, registration cross-ref, Street View imagery, traffic rule lookup, common defenses, and past dispute history

ParametersJSON Schema
NameRequiredDescriptionDefault
cityYesWhich city issued the ticket
violation_numberYesThe violation/ticket number

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds meaningful behavioral scope beyond that by disclosing the composite data sources it pulls (registration cross-ref, Street View, rule lookup, defenses, dispute history), which tells the agent this is a multi-source aggregation, not a simple lookup.

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?

A single front-loaded sentence with no filler; the evidence enumeration is dense but each item conveys what the tool returns. Slightly list-heavy but appropriately sized.

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

Completeness4/5

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

With no output schema, the description usefully describes the return content by enumerating the evidence categories. Combined with annotations covering the safety profile, an agent has enough to call this correctly; minor gaps remain around result format and failure behavior.

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

Parameters3/5

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

Schema description coverage is 100% with only two parameters (city enum and violation_number), both documented in the schema. The description adds no syntax, format, or constraint detail beyond what the schema already provides, so the baseline 3 applies.

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?

States a specific verb ('Gather evidence') and resource ('a specific violation'), then enumerates the evidence types, so the agent knows this is a composite read/analysis tool. It is distinguishable from siblings like check_tickets and generate_dispute, though it never names them.

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

Usage Guidelines3/5

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

Usage is only implied: gathering evidence suggests it precedes a dispute generation step, but the description never states when to call this versus check_tickets, check_status, or generate_dispute, nor any prerequisites or exclusions.

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

check_statusB
Read-only

Check dispute status via city portal scrape or Gmail search for decision emails

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity (required with violation_number)
gmail_searchNoSearch Gmail for decision emails
violation_numberNoViolation number to check on city portal

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds that retrieval involves scraping an external city portal or searching Gmail, hinting at network dependence and possible failure, but it says nothing about latency, partial results, or rate limits on scraping.

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?

A single compact sentence with no filler, front-loading the purpose and the two modes. It is appropriately sized, though it is terse to the point of omitting return-shape information.

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?

There is no output schema, so the description should carry the burden of telling the agent what a check returns (status value, decision text, not-found case). It does not, leaving a real gap for a tool whose whole job is reporting a result.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents city, gmail_search, and violation_number, including the required-with-violation_number constraint. The description only echoes the city-portal/Gmail split, adding no format details or parameter interplay beyond the schema, so the baseline 3 applies.

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?

States a specific verb ('check') plus resource ('dispute status') and names the two retrieval mechanisms (city portal scrape, Gmail search for decision emails). It is distinguishable from siblings like check_tickets, though it never explicitly contrasts itself with them.

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

Usage Guidelines3/5

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

The description implies two usage modes (portal lookup vs. Gmail search) but gives no guidance on when to prefer one, what the prerequisite setup is (e.g. setup_gmail, a sibling tool), or when to use this instead of check_tickets. Usage is inferable from the parameters rather than stated.

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

check_ticketsA
Read-only

Check for open parking tickets by scraping city violation portals. Checks all saved plates if no plate specified.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoFilter to one city
plateNoSpecific plate number to check

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds that it scrapes external portals, which is useful context aligning with openWorldHint. However, it doesn't disclose rate limits, potential failures, or what 'check' entails (e.g., does it return ticket details?).

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?

Two sentences with zero waste. The first sentence defines the action and the second specifies the default plate behavior. Both are front-loaded and earn their place.

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?

For a tool with 2 optional parameters, full schema coverage, and annotations, the description is adequate but lacks detail on what the tool returns (no output schema exists). It also doesn't mention any limitations, error cases, or the structure of results, which would be helpful for an agent to interpret the outcome.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters. The description only adds the default behavior for the plate parameter, but provides no extra information for the city parameter or the semantics of the plate value beyond what the schema states.

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?

Clear verb (check) and resource (parking tickets) with a concrete implementation detail (scraping city violation portals). It distinguishes itself from siblings like generate_dispute or submit_dispute, but doesn't explicitly contrast with analyze_ticket or check_status.

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

Usage Guidelines4/5

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

The description specifies a default behavior: 'Checks all saved plates if no plate specified.' This implicitly guides usage around the optional plate parameter, but it doesn't name alternative tools or specify when to avoid this one.

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

generate_disputeA
Read-only

Format dispute arguments into city-specific form structure. Returns a preview — does NOT submit.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityYesWhich city
argumentsYesThe dispute text/arguments to submit
evidence_pathsNoFile paths to photos/documents to attach
violation_numberYesThe violation/ticket number

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds genuine behavioral context beyond them: the output is a preview and nothing is persisted/submitted. It does not describe what the preview contains or whether evidence must be pre-uploaded, so it is not exhaustive.

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?

Two short sentences with zero filler; the core action is front-loaded and the critical non-submission caveat is stated immediately after. Every sentence earns its place.

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

Completeness4/5

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

For a four-parameter formatting tool with no output schema, the description covers the essential traits: it formats for a city and returns a non-persisting preview. A brief note on what the preview yields (e.g., a form payload to pass to submit_dispute) would close the remaining gap, but nothing required to call it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so all four parameters (violation_number, city, arguments, evidence_paths) are already documented in the schema. The description adds only the general notion that output is city-specific, which loosely signals that city drives formatting, but no per-parameter detail beyond the schema. Baseline 3 applies.

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?

Specific verb+resource ('Format dispute arguments into city-specific form structure') with an explicit scope boundary: 'Returns a preview — does NOT submit.' This cleanly separates it from the sibling submit_dispute without the agent opening any schema.

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

Usage Guidelines4/5

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

The 'does NOT submit' clause strongly implies when to use it (draft/preview) versus the submit_dispute sibling, and the city-specific framing implies a per-city preparation step. It stops short of naming the alternative tool or stating prerequisites explicitly, so it is clear context but not full when/when-not guidance.

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

manage_platesC

Add, remove, or list saved license plates for ticket monitoring

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity (for add/remove)
typeNoPlate type, e.g. PAS, COM (for add)
stateNoPlate state, e.g. NY, IL, FL (for add)
actionYesAction to perform
numberNoPlate number (for add/remove)

TDQS

C2.9/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, openWorldHint=false and destructiveHint=false, so the mutation profile is covered structurally. The description adds essentially no behavioral context beyond the action list itself: it does not say whether removals are reversible, where plates persist, or that 'remove' deletes saved state (a point that sits awkwardly with destructiveHint=false).

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?

A single front-loaded sentence with no filler; the resource leads and the allowed operations follow. It is efficient, though its brevity is the direct cause of the missing workflow context rather than a virtue of trimming redundancy.

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?

With 5 parameters, two enums, no output schema and only generic annotations, the description is thin for the complexity: it never states that 'action' is required, which fields each action needs, or how stored plates feed the other tools. The schema absorbs some of that burden at 100% coverage, leaving a minimally adequate definition.

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

Parameters3/5

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

Schema description coverage is 100% and each property already documents its role, including the per-action qualifiers ('for add', 'for add/remove'). The description adds no parameter nuance beyond that, so the baseline 3 applies.

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?

Specific verb set (add/remove/list) paired with a concrete resource (saved license plates) and a stated domain ('for ticket monitoring'), so an agent immediately knows the tool's scope. It does not name or contrast against any sibling such as check_tickets, which consumes these saved plates, so it falls short of the 5 tier.

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?

There is no when-to-use guidance, no prerequisite (e.g. that a plate must be added before check_tickets can monitor it), and no routing advice relative to siblings like check_tickets or analyze_ticket. 'For ticket monitoring' hints at context but leaves the workflow decision entirely to inference.

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

open_dashboardB

Open the Ticket Fighter dashboard in the MCP App UI.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It does not say what invoking the tool actually does (launch a UI, return a URL, mutate server state) or what the caller observes afterward, which is a meaningful gap even for a zero-parameter tool.

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?

A single front-loaded sentence with no filler or repetition. It is appropriately sized, though it is short enough that the lack of any operational detail is noticeable rather than intentional economy.

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?

For a trivial zero-parameter, no-output tool the description is minimally viable, but it omits what 'MCP App UI' means and when the agent should reach for this versus the ticket management siblings. It is adequate but leaves the invocation context to inference.

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

Parameters4/5

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

The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. The description correctly implies the tool is parameterless.

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 names a specific verb ('Open') and resource ('Ticket Fighter dashboard') and locates it in the MCP App UI, so the agent knows exactly what action it performs. It is a self-contained, unambiguous action that is clearly distinct from the ticket/dispute siblings, though it does not explicitly contrast itself with them.

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?

There is no guidance on when this tool should be invoked versus alternatives, nor any mention of prerequisites or the state the user must be in. Usage is only weakly implied by the phrase 'dashboard', leaving the agent to infer the trigger condition.

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

setup_gmailA

Launch a visible browser for Gmail login. Saves auth state for headless reuse by check_status.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare a non-read-only, open-world, non-destructive operation, and the description adds real context on top: a visible browser window is launched (interactive, user-facing side effect) and auth state is persisted to disk for later reuse. It stops short of saying whether the call blocks until login completes, what happens on timeout/cancel, or where the state is stored.

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?

Two short sentences, zero filler, with the primary action front-loaded and the persistence/consumer detail following. Every clause earns its place.

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

Completeness4/5

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

For a zero-parameter tool whose annotations already cover the safety profile, the definition supplies the essentials: what is launched, what is persisted, and who consumes it. The remaining gaps (blocking behavior, timeout, auth-state location, return value) are minor but real for an interactive browser flow.

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

Parameters4/5

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

The tool takes zero parameters and the schema is empty, so there is no parameter semantics for the description to carry. Baseline 4 applies for a no-argument tool; nothing is missing or misdescribed.

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?

Names a specific verb and resource ('Launch a visible browser for Gmail login') plus the side artifact it produces ('saves auth state'), which is enough to distinguish it from every sibling in the list. The downstream consumer, check_status, is named explicitly.

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

Usage Guidelines4/5

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

The description makes the usage context clear: this is the interactive login step whose saved state is later reused headlessly by check_status. It does not state exclusions or prerequisites (e.g. that it must run before check_status, or what to do if auth already exists), so it falls short of a full when/when-not statement.

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

submit_disputeB
Destructive

Submit a previously previewed dispute. Requires confirmed=true as a safety gate.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityYesWhich city
argumentsYesThe dispute text to submit
confirmedYesMust be true to submit. Safety gate.
evidence_pathsNoFile paths to evidence
violation_numberYesThe violation/ticket number

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true, openWorldHint=true, so the agent knows this is an irreversible external write. The description adds the confirmed=true gate, which is real value, but does not say what gets submitted, what happens to a dispute after submission, or that it cannot be undone beyond the destructive hint.

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?

Two short sentences, front-loaded with the action and the precondition. No waste, though it is terse enough to under-specify the submission consequences.

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?

Covers the action and the safety gate, but for a destructive external submission with no output schema the description omits what a successful or failed submission returns and what the ticketing system does with the dispute. Adequate but incomplete for the stakes.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all five parameters including the confirmed gate. The description adds no syntax, format, or behavioral meaning beyond what the schema and enum already provide. Baseline 3 applies.

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?

States a specific verb+resource: submit a dispute, and scopes it to a 'previously previewed' dispute, distinguishing it from the sibling generate_dispute. It does not name check_status or other siblings, but the action is unambiguous.

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

Usage Guidelines3/5

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

Implies a workflow precondition (must be previously previewed, confirmed=true safety gate) but never explicitly says when to use this vs generate_dispute or check_status. The gate is stated, but the routing context is left to inference.

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. 8 tool updatesv1.0.0
    • First observedanalyze_ticket
    • First observedcheck_status
    • First observedcheck_tickets
    • First observedgenerate_dispute
    • First observedmanage_plates
    • First observedopen_dashboard
    • First observedsetup_gmail
    • First observedsubmit_dispute

TDQS

A3.7/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct step or resource in the parking ticket dispute workflow. check_tickets (open tickets) and check_status (dispute status) are clearly differentiated by their descriptions, and generate_dispute vs submit_dispute is explicitly separated by preview vs actual submission.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: manage_plates, check_tickets, analyze_ticket, generate_dispute, check_status, submit_dispute, setup_gmail, open_dashboard. The convention is predictable and easy to parse.

Tool Count5/5

Eight tools is well-scoped for a parking ticket dispute assistant. Each tool maps to a clear step or utility, with no redundant or filler tools.

Completeness4/5

The set covers the full lifecycle: plate management, ticket checking, evidence analysis, dispute generation, submission, status checking, Gmail setup, and dashboard access. Minor gaps exist, such as no explicit tool to update, cancel, or list all disputes, but core workflows are fully supported.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers