Offendersearch
Server Details
Search US sex-offender registries and criminal records, with per-source citations.
- Status
- Healthy
- Uptime
- 100.0% over 48 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- Clavaa/offendersearch-quickstart
- GitHub Stars
- 0
TDQS
Scored across 10 tools
The set splits cleanly into search (search_offenders, search_criminal, batch_search), coverage discovery (get_registry_coverage, get_criminal_coverage), and mapping (map_viewport, map_area, map_route, map_group, map_open_record), and the descriptions explicitly distinguish each. The main overlaps are intentional and documented — batch_search is a bulk version of search_offenders, and map_area duplicates map_viewport for a shape's bounding box — but map_area vs map_route (both accept route shapes) could still cause misselection.
Every tool follows a predictable action_noun snake_case pattern: get_*_coverage, search_*, map_*, batch_search. The prefix families are readable and map directly to the functional groups, so an agent can guess a tool's purpose from its name.
10 tools is well within the sweet spot, and each one covers a distinct capability (search, bulk search, two coverage catalogs, and five mapping operations). Nothing appears redundant or padded.
The surface covers the core read-only domain thoroughly: registry and criminal search, bulk offender search, coverage discovery, and a full mapping pipeline from viewport to individual record open with persistent recordRefs. Minor gaps exist — there is no bulk criminal search and search_criminal requires a surname so location-only criminal queries are impossible — but these are workable limitations rather than dead ends.
Available Tools
10 toolsbatch_searchAInspect
Run many person/location lookups in one call (row-in / row-out).
Each row goes through the SAME engine as search_offenders, so a row's records
are identical to what a single search would return. A row that fails is
reported with status='error' in place and never aborts the batch. Max 1000 rows.
Returns: { count, results: [ { index, status, counts{records,sourcesQueried,
sourcesIncomplete}, warnings: [str], records: [Record], error? } ] } in input
order. ★ A row with `counts.sourcesIncomplete > 0` could not be searched to the
end — its `records` are a LOWER BOUND, not a clean 'no match'.
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| match | No | Fuzzy tolerance applied to every row (see search_offenders). | balanced |
| queries | Yes | List of query objects (max 1000). Each may set any of: firstName, lastName, dob (YYYY-MM-DD), age, city, state, zipcode, address, lat, lng, radiusMiles, q. One row in = one result out, in input order. | |
| extensive | No | Request extensive detail (offenses[], stateData, images) for every row. | |
| freshness | No | Cache/pricing tier applied to every row: daily=<=24h (default), weekly=<=7d. | daily |
| jurisdictions | No | Registry codes applied to EVERY row (e.g. ['FL','TX']). Omit = all 58 registries. | |
| location_scoped | No | Apply per-state scoping to every row (see search_offenders). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: row-by-row engine equivalence, error handling (status='error', never aborts batch), max rows, return format, and the crucial caveat about sourcesIncomplete meaning 'lower bound'. It also documents authentication via X-API-Key or env var. This is rich, transparent context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is densely informative without fluff. The first sentence captures the core function, then proceeds logically: behavior, return format, caveat, auth. The use of bullets and the star-marked warning keep critical caveats prominent. Every sentence earns its place despite length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no output schema, the description covers all essential aspects: the input query format, return structure with counts and errors, error semantics, the lower-bound warning, authentication, and a pointer to search_offenders for shared parameter meanings. An agent can invoke it correctly and interpret results accurately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds significant semantic value: explains 'queries' as row-in/row-out with input order, enumerates allowed fields, and outlines result structure. It also interprets match/freshness/jurisdictions by referencing search_offenders for context. This goes well beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with 'Run many person/lookup lookups in one call (row-in / row-out)', clearly stating the tool's verb, resource, and batching behavior. It explicitly distinguishes from siblings by noting 'same engine as search_offenders', making its niche unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for multiple lookups ('many... in one call') and references search_offenders as the single-query alternative, but does not explicitly say 'use this instead of search_offenders when you have multiple queries'. It provides constraints (max 1000 rows) but not a direct usage contrast.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_criminal_coverageAInspect
List the criminal-record jurisdictions searched, with kind and status.
Use it to discover which states and counties are reachable and which are
answering today, before relying on an empty result. Depth is uneven by design:
counties publish independently, so a state with many county jurisdictions is
not "better covered" than one that publishes a single statewide source — it is
differently structured.
Returns the jurisdiction roster; each entry carries its code, the state it
belongs to, the kind of records it holds (jail / prison / court / warrant /
registry) and whether it is currently answering.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden, and it does so well: it reveals that the data is dynamic ('currently answering'), that coverage depth varies, and that a state with many county jurisdictions is not necessarily better covered. It stops short of mentioning refresh behavior or operational constraints like rate limits, but for a zero-parameter listing tool the key traits are covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short paragraphs, each earning its place: one states the core action, one gives usage context and an interpretive caveat, and one clarifies the return contents. It is front-loaded and avoids filler or restatement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with no output schema, the description is nearly complete: it explains what is returned, how to use the result, and how to interpret an important data-quality nuance. It does not explicitly contrast with the similar-sounding get_registry_coverage sibling, which would have made the tool boundary fully unambiguous.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is little to add beyond the baseline. The description still enriches the output semantics by explaining what each jurisdiction entry will contain—code, state, kind, and status—giving an agent a mental model even without schema-provided parameter docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List the criminal-record jurisdictions searched, with kind and status.' It clearly distinguishes the tool's coverage-mapping purpose from the sibling search tools, which focus on queries rather than jurisdiction availability.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit guidance to use this tool 'before relying on an empty result,' which tells an agent when the tool matters. It also explains how to interpret uneven coverage, but it does not explicitly name alternatives or state when not to use this tool versus get_registry_coverage or the search tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_registry_coverageAInspect
List every registry we cover plus its scope, legal status, and health.
Public coverage catalog (no API key required). Use it to discover the
`jurisdictions` codes accepted by search_offenders / batch_search and to
check per-registry freshness/health before relying on a result.
Returns: { count, registries: [ SourceInfo ] } where each SourceInfo is:
- id: registry code (e.g. 'IL', 'TX', 'PR')
- name: human-readable registry name
- covers: [state codes] a registry covers ('*' = national / all)
- scope: 'state' | 'national'
- status: 'live' | 'building'
- legal: { commercialUse: 'allowed'|'restricted'|'prohibited'|'unknown' }
- health: { lastSuccessAt, typicalLatencyMs, ageSeconds, freshFor }
`health` is OPERATIONAL COVERAGE METADATA about our ingest schedule, published
for transparency. It is NOT a quality warning about a search result: a search
serves every registry's best available data regardless of `freshFor`, so a
registry listing only 'weekly' still contributes its records to a
freshness='daily' search. Do NOT tell a user their search results are stale,
unreliable or out of date on the basis of these fields — they are not. The only
completeness signal that belongs in an answer is `counts.sourcesIncomplete` /
`warnings[]` from the search response itself.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral disclosure burden. It thoroughly explains the return shape, the meaning of each SourceInfo field, and the crucial semantic distinction that health fields are operational metadata, not search-quality indicators. It also states that no API key is required.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but every section earns its place: a one-sentence purpose, a structured return field listing, and a critical behavioral warning that prevents misinterpretation. The most important caveat about health fields is clearly separated and emphasized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter tool with no output schema, the description is exceptionally complete. It covers the purpose, use cases, return contract, field enums, and operational semantics, including exactly what the health fields should and should not be used for. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters and 100% schema coverage, so there is no parameter semantics burden for the description. The description adds no parameter-level meaning, but none is needed. Baseline 4 for a no-parameter tool is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'List every registry we cover plus its scope, legal status, and health.' This clearly identifies what the tool does. However, it does not explicitly distinguish itself from the sibling tool get_criminal_coverage, relying on name similarity rather than an explicit differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: discover jurisdiction codes accepted by search_offenders/batch_search and check per-registry freshness/health. It also gives a strong 'do not' instruction against interpreting health fields as search-quality warnings, which is essential for correct use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
map_areaAInspect
Get what to draw inside a drawn shape: a polygon, or a line with a buffer.
The same answer as map_viewport for the shape's bounding box, limited to what
is inside the shape, at the same detail levels (clusters, pins, or named pins
at zoom 15+). The response adds `shape: 'polygon' | 'route'`.
Returns: { shape, mode, zoom, bbox, datasetVersion, total, breakdown {street,
housed, homeless, incarcerated}, clusters[], markers[], areas[], unplaced
{count, states}, notice }.
- A marker with `id: null` and a `groupId` stands for several people at one
address: call map_group with that `groupId`.
- `areas` are people placed only at the middle of a ZIP, city or county.
Never describe them as being at an exact spot.
- To see who one marker is, call map_open_record with its `id`.
A pin shows a REGISTERED ADDRESS, not a person's current location — say so
when you describe a result (`notice` carries the sentence).
Billing: one map request per call ($2 per 1,000), whatever the shape holds.
Marker and group ids work for 24 hours. The Map API must be turned on for the
account (403 `map_not_enabled` otherwise); `sandbox=true` works without it.
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| zoom | No | Optional map zoom, 0 to 22. Decides the detail as on map_viewport: 3-12 clusters, 13-14 pins without names, 15+ pins with names. Omit it and the zoom is worked out from the size of the shape. | |
| detail | No | full = clusters or pins (default); count = numbers only. | full |
| housing | No | Keep only people with one of these housing statuses. | |
| polygon | No | A ring of 3 to 200 [lng, lat] points (GeoJSON order: longitude first), e.g. [[-83.0,39.9],[-82.9,39.9],[-82.95,40.0]]. A repeated closing point is fine. Send this OR route_points, not both. | |
| sandbox | No | If true, answer in test mode: made-up people (labels start with 'Sample') in the real response shape. Needs no plan and is never billed. | |
| street_only | No | If true, keep only people with an exact street address. | |
| buffer_miles | No | Distance either side of route_points, in miles, 0.05 to 5. | |
| route_points | No | A line of 2 to 200 [lng, lat] points (GeoJSON order). Everyone within buffer_miles either side of it is counted. Send with buffer_miles, instead of polygon. For exact per-leg and per-stop counts along a walking or bus route use map_route. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: billing ($2 per 1,000, one request per call regardless of shape size), 24-hour id lifetime, the 403 map_not_enabled requirement, sandbox mode that bypasses the plan, and auth via X-API-Key. It also warns that a pin is a REGISTERED ADDRESS, not a current location, and that `areas` are ZIP/city-level placements that must not be described as exact spots.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose sentence and then organized by concern (return shape, marker semantics, billing, auth), so a reader can stop early. The inline Returns block is long but justified because no output schema exists; only minor duplication of the schema's zoom semantics keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter, zero-required geospatial query with no output schema and no annotations, the description fills every gap an agent needs: return structure, id/groupId semantics, placement caveats, cost, auth, and the one notable failure mode. 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.
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 zoom, polygon, route_points, buffer_miles and the rest; that sets the baseline at 3. The description adds only marginal parameter meaning beyond it — the detail-level mapping (clusters/pins/named pins at zoom 15+) and the route_points/buffer_miles pairing are both already stated in the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ('Get what to draw inside a drawn shape') and immediately scopes it to two shape types, polygon or buffered line. It explicitly contrasts itself with map_viewport ('the same answer ... limited to what is inside the shape'), so an agent can separate the two without reading either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Routes the agent to the right sibling for each sub-case: map_group for a marker with id null plus groupId, map_open_record to see who one marker is, and map_route for exact per-leg/per-stop counts. It also states the polygon-vs-route_points mutual exclusion, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
map_groupAInspect
List the people behind a many-people pin or an approximate-area pin.
Returns: { total, page, perPage, totalPages, kind: 'address' | 'area', named,
members: [ { id, addressType, label, housingStatus, hasPhoto } ] }. Members
carry `label` only when the group id came from a view at zoom 15 or closer
(`named: true`). Each member `id` opens with map_open_record.
Billing: one map request per page. A group id works for 24 hours and only
for the account it was issued to; after that, call map_viewport again.
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, starting at 1. | |
| group_id | Yes | A `groupId` ('mg_...') from a map_viewport, map_area or map_route marker with `id: null`, from a map_route `groups` entry, or from an entry in `areas` / `approximate.areas`. | |
| per_page | No | People per page, 1 to 100. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: billing (one map request per page), credential binding and 24-hour expiry of group ids, and the auth mechanism (X-API-Key header or env var) are all disclosed. It also explains the conditional presence of `label` based on the source zoom level.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence, then clearly labeled Returns/Billing/Auth blocks. The Returns block is verbose but justified since there is no output schema; every line carries operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a paginated read tool with no output schema and no annotations, the description supplies the return shape, pagination fields, billing cost, credential requirements, and id lifetime — everything an agent needs to invoke and chain it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by constraining group_id behavior (valid for 24 hours, only for the issuing account) and clarifying what `named: true` implies about returned labels.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the people behind a many-people pin or an approximate-area pin') and clearly distinguishes itself from siblings map_viewport/map_area/map_route, which produce the group ids it consumes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete follow-up routing ('Each member id opens with map_open_record') and a recovery path ('after that, call map_viewport again'), plus the 24-hour/account-bound lifetime condition. It stops short of an explicit when-to-prefer-this-over-X statement, but the group-id provenance is clear from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
map_open_recordAInspect
Open the complete record behind one map marker, or behind a saved reference.
Returns: { record, recordRef, billing: { billed, unit, reason }, notice }.
`record` is the same Record object search_offenders returns. `recordRef`
('mr_...') is a lasting reference: keep it to open the same record later,
after the marker id has expired.
Billing: one record open per person per map response, at the account's
record-open rate (published price $0.035 per open; an account's agreed rate
may differ) — so open a marker only when the user wants that person's
record, not every marker in a view or along a route.
- The same marker id again is free (`reason: 'marker_already_opened'`).
- A new map_viewport, map_area, map_route or map_group answer carries new
ids; opening the same person from it is a new charge.
- Opening by `recordRef` is one record open, then free for 24 hours. A
record just opened from a marker is also free by its reference for 24
hours.
`billing.billed` says whether THIS open was charged.
Marker ids work for 24 hours (410 `marker_expired` after that). A 410
`record_no_longer_listed` means the registry no longer lists the person; it
is not billed.
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| marker_id | Yes | A marker id ('mk_...') from map_viewport, map_area, map_route or map_group, or a saved record reference ('mr_...') from an earlier map_open_record. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it does: pricing ($0.035/open, account rate may differ), 24-hour marker expiry with 410 marker_expired, 410 record_no_longer_listed being unbilled, and X-API-Key auth. The only real gap is that it doesn't state rate limits or pagination-like concurrency behavior, but for a single-record fetch that is minor.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and return shape, then grouped under Returns/Billing/Auth labels with bullet sub-cases. It is long for a one-parameter tool, but nearly every sentence carries non-obvious billing or expiry semantics that an agent must know before calling.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description compensates by spelling out the return envelope ({ record, recordRef, billing: { billed, unit, reason }, notice }), the error codes, the caching windows, and the auth header. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the mk_/mr_ prefixes and their sources. The description goes beyond it by stating that marker ids expire after 24 hours while recordRef is 'a lasting reference', and by explaining free re-open semantics for each form.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: 'Open the complete record behind one map marker, or behind a saved reference.' It also anchors the returned object to a named sibling ('the same Record object search_offenders returns'), so an agent can distinguish it from map_viewport/map_area which return markers rather than records.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when/when-not guidance tied to cost: 'open a marker only when the user wants that person's record, not every marker in a view or along a route.' It further enumerates which situations constitute a new charge versus a free re-open.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
map_routeAInspect
Exact counts of registered addresses along one walking or bus route.
Counts a corridor either side of the line, a radius around each stop, or
both, and returns exact numbers per leg and per stop with nameless pins and
their distances. Never an estimate and never partial: the answer is complete
or the call fails without a charge.
Returns: { shape: 'route', profile, measure, detail, datasetVersion, complete,
lengthMiles, corridorMiles, stopRadiusFeet, parcelAllowanceFeet, units,
total, corridorTotal, stopsTotal, breakdown {street, housed, homeless,
incarcerated}, legs: [ {leg, fromStop, toStop, lengthMiles, count} ],
stops: [ {stopId, alongMiles, count, nearestFeet, markerIds} ],
markers: [ {id, lat, lng, precision, addressType, distanceMiles, leg,
alongMiles, nearestStop, stopDistanceFeet} ], groups[], approximate {count,
areas[]}, unplaced {count, states}, externalId, notice, routeNotice }.
- `total` = distinct people with a street address in the corridor or a
stop's reach; leg counts sum to `corridorTotal`.
- Pins carry NO NAMES. A `groups` entry (several people at one address) and
an `approximate.areas` entry (people placed only at the middle of a ZIP,
city or county; never in `total`) open with map_group.
- To see who one marker is, call map_open_record with its `id` — a
separate charge at the account's record-open rate (published price
$0.035 per open; an account's agreed rate may differ). Open only the
records the user asks for, not every marker on the route.
- More than 300 pins at detail=full is a 422 `route_too_many_people` that
carries the exact counts and is not charged: use detail='count' or split
the route.
A count shows REGISTERED ADDRESSES, NOT WHERE ANYONE IS, and is not a rating
of the route. Never describe a route as safe or unsafe; relay `notice` and
`routeNotice`. It supports the user's process; it is not a legal
determination.
Billing: route units, each one map request ($2 per 1,000): one per started
mile of measured corridor plus one per 10 stops when stop radii are measured
(minimum 1); `units` in the answer says how many. detail='count' costs the
same. E.g. a 17.4-mile bus route with 35 stops = 18 + 4 = 22 units. Test
mode is free. The Map API must be turned on for the account.
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | The route line: a GeoJSON LineString {'type':'LineString','coordinates':[[lng,lat],...]} (or a Feature holding one), or a plain list [[lng, lat], ...] in GeoJSON order. Send at most one of path or polyline. | |
| stops | No | Stops along the route, in order: [{'id':'s1','lng':...,'lat':...}, ...] or [[lng, lat], ...]. Ids default to s1, s2, .... With no path or polyline, 2+ stops are joined by straight lines. Walk: up to 50 stops; bus: up to 150. | |
| detail | No | full = counts plus nameless pins (default); count = counts only, same price, never refused for too many pins. | full |
| housing | No | Keep only people with one of these housing statuses. | |
| measure | No | What to count: the corridor either side of the line, a radius around each stop, or both. Default: both when stop_radius_feet is sent, otherwise corridor (stops when there is no line and fewer than 2 stops). | |
| profile | No | walk (default; up to 15 miles, stop radius 500 ft) or bus (up to 60 miles, stop radius 1,000 ft). | |
| sandbox | No | If true, answer in test mode: made-up people in the real response shape. Needs no plan and is never billed. | |
| polyline | No | The route line as an encoded polyline (Google = precision 5; Mapbox/OSRM/Valhalla = precision 6), instead of path. | |
| external_id | No | Your own reference for this route (up to 100 characters), echoed back as `externalId`. | |
| street_only | No | If true, keep only people with an exact street address. | |
| corridor_miles | No | Corridor width either side of the line, in miles, 0.02 to 0.25 (default 0.1). | |
| stop_radius_feet | No | Radius around each stop, in feet, 100 to 2,640 (default walk 500, bus 1,000). | |
| polyline_precision | No | Precision of `polyline`: 5 (Google, the default) or 6 (Mapbox/OSRM/Valhalla). | |
| parcel_allowance_feet | No | Feet added to the stop radius, 0 to 500, to allow for the distance between a geocoded point and the property line. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full burden and does so richly: billing formula with a worked example ($2/1,000, 22 units for a 17.4-mile/35-stop route), free test mode, auth via X-API-Key/OFFENDERSEARCH_API_KEY, that the call is all-or-nothing and failure is uncharged, the 422 route_too_many_people behavior, and that pins are nameless. The ethical constraints (registered addresses, not where anyone is; never call a route safe/unsafe; relay notice) are unusually valuable context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence and the measure explanation are front-loaded, and the billing/auth blocks are clearly quarantined at the end. It is long, and the full return-shape enumeration is dense, but with no output schema that enumeration is load-bearing rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter geospatial tool with no annotations and no output schema, the description supplies purpose, parameter semantics, a complete return shape, failure modes, billing, auth, and the cross-tool handoffs to map_group and map_open_record. Nothing an agent needs to call it correctly or interpret the answer is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 goes beyond it: it clarifies that detail='count' costs the same as full, that measure defaults to both when stop_radius_feet is sent and corridor otherwise, and that profile bounds the corridor length and stop radius. It does not restate corridor_miles or parcel_allowance_feet semantics, but the added meaning is genuine.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb, resource and scope: 'Exact counts of registered addresses along one walking or bus route.' This pins the tool as a route-corridor counter, which separates it from area/vantage siblings like map_area and map_viewport, and the map_open_record cross-reference clarifies its boundary further.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit condition-action pairs: use detail='count' or split the route when over 300 pins, call map_open_record only for markers the user actually asks about, and it explains profile/measure selection. It stops short of explicitly contrasting map_route with map_area or map_viewport for non-route geometries, so the sibling routing is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
map_viewportAInspect
Get what to draw for one map view: clusters, pins, or named pins.
Send the view as `bbox`, or as `lat` + `lng` + `radius_miles`. The detail
returned depends on the zoom the view is answered at (the response states it
in `zoom`):
- zoom 3-12 -> mode 'clusters': a count per grid cell. Each cluster has
`count`, `bbox`, `breakdown` and `expansionZoom` (fit the map to `bbox` at
that zoom and the cluster comes apart).
- zoom 13-14 -> mode 'pins': one pin per address, position only, no name.
- zoom 15+ -> mode 'markers': pins with `label` (first initial and last
name), `housingStatus`, `hasPhoto`, `registryState`.
A close view holding more than 300 pins is answered as clusters instead.
Returns: { mode, zoom, bbox, datasetVersion, total, breakdown {street, housed,
homeless, incarcerated}, clusters[], markers[], areas[], unplaced {count,
states}, notice }. In radius mode also `center`, `radiusMiles` and
`withinRadius` (exact), and each marker has `distanceMiles`.
- A marker with `id: null` and a `groupId` stands for several people at one
address: call map_group with that `groupId`.
- `areas` are people placed only at the middle of a ZIP, city or county;
each has a `groupId` too. Never describe them as being at an exact spot.
- `unplaced` counts people in the states this view touches who have no
mappable address. Mention it rather than implying the map shows everyone.
- To see who one marker is, call map_open_record with its `id`.
A pin shows a REGISTERED ADDRESS, not a person's current location — say so
when you describe a result (`notice` carries the sentence).
Billing: one map request per call ($2 per 1,000), whatever the view holds. Marker and group
ids work for 24 hours. The Map API must be turned on for the account
(the API answers 403 `map_not_enabled` otherwise); `sandbox=true` works
without it.
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude of the centre, instead of bbox (send with lng and radius_miles). | |
| lng | No | Longitude of the centre, instead of bbox (send with lat and radius_miles). | |
| bbox | No | The view as 'west,south,east,north' in degrees, e.g. '-83.5,39.6,-82.4,40.3'. Any size. Send this OR lat/lng with radius_miles, not both. | |
| zoom | No | Optional map zoom, 0 to 22. Decides the detail: 3-12 clusters, 13-14 pins without names, 15+ pins with names. Omit it and the zoom is worked out from the size of the view. | |
| detail | No | full = clusters or pins (default); count = numbers only. | full |
| housing | No | Keep only people with one of these housing statuses. | |
| sandbox | No | If true, answer in test mode: made-up people (labels start with 'Sample') in the real response shape. Needs no plan and is never billed. | |
| street_only | No | If true, keep only people with an exact street address. | |
| radius_miles | No | Radius in miles around lat/lng, 0.1 to 100. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden and does so richly: per-call billing ($2/1,000), 24-hour id validity, the 403 map_not_enabled dependency and the sandbox bypass, the >300-pin downgrade rule, and the caveat that pins are registered addresses rather than current locations (reinforced by the `notice` field). This is far beyond a bare mutation/read disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence, then structured into view-spec, zoom modes, return shape, and billing/auth sections with compact bullets. It is long, but nearly every line conveys actionable detail; only minor redundancy between the zoom bullet and the schema's own zoom description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter tool with no output schema and no annotations, the description fully compensates: it documents the response envelope field-by-field, the mode-dependent shape, the areas/unplaced edge cases, and auth/billing constraints. An agent has everything needed to call it and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 semantics the schema does not: the zoom-to-mode mapping table, the radius-mode return differences, and especially the >300-pin clustering override. It also explains how to interpret `id: null` markers with a `groupId`, which is behavioral meaning layered on the parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get what to draw for one map view') and immediately enumerates the three output modes (clusters, pins, named pins). It also names siblings map_group and map_open_record in the context where they apply, so an agent can distinguish this tool from the family 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives two mutually-exclusive ways to specify the view (bbox OR lat+lng+radius_miles) and routes sub-cases to siblings ('call map_group with that groupId', 'call map_open_record with its id'). It lacks an explicit when-not-this-tool statement against siblings like map_area or map_route, but the context needed to invoke correctly is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_criminalAInspect
Search US criminal records — county jail bookings, state prison custody, court cases and warrants.
Covers county jail rosters, statewide prison systems, court sources, warrant
systems and statewide registries across the states, DC and the territories,
plus the federal layer — which is a separate system holding offences no state
search will surface.
A surname is REQUIRED. Supply firstName and a DOB or birth year wherever you
have them: a bare common surname returns thousands of people, and the scoring
cannot tell you which one is yours.
Each record carries `recordType`, and YOU MUST READ IT BEFORE CHARACTERISING
ANYONE:
- a jail booking is an ARREST-stage record — charges at booking are
frequently reduced, dismissed, or never filed. It is NOT a conviction.
- prison custody implies a sentence, and therefore a conviction.
- a court record carries the DISPOSITION — the authoritative statement of
how a case actually ended.
- a warrant means the person is SOUGHT. Nothing has been tested.
Never describe someone as convicted on the strength of a booking record.
Records also carry: name, aliases, dob/birthYear/dobPrecision, sex, race,
state, county, custody status and facility, sentence and parole detail,
`cases`, `sources` (per-source citation), and `matchConfidence`/`matchBasis`
explaining why it matched. `counts.records` is the total found and
`counts.recordsReturned` the number in this page.
Not a consumer report: results must not be used for FCRA-covered decisions
(employment, tenancy, credit) without appropriate process.
| Name | Required | Description | Default |
|---|---|---|---|
| age | No | Approximate current age, when neither DOB nor birth year is known. | |
| dob | No | Date of birth, YYYY-MM-DD. The single strongest disambiguator. | |
| limit | No | Max records to return. Default 50. | |
| state | No | 2-letter state code (e.g. 'TX'). Narrows to that state's jurisdictions. | |
| county | No | County name, to narrow within a state. | |
| lastName | Yes | REQUIRED surname. The criminal corpus refuses an unbounded query — a name is the field that cannot be enumerated. | |
| birthYear | No | Birth year alone, when a full DOB is unknown. | |
| firstName | No | Given name. Strongly recommended: a bare common surname returns thousands. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description assumes the full disclosure burden and does it well: it defines what each recordType implies, warns that bookings are not convictions, that warrants mean 'SOUGHT', and attaches FCRA restrictions. It even instructs the agent to read recordType before characterizing anyone. This is far beyond the minimum.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with the core purpose and organized into readable paragraphs; the surname/recordType/FCRA guidance is all substantive. A few phrases, like the federal-layer explanation, are useful context rather than waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, it documents the returned record fields (name, aliases, dob, sex, race, state, county, custody, sentence, cases, sources, matchConfidence/matchBasis) and the pagination counts. It covers search behavior, caveats, and legal constraints, leaving the agent enough to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema already describes all 8 parameters, so baseline is 3; the description adds real value by explaining that surname is non-optional, that firstName + DOB or birthYear strengthen matching, and that a common surname yields thousands of results. It also calls DOB 'the single strongest disambiguator,' which is not in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a clear verb and resource: "Search US criminal records" and enumerates county jail bookings, prison custody, court cases, and warrants. Scope is unambiguous, but it never explicitly distinguishes itself from the sibling search_offenders or tells the agent which searches are excluded, so sibling differentiation is absent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit invocation guidance — 'A surname is REQUIRED' and advises supplying firstName plus DOB/birth year 'wherever you have them' — and explains why (bare common surnames return thousands). It doesn't state when to prefer a sibling tool like search_offenders, so no exclusions/alternatives are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_offendersAInspect
Search US sex-offender registries for one person and/or location.
Fans out across all 58 registries (or the ones named in `jurisdictions`),
de-duplicates people across registries, scores each match, and returns the
normalized records. Supply whatever identifiers you have — all args are
optional but at least a name, location, or free-text `q` should be given.
Returns a SearchResponse object (docs/openapi.yaml / FIELD-DICTIONARY.md):
- status: 'complete' | 'partial' (partial = a source errored, or a source
could not be searched to completion)
- counts: { records, sourcesQueried, sourcesIncomplete }
- warnings: [str] — ALWAYS present, `[]` when the search ran clean
- sourceStatus: [ { source, status, matched, fromCache, note,
incomplete, incompleteReason } ] per-registry outcome
★ READ `counts.sourcesIncomplete` BEFORE REPORTING A RESULT. Above 0, `records`
is a LOWER BOUND: those registries could not be searched to the end, and an
empty or short result is NOT evidence that a person is unregistered. Say so.
`warnings[0]` states it in plain language; relay it rather than summarising it
away.
- records: [ Record ], each with:
recordId, matchConfidence, matchBasis[],
name {first, middle, last, suffix, full}, aliases[], nicknames[],
dob, dobPrecision, age, sex, race, ethnicity, height, weight,
eyeColor, hairColor, marks, addresses[{type,line1,city,county,state,zipcode,lat,lng}],
offense {crime,statute,riskLevel,tier,convictionDate,...}, flags{absconder,predator},
source {jurisdiction,registryName,recordUrl,scrapedAt,sourceUpdatedAt}, sources[],
dobVerification, unverified
(offenses[], stateData, images[] are populated only when extensive=true)
Auth: uses the caller's X-API-Key (request header or OFFENDERSEARCH_API_KEY env).
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Free-text search across name/alias/address/city/state/zip (all tokens must appear). | |
| age | No | Age filter, used when DOB is unknown. Matched +/-1 year for birthday drift. | |
| dob | No | Date of birth 'YYYY-MM-DD'. Improves match precision; drives dobVerification (dob_match / year_match). | |
| lat | No | Latitude for a GIS radius search (pair with lng). | |
| lng | No | Longitude for a GIS radius search (pair with lat). | |
| city | No | Residence city filter. | |
| match | No | Fuzzy tolerance: strict=exact; balanced=nicknames/variants/initials/typos on first name, exact last; broad=also prefix/typo on last name. | balanced |
| state | No | 2-letter state/territory code (e.g. 'IL', 'PR'), or the full name. A residence FILTER — it does NOT change which registries run; all 58 are still searched. It filters as a UNION: a record is kept when it has an address in that state OR that state's registry is the one holding it. Each record carries `registrationState` and `addressStates` so you can tell which half matched; for the registration half alone, pass `jurisdictions` instead. | |
| address | No | Fuzzy street-address filter (every token must appear in some record address). | |
| zipcode | No | Residence ZIP (first 5 digits used). | |
| extensive | No | If true, request extensive detail (retains offenses[], stateData, images). A light call drops them. | |
| freshness | No | Cache/pricing tier: daily=<=24h (default), weekly=<=7d. | daily |
| last_name | No | Surname — the primary match key, e.g. 'Smith'. | |
| first_name | No | Given name, e.g. 'John'. | |
| deadline_ms | No | Max time to wait, in ms (default 120000 / 2 min). Lower for a faster bounded response; partial results return status='partial'. | |
| radius_miles | No | GIS radius in miles around lat/lng. Defaults to 1 when a point is given; capped at 100. | |
| jurisdictions | No | Registry codes to query (e.g. ['IL','TX']). Omit/null = ALL 58 registries. See get_registry_coverage for codes. | |
| location_scoped | No | OPT-IN ONLY, and never inferred from `state`. If true AND a state is set, run only the registries covering that state instead of all 58. It is a cost knob that COSTS RECALL: anyone registered by another state's registry while residing in the requested state is excluded (7.0% of records). The response reports counts.sourcesSkippedByScope and a NARROWED SEARCH warning when it applies. Leave it false unless the caller explicitly wants the cheaper, narrower search. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure and meets it thoroughly. It reveals that results may be partial, that counts.sourcesIncomplete makes records a lower bound, that warnings are always present, and that registries can fail without invalidating the search. It also exposes the auth mechanism and the difference between light and extensive calls.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized: a one-line summary, then fan-out behavior, a clear warning section, a structured return-field list, and an auth note. Critical operational guidance (read sourcesIncomplete before reporting) is highlighted early and in plain language. Every section earns its place given the 18-parameter surface and absence of an output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 18-parameter read tool with no output schema, the description is remarkably complete. It documents the response structure, per-source status fields, cache tiers, geo-search behavior, jurisdiction control, and the crucial lower-bound caveat. An agent has enough context to call it correctly and interpret its results without additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 substantial meaning beyond field names and types. It clarifies subtle behaviors such as `state` being a residence filter that does not change which registries run, `location_scoped` being an opt-in recall-reducing knob, `match` levels affecting fuzzy tolerance, and `deadline_ms` causing partial results. This materially improves an agent's ability to choose correct parameter combinations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Search US sex-offender registries for one person and/or location.' It goes beyond a vague summary by explaining the fan-out, de-duplication, scoring, and normalized record output. The resource is clearly distinct from siblings like search_criminal at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear guidance on when to call the tool: when searching sex-offender registries, and it explains what identifiers to supply ('at least a name, location, or free-text q should be given'). It also references get_registry_coverage for registry codes, pointing the agent to the right companion tool. It does not explicitly contrast with search_criminal or batch_search, but the resource scope makes the primary context clear.
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.
5 tool updates
- Added
map_area - Added
map_group - Added
map_open_record - Added
map_route - Added
map_viewport
5 tool updates
- First observed
batch_search - First observed
get_criminal_coverage - First observed
get_registry_coverage - First observed
search_criminal - First observed
search_offenders
Related MCP Connectors
US public-records lookups: people search, reverse phone, property and criminal records.
Research a person's public footprint from a name, phone, email, or username. Sourced.
Is this person indexed on that data-broker domain? A three-state verdict, with the evidence.
US crime scores, incidents, neighborhood demographics, rent data, and offender search by address.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables searching all US sex-offender registries from any MCP client, returning scored, de-duplicated records with provenance and per-registry status.-
- AlicenseNot gradedqualityDmaintenanceScreens individuals and entities against the OIG LEIE exclusion list, returning candidate matches that require human verification.MIT
- AlicenseNot gradedqualityBmaintenanceEnables querying US federal criminal docket metadata, such as party names, courts, docket numbers, and filing dates, through search and recent-case tools.198 npmMIT
- AlicenseNot gradedqualityCmaintenanceChecks names against US FinCEN financial crime lists for compliance and AML due diligence, with a single read-only tool.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.