Skip to main content
Glama

Server Details

City council meetings, transcripts, votes, and documents for U.S. cities, with citations.

Ownership verified
Status
Healthy
Uptime
49.9% over 21 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL

TDQS

A4.5/5.0

Scored across 12 tools

Disambiguation4/5

The set has several search-adjacent tools (search, search_meetings, search_documents, search_by_official, search_decisions), but each targets a distinct source or scope and the WHEN/WHEN NOT guidance sharply separates them. fetch vs get_transcript_window and whats_changed vs search_decisions are the closest overlaps, yet their descriptions clarify when to prefer each.

Naming Consistency4/5

All names use snake_case, and families like search_* and *_timeline are predictable. Minor deviations exist: fetch is a bare verb, application_timeline/issue_timeline are noun phrases, and whats_changed lacks the apostrophe, but overall consistency is high.

Tool Count5/5

12 tools is well within the 3–15 sweet spot and each tool maps to a distinct civic-record query intent (search, timelines, officials, votes, decisions, summaries, retrieval). No tool appears redundant enough to remove.

Completeness4/5

The surface covers core retrieval workflows: search across transcripts/documents/decisions, official lookup, voting records, issue/application timelines, change summaries, full fetch, and transcript windows. Minor gaps remain, such as direct list/browse operations for meetings or issues without a keyword, but most gaps have workarounds through search or timelines.

Available Tools

12 tools
application_timelineDevelopment application timelineA
Read-onlyIdempotent
Inspect

How a development project moved through the city — a rezone, subdivision, site plan, conditional-use permit, or apartment/commercial build. Returns the application's lifecycle across meetings (pending → under-review → hearing → approved/denied), oldest first, with the status recorded at each step.

WHEN: 'What's the status of the Silo Park development?', 'How did rezone X move through the council?'. WHEN NOT: For issues/policy (not a specific project) use issue_timeline; for quotes use search_meetings.

EXAMPLES: { "q": "Silo Park", "city": "lehi-ut" } { "application_id": "" }

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoResolve by a project-name / address / slug substring when you don't have the id (e.g. 'Silo Park'). Ignored if application_id is set.
cityNoCity slug to scope resolution (e.g. 'lehi-ut'). Required with q when you have access to more than one city.
limitNoMax timeline entries. Default 100.
application_idNoUUID of the development application. Preferred when known.

Output Schema

ParametersJSON Schema
NameRequiredDescription
timelineYesEvery meeting where the application came up, oldest first — read status_at_mention down the list to see the lifecycle.
applicationYesThe resolved application, or null when nothing matched the query/scope.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, and open-world, so the safety profile is covered. The description adds genuine behavioral context beyond that: entries are returned oldest-first, each step carries the status recorded at that step, and the lifecycle state machine (pending → under-review → hearing → approved/denied) is disclosed. It stops short of discussing resolution failure behavior or pagination beyond the limit param.

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?

Front-loaded purpose sentence, then clearly delimited WHEN / WHEN NOT / EXAMPLES blocks. Every line earns its place and nothing is repeated from structured fields unnecessarily.

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

Completeness5/5

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

An output schema exists, so return values need not be re-explained, and annotations carry the safety profile. The description still supplies the ordering guarantee, the lifecycle vocabulary, and the sibling routing, leaving nothing an agent needs to call this correctly.

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 q, city, limit, and application_id are all documented in the schema itself, including the q-ignored-when-id-set rule and the UUID format. The description adds examples showing q+city together but no semantics beyond what the schema already states, so the 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?

States a specific verb+resource: it returns how a development project moved through meetings, with named application types (rezone, subdivision, site plan, CUP, build). It also implicitly distinguishes itself from the policy-oriented sibling issue_timeline. An agent can tell this apart from search_meetings or issue_timeline without opening a schema.

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

Usage Guidelines5/5

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

