mcp-courtwatch
This server provides access to U.S. case law, court dockets, citations, and judge data via the free CourtListener API — a free alternative to services like Westlaw or PACER.
opinion_search: Full-text search of U.S. court opinions, with filters for court, date range, and sort order (relevance, newest, oldest, most cited). Returns case name, court, date, citations, snippets, and links. Supports cursor-based pagination.docket_lookup: Search court dockets by case name, free text, and/or docket number, optionally filtered by court. Returns case name, docket number, filed/terminated dates, nature of suit, and a direct link.court_list: List all CourtListener courts and their IDs, filterable by jurisdiction type (e.g.,Ffor federal,Sfor state) or name substring. Court IDs are used as filters in other tools.case_detail: Fetch full details for a case cluster (name, citations, date, judges, opinion IDs) or the full text of a specific opinion by ID. Requires an API token.citation_lookup: Verify legal citations from free text (up to 64,000 characters) against CourtListener's database. Each citation is flagged asFOUND,NOT_FOUND,UNKNOWN_REPORTER, orNOT_CHECKED_OVER_CAP— useful for catching fabricated or mis-cited authorities. Requires an API token.judge_lookup: Search for judges by first and/or last name. Returns judge ID, full name, birth/death dates and place, gender, and number of court positions on record.
Authentication: case_detail and citation_lookup require a COURTLISTENER_API_TOKEN. Other tools work without a token but benefit from higher rate limits when one is provided.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-courtwatchsearch for tenant rights opinions in California"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
|
| Full-text case-law search ( |
|
| Docket search ( |
|
| Courts and their ids ( |
|
| Full case by id. A cluster ( |
|
| Verify citations ( |
|
| Judges / people ( |
|
| Every opinion citing a given opinion, via the |
|
| The authorities an opinion relies on (its table of authorities) with a per-authority citation depth, via |
|
| 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-argument audio search ( |
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/v4Auth: 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 opaquecursor;/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/, andPOST /citation-lookup/return HTTP 401 without a token, socase_detail,citation_lookup,case_authorities, anddocket_entriesrequire one. The/docket-entries/filter parameter isdocket(notdocket_id— the API answers 400unknown_paramsotherwise; found live).Citation-lookup limits (server-side):
textmax 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:
REST API v4 overview and auth: https://www.courtlistener.com/help/api/rest/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/overview)
Search API (params,
typeenum, response fields): https://www.courtlistener.com/help/api/rest/search/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/search)Case Law API (clusters, opinions): https://www.courtlistener.com/help/api/rest/case-law/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/case-law)
Citation Lookup API: https://www.courtlistener.com/help/api/rest/citation-lookup/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/citation-lookup), plus the endpoint's source in the CourtListener repo:
cl/citations/api_views.pyandapi_serializers.py(request/response fields, per-citation status codes) andcl/settings/project/citations.py(the 250-citations-per-request cap). The endpoint returns HTTP 401 without a token.The live API itself, for the search / courts / people field names:
/search/?type=o,/search/?type=r,/courts/,/people/(all answer unauthenticated GETs).
Field map (CourtListener to normalized output)
CourtListener field | Normalized field | Where |
|
| opinion_search, docket_lookup |
|
| search hits |
|
| search hits |
|
| opinion_search |
|
| search hits |
|
| opinion_search |
|
| search hits |
|
| search hits |
|
| docket_lookup |
|
| court_list |
|
| case_detail (cluster) |
|
| case_detail (cluster) |
|
| case_detail (opinion) |
| same names | citation_lookup (per citation) |
|
| citation_lookup (per citation) |
|
| 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.jsnpm 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, soall_verified: truemeans "every recognized citation resolved" — never "nothing in this text is fake." Everycitation_lookupresponse carries acoverage_notesaying exactly this.The clusters returned by
citation_lookupdo not include the court (in CourtListener's model the court hangs off the docket, not the cluster). For the court, follow the match'sabsolute_urlor pass itscluster_idtocase_detail. Deliberately not auto-fetched: a 250-citation brief would fan out into hundreds of extra docket calls.A
docket_numberargument is sent through the fieldeddocketNumber:"..."search operator (live: 6 matches where the free-text form matched thousands). Combine withqfor case-name context when a docket number alone under-returns.court_listwith a name filter walks the full courts table one page at a time (the/courts/endpoint ignorespage_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 byjurisdictionto 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, andoral_argumentsreturn one fixed/search/page of ~20 results; for more, passnext_cursorback ascursor. The endpoint ignorespage_size, solimitcaps 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_authoritiescome backnullwithtotal_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 stdioTwo 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 -lWhat 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 toolscase_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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max authorities to return (1-50, default 50). | |
| opinion_id | Yes | Numeric OPINION id whose authorities to list. |
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. 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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Numeric cluster id (default) or opinion id. | |
| type | No | Which resource `id` refers to (default "cluster"). A cluster is the case; an opinion is one document within it. |
TDQS
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.
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.
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.
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.
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.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Free 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max results from this page (1-20, default 20). | |
| cursor | No | Opaque cursor from a previous response's next_cursor. | |
| order_by | No | Sort order (default newest). | |
| opinion_id | Yes | Numeric OPINION id (not a cluster id). case_detail on a cluster lists its sub_opinion_ids. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Optional case-insensitive substring matched against court id / full name / short name / citation string (applied to the fetched page). | |
| limit | No | Max courts to return (1-50, default 25). | |
| jurisdiction | No | Optional jurisdiction code filter (e.g. "F", "FD", "S"). |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max entries to return (1-50, default 50). | |
| cursor | No | Opaque cursor from a previous response's next_cursor. | |
| docket_id | Yes | Numeric docket id (from docket_lookup results). |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Case name or free-text query (e.g. an employer or agency name). | |
| court | No | Optional court id filter (e.g. "nysd"). Get ids from court_list. | |
| limit | No | Max 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. | |
| cursor | No | Opaque pagination cursor from a previous response's next_cursor; fetches the next page (keep the other args the same). | |
| docket_number | No | Docket number to match (e.g. "1:20-cv-03590"). |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max people to return (1-50, default 10). | |
| name_last | No | Last name to match (e.g. "Ginsburg"). | |
| name_first | No | First name to match (e.g. "Ruth"). |
TDQS
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.
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.
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.
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.
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.
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.
opinion_searchA
Full-text search of U.S. case law / court opinions (CourtListener type=o). Returns the top matching page (up to limit) with case name, court, date filed, citations, docket number, a snippet, citation count, and a link. Works without a token; set COURTLISTENER_API_TOKEN for a higher rate limit.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | Search query. Supports plain terms and phrases (e.g. "warrantless search", "qualified immunity"). | |
| court | No | Optional court id to filter to (e.g. "scotus", "ca9", "nysd"). Get ids from court_list. | |
| limit | No | Max 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. | |
| cursor | No | Opaque pagination cursor from a previous response's next_cursor; fetches the next page (keep the other args the same). | |
| order_by | No | Sort order (default relevance). | |
| filed_after | No | Optional ISO date (YYYY-MM-DD); only opinions filed on/after. | |
| filed_before | No | Optional ISO date (YYYY-MM-DD); only opinions filed on/before. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It details the return fields (case name, court, date, citations, docket number, snippet, citation count, link) and notes the token requirement for rate limits. No destructive actions or contradictions.
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 two concise sentences, front-loading the core purpose and listing key return fields. It could use slight structuring, but it is efficient and clear.
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?
Despite no output schema, the description enumerates the return fields and explains pagination and ordering. It covers essential behaviors for a 7-parameter search tool, though error handling is omitted.
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%. The description adds valuable context like example queries for 'q', pagination details for 'limit' and 'cursor', and sorting options, going beyond the schema's basic parameter descriptions.
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 explicitly states 'Full-text search of U.S. case law / court opinions' with a specific verb ('search') and resource ('opinions'), and distinguishes itself from sibling tools like case_detail and citation_lookup by focusing on open-ended text queries.
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 notes it works without a token but recommends setting COURTLISTENER_API_TOKEN for higher rate limits, offering clear context. It does not explicitly contrast with siblings, but the purpose is sufficiently distinct.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | Search query (case name, party, or topic). | |
| court | No | Optional court id filter (e.g. "scotus", "ca2"). Get ids from court_list. | |
| limit | No | Max results from this page (1-20, default 20). | |
| cursor | No | Opaque cursor from a previous response's next_cursor. | |
| order_by | No | Sort order (default relevance; newest/oldest sort by argue date). | |
| argued_after | No | Optional ISO date (YYYY-MM-DD); only arguments on/after. | |
| argued_before | No | Optional ISO date (YYYY-MM-DD); only arguments on/before. |
TDQS
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.
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.
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.
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.
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.
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.
4 tool updates
v1.1.0- Added
case_authorities - Added
cited_by - Added
docket_entries - Added
oral_arguments
6 tool updates
v1.0.0- First observed
case_detail - First observed
citation_lookup - First observed
court_list - First observed
docket_lookup - First observed
judge_lookup - First observed
opinion_search
TDQS
Scored across 10 tools
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.
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.
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.
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
Related MCP Connectors
MCP for CourtListener: US federal and state opinions, dockets, judges, plus eCFR regulations.
CourtListener MCP — Free Law Project's CourtListener API (free, no auth required for basic access)
Search US court opinions, federal dockets, judges, citations, and oral arguments via CourtListener.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP Server providing AI agents access to over 3 million US court decisions via CourtListener and EU legislation via EUR-Lex, with tools for searching cases, citations, judges, and court information.6MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server providing AI agents access to CourtListener's comprehensive legal database, featuring semantic search, hybrid search, citation verification, and research tools.7MIT
- AlicenseNot gradedqualityDmaintenanceA 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
- AlicenseAqualityDmaintenanceAn 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.342MIT