Skip to main content
Glama
haksanlulz

mcp-courtwatch

by haksanlulz

mcp-courtwatch

MCP server for free U.S. case-law and court-docket search, over CourtListener (the Free Law Project's open legal database). Built for legal-aid orgs, tenant-defense and pro-se litigants, and public-interest lawyers who cannot afford Westlaw or PACER.

It wraps CourtListener's REST API v4, normalizing the raw JSON (caseName, dateFiled, cluster_id, docket_absolute_url, and so on) rather than passing the envelope through — see the field map below.

Tools

Tool

Arguments

Returns

opinion_search

q (required), court, filed_after, filed_before, order_by, limit, cursor

Full-text case-law search (/search/?type=o). Per hit: case name, court, date filed, citations, docket number, snippet, citation count, cluster id, link. Also returns next_cursor (pass it back as cursor for the next page).

docket_lookup

q and/or docket_number (at least one), court, limit, cursor

Docket search (/search/?type=r). Per hit: case name, court, docket number, filed/terminated dates, nature of suit, docket id, link. Also returns next_cursor (pass it back as cursor for the next page).

court_list

jurisdiction, q, limit

Courts and their ids (/courts/), the values used as the court filter above. Optional jurisdiction filter and a name substring filter applied across the full courts table (paged server-side).

case_detail

id (required), type (cluster or opinion)

Full case by id. A cluster (/clusters/{id}/) gives case name, citations, date, judges, and its opinion ids. An opinion (/opinions/{id}/) gives the full opinion text. Requires a token.

citation_lookup

text (required)

Verify citations (POST /citation-lookup/). Pass free text (a brief, a draft) or a single citation string; every citation recognized is checked against the database of real cases. Per citation: FOUND (with matched case name, date, link) or an explicit NOT_FOUND / UNKNOWN_REPORTER flag. Requires a token.

judge_lookup

name_last and/or name_first (at least one), limit

Judges / people (/people/). Per person: id, assembled name, birth and death dates and place, gender, count of positions on file.

cited_by

opinion_id (required), order_by, limit, cursor

Every opinion citing a given opinion, via the cites:() search operator — a free citator check (who still relies on this case). Newest-first by default. No treatment classification. Keyless.

case_authorities

opinion_id (required), limit

The authorities an opinion relies on (its table of authorities) with a per-authority citation depth, via /opinions-cited/. Token required.

docket_entries

docket_id (required), limit, cursor

A federal docket's filing history from the RECAP archive: numbered entries, dates, descriptions, archived PACER documents with page counts and availability. Token required. RECAP holds what its users bought from PACER.

oral_arguments

q (required), court, order_by (relevance/newest/oldest), argued_after, argued_before, limit, cursor

Oral-argument audio search (type=oa): case, court, argue date, panel judges, duration, MP3 link. Keyless.

order_by for opinion_search is one of relevance (default), newest, oldest, most_cited. Court jurisdiction codes include F (federal appellate and other), FD (federal district), FB (bankruptcy), S (state), SA (state appellate), SS (state supreme).

Related MCP server: courtlistener-mcp

Data source

  • Base URL: https://www.courtlistener.com/api/rest/v4

  • Auth: a free API token, sent as the header Authorization: Token <token>.

  • Envelope: search and list endpoints return the DRF shape { count, next, previous, results: [...] }. /search/ and /people/ paginate by opaque cursor; /courts/ paginates by page number (?page=N). Detail endpoints return a bare object. POST /citation-lookup/ returns a bare JSON array (one item per citation recognized in the text).

  • Access: /search/, /courts/, and /people/ answer without a token at a low rate limit, so those tools attach the token only when it is set (a token raises the limit). /clusters/{id}/, /opinions/{id}/, /opinions-cited/, /docket-entries/, and POST /citation-lookup/ return HTTP 401 without a token, so case_detail, citation_lookup, case_authorities, and docket_entries require one. The /docket-entries/ filter parameter is docket (not docket_id — the API answers 400 unknown_params otherwise; found live).

  • Citation-lookup limits (server-side): text max 64,000 characters (enforced pre-flight here with a clear error; the tool never truncates, since a dropped tail would mean unchecked citations); the first 250 citations per call are looked up and any beyond that come back flagged per-item as not checked; rate limit 60 citations/min.

Sources:

Field map (CourtListener to normalized output)

CourtListener field

Normalized field

Where

caseName (fallback: caseNameFull on opinion hits, case_name_full on docket hits)

case_name

opinion_search, docket_lookup

court_id, court

court_id, court

search hits

dateFiled

date_filed

search hits

citation (array)

citations

opinion_search

docketNumber

docket_number

search hits

opinions[].snippet

snippet

opinion_search

cluster_id, docket_id

cluster_id, docket_id

search hits

absolute_url / docket_absolute_url

absolute_url (made a full link)

search hits

dateTerminated, suitNature

date_terminated, nature_of_suit

docket_lookup

id, full_name, short_name, jurisdiction, citation_string, url

id, full_name, short_name, jurisdiction, citation_string, website

court_list

citations (array of {volume, reporter, page})

citations (formatted strings)

case_detail (cluster)

sub_opinions (array of URLs)

sub_opinion_ids

case_detail (cluster)

plain_text (fallback html_with_citations)

text (+ text_source, text_truncated)

case_detail (opinion)

citation, normalized_citations, start_index, end_index

same names

citation_lookup (per citation)

status (200/300/400/404/429), error_message

status + verdict (FOUND, FOUND_MULTIPLE, UNKNOWN_REPORTER, NOT_FOUND, NOT_CHECKED_OVER_CAP) + verified, error_message

citation_lookup (per citation)

clusters (array of cluster objects)

matches (cluster id, case name, date, citations, link)

citation_lookup (per citation)

Install

Nothing to clone. Point your MCP client at it and npm fetches it on first run:

{
  "mcpServers": {
    "courtwatch": {
      "command": "npx",
      "args": ["-y", "@haksanlulz/mcp-courtwatch"],
      "env": { "COURTLISTENER_API_TOKEN": "your-courtlistener-token" }
    }
  }
}
git clone https://github.com/haksanlulz/mcp-courtwatch
cd mcp-courtwatch
npm install
npm run build     # emits dist/; the published bin is dist/index.js

npm start runs the TypeScript directly via tsx without building.

API token

case_detail, citation_lookup, case_authorities, and docket_entries need a free CourtListener token, and the other tools run faster (higher rate limit) with one. Create a free account, open Profile then the API page, and copy the token. Docs: https://www.courtlistener.com/help/api/rest/

Expose it as COURTLISTENER_API_TOKEN:

export COURTLISTENER_API_TOKEN=your-token-here   # macOS / Linux
setx COURTLISTENER_API_TOKEN your-token-here      # Windows (new shells)

Without the token, opinion_search, docket_lookup, court_list, judge_lookup, cited_by, and oral_arguments still work at CourtListener's unauthenticated rate limit. The token-gated tools return a clear error telling you to set the token. The token is never logged.

New-account rate limit: fresh CourtListener accounts are throttled at 5 requests/minute (it rises as the account ages). Until then, set COURTWATCH_THROTTLE_MS=15000 in the server's env to pace requests under that limit — the default spacing is 200ms.

Example

Call opinion_search with { "q": "warrantless search", "court": "scotus", "order_by": "most_cited", "limit": 1 } (output captured live, 2026-07; counts drift as CourtListener grows):

{
  "query": { "q": "warrantless search", "court": "scotus", "filed_after": null, "filed_before": null, "order_by": "most_cited", "cursor": null },
  "total_matches": 282,
  "returned": 1,
  "next_cursor": "cz01MTI3JnM9MTA5NjkzJnQ9byZkPTIwMjYtMDctMTcmcD0y",
  "results": [
    {
      "case_name": "Monell v. New York City Dept. of Social Servs.",
      "court": "Supreme Court of the United States",
      "court_id": "scotus",
      "date_filed": "1978-06-06",
      "citations": ["56 L. Ed. 2d 611", "98 S. Ct. 2018", "436 U.S. 658", "1978 U.S. LEXIS 100", "16 Empl. Prac. Dec. (CCH) 8345", "17 Fair Empl. Prac. Cas. (BNA) 873"],
      "docket_number": "75-1914",
      "cite_count": 42298,
      "status": "Published",
      "snippet": "436 U.S. 658 (1978)\nMONELL ET AL.\nv.\nDEPARTMENT OF SOCIAL SERVICES OF THE CITY OF NEW YORK ET AL.\nNo. 75-1914.\nSupreme Court of the United States. ...",
      "cluster_id": 109881,
      "docket_id": 266243,
      "absolute_url": "https://www.courtlistener.com/opinion/109881/monell-v-new-york-city-dept-of-social-servs/"
    }
  ],
  "disclaimer": "Raw public court records from CourtListener, reproduced as published. This is not legal advice and is not a substitute for a lawyer. Docket entries record filings, not rulings; the absence of a record is not evidence that nothing happened."
}

The disclaimer is attached to every response, in the payload rather than only in the tool description — a model composing an answer has the payload in hand and may no longer be holding the description.

Then pass the cluster_id to case_detail ({ "id": 109881 }) for the citations, judges, and opinion ids, or case_detail with { "id": <opinion id>, "type": "opinion" } for the full opinion text. For the next page, pass next_cursor back as cursor.

Example: verifying citations before filing

Courts have sanctioned filings built on citations that do not exist. Run a draft's citations through citation_lookup before filing.

Call citation_lookup with { "text": "Tenants are protected here. See Roe v. Wade, 410 U.S. 113 (1973); Smith v. Imaginary, 999 U.S. 9999 (2099)." }. The output below is illustrative of the response shape (the live smoke runs this exact real-plus-fabricated check and fails unless the real one resolves and the fake flags NOT_FOUND):

{
  "query": { "text_chars": 107 },
  "citations_checked": 2,
  "found": 1,
  "not_found": 1,
  "invalid": 0,
  "not_checked": 0,
  "all_verified": false,
  "warning": "1 of 2 citation(s) did NOT verify: 1 not found in CourtListener (likely fabricated or mis-cited). Do not cite unverified authorities — check them by hand before filing.",
  "results": [
    {
      "citation": "410 U.S. 113",
      "verified": true,
      "verdict": "FOUND",
      "status": 200,
      "error_message": null,
      "normalized_citations": ["410 U.S. 113"],
      "start_index": 45,
      "end_index": 57,
      "matches": [
        {
          "cluster_id": 108713,
          "case_name": "Roe v. Wade",
          "date_filed": "1973-01-22",
          "citations": ["410 U.S. 113", "93 S. Ct. 705", "35 L. Ed. 2d 147"],
          "precedential_status": "Published",
          "citation_count": 12030,
          "judges": "Blackmun",
          "docket_id": 4463,
          "absolute_url": "https://www.courtlistener.com/opinion/108713/roe-v-wade/"
        }
      ]
    },
    {
      "citation": "999 U.S. 9999",
      "verified": false,
      "verdict": "NOT_FOUND",
      "status": 404,
      "error_message": "Citation not found: '999 U.S. 9999'",
      "normalized_citations": ["999 U.S. 9999"],
      "start_index": 86,
      "end_index": 99,
      "matches": []
    }
  ],
  "disclaimer": "Raw public court records from CourtListener, reproduced as published. This is not legal advice and is not a substitute for a lawyer. Docket entries record filings, not rulings; the absence of a record is not evidence that nothing happened."
}

The fabricated citation comes back NOT_FOUND with a top-level warning. Per-citation status mirrors the API's own codes: 200 found, 300 found with multiple matching clusters (FOUND_MULTIPLE — a real citation, ambiguous mapping), 400 unknown reporter, 404 not found, 429 past the 250-citations-per-call cap (NOT_CHECKED_OVER_CAP — split the text and re-run the rest). A lookup that recognizes zero citations says so in a note instead of pretending to have verified anything.

The blind spot to know about: the extractor can only flag what it can recognize. 999 U.S. 9999 is caught (real reporter, fake volume: NOT_FOUND), but a cite with an invented reporter — live example 999 A.D.9th 999 — is not recognized as a citation at all, so it is neither counted nor flagged. Every response carries a coverage_note stating this; treat all_verified as covering recognized citations only.

Caveats and verification state

Every tool — including all four token-gated ones — has been run live against the real API with a real token (npm run smoke, 10/10, 2026-08-23). Two contract facts were only discoverable live and are baked in: the /docket-entries/ filter parameter is docket (an unauthenticated probe cannot see this, since auth is checked before params), and new-account rate limiting is 5 requests/minute (see the token section). Standing caveats that are properties of the API, not gaps in verification:

  • The citation checker has a structural blind spot, named in every payload. It can only check citations whose reporter it recognizes. A fabricated cite with an invented reporter (live example: 999 A.D.9th 999) is not recognized, not counted, and not flagged, so all_verified: true means "every recognized citation resolved" — never "nothing in this text is fake." Every citation_lookup response carries a coverage_note saying exactly this.

  • The clusters returned by citation_lookup do not include the court (in CourtListener's model the court hangs off the docket, not the cluster). For the court, follow the match's absolute_url or pass its cluster_id to case_detail. Deliberately not auto-fetched: a 250-citation brief would fan out into hundreds of extra docket calls.

  • A docket_number argument is sent through the fielded docketNumber:"..." search operator (live: 6 matches where the free-text form matched thousands). Combine with q for case-name context when a docket number alone under-returns.

  • court_list with a name filter walks the full courts table one page at a time (the /courts/ endpoint ignores page_size; ~3,400 courts over ~170 pages). A complete walk is cached in-process for 24 hours, so it happens at most once per day per server process; scope by jurisdiction to avoid it entirely. On a 5-req/min account, a full walk cannot finish inside one client timeout — filter by jurisdiction until the account limit rises.

  • opinion_search, docket_lookup, cited_by, and oral_arguments return one fixed /search/ page of ~20 results; for more, pass next_cursor back as cursor. The endpoint ignores page_size, so limit caps at 20 rather than advertising an unreachable number.

  • /docket-entries/ and /opinions-cited/ use v4 cursor pagination, which often omits the total count: total_entries / total_authorities come back null with total_reported: false — that means "not reported", never zero.

Testing

npm test           # offline: vitest, fetch mocked with the documented response shapes (no token needed)
npm run smoke      # live: one real call per tool (needs COURTLISTENER_API_TOKEN; skips cleanly without)
npm run typecheck
npm run verify:pack  # packs, installs into a temp project, spawns the bin shim over real stdio

Two tiers, split by script rather than by marker. npm test is the offline suite; CI runs it plus npm run typecheck, npm run build, and npm run verify:pack (ci.yml jobs test, package, consume). npm run smoke is the live upstream contract, token-gated, and not run in CI.

Counts as of 2026-09-11: 54 tests in 2 files (npm test), 1541 lines of app source, 1112 lines of test source.

find . -path ./node_modules -prune -o -path ./dist -prune -o -path ./test -prune -o \( -name '*.ts' -o -name '*.mjs' \) -print | grep -v smoke.ts | xargs wc -l
find test -name '*.test.ts' | xargs wc -l

What the tests cover, by layer: test/server.test.ts drives every tool through a real MCP client over an in-memory transport with fetch stubbed, and asserts the outgoing request (path, query params, Authorization header, POST body) and the normalized response shape, plus the retry policy (5xx and 429 retried three times, 4xx and non-JSON not retried), the response cache, and the argument validators that must fail before any network call. test/no-http-stack.test.ts pins the dependency surface. The live smoke checks each tool once against the real API.

Mutation probe (2026-09-11): raising CITATION_TEXT_CAP in server.ts from 64000 to 65000 turned exactly one test red, citation_lookup > rejects oversized text before any network call instead of truncating, 53 of 54 passing; the source was then restored.

The 19 toHaveBeenCalled* assertions were audited and all kept: each one pins a named contract (no request leaves on a validation or missing-token error, retry count, cache hit, two-page walk). Policy: assert behavior and payloads, never merely that a function was called.

AI assistance

This project was built with AI assistance (Claude). Correctness was established by the test suite and typecheck (npm test, npm run typecheck): every tool is driven through a real MCP client over an in-memory transport with fetch stubbed to the documented CourtListener response shapes, and the unauthenticated search / courts / people surfaces were additionally checked against the live API. As of 2026-08-23 every tool, including the token-gated four, has additionally been verified live with a real token (npm run smoke, plus persona-driven scenario probes that surfaced and fixed the docket filter-param and fake-reporter-coverage findings). The author is accountable for what ships here.

License

MIT. See LICENSE. Data from CourtListener / the Free Law Project (public court records and openly licensed legal data). Unofficial, not affiliated with CourtListener or the Free Law Project.

Available Tools

10 tools
case_authoritiesA

The reverse of cited_by: every authority a given opinion RELIES ON (its table of authorities), with a depth count of how many times each is cited. Pass the citing opinion's id. Requires COURTLISTENER_API_TOKEN (authentication-only endpoint). Returns cited opinion ids; fetch interesting ones with case_detail (type opinion) or their clusters.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax authorities to return (1-50, default 50).
opinion_idYesNumeric OPINION id whose authorities to list.

TDQS

A4.3/5.0
Behavior4/5

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. It discloses that this is an authentication-only endpoint requiring COURTLISTENER_API_TOKEN, which is important behavioral context. It also explains the output shape at a high level: cited opinion ids with a depth count.

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

Conciseness5/5

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

The description is compact and front-loaded with the core concept: 'The reverse of cited_by'. Every sentence earns its place, covering the key behavior, required authentication, and downstream next-step guidance without unnecessary 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?

Given low complexity (2 parameters, no output schema, no annotations), the description is complete enough for correct invocation. It specifies the required input, the auth requirement, the return behavior, and even suggests how to fetch fuller details using case_detail or clusters.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters clearly. The description adds modest reinforcement by explaining that opinion_id is the citing opinion's id and that the result includes depth counts, but it does not add substantial new 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?

The description clearly states the tool's function: it returns the authorities an opinion relies on, with a citation depth count. It also explicitly contrasts itself with cited_by, allowing an agent to distinguish it from a closely related sibling.

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

Usage Guidelines4/5

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

The description clearly implies when to use this tool by labeling it 'the reverse of cited_by' and explaining that the caller passes the citing opinion's id. It gives useful context and names the main alternative, though it does not explicitly state when-not-to-use or provide explicit exclusion conditions.

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

case_detailA

Fetch a full case by id: a cluster (the case: name, citations, date, judges, and its opinion ids) or a single opinion (its full text). Requires COURTLISTENER_API_TOKEN (these endpoints are authentication-only). Use the cluster_id from opinion_search results.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesNumeric cluster id (default) or opinion id.
typeNoWhich resource `id` refers to (default "cluster"). A cluster is the case; an opinion is one document within it.

TDQS

A4/5.0
Behavior3/5

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

No annotations are provided, so the description must carry the full burden. It discloses the authentication need and outlines the response structure (cluster vs. opinion fields). However, it lacks details on error behavior (e.g., missing id, invalid type) and does not mention any side effects or rate limits. For a read-only fetch, this is adequate but not thorough.

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

Conciseness5/5

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

The description is extremely concise: three sentences covering purpose, auth, and usage. No unnecessary words or repetition. It is well front-loaded with the core action.

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

Completeness4/5

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

Given the complexity (two resource types) and no output schema, the description manages expectations well by listing what each resource returns (cluster fields: name, citations, date, judges, opinion ids; opinion: full text). It could mention potential errors, but for a fetch tool, the core information is present.

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?

The schema already covers both parameters with clear descriptions (id: numeric, type: enum). The description adds the context of using cluster_id from search results, but does not significantly enhance the understanding of the parameters themselves. With 100% schema coverage, the baseline is 3.

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

Purpose5/5

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

The description clearly states 'Fetch a full case by id' and distinguishes between two resource types: a cluster (the case) with its fields, or a single opinion. This specific verb-resource pairing and the differentiation from other tools like 'opinion_search' makes the purpose unambiguous.

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

Usage Guidelines4/5

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

The description tells when to use the tool (to get full details of a case or opinion), mentions the authentication requirement, and even suggests how to obtain the id ('Use the cluster_id from opinion_search results'). It does not explicitly list when not to use it, but the context and sibling tools imply alternatives.

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

citation_lookupA

Verify legal citations against CourtListener's database of real cases before relying on them; catches fabricated or mangled citations. Pass free text (a brief, memo, or draft) or a single citation string; every citation recognized in the text is checked. Per citation: FOUND (with case name, date, and link) or an explicit NOT_FOUND / UNKNOWN_REPORTER flag. Requires COURTLISTENER_API_TOKEN (authentication-only endpoint). Caps: 64000 characters of text and 250 citations per call (server rate limit: 60 citations/min).

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesFree text to scan for citations (max 64000 characters), or a single citation string like "410 U.S. 113". The first 250 citations recognized are looked up; any beyond that are returned flagged NOT_CHECKED_OVER_CAP.

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It discloses the required authentication token, character and citation caps, rate limit, and output flags (FOUND, NOT_FOUND, UNKNOWN_REPORTER, NOT_CHECKED_OVER_CAP). It does not cover error handling for invalid tokens, but the disclosed behavior is sufficient.

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

Conciseness5/5

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

The description is a single, well-structured paragraph of five sentences. It is front-loaded with the primary purpose, followed by usage instructions, then behavioral details and limitations. Every sentence adds value with no redundancy or fluff.

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?

Given the tool has a single parameter, no output schema, and no annotations, the description covers all necessary aspects: purpose, usage, authentication, limits, and output type. It is complete for an agent to decide when and how to invoke the tool.

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

Parameters4/5

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

The schema already provides a description for the 'text' parameter, achieving 100% coverage. The description adds significant value by explaining the two input forms (free text or single citation string), the maximum character length, and the citation cap behavior. This goes beyond the schema definition.

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

Purpose5/5

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

The description clearly states the tool's purpose: verifying legal citations against CourtListener's database to catch fabricated or mangled citations. It specifies the verb 'verify' and the resource 'legal citations', and distinguishes itself from sibling tools like case_detail or opinion_search.

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

Usage Guidelines4/5

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

The description provides clear context on when to use the tool ('before relying on legal citations'), how to use it (pass free text or a single citation string), and operational limits (characters, citations, rate limit). It does not explicitly list when not to use it or mention alternatives, but the purpose is distinct enough.

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

cited_byA

Every opinion that CITES a given opinion — the free version of a citator check ('is this case still being relied on, and by whom'). Pass an opinion id (from case_detail's sub_opinion_ids, or an opinion_search hit's cluster via case_detail). Returns citing opinions newest-first or most-cited-first with the same fields as opinion_search. Works without a token. NOTE: this reports who cites the case; it does NOT classify the treatment (followed/distinguished/overruled) — read the citing opinions.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results from this page (1-20, default 20).
cursorNoOpaque cursor from a previous response's next_cursor.
order_byNoSort order (default newest).
opinion_idYesNumeric OPINION id (not a cluster id). case_detail on a cluster lists its sub_opinion_ids.

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full burden, and it delivers: sorts are disclosed, token requirements are stated, the lack of treatment classification is explicitly highlighted, and the note to 'read the citing opinions' sets proper expectations. This is unusually transparent for a tool definition.

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

Conciseness5/5

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

The description is front-loaded with the core purpose, then supplies indispensable usage details, then ends with the critical limitation. Every sentence earns its place, and the caveat is clearly separated with 'NOTE' so an agent does not miss the non-classification behavior.

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

Completeness4/5

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

The description covers ID sourcing, sorting, authentication, output similarity to opinion_search, and important limitations. It relies on 'same fields as opinion_search' to describe the return shape rather than enumerating fields, which is a minor gap given there is no output schema, but the sibling tool is available for reference.

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 adds valuable context beyond the schema by explaining that opinion_id must be a numeric OPINION id and not a cluster id, and by showing where to obtain that ID from related tools. This meaningfully helps an agent pass the correct value.

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

Purpose5/5

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

The description opens with a clear, specific statement: 'Every opinion that CITES a given opinion.' It also positions this as a citator-check tool, which distinguishes it from related siblings like citation_lookup and clarifies that it focuses on citing opinions, not treatment classification.

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

Usage Guidelines4/5

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

It gives concrete guidance on where to obtain the opinion_id (case_detail's sub_opinion_ids or via opinion_search's cluster through case_detail), clearly distinguishes opinion IDs from cluster IDs, and notes that it works without a token. The explicit caveat that it does NOT classify treatment gives a clear when-not-to-use signal, though it does not name a specific alternative tool for treatment analysis.

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

court_listA

List CourtListener courts and their ids (the values used as the court filter in opinion_search / docket_lookup). Optionally filter by jurisdiction code and/or a name substring. Jurisdiction codes include "F" (federal appellate/other), "FD" (federal district), "FB" (bankruptcy), "S" (state), "SA" (state appellate), "SS" (state supreme). Works without a token.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoOptional case-insensitive substring matched against court id / full name / short name / citation string (applied to the fetched page).
limitNoMax courts to return (1-50, default 25).
jurisdictionNoOptional jurisdiction code filter (e.g. "F", "FD", "S").

TDQS

A4.6/5.0
Behavior4/5

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

No annotations provided, so description carries full burden. Discloses that it lists courts with ids, supports optional filtering, and requires no authentication. As a read-only list operation, this is sufficiently transparent.

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?

Description is concise (three sentences) and well-structured: first sentence states purpose, second explains filters, third explains jurisdiction codes. No filler or redundancy.

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?

Given no output schema, description adequately covers return (list of courts and ids). Covers all three parameters with clear context. Also connects to sibling tools (opinion_search, docket_lookup). Complete for a list tool.

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

Parameters5/5

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

Adds meaning beyond 100% schema coverage: explains jurisdiction codes in detail, notes that 'q' is case-insensitive and matches multiple fields, and clarifies that limit controls page size. This helps the agent use parameters effectively.

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?

Description clearly states 'List CourtListener courts and their ids' and explains their use in other tools. Distinguishes from siblings by focusing on listing courts rather than searching opinions, dockets, etc.

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

Usage Guidelines4/5

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

Explicitly says 'Works without a token' and explains optional filters. Implies usage for obtaining court ids before using opinion_search/docket_lookup. Could add explicit when-to-use vs alternatives, but context is clear.

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

docket_entriesA

The actual filing history of a federal docket from the RECAP archive: numbered entries, dates, descriptions, and any archived PACER documents (with page counts and availability). Pass a docket_id from docket_lookup. Requires COURTLISTENER_API_TOKEN (authentication-only endpoint). Coverage note: RECAP holds what its users have bought from PACER — an entry or document not present may still exist on PACER.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax entries to return (1-50, default 50).
cursorNoOpaque cursor from a previous response's next_cursor.
docket_idYesNumeric docket id (from docket_lookup results).

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the behavioral disclosure burden. It reveals the authentication-only nature and flags an important data caveat: RECAP holdings depend on what users have purchased on PACER, so absence of an entry/document may not mean it doesn't exist on PACER. It also explains what document metadata is returned. It does not mention rate limits or error behavior, but the key non-obvious behaviors 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.

Conciseness5/5

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

Three sentences, each with a distinct purpose: what the tool returns, how to invoke it (docket_id source and auth), and the data coverage caveat. No repetition or 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?

The definition is self-sufficient for an agent to call the tool correctly: input source, auth requirement, output contents, and data limitations are all described. Pagination is handled by the schema's cursor description, so no gap. The coverage caveat is especially valuable for interpreting results.

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

Parameters3/5

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

Schema description coverage is 100%, so all three parameters are already documented, including docket_id's origin from docket_lookup results. The description adds no new parameter semantics beyond repeating the docket_id source, so the baseline 3 is appropriate.

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

Purpose5/5

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

The description clearly identifies the resource as 'the actual filing history of a federal docket from the RECAP archive' and itemizes the return contents: numbered entries, dates, descriptions, and archived PACER documents with page counts and availability. It also positions itself relative to docket_lookup by stating that a docket_id comes from that tool's results.

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

Usage Guidelines4/5

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

It provides concrete usage context: pass a docket_id from docket_lookup, and requires COURTLISTENER_API_TOKEN. It does not explicitly name sibling alternatives or state when not to use this tool, but the workflow cue ('from docket_lookup') makes the intended usage clear.

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

docket_lookupA

Search court dockets (CourtListener type=r) by case name, free text, and/or docket number, optionally scoped to a court. Returns case name, court, docket number, filed/terminated dates, nature of suit, and a link. Works without a token.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNoCase name or free-text query (e.g. an employer or agency name).
courtNoOptional court id filter (e.g. "nysd"). Get ids from court_list.
limitNoMax results from this page (1-20, default 20). The /search/ endpoint returns one fixed page of ~20; to get more, pass the response's next_cursor back as cursor.
cursorNoOpaque pagination cursor from a previous response's next_cursor; fetches the next page (keep the other args the same).
docket_numberNoDocket number to match (e.g. "1:20-cv-03590").

TDQS

A4/5.0
Behavior4/5

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

Since no annotations are provided, the description carries full burden. It discloses that the tool works without authentication and returns specific fields. However, it does not mention pagination behavior or any rate limits, which are relevant for a search tool.

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

Conciseness5/5

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

The description is two sentences, front-loading the core purpose and return values. Every sentence contributes value, with no fluff or repetition.

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

Completeness4/5

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

The description covers the tool's purpose, parameters, and returned fields. However, it omits mention of pagination cursors in the return structure, which are referenced in the parameter description but not in the output summary.

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?

The input schema has 100% coverage with descriptions for all 5 parameters. The tool description adds a summary that aligns with parameters but provides no additional meaning beyond the schema definitions.

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

Purpose5/5

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

The description clearly states this tool searches court dockets by case name, free text, or docket number, with optional court scoping. It distinguishes itself from siblings like opinion_search or case_detail by focusing specifically on docket records.

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

Usage Guidelines3/5

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

The description implies usage (search dockets) but does not explicitly state when to use this tool versus siblings like citation_lookup or judge_lookup. No 'when not to use' guidance is provided.

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

judge_lookupA

Look up judges / people in CourtListener's judiciary database (type via /people/) by last and/or first name. Returns id, assembled name, birth/death dates and place, gender, and how many positions are on file. Works without a token.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax people to return (1-50, default 10).
name_lastNoLast name to match (e.g. "Ginsburg").
name_firstNoFirst name to match (e.g. "Ruth").

TDQS

A4.4/5.0
Behavior4/5

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

No annotations, but description explicitly lists return fields (id, name, dates, gender, positions count) and states no token required, providing good behavioral insight.

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

Conciseness5/5

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

Two concise sentences, front-loaded with purpose and return details, no redundant information.

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

Completeness4/5

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

For a 3-parameter look-up tool with no output schema or annotations, description provides return field info and auth requirement, but lacks error handling or pagination details.

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 covers all 3 parameters with descriptions; description adds value by detailing return fields beyond schema, helping agent understand outputs.

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

Purpose5/5

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

The description clearly states the tool looks up judges/people in CourtListener's judiciary database by name, distinguishing it from siblings that deal with cases, citations, courts, dockets, and opinions.

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

Usage Guidelines4/5

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

No explicit when-to-use or alternatives, but sibling tools are unrelated so usage is clear. Mentions it works without a token, implying ease of use.

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

oral_argumentsA

Search oral-argument audio recordings (CourtListener type=oa): case name, court, argue date, judges on the panel, duration, and an MP3 download link. Useful for hearing how an issue was actually argued. Works without a token.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYesSearch query (case name, party, or topic).
courtNoOptional court id filter (e.g. "scotus", "ca2"). Get ids from court_list.
limitNoMax results from this page (1-20, default 20).
cursorNoOpaque cursor from a previous response's next_cursor.
order_byNoSort order (default relevance; newest/oldest sort by argue date).
argued_afterNoOptional ISO date (YYYY-MM-DD); only arguments on/after.
argued_beforeNoOptional ISO date (YYYY-MM-DD); only arguments on/before.

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the behavioral burden. It clarifies the operation is a search (read-only), specifies the result fields including the MP3 download link, and discloses that no authentication token is needed. It doesn't mention pagination or rate limits, but for a read-only search tool these are minor omissions.

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

Conciseness5/5

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

Two concise sentences provide the essential information with zero filler. The primary action and resource are front-loaded, followed by a use case and the auth note, making it easy for an agent to parse.

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?

Despite having no output schema or annotations, the description covers what is searched, what is returned, the intended use case, and authentication requirements. The 100% schema coverage handles parameter details, so nothing critical is missing for an agent to invoke this tool 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 every parameter is already documented with its own description. The tool description does not add parameter-level syntax or clarification beyond restating the domain fields, so the baseline 3 is appropriate.

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

Purpose5/5

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

The description opens with a specific verb and resource ('Search oral-argument audio recordings'), names the CourtListener type (oa), and enumerates the returned fields (case name, court, argue date, judges, duration, MP3 link). This clearly differentiates it from siblings like opinion_search, which focus on written opinions, and docket_lookup.

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

Usage Guidelines4/5

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

The description gives a concrete usage scenario—'hearing how an issue was actually argued'—and notes that it works without a token. It does not explicitly name alternatives or state when not to use it, but the sibling tool list and the framing provide enough context for an agent to route correctly.

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. 4 tool updatesv1.1.0
    • Addedcase_authorities
    • Addedcited_by
    • Addeddocket_entries
    • Addedoral_arguments
  2. 6 tool updatesv1.0.0
    • First observedcase_detail
    • First observedcitation_lookup
    • First observedcourt_list
    • First observeddocket_lookup
    • First observedjudge_lookup
    • First observedopinion_search

TDQS

A4.1/5.0

Scored across 10 tools

Disambiguation4/5

Each tool targets a distinct CourtListener data type (opinions, dockets, courts, citations, judges, oral arguments), so there is little overlap in primary purpose. The only potentially confusing pair is cited_by vs case_authorities—both take an opinion id and concern citation networks—but their descriptions explicitly frame them as reverse directions.

Naming Consistency3/5

Five tools follow a clean resource_action pattern (opinion_search, docket_lookup, court_list, citation_lookup, judge_lookup), but the other five diverge into noun phrases or other forms (case_detail, cited_by, case_authorities, docket_entries, oral_arguments). The mix is readable but not consistent.

Tool Count5/5

Ten tools is right-sized for a legal research server: opinion, docket, court, citation, judge, and oral-argument functionality each have dedicated tools without redundancy. The count matches the breadth of the CourtListener API surface without feeling bloated.

Completeness4/5

Core research workflows are covered end-to-end: find opinions, retrieve full text, follow the citation graph in both directions, verify citations, search dockets, and view docket histories. Minor gaps remain—no retrieval of docket entry document content (PACER) and no citator treatment classification—but these are documented limitations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A remotely callable MCP server for US legal research that provides tools to search, retrieve, and analyze US case law from the CourtListener API, enabling agents to build evidence packs from primary sources without generating legal content.
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that provides AI assistants access to the CourtListener legal database (US court opinions, dockets, RECAP, PACER, oral arguments, judges) and the full eCFR federal regulations via the official CourtListener API v4. It supports bring-your-own-key authentication and is designed for use with MCP-compatible clients like Claude, VS Code, and Cursor.
    34
    2
    MIT