Explicit WHEN examples ('What's the status of the Silo Park development?') and WHEN NOT routing to issue_timeline for policy issues and search_meetings for quotes. The alternative selection conditions are spelled out rather than inferred.

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

fetchFetch a full transcript or documentA
Read-onlyIdempotent
Inspect

Retrieve the full record behind a search result: the complete meeting transcript (for meeting:… ids) or the full document text (for doc:… ids). Long records are truncated at a safe length with a marker.

WHEN: After the search tool, to read a result in full before answering or citing. WHEN NOT: Ids are opaque — never construct one by hand; only use ids returned by search.

EXAMPLES: { "id": "meeting:lehi-ut:1f0c…" } { "id": "doc:lehi-ut:1f0c…:42" }

A not-found error means that specific id is stale or unindexed — re-run search for fresh ids; it is not an access restriction.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesAn id returned by the search tool.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
urlYesCanonical citation URL.
textYesFull text of the record (transcript or document), possibly truncated.
titleYes
metadataNo

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description goes further by disclosing truncation of long records with a marker and by clarifying that a not-found error means a stale id rather than an access restriction. That error-semantics detail is context annotations cannot express.

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?

Front-loads the core action, then uses short labeled sections (WHEN, WHEN NOT, EXAMPLES, error note) with zero filler. Every sentence conveys a constraint or a failure mode the agent needs.

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

Completeness5/5

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

An output schema exists, so return-value documentation is not required, yet the description still covers truncation, id provenance, and error interpretation. For a single-parameter read tool this is fully sufficient to call correctly.

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?

Schema coverage is 100% and there is only one parameter, so the baseline is 3. The description adds real meaning beyond the schema's terse 'An id returned by the search tool': the meeting:/doc: prefixes, the opacity of ids, and the prohibition on hand-constructing them.

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?

States a specific verb (retrieve) and resource (full record) and explicitly maps the two id namespaces to two outcomes: 'complete meeting transcript (for meeting:… ids) or the full document text (for doc:… ids)'. This lets an agent distinguish it from search and search_meetings without opening a schema.

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

Usage Guidelines5/5

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

Gives explicit WHEN ('after the search tool, to read a result in full before answering or citing') and WHEN NOT ('never construct one by hand; only use ids returned by search'), plus the remedy for the most likely failure mode. Nothing about selection 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.

get_transcript_windowRead the transcript around a momentA
Read-onlyIdempotent
Inspect

The passage of a meeting transcript surrounding a given moment — what was said before and after, with speakers and timestamps. Pass the meeting_id and start_seconds from a search_meetings hit.

WHEN: ALWAYS, before quoting or reasoning from a search_meetings hit. Search returns individual segments, and a segment is often a fragment — one real hit was the entirety of "does not have a contract with FLOC". The answer is in the passage around it, not in the segment. WHEN NOT: To find something, use search_meetings first — this tool has no query and only reads a meeting you already located. For a whole document, use fetch.

Prefer this over fetch for transcripts: fetch truncates at 40,000 characters from the START of a meeting, so on a three-hour council meeting anything after roughly the first hour is missing entirely — including most late-agenda votes.

EXAMPLES: { "meeting_id": "977675c0-...", "around_seconds": 5113 } { "meeting_id": "977675c0-...", "around_seconds": 5113, "before_seconds": 300, "after_seconds": 300 }

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax segments returned. Default 80.
meeting_idYesMeeting UUID, taken from a search_meetings or search_documents hit.
after_secondsNoSeconds of transcript to include after the centre. Default 180 — a little longer than `before`, because the answer to 'what happened here' usually follows the mention.
around_secondsYesElapsed seconds into the meeting to centre the window on — pass the `start_seconds` of the hit you want context for.
before_secondsNoSeconds of transcript to include before the centre. Default 120, max 900.

Output Schema

ParametersJSON Schema
NameRequiredDescription
windowYesThe time range actually covered, after clamping to the meeting.
segmentsYes
city_slugYes
truncatedYesTrue when `limit` cut the window short — widen nothing, ask for a narrower range.
video_urlYesJumps to the start of this window. Use verbatim — do not invent URLs.
meeting_idYes
transcriptYesThe window as one readable passage, speaker-prefixed. Quote from this verbatim — do not paraphrase and present it as a quote.
meeting_urlYesUse this verbatim when citing — do not invent URLs.
meeting_dateYesUnix seconds, UTC midnight.
meeting_titleYes

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, openWorld, non-destructive, so the safety profile is covered. The description adds real behavioral value annotations cannot carry: search returns fragmentary segments, and fetch truncates at 40,000 characters from the START of a meeting, silently losing late-agenda content. It stops short of describing output shape or any rate limits, but the truncation caveat is exactly the kind of context that prevents a wrong tool choice.

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?

Front-loaded with the one-line definition, then WHEN / WHEN NOT / EXAMPLES in scannable order. The anecdote about the FLOC fragment and the fetch truncation detail both earn their length by justifying the routing rule.

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

Completeness5/5

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

An output schema exists, so return values need not be explained. Combined with annotations, a 100%-covered schema, and explicit routing guidance, everything an agent needs to invoke this correctly is present.

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?

Schema coverage is 100%, so baseline is 3, but the description adds the non-obvious mapping that the caller should pass start_seconds from a search_meetings hit as around_seconds, and provides two concrete invocation examples including before/after overrides. That is genuine meaning beyond the schema.

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?

States a specific verb and resource — return the transcript passage surrounding a given moment, with speakers and timestamps — and immediately frames it against siblings (search_meetings hits, fetch). An agent can distinguish it from every other sibling without opening a schema.

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

Usage Guidelines5/5

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

Explicit WHEN (always, before quoting or reasoning from a search hit) and WHEN NOT (to find something, use search_meetings; for a whole document, use fetch), plus a stated preference rule over fetch with the reason. Alternatives and selection conditions are fully specified.

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

issue_timelineIssue lifecycle timelineA
Read-onlyIdempotent
Inspect

How a local issue developed over time — a zoning change, a housing or density fight, a tax or fee, a road, park, or police matter. Returns the chronological lifecycle of the issue across meetings (raised → discussed → voted), oldest first, each entry linking to the meeting.

WHEN: 'How has the short-term-rental issue progressed?', 'When was X first discussed and what happened since?'. WHEN NOT: For what a specific person said, use search_by_official; for how they voted, use track_position. For a one-off keyword search, use search_meetings.

Pass city whenever you pass q. The same phrase names a different fight in every city, and without a city the match is ambiguous — you will get issue: null plus a candidates list to choose from rather than a confident answer about the wrong city. Check candidates even on a resolved issue: 'short-term rentals' matches both a citywide ordinance and one subdivision's area-plan amendment.

EXAMPLES: { "q": "short-term rentals", "city": "lehi-ut" } — ALWAYS pass city with q { "issue_id": "" }

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoResolve the issue by a title/slug substring when you don't have the id (e.g. 'short-term rentals'). Ignored if issue_id is set.
cityNoCity slug to scope resolution (e.g. 'lehi-ut'). Required with q when you have access to more than one city.
limitNoMax timeline entries. Default 100.
issue_idNoUUID of the issue. Preferred when known.

Output Schema

ParametersJSON Schema
NameRequiredDescription
issueYesThe resolved issue. Null when nothing matched, OR when `q` matched issues in more than one city and no `city` was given — check `candidates` in that case and re-call with a city or an issue_id.
timelineYesEvery meeting where the issue was discussed, oldest first.
candidatesYesOther issues matching `q`. Populated (with issue null) when the match was ambiguous ACROSS cities — pick one rather than assuming. Also lists same-city alternates alongside a resolved issue, since one phrase often matches both a citywide ordinance and a single development's version of it.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds non-obvious runtime behavior: oldest-first ordering, per-entry meeting links, and the fallback where an ambiguous match yields issue: null plus a candidates list. That is real behavioral disclosure beyond structured fields.

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?

Front-loaded with purpose, then WHEN/WHEN NOT, then examples; nearly every sentence earns its place. Slight redundancy in the two sentences about candidates, but no filler.

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

Completeness5/5

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

With an output schema present, return values need not be described, and the description still covers invocation guidance, resolution ambiguity behavior, and required pairings. Nothing an agent needs to call this correctly is missing.

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?

Schema coverage is 100% so the baseline is 3, but the description adds resolution semantics the schema does not convey — the city-scoping rationale (same phrase means a different fight per city) and the candidates list even on a resolved issue. limit/issue_id precedence is left to the schema.

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?

States a specific resource (an issue's chronological lifecycle) with concrete domain examples (zoning, housing, tax, road, park) and the shape of the return (raised → discussed → voted, oldest first, each entry linking to the meeting). It is clearly distinguishable from siblings like search_meetings and track_position.

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

Usage Guidelines5/5

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

Explicit WHEN examples, explicit WHEN NOT with named alternatives and the condition that selects each (person's statements → search_by_official, votes → track_position, one-off keyword → search_meetings). Also prescribes passing city with q.

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

list_officialsList elected officialsA
Read-onlyIdempotent
Inspect

Who serves on a city council — mayors and council members — looked up by city, state, or name.

Returns the CURRENT ELECTED roster by default: people in office right now, no appointed board members, no staff. Answer 'who represents me' straight from this — no need to hedge about whether someone still holds the seat. Each row carries role, status, and term dates.

WHEN: First stop for 'who represents…' questions, and the prerequisite for any search_by_official / track_position call (both need a UUID this tool returns). WHEN NOT: For voting records use track_position; for quotes use search_by_official, with an id from here.

Set include_former for historical questions ('who was mayor in 2024?') or when reading an older meeting whose speakers have since left office — an official_id you got elsewhere may belong to someone no longer seated. Set include_appointed for planning commissioners and city staff.

EXAMPLES: { "city": "lehi-ut" } — the sitting Lehi council { "city": "lehi-ut", "include_former": true } — plus everyone who has left office { "state": "UT", "name_contains": "binns" } — find 'Paul Binns' across Utah { "city": "lehi-ut" } then pivot to track_position with one of the returned ids

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity slug (e.g. 'lehi-ut'). Strongly recommended — narrows the response to one city's roster. Without it, returns officials across every city you have access to (can be hundreds of rows).
limitNoMax rows returned. Default 50.
stateNoTwo-letter US state abbreviation (e.g. 'UT', 'CA'). Use when you want every city in a state. Case-insensitive.
name_containsNoCase-insensitive substring match on the official's name (e.g. 'binns' matches 'Paul Binns'). Combine with `city` or `state` to look up someone specific.
include_formerNoInclude officials who have left office. Default false — 'who represents me' means the sitting roster. Turn on for historical questions ('who was mayor in 2024?') or when reading an old meeting where the speakers are no longer seated.
include_appointedNoInclude appointed board members (planning commissioners and the like) and city staff (administrator, attorney, recorder). Default false — they are not elected and do not vote on the council.

Output Schema

ParametersJSON Schema
NameRequiredDescription
totalYesNumber of officials returned in this response.
officialsYesOfficials matching the filters — by default the CURRENT ELECTED roster, so this answers 'who serves on the council' directly. Public-record data from city government websites.
citiesQueriedYesNumber of cities scanned.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already cover read-only/idempotent/non-destructive semantics, and the description adds real behavior beyond them: the default roster excludes appointed members and staff, former officials require an explicit flag, and a stale official_id may point to someone no longer seated. The mention of role/status/term-date columns is mildly redundant given the output schema exists, keeping this just short of top marks.

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?

Well front-loaded with the most decision-relevant fact first (current roster by default), then WHEN/WHEN NOT, then examples. It is longer than strictly necessary because the include_former and include_appointed rationales are largely duplicated in the schema descriptions.

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

Completeness5/5

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

For a six-parameter, annotation-rich tool with an output schema, the description covers purpose, default filtering behavior, flag semantics, prerequisites, and sibling routing without needing to explain return values. Nothing an agent needs in order 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.

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds intent-level meaning: include_former is framed as the historical/old-meeting switch, include_appointed as the planning-commissioner/staff switch. The EXAMPLES block demonstrates realistic parameter combinations (city+include_former, state+name_contains) that the schema alone does not convey.

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?

States a specific verb and resource — looking up who serves on a city council — and pins the default scope precisely (current elected officials, no appointed members, no staff). An agent can distinguish it from track_position and search_by_official without reading a schema.

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

Usage Guidelines5/5

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

Explicit WHEN and WHEN NOT sections name the conditions and the alternatives: track_position for voting records, search_by_official for quotes. It also declares a prerequisite relationship (both siblings need a UUID this tool returns), which is exactly the routing information an agent needs.

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

search_by_officialSearch what an official said (paid)A
Read-onlyIdempotent
Inspect

Retrieve every transcript segment a specific elected official has spoken. Optional q narrows within their segments. Returns their speaking history, newest first — what they argued, asked, and moved, in their own words.

WHEN: 'What has Councilmember X said about Y', their reasoning on an issue, or a verbatim quote with a jump-to timestamp. WHEN NOT: For how they voted, use track_position — that reads the recorded roll call (yes/no/abstain per decision). Transcripts capture discussion, not the tally, so compiling a voting record from these segments systematically under-reports and will miss votes entirely. If you don't yet have their UUID, call list_officials first. For non-elected speakers (staff, public commenters), use search_meetings.

EXAMPLES: { "official_id": "", "q": "housing" } { "official_id": "" } — full speaking history newest-first

REQUIRES: a paid plan (Resident and above). Free callers get an upgrade hint, no data.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoOptional free-text query to narrow within this official's segments (e.g. 'budget', 'zoning').
limitNoMax hits returned. Default 10.
citiesNoOptional city-slug allow-list. Officials belong to one city already, so this is rarely needed; a list that excludes the official's city returns no hits.
official_idYesUUID of the elected official. Get this from list_officials or from the official_id field on a search_meetings hit.

Output Schema

ParametersJSON Schema
NameRequiredDescription
hitsYesTranscript segments where this official spoke, newest first.
totalYesTotal estimated matches for this official.
citiesQueriedYesNumber of cities actually searched.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, openWorld), and the description adds context they cannot: a paid-plan gate (Resident and above), the concrete free-tier behavior ('upgrade hint, no data'), and the newest-first ordering of results. These are exactly the behavioral traits an agent needs before invoking.

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?

Front-loaded with the core behavior, then cleanly sectioned into WHEN / WHEN NOT / EXAMPLES / REQUIRES. Every line carries routing or behavioral information; nothing is filler despite the length.

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

Completeness5/5

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

With an output schema present, return-value explanation is unnecessary, and the description covers everything else an agent needs: prerequisites (UUID from list_officials), paywall gating, alternative tools, and example calls. No material gap remains.

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?

Schema coverage is 100%, so the baseline is 3, but the description adds invocation-shape value the schema doesn't: it clarifies that omitting q returns full speaking history and shows two worked examples. It slightly duplicates the schema's official_id sourcing note, keeping it from a 5.

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?

States a specific verb and resource — retrieving every transcript segment a specific elected official has spoken — and scopes it ('spoken', newest-first). It explicitly distinguishes itself from siblings by naming track_position and search_meetings, so an agent can route correctly without opening other schemas.

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

Usage Guidelines5/5

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

Explicit WHEN ('what has X said about Y', reasoning, verbatim quote with timestamp) and WHEN NOT sections name the exact alternatives: track_position for votes, list_officials for the UUID prerequisite, search_meetings for non-elected speakers. It even explains *why* the alternative is correct (transcripts under-report voting records), which is unusually strong routing guidance.

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

search_decisionsSearch recorded motions, votes and amountsA
Read-onlyIdempotent
Inspect

What a body actually DECIDED, from the approved minutes — the motion as recorded, who moved it, the roll-call tally, and any dollar figure attached. This is the structured record, not people talking: use it whenever the question is what was approved, denied, tabled, or how much something cost.

WHEN: 'Which cities approved Flock Safety cameras?', 'Show me every contract over $100k in Texas this year', 'Where did accessory-dwelling ordinances stall?', 'What did Lehi vote on last month?'. WHEN NOT: For what someone SAID, use search_meetings. For one official's record across items, use track_position. For a project's lifecycle, use application_timeline.

TWO THINGS THAT WILL MISLEAD YOU IF IGNORED: • Report outcome, not result. A passed motion TO TABLE means the item did NOT advance; 161 published motions are exactly that. outcome already combines motion_kind with result. • amount_deferred: true means the money was named inside a motion to delay or table. Never describe it as spending. • EMPTY IS NOT "NOTHING WAS DECIDED". Motions come only from minutes we have extracted, which lag the meeting and are missing for many cities. Read coverage / coverage_note before answering, and fall back to search_documents for the minutes or agenda. • unofficial_decisions are decisions heard in the RECORDING of a meeting where no official motion covers that item — usually because its minutes are not published yet. They are NOT the official record: say "according to the meeting recording" and repeat the row's record_note (it says whether the minutes are unpublished or simply have no matching motion), never present their vote_count as an official roll call, and never count them into total. Verify a specific one with get_transcript_window at its timestamp_seconds.

q matches whole words, so 'Flock' will not return a person named Flocke. Every row carries a citation_url pointing at that exact motion.

EXAMPLES: { "q": "Flock Safety" } { "q": "accessory dwelling", "outcome": "tabled" } { "min_amount_usd": 100000, "basis": ["award"], "since": "2026-01-01" }

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoTerm matched as a WHOLE WORD or phrase against the motion text — a vendor ('Flock Safety'), an instrument ('Ordinance 26-08'), a subject ('accessory dwelling'). Whole-word matching means 'Flock' will not match a person named Flocke. Omit to browse by city, date or amount alone.
basisNoRestrict to how the money is being used. 'award' is a contract/grant/purchase; 'appropriation' is budget/bond/levy; 'fee' is a fee, fine or waiver. Rates and third-party figures are never returned.
limitNoMax motions returned, newest first. Default 40.
matchNoHow `q` is matched. 'phrase' (default): the whole of `q` as one whole-word phrase — for an instrument or vendor ('Ordinance 26-08', 'Flock Safety'). 'any': each word of `q` as a whole word, in any order, a plural matching its singular; a motion matching more of the words ranks first. Use 'any' for a subject described in a resident's words ('sycamore trees', 'budget adopted').phrase
sinceNoMeetings on or after this date (YYYY-MM-DD).
untilNoMeetings on or before this date (YYYY-MM-DD).
citiesNoCity-slug allow-list (e.g. ['lehi-ut']). Omit to search every city the plan allows.
outcomeNoFilter by what happened to the ITEM, not to the motion. 'tabled' means a motion to table passed, so the item did not advance. Use 'denied' or 'tabled' to find where something stalled — for policy-diffusion questions that is the more informative half.any
min_amount_usdNoOnly motions carrying a parsed dollar figure at or above this many whole dollars. Use 0 for every motion that carries any dollar figure. Excludes tax rates, third-party figures and deferred amounts automatically.

Output Schema

ParametersJSON Schema
NameRequiredDescription
totalYesNumber of OFFICIAL motions returned, from published minutes (not an estimate — this is the row count). Does not include unofficial_decisions; see `returned`.
blockedYesTabled, denied, continued or withdrawn — the item did not advance.
summaryYesOne sentence saying what came back, official and recording-reported separately. Read this first: `total` counts OFFICIAL motions only, so a response can carry decisions while total is 0.
approvedYes
coverageYesMinutes coverage for each queried city that returned NO decisions, so an empty result can be told apart from a gap in our record. Omitted cities had hits. Empty when every city had hits, or when more than 8 cities came back empty (see coverage_note).
returnedYesEverything returned: `total` (official motions) + `unofficial_total` (recording-reported decisions).
decisionsYes
citiesQueriedYes
coverage_noteYesPlain-language caveat to relay when results are thin because minutes have not been extracted. Null when every queried city returned decisions.
citiesWithHitsYesHow many distinct cities appear in the results. The useful denominator for 'how many cities have done this'.
totalAmountUsdYesSum of the returned motions' amounts, in whole dollars, excluding rates, third-party figures and deferred amounts. NULL when none carried a figure. Treat as a floor, not a budget: budgets, financings, awards and amendments legitimately overlap, so this can double-count the same dollars across instruments.
unofficial_totalYesNumber of unofficial_decisions returned. NOT included in `total`, `approved` or `blocked`, which count official motions only.
unofficial_decisionsYesDecisions heard in the RECORDING of a meeting where no official motion covers that item: usually the approved minutes have not been published or extracted yet, and sometimes the published minutes have no motion for the item. NOT the official record: report them as 'according to the meeting recording' and repeat each row's record_note, which says which of the two cases applies. Never merge them into official results or present vote_count as an official roll call. A row is dropped when a published motion covers the same agenda item, so these do not restate `decisions`. Omitted when a dollar filter is set (transcript decisions carry no parsed amounts).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnly, idempotent, non-destructive, open world), so the bar is lower — yet the description adds substantial non-obvious behavior: outcome vs. result semantics, amount_deferred meaning, that empty results reflect extraction lag rather than absence of decisions, that unofficial_decisions must not be counted in total or presented as official roll calls, and that every row carries a citation_url. This is exactly the kind of context annotations cannot carry.

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?

Well front-loaded, with WHAT, WHEN, WHEN NOT and pitfalls in scannable blocks despite the length — justified by a 9-parameter tool with subtle semantics. Minor duplication: the 'Flock'/'Flocke' whole-word illustration restates the q schema description verbatim and could be dropped.

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

Completeness5/5

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

An output schema exists, so return values need not be explained; the description instead covers the interpretive layer the schema cannot — coverage/coverage_note caveats, how to handle unofficial_decisions, and where to verify a specific one (get_transcript_window). Complete for the tool's complexity.

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?

Schema coverage is 100%, so the baseline is 3 and the schema documents every parameter thoroughly. The description adds value through worked example invocations that demonstrate non-obvious combinations (outcome:'tabled' with a free-text subject; min_amount_usd with basis:['award'] and since), plus the outcome-not-result guidance. It repeats the whole-word matching rule already in the schema, so it is not a clean 5.

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?

States a specific verb and resource ('search recorded motions, votes and amounts') and immediately scopes it: the structured record of what a body decided, drawn from approved minutes. It also names the sibling it is not ('not people talking... use search_meetings'), so an agent can route without opening a schema.

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

Usage Guidelines5/5

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

Explicit WHEN section with natural-language queries, an explicit WHEN NOT section naming three alternatives (search_meetings, track_position, application_timeline) with the condition selecting each, and a documented fallback (search_documents) when coverage is empty. Nothing 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.

search_documentsSearch meeting documentsA
Read-onlyIdempotent
Inspect

What the city put in writing — agendas, minutes, staff reports, meeting packets, attachments, ordinances, and resolutions. Keyword search across extracted document text. Use this when the value is in the written record, not the spoken transcript.

WHEN: Looking for ordinance language, budget tables, agenda text, staff reports, attached PDFs. WHEN NOT: For what was said in the meeting, use search_meetings. For metadata-only queries ('what meetings happened last week?'), search_meetings with q on a placeholder works better.

EXAMPLES: { "q": "ADU ordinance", "cities": ["lehi-ut"] } { "q": "FY2027 budget", "cities": ["lehi-ut"] } { "q": "developer presentation Main Street" }

hits: [] means no document text matched — simplify the query and retry; never report it as missing access to a city.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYesFree-text query matched against extracted text from agendas, minutes, packets, and attachments.
limitNoMax hits returned. Default 25, up to 150. Results are spread across cities and meetings so one verbose meeting cannot fill the response. For statewide or multi-city questions pass a high limit and filter the results yourself — that is cheaper and more complete than many narrow queries.
citiesNoCity-slug allow-list. Strongly recommended — searches every accessible city otherwise.
doc_typesNoFilter by doc_type values, e.g. ['agenda', 'minutes', 'packet', 'attachment'].

Output Schema

ParametersJSON Schema
NameRequiredDescription
hitsYesDocument matches, newest first.
totalYesRough upper bound on candidate documents, NOT a count containing your full query — matching relaxes trailing words to keep recall up. Never report this as 'N mentions'; count `hits` instead.
citiesQueriedYesNumber of cities actually searched.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/openWorld, but the description adds real behavioral context: the meaning of an empty `hits: []` (no text match, not missing access), the retry guidance, and the note that `limit` results are spread across cities and meetings. It stops short of documenting result shape or any auth/rate constraints.

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?

Front-loaded and scannable with labeled WHEN / WHEN NOT / EXAMPLES sections, and every block earns its place. The opening clause is stylistic rather than the operational verb, which pushes the actual function into the second sentence.

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

Completeness5/5

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

Output schema exists so return values need not be spelled out, yet the description still explains the empty-result case that an agent would otherwise misreport. With 4 well-documented parameters and full sibling routing, nothing needed 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.

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3; the description goes beyond it with three worked examples that demonstrate realistic `q` + `cities` combinations and the newline `q` placeholder pattern for the sibling tool. It does not add format or enum detail the schema lacks, but the examples are genuinely additive.

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?

States a specific verb+resource (keyword search across extracted document text) and enumerates the covered artifact types (agendas, minutes, staff reports, packets, attachments, ordinances, resolutions). It explicitly distinguishes itself from the sibling search_meetings by contrasting the written record with the spoken transcript.

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

Usage Guidelines5/5

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

Provides explicit WHEN and WHEN NOT blocks naming the alternative tool (search_meetings) and the conditions that select it, including the metadata-only case with the `q` placeholder trick. Nothing about tool selection 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.

search_meetingsSearch meeting transcriptsA
Read-onlyIdempotent
Inspect

What was actually said out loud at a city council meeting, planning-commission hearing, or any other public city-government meeting — about zoning, housing, the city budget, taxes, permits, ordinances, roads, parks, police, or public comment. Keyword search across transcript segments; each hit includes speaker, snippet, timestamp, and — when the speaker matches an elected official — an official_id UUID.

WHEN: 'What did people say about X?', 'When was Y last discussed?', or any query where the value is what was spoken in a meeting. WHEN NOT: For one person's complete speaking history, use search_by_official (better signal, no false positives from name collisions). For ordinance text, packets, or attached PDFs, use search_documents.

For 'recent' or 'this year' questions pass since — the corpus runs back years, and without a window old material competes with new. For 'what did OFFICIALS say' pass officials_only — it keeps segments whose speaker matched the city roster (elected, appointed or senior staff), because everyone else is unnamed by design and their quotes cannot be cited to a person.

EXAMPLES: { "q": "short-term rentals", "cities": ["lehi-ut"] } { "q": "housing affordability", "cities": ["lehi-ut"], "since": "2026-01-01", "officials_only": true } { "q": "downtown parking", "cities": ["lehi-ut"], "meeting_types": ["city_council"] } { "q": "developer Main Street" } — last meetings across allowed cities, newest first

hits: [] means no transcript segments matched — simplify the query and retry; never report it as missing access to a city.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYesFree-text query matched against transcript text + speaker names + agenda items.
limitNoMax hits returned. Default 25, up to 150. Results are spread across cities and meetings so one verbose meeting cannot fill the response. For statewide or multi-city questions pass a high limit and filter the results yourself — that is cheaper and more complete than many narrow queries.
sinceNoOnly search meetings on or after this date (YYYY-MM-DD). Use for 'recent' / 'this year' questions — without it the corpus goes back years and old material outranks new.
untilNoOnly search meetings on or before this date (YYYY-MM-DD).
citiesNoCity-slug allow-list (e.g. ['lehi-ut']). Strongly recommended — searches every accessible city otherwise.
meeting_typesNoFilter by meeting_type values (e.g. ['city_council', 'planning_commission']).
officials_onlyNoReturn only segments whose speaker was matched to the city's official roster — elected members, appointed board members, AND senior staff (city administrator, attorney, recorder). NOT elected-only: filtering is on whether the speaker is identified at all. Use for 'what did OFFICIALS say about X'; without it, most hits are applicants and residents at the comment mic, whose names are withheld by design, so the quotes come back unattributed and cannot be cited to a person. To keep only elected speakers, cross-reference the returned official_id against list_officials.

Output Schema

ParametersJSON Schema
NameRequiredDescription
hitsYesTranscript segments matching the query, newest first.
totalYesNOT a count of segments containing your full query, and never safe to report to a user as 'N mentions' — count `hits`, or say the record contains 'many'. With hybrid ranking on it is the number of hits returned; otherwise it is a rough upper bound on candidates, and because matching relaxes trailing words to keep recall up, a two-word query can report tens of thousands while only dozens contain both words.
citiesQueriedYesNumber of cities actually searched.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the added value here is real behavioral context: result spread across cities and meetings, the `official_id` field appearing only when a speaker matches an elected official, attribution limits for unnamed residents, and an explicit instruction that `hits: []` means no match rather than missing access. The last point prevents a concrete failure mode the annotations never mention.

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?

Front-loaded with what is searched, then WHEN/WHEN NOT, then examples, then the empty-result rule — a sensible priority order. It runs long and duplicates the `since` and `limit` rationale already present in the schema descriptions, which is the main waste.

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

Completeness5/5

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

An output schema exists, so return shape needn't be explained, and the description covers everything else an agent needs: scope, filters, routing to sibling tools, the meaning of an empty hit list, and the citation caveat. 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.

Parameters4/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 seven parameters and the baseline would be 3. The description still adds value through worked examples that show parameters being combined (cities + since + officials_only, meeting_types, and a bare-query case), plus a cross-reference pointing elected-only filtering to list_officials. Some of the `since` rationale restates the schema text verbatim, which caps this below a 5.

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?

States a specific verb (keyword search) and resource (meeting transcript segments) and immediately scopes what counts: city council, planning-commission, and other public city meetings. It names the differentiating siblings — search_by_official for a person's speaking history and search_documents for ordinance text and PDFs — so an agent can route correctly without 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 Guidelines5/5

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

Explicit WHEN block gives the triggering question shapes ('What did people say about X?'), and the WHEN NOT block names the two alternatives with the condition that selects each. Conditional guidance on `since` for 'recent' questions and `officials_only` for 'what did OFFICIALS say' closes the remaining ambiguity.

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

track_positionTrack an official's position over timeA
Read-onlyIdempotent
Inspect

The voting record of one elected official. Their actual recorded roll-call votes (yes/no/abstain, per decision, with the decision title) plus expressed stances, in chronological order, with cited quotes, jump-to timestamps, and detected position reversals (flips).

This is the ONLY tool that returns how someone voted. topic and the since/until date window are all optional — omit them all for a complete record.

WHEN: any question about how a named official voted — 'How has Councilmember X voted over the last couple months?' (pass since/until, no topic), 'How has X voted on housing?' (pass topic), 'Has the mayor changed position on short-term rentals?'. WHEN NOT: For what they said rather than how they voted, use search_by_official. For a topic across everyone (not one person) use whats_changed or search_meetings; to find the official_id first, use list_officials.

Do NOT try to reconstruct a voting record from transcript segments — transcripts capture discussion, not the tally, so that reliably under-reports. Votes live here.

PAID plan required (attributes positions to a named official).

EXAMPLES: { "official_id": "", "since": "2026-06-01" } — recent voting record, all topics { "official_id": "", "topic": "housing" } { "official_id": "" } — the complete record

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity slug to scope to (e.g. 'lehi-ut'). Defaults to the official's city.
limitNoMax trajectory entries. Default 100.
sinceNoOnly include meetings on or after this date (YYYY-MM-DD). Use with `until` for 'the last couple of months'.
topicNoOptional topic / issue to narrow to (e.g. 'housing', 'short-term rentals'). Omit to get the official's complete voting and stance record — that is the right call for 'how has X voted recently', which no topic reliably captures.
untilNoOnly include meetings on or before this date (YYYY-MM-DD).
official_idYesUUID of the official. Get it from list_officials or a search_meetings hit's official_id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
topicYesEcho of the topic filter, or null when the full record was requested.
summaryYesRoll-up of the trajectory, including detected position reversals.
officialYes
trajectoryYesChronological (oldest first) positions this official took — narrowed to `topic` and the date window when given. When truncated by `limit`, the OLDEST entries are dropped, so the most recent record is always present.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already cover read-only/idempotent, but the description adds non-obvious context: a paid-plan requirement, a warning not to reconstruct voting records from transcript segments (they under-report because they capture discussion not tally), and the claim that this is the only tool returning votes. These are genuinely valuable behavioral facts beyond the structured data.

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?

Front-loaded headline plus tightly organized WHEN/WHEN NOT/EXAMPLES sections; sentences are dense but each carries routing or caveat information. Slightly long, with some repetition between prose and examples, keeping it short of a 5.

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

Completeness5/5

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

With an output schema present, annotations covering the safety profile, 100% schema coverage, and explicit cost/limitation caveats, an agent has everything needed to select and invoke it correctly. The dependency on list_officials for the UUID is called out.

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 the schema for topic/since/until already states optionality and the 'omit for complete record' guidance — so the description largely restates rather than extends it. The example payloads add marginal value by showing valid argument combinations, but the baseline of 3 applies when the schema does the heavy lifting.

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?

Opens with a concrete verb+resource ('The voting record of one elected official') and immediately scopes the return ('roll-call votes ... plus expressed stances, chronological'). It explicitly distinguishes itself from siblings — search_by_official for statements, whats_changed/search_meetings for topic-wide queries, list_officials for the ID.

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

Usage Guidelines5/5

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

Has explicit WHEN / WHEN NOT blocks with literal example questions mapped to argument patterns ('How has X voted on housing?' → pass topic) and named alternatives for each adjacent case. No inference is required to route correctly.

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

whats_changedWhat changed since a dateA
Read-onlyIdempotent
Inspect

What the city council actually decided recently — the changeset of council activity in a city since a date: decisions taken (with tallies where a roll call was recorded), issues discussed, development-application status changes, and — on paid plans — per-member votes and stance reversals. Free plans get the aggregated changeset without member attribution (redacted: true). Most decisions are unanimous voice votes with roll_call: false and no tally — they are still decisions; report them.

WHEN: 'What did the council do in the last two weeks?', 'Any movement on development since June?'. WHEN NOT: For one person or one issue over time, use track_position / issue_timeline.

EXAMPLES: { "city": "lehi-ut", "since": "2026-06-21" }

ParametersJSON Schema
NameRequiredDescriptionDefault
cityYesCity slug (e.g. 'lehi-ut').
limitNoMax decisions/issues/applications each. Default 50.
sinceYesISO date (YYYY-MM-DD). Only activity on/after this date is returned.

Output Schema

ParametersJSON Schema
NameRequiredDescription
periodYes
redactedYesTrue when member-level attribution (vote-by-member, named stance flips) was withheld because the plan does not identify officials. Tallies and decision titles are complete either way.
decisionsYesDecisions taken in the window — approved, denied, tabled or continued — whether or not a roll call was recorded (see `roll_call`). Items only discussed are not decisions and appear under issues_active instead.
truncatedYesTrue when the window held more activity than one call reads, so the OLDEST part of it is missing. Narrow `since` and call again rather than reporting the result as complete.
stance_flipsYesMembers who reversed position within the window. Empty when nobody flipped, or when `redacted` is true.
issues_activeYesIssues discussed in the window.
meeting_countYes
applications_activeYesDevelopment applications that came up, with the statuses seen in the window.

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the read-only/idempotent annotations by disclosing plan-gated behavior (free plans return `redacted: true` with no member attribution) and a real interpretive trap: most decisions are unanimous voice votes with `roll_call: false` and no tally, yet must still be reported. This is exactly the kind of behavioral context an agent cannot derive from annotations or schema.

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?

Purpose is front-loaded, followed by WHEN / WHEN NOT and a single concrete example, with zero filler. Every sentence carries a distinct load: scope, plan behavior, edge case, routing, and a usable call snippet.

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

Completeness5/5

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

For a three-parameter, output-schema-backed read tool, the description covers everything an agent needs: scope, selection criteria, sibling routing, plan gating, and a data-interpretation warning. Return values are already covered by the output schema, so nothing material 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 coverage is 100%, so city, since, and limit are already fully documented in the schema; the description adds no syntax, format, or edge-case meaning for them. The worked example demonstrates a valid call but does not extend parameter semantics, so the 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?

States a specific verb and resource — the 'changeset of council activity in a city since a date' — and enumerates exactly what it contains (decisions with tallies, issues discussed, development-application status changes, paid-plan member votes). It further distinguishes itself from siblings by naming track_position and issue_timeline as the wrong tools for single-entity queries.

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

Usage Guidelines5/5

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

Explicit WHEN section gives sample user questions ('What did the council do in the last two weeks?') and an explicit WHEN NOT that routes single-person or single-issue longitudinal queries to track_position / issue_timeline. The alternative and the condition selecting it are both stated.

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. 12 tool updates
    • First observedapplication_timeline
    • First observedfetch
    • First observedget_transcript_window
    • First observedissue_timeline
    • First observedlist_officials
    • First observedsearch
    • First observedsearch_by_official
    • First observedsearch_decisions
    • First observedsearch_documents
    • First observedsearch_meetings
    • First observedtrack_position
    • First observedwhats_changed

Publisher details

Operator
OpenCityRecord · Publisher source
Vendor relationship
First-party
Trust center
Not available
Restrictions
Requires an OpenCityRecord account; the free account covers one city.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides programmatic access to municipal codes, ordinances, and zoning regulations from thousands of US cities and counties through the Municode digital library, enabling search, navigation, and retrieval of local government legal documents.
    6
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A read-only MCP server for querying Los Angeles City legislative data - Council Files, votes, member activity, and Neighborhood Council engagement - through parameterized tools without raw SQL.
    1
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources