courtlistener-mcp-server
An MCP server that provides tools to search and retrieve US court opinions, federal dockets, judge records, citation networks, and oral arguments from CourtListener's corpus. It supports full-text search with field-level filtering, fetching opinion variants, tracing citation networks, resolving legal citations, searching dockets via RECAP, and looking up judges and courts.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://courtlistener.caseyjhand.com/mcpWhat its tools do
14 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.
Read-only (14)
courtlistener_search_opinionscourtlistener_get_opinioncourtlistener_get_citationscourtlistener_lookup_citationcourtlistener_search_docketscourtlistener_get_docketcourtlistener_get_partiescourtlistener_search_judgescourtlistener_get_judgecourtlistener_lookup_courtscourtlistener_search_oral_argumentscourtlistener_get_oral_argumentcourtlistener_search_financial_disclosurescourtlistener_get_financial_disclosure
Checks and signals
Each line is separate evidence, not a trust score.
- Passed Endpoint answered the live check ·
- Availability 1 of 1 checks passed in 30 days
What you can do with it
- Search US court opinions with field syntax and boolean operators
- Fetch opinion cluster metadata and variant text including concurrences and dissents
- Trace citation networks to find opinions that cite or are cited by a specific case
- Search federal dockets and retrieve extracted text from filings via RECAP
Source and maintenance
- Maintenance checked
Protocol and capabilities
- Server
- courtlistener-mcp-server 0.9.0
- MCP protocol negotiated in check
- 2025-11-25
- Tools
- 14 advertised
- Resources
- 2 advertised
- Resource templates
- 1 advertised
- Prompts
- 1 advertised
{
"tools": {
"listChanged": true
},
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"extensions": {
"io.modelcontextprotocol/skills": {
"directoryRead": true
}
}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
14 advertised
courtlistener_search_opinions — Search Court Opinions
Full-text search across 9M+ written US court opinions with field-level filtering. Returns opinion cluster summaries with case metadata, citations, matched text snippets, and the individual opinion variants filed in each case. Supports CourtListener field syntax (caseName:"roe v wade", court_id:scotus, judge:"Alito") and boolean operators (AND, OR, NOT). Use courtlistener_lookup_courts to find court IDs. CourtListener publishes free-tier limits of 5 req/min, 50/hr, 125/day; actual limits vary by token tier.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"description": "Full-text query. Supports field syntax (caseName:\"roe v wade\", court_id:scotus, judge:\"Alito\") and boolean operators (AND, OR, NOT). Use plain English for semantic-style queries or legal citations."
},
"court": {
"type": "string",
"description": "Filter to a specific court by court ID (e.g., \"scotus\", \"ca9\", \"nyed\"). Use courtlistener_lookup_courts to find court IDs."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a previous response's next_cursor field. Omit for the first page."
},
"status": {
"enum": [
"Published",
"Unpublished",
"Errata",
"Separate",
"In-chambers",
"Relating-to",
"Unknown"
],
"type": "string",
"description": "Opinion publication status. \"Published\": precedential. \"Unpublished\": not citable as precedent in most jurisdictions. \"Errata\": corrections. \"Separate\": separate opinion filed outside main cluster. \"In-chambers\": single-justice order. \"Relating-to\": companion or related-case order. Omit to use CourtListener’s Published default."
},
"order_by": {
"enum": [
"score desc",
"dateFiled desc",
"dateFiled asc",
"citeCount desc"
],
"type": "string",
"default": "score desc",
"description": "Result ordering. \"score desc\" (default) ranks by relevance. \"citeCount desc\" surfaces most-cited opinions first."
},
"page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested page size (default 20), bounded to 20 before retrieval. Upstream search has a 20-row minimum; empty and final pages can be smaller. Full upstream pages and continuation are preserved; page_sizing reports requested, bounded and actual sizes."
},
"filed_after": {
"type": "string",
"description": "Earliest filing date (ISO 8601, e.g., \"2020-01-01\"). Narrows search to opinions filed on or after this date."
},
"filed_before": {
"type": "string",
"description": "Latest filing date (ISO 8601). Narrows search to opinions filed before or on this date."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results",
"next_cursor",
"totalCount",
"effectiveQuery"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_query",
"rate_limited",
"empty_query",
"invalid_date"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_query`: CourtListener rejects caller-authored query or filter syntax with a recognized diagnostic. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `empty_query`: q is empty or whitespace-only after trimming — no request is sent. `invalid_date`: filed_after or filed_before is not a valid ISO 8601 calendar date. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Recovery hint when results are empty — echoes filters and suggests how to broaden."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"cluster_id",
"case_name",
"case_name_full",
"court",
"court_id",
"date_filed",
"docket_number",
"docket_id",
"citations",
"cite_count",
"judges",
"status",
"snippet",
"opinions"
],
"properties": {
"court": {
"type": "string",
"description": "Court display name."
},
"judges": {
"type": "string",
"description": "Judge names associated with the opinion."
},
"status": {
"type": "string",
"description": "Publication status (Published, Unpublished, etc.)."
},
"snippet": {
"type": "string",
"description": "Matched text excerpt, taken from the first entry in opinions[] that carries one; empty string when no variant has an excerpt. CourtListener does not mark which variant the search matched, so treat this as a relevance preview for the cluster, not as an excerpt attributable to a specific opinion — read opinions[] to attribute it."
},
"court_id": {
"type": "string",
"description": "Court identifier for use in subsequent filter parameters."
},
"opinions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"type",
"author_id",
"per_curiam",
"download_url",
"local_path",
"cites"
],
"properties": {
"id": {
"type": "number",
"description": "Opinion ID for this variant — identifies one opinion within the cluster (the cluster itself is cluster_id)."
},
"type": {
"type": "string",
"description": "Variant type as an expanded label (e.g. \"combined-opinion\", \"lead-opinion\", \"dissent\")."
},
"cites": {
"type": "array",
"items": {
"type": "number"
},
"description": "Opinion IDs this variant cites. These are opinion-level IDs, not cluster IDs — courtlistener_get_opinion and courtlistener_get_citations both take a cluster_id, so do not pass these values to them directly."
},
"author_id": {
"type": [
"number",
"null"
],
"description": "Person ID of the authoring judge — pass to courtlistener_get_judge; null when unattributed."
},
"local_path": {
"type": [
"string",
"null"
],
"description": "CourtListener-hosted copy of the source document (https://storage.courtlistener.com/...); null if not stored."
},
"per_curiam": {
"type": "boolean",
"description": "True when the opinion was issued per curiam (by the court)."
},
"download_url": {
"type": [
"string",
"null"
],
"description": "URL of the originating court's copy; null when none was recorded. Often plain HTTP and prone to rot — prefer local_path."
}
},
"description": "One opinion variant within the cluster.",
"additionalProperties": false
},
"description": "Opinion variants filed in this case (majority, concurrence, dissent, per curiam). Empty when upstream returned none."
},
"case_name": {
"type": "string",
"description": "Short case name (e.g., \"Roe v. Wade\")."
},
"citations": {
"type": "array",
"items": {
"type": "string"
},
"description": "Formatted citation strings (e.g., \"410 U.S. 113\")."
},
"docket_id": {
"type": "number",
"description": "Docket ID — pass to courtlistener_get_docket."
},
"cite_count": {
"type": "number",
"description": "Number of times this opinion has been cited by other opinions."
},
"cluster_id": {
"type": "number",
"description": "Opinion cluster ID — pass to courtlistener_get_opinion or courtlistener_get_citations."
},
"date_filed": {
"type": "string",
"description": "Date the opinion was filed (YYYY-MM-DD)."
},
"docket_number": {
"type": "string",
"description": "Docket number for this case."
},
"case_name_full": {
"type": "string",
"description": "Full case name with parties."
}
},
"description": "Opinion cluster summary.",
"additionalProperties": false
},
"description": "Matching opinion cluster summaries."
},
"totalCount": {
"type": "number",
"description": "Total matching opinions in the corpus."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Pagination cursor for the next page; null when no more results."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
},
"effectiveQuery": {
"type": "string",
"description": "Query terms sent to CourtListener."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_get_opinion — Get Court Opinion
Fetch text and metadata for an opinion cluster by cluster ID. Returns majority, concurrence and dissent variants with raw HTML and readable plain text, variants_completion for source coverage, and docket_enrichment. Oversized selections return outline then page responses; continue retrieval.next_cursor as cursor with the unchanged ID/sections selection until null. Oversized docket backfill has independent enrichment_retrieval coordinates; continue its next_cursor as enrichment_cursor and discard prior enrichment slices when source_id changes. Obtain cluster IDs from courtlistener_search_opinions, courtlistener_lookup_citation, or docket results.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"cluster_id"
],
"properties": {
"cursor": {
"type": "string",
"maxLength": 1024,
"description": "Retrieval next_cursor from the previous response. Repeat the original ID and sections/categories selection unchanged; omit to start."
},
"sections": {
"type": "array",
"items": {
"type": "string"
},
"description": "Opinion variant identifiers to select (e.g. [\"opinion_12345\"]). Omit for all fetched variants. Oversized selections page; keep this selection unchanged while following cursor."
},
"cluster_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Opinion cluster ID — identifies a case decision and groups all opinion variants (majority, concurrence, dissent). Obtain from courtlistener_search_opinions, courtlistener_lookup_citation, or from docket results that link to opinions."
},
"enrichment_cursor": {
"type": "string",
"maxLength": 1024,
"description": "Continue enrichment_retrieval.next_cursor independently of primary cursor. A changed docket summary restarts only enrichment slices."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"cluster_id",
"docket_id",
"cite_count",
"kind"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"kind": {
"enum": [
"full",
"outline",
"page"
],
"type": "string",
"description": "'full' carries a small selected record; 'outline' pages the section catalog; 'page' carries typed rows and field-path text chunks. Bounded identity remains present throughout retrieval."
},
"court": {
"type": "string",
"description": "Court display name."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_cursor",
"stale_cursor",
"not_found",
"rate_limited",
"unknown_section"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_cursor`: Retrieval cursor is malformed, out of range or belongs to another request. `stale_cursor`: The normalized selected source changed since the previous page. `not_found`: Cluster ID does not exist in CourtListener. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `unknown_section`: A requested sections name matches no opinion variant in this cluster. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"judges": {
"type": "string",
"description": "Judge names."
},
"posture": {
"type": "string",
"description": "Procedural posture (may be empty)."
},
"court_id": {
"type": "string",
"description": "Court identifier."
},
"opinions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"author_id",
"per_curiam"
],
"properties": {
"id": {
"type": "number",
"description": "Individual opinion ID."
},
"type": {
"type": "string",
"description": "Raw CourtListener opinion-type code (e.g. \"030concurrence\"); the numeric prefix is a sort key, not part of the type. Empty when upstream recorded none."
},
"cites": {
"type": "array",
"items": {
"type": "number"
},
"description": "Opinion IDs this opinion cites."
},
"author_id": {
"type": [
"number",
"null"
],
"description": "Person ID of the author; null if per curiam or unknown."
},
"html_text": {
"type": "string",
"description": "Full opinion text as HTML, drawn from the best available variant (citation-linked when present); empty only when no HTML text is stored — use download_url then."
},
"per_curiam": {
"type": "boolean",
"description": "True if this is a per curiam opinion."
},
"plain_text": {
"type": "string",
"description": "Supplied plain text preserved exactly, or readable text derived from source markup when absent; empty if neither exists."
},
"type_label": {
"type": "string",
"description": "Opinion type expanded to the label courtlistener_search_opinions serves for the same variant: \"lead-opinion\", \"concurrence-opinion\", \"dissent\", \"combined-opinion\", etc. An unmapped code passes through as the code itself."
},
"download_url": {
"type": [
"string",
"null"
],
"description": "Direct download URL for the original opinion document; null if not available."
}
},
"description": "Individual opinion variant; omitted partial fields are recoverable through retrieval.",
"additionalProperties": false
},
"description": "Fetched variants; variants_completion describes source coverage. Pages can contain partial typed variants; omitted text is recoverable through retrieval.text_chunks at original field paths."
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"bytes"
],
"properties": {
"name": {
"type": "string",
"description": "Section identifier — pass in `sections` to retrieve it"
},
"bytes": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Serialized byte size of the section"
}
},
"description": "A retrievable opinion variant (opinion_<id>) and its serialized byte size.",
"additionalProperties": false
},
"description": "Section catalog in source order, including paged metadata. Only opinion_<id> names select variants; follow retrieval.next_cursor to finish the catalog and retrieve data."
},
"syllabus": {
"type": "string",
"description": "Syllabus text (may be empty)."
},
"case_name": {
"type": "string",
"description": "Short case name."
},
"citations": {
"type": "array",
"items": {
"type": "string"
},
"description": "All known citation strings for this case."
},
"docket_id": {
"type": "number",
"description": "Associated docket ID."
},
"retrieval": {
"type": "object",
"required": [
"next_cursor",
"ranges",
"text_chunks"
],
"properties": {
"ranges": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"unit",
"start",
"end",
"total"
],
"properties": {
"end": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Exclusive absolute end."
},
"path": {
"type": "string",
"description": "JSON Pointer into the normalized unsliced selected view."
},
"unit": {
"enum": [
"rows",
"code_points",
"sections"
],
"type": "string",
"description": "Coordinate unit."
},
"start": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Inclusive absolute start."
},
"total": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Length of the complete normalized collection or text field."
}
},
"description": "Source range.",
"additionalProperties": false
},
"description": "Absolute source coordinates; merge typed rows by index rather than appending duplicates."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Continue with cursor and the same ID/selection; null when this fetched view is exhausted."
},
"text_chunks": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"text"
],
"properties": {
"path": {
"type": "string",
"description": "JSON Pointer of the original string field or string-array element."
},
"text": {
"type": "string",
"description": "Unescaped normalized substring, matching its code_points range."
}
},
"description": "Readable string slice.",
"additionalProperties": false
},
"description": "Text omitted from partial rows/metadata, recoverable exactly using the matching ranges."
}
},
"description": "Caller retrieval completion, separate from upstream source completion.",
"additionalProperties": false
},
"cite_count": {
"type": "number",
"description": "Total number of citations from other opinions."
},
"cluster_id": {
"type": "number",
"description": "Opinion cluster ID."
},
"date_filed": {
"type": "string",
"description": "Date the opinion was filed."
},
"docket_number": {
"type": "string",
"description": "Docket number."
},
"case_name_full": {
"type": "string",
"description": "Full case name with parties."
},
"retrieval_notice": {
"type": "string",
"description": "How to continue bounded retrieval using the unchanged ID and selection."
},
"docket_enrichment": {
"type": "object",
"required": [
"status"
],
"properties": {
"reason": {
"enum": [
"not_found",
"lookup_failed"
],
"type": "string",
"description": "Safe lookup failure category, without upstream error text."
},
"status": {
"enum": [
"not_linked",
"resolved",
"source_fields_absent",
"lookup_failed"
],
"type": "string",
"description": "Outcome of the optional linked-docket lookup."
},
"error_code": {
"type": "number",
"description": "Sanitized MCP error code when the lookup failed."
}
},
"description": "Linked-docket enrichment outcome, independent of opinion text availability.",
"additionalProperties": false
},
"precedential_status": {
"type": "string",
"description": "Publication/precedential status."
},
"variants_completion": {
"type": "object",
"required": [
"complete"
],
"properties": {
"complete": {
"type": "boolean",
"description": "True only when all source variants were fetched."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Remaining upstream variant cursor; null at the end."
}
},
"description": "Source-walk completion. An oversized upstream next_cursor is omitted on partial responses and recovered at /variants_completion/next_cursor through retrieval.text_chunks.",
"additionalProperties": false
},
"enrichment_retrieval": {
"type": "object",
"required": [
"next_cursor",
"ranges",
"text_chunks",
"source_id"
],
"properties": {
"ranges": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"unit",
"start",
"end",
"total"
],
"properties": {
"end": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Exclusive absolute end."
},
"path": {
"type": "string",
"description": "JSON Pointer into the normalized unsliced selected view."
},
"unit": {
"enum": [
"rows",
"code_points",
"sections"
],
"type": "string",
"description": "Coordinate unit."
},
"start": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Inclusive absolute start."
},
"total": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Length of the complete normalized collection or text field."
}
},
"description": "Source range.",
"additionalProperties": false
},
"description": "Absolute source coordinates; merge typed rows by index rather than appending duplicates."
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"bytes"
],
"properties": {
"name": {
"type": "string",
"description": "Section identifier — pass in `sections` to retrieve it"
},
"bytes": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Serialized byte size of the section"
}
},
"description": "Enrichment metadata field descriptor.",
"additionalProperties": false
},
"description": "Current enrichment field catalog when this response pages its descriptors."
},
"source_id": {
"type": "string",
"description": "Identity of the current docket backfill; discard previously collected enrichment slices when this changes."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Continue with cursor and the same ID/selection; null when this fetched view is exhausted."
},
"text_chunks": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"text"
],
"properties": {
"path": {
"type": "string",
"description": "JSON Pointer of the original string field or string-array element."
},
"text": {
"type": "string",
"description": "Unescaped normalized substring, matching its code_points range."
}
},
"description": "Readable string slice.",
"additionalProperties": false
},
"description": "Text omitted from partial rows/metadata, recoverable exactly using the matching ranges."
}
},
"description": "Independent coordinates for oversized docket backfill fields. Paths refer to top-level fields, independently of primary retrieval ranges. Continue with enrichment_cursor; changed enrichment restarts at its own outline.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}courtlistener_get_citations — Get Citation Network
Retrieve the citation network for an opinion cluster. Supports two directions: "cited_by" (opinions that cite this one — measures precedential influence) and "citing" (opinions this one cites — reveals the authority chain relied on). This is the primary tool for tracing legal precedent chains. Note: the free tier supports shallow traversal — following 1–2 hops of a single case is practical; deep multi-hop analysis burns through the daily budget quickly.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"cluster_id"
],
"properties": {
"court": {
"type": "string",
"description": "Filter results to a specific court (e.g., \"scotus\", \"ca9\"). Applies to both directions."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from next_cursor. For citing, a nonnegative safe decimal integer offset; for cited_by, an opaque upstream token."
},
"direction": {
"enum": [
"citing",
"cited_by"
],
"type": "string",
"default": "cited_by",
"description": "\"cited_by\" (default): opinions that cite this one — measures precedential influence and downstream adoption. \"citing\": opinions this one cites — reveals the authority chain the court relied on."
},
"page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested size (default 20), bounded to 20. cited_by has an upstream minimum of 20; citing slices at most 20 cited IDs by the bounded size before filtering. Full upstream pages are preserved. Final or filtered pages can be smaller or empty; retain next_cursor to continue. page_sizing distinguishes requested, bounded and actual sizes. A normal call costs three requests plus extra variant pages."
},
"cluster_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Opinion cluster ID to retrieve citations for. Obtain from courtlistener_search_opinions or courtlistener_lookup_citation."
},
"filed_after": {
"type": "string",
"description": "Limit to citations filed after this date (ISO 8601). For \"cited_by\", useful for \"how has this precedent been applied recently?\""
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"source_cluster_id",
"source_case_name",
"direction",
"results",
"next_cursor"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_cursor",
"not_found",
"rate_limited",
"invalid_date"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_cursor`: A citing cursor is not a nonnegative safe decimal integer offset. `not_found`: Cluster ID does not exist in CourtListener. Both directions resolve the source cluster before searching, so a bad ID fails here rather than returning an empty network. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `invalid_date`: filed_after is not a valid ISO 8601 calendar date. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Context when no citations are returned — either that this page had no match under the filters and more pages remain, or a recovery hint echoing direction and filters."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"cluster_id",
"case_name",
"court",
"court_id",
"date_filed",
"citations",
"cite_count",
"snippet"
],
"properties": {
"court": {
"type": "string",
"description": "Court that issued the related opinion."
},
"snippet": {
"type": "string",
"description": "Matched text excerpt from the related opinion, taken from the first opinion variant in the cluster that carries one; empty string when none does. It is a relevance preview for the cluster, not necessarily text surrounding the citation itself."
},
"court_id": {
"type": "string",
"description": "Court identifier for use in filter parameters."
},
"case_name": {
"type": "string",
"description": "Case name of the related opinion."
},
"citations": {
"type": "array",
"items": {
"type": "string"
},
"description": "Citation strings for the related opinion."
},
"cite_count": {
"type": "number",
"description": "This opinion's own citation count — its authority weight."
},
"cluster_id": {
"type": "number",
"description": "Cluster ID of the related opinion."
},
"date_filed": {
"type": "string",
"description": "Date the related opinion was filed."
}
},
"description": "Related opinion in the citation network.",
"additionalProperties": false
},
"description": "Related opinions in the citation network."
},
"direction": {
"enum": [
"citing",
"cited_by"
],
"type": "string",
"description": "Direction of the citation relationship returned."
},
"totalCount": {
"type": "number",
"description": "Exact total for the fetched direction when source variants are complete; absent when total_is_partial is true. For cited_by this counts matching clusters after filters; for citing it counts distinct cited opinions before any filter, which can exceed the cluster rows."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Pagination cursor for the next page; null when no more results."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
},
"observed_total": {
"type": "number",
"description": "Citation total observed from the fetched source variants; a lower bound when total_is_partial is true."
},
"source_case_name": {
"type": "string",
"description": "Case name for the source cluster."
},
"total_is_partial": {
"type": "boolean",
"description": "True when citation results and totals are based on an incomplete source-variant set."
},
"source_cluster_id": {
"type": "number",
"description": "The cluster ID this citation network is for."
},
"source_variants_completion": {
"type": "object",
"required": [
"complete",
"next_cursor"
],
"properties": {
"complete": {
"type": "boolean",
"description": "True only when all source variants were fetched."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Remaining upstream variant cursor; null at the end."
}
},
"description": "Completion of the source opinion-variant walk.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_lookup_citation — Lookup Legal Citation
Resolve legal citations (e.g., "410 U.S. 113", "93 S. Ct. 705") to opinion cluster IDs and case metadata. Enables workflows that start from a known citation rather than a search query. CourtListener extracts every citation it finds in the submitted text, so passing a passage returns one entry per citation, each with its own resolution status — an unresolved or ambiguous citation is reported in the results, not raised as an error. Supports standard US reporter formats. Costs one request against CourtListener's per-citation quota, plus one ordinary request per distinct docket whose court is resolved — max_court_lookups bounds that second half (default 4, set 0 to skip court resolution entirely). CourtListener meters this endpoint by citations submitted rather than by call, so a long passage spends proportionally more of that quota. Requires authentication — uses the CourtListener /citation-lookup/ endpoint.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"citation"
],
"properties": {
"citation": {
"type": "string",
"description": "Text to extract citations from — normally a single citation (e.g., \"410 U.S. 113\", \"347 U.S. 483\", \"93 S. Ct. 705\"), but any passage works and every citation in it is resolved. Supports standard reporter formats. Up to 64000 characters, which is CourtListener's own ceiling; a longer passage is rejected here rather than spending a request to be refused upstream."
},
"max_court_lookups": {
"type": "integer",
"default": 4,
"maximum": 20,
"minimum": 0,
"description": "How many distinct dockets this call may spend a request on to resolve cluster courts. The lookup itself is metered separately by CourtListener (per citation submitted), so this budget is drawn entirely from the ordinary per-request allowance — published free tier 5/min, 50/hour, 125/day, varying by token tier. 0 skips court resolution and costs nothing beyond the lookup; 20 is the ceiling. Clusters past the budget come back with court null and court_resolution \"over_budget\"."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"matches",
"queriedCitation"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"rate_limited",
"empty_citation",
"citation_too_long"
],
"description": "Machine-readable failure mode. Declared by this tool: `not_found`: CourtListener could not parse any citation out of the submitted text. A citation that parses but matches nothing is a result with status 404, not this error. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `empty_citation`: citation is empty or whitespace-only after trimming — no request is sent. `citation_too_long`: citation exceeds the 64000-character ceiling CourtListener accepts — no request is sent. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Caveats on this result: a recovery hint when no citation in the input resolved to a case, and counts of the clusters whose court went unresolved — split by whether the per-call docket budget ran out or an attempted lookup returned nothing, since only the first is worth retrying with a larger budget. Absent when none applies."
},
"matches": {
"type": "array",
"items": {
"type": "object",
"required": [
"citation",
"normalized_citation",
"status",
"status_label",
"error_message",
"clusters"
],
"properties": {
"status": {
"type": "number",
"description": "Resolution status for this citation alone: 200 one case, 300 several candidates, 400 unrecognized reporter, 404 no case found, 429 past the per-request citation cap. Not the status of the request, which succeeded."
},
"citation": {
"type": "string",
"description": "The citation as CourtListener matched it in the submitted text."
},
"clusters": {
"type": "array",
"items": {
"type": "object",
"required": [
"cluster_id",
"case_name",
"court",
"court_id",
"court_resolution",
"date_filed",
"docket_id",
"citations",
"cite_count",
"precedential_status",
"judges"
],
"properties": {
"court": {
"type": [
"string",
"null"
],
"description": "Court display name. The citation-lookup payload carries no court, so this is resolved from the cluster's docket — one extra request each, capped by max_court_lookups (default 4 distinct dockets per call). Null when that lookup was skipped past the budget, failed, or the cluster has no docket_id; court_resolution says which. Pass docket_id to courtlistener_get_docket, or cluster_id to courtlistener_get_opinion, to resolve one."
},
"judges": {
"type": [
"string",
"null"
],
"description": "Free-text judge names; null or empty if not recorded."
},
"court_id": {
"type": [
"string",
"null"
],
"description": "Court identifier for the `court` filter on the search tools (e.g. \"scotus\"); null under the same conditions as `court`."
},
"case_name": {
"type": [
"string",
"null"
],
"description": "Case name; null if not recorded."
},
"citations": {
"type": "array",
"items": {
"type": "string"
},
"description": "All known citation strings for this case."
},
"docket_id": {
"type": [
"number",
"null"
],
"description": "Linked docket — pass to courtlistener_get_docket. Null if not recorded."
},
"cite_count": {
"type": [
"number",
"null"
],
"description": "Times other opinions cite this case — a rough authority weight. Null if not recorded."
},
"cluster_id": {
"type": [
"number",
"null"
],
"description": "Opinion cluster ID — pass to courtlistener_get_opinion. Null when upstream sent no ID."
},
"date_filed": {
"type": [
"string",
"null"
],
"description": "Date the opinion was filed; null if not recorded."
},
"court_resolution": {
"enum": [
"resolved",
"no_docket",
"lookup_failed",
"over_budget"
],
"type": "string",
"description": "Why court/court_id are or are not populated: \"resolved\" the docket lookup returned a court; \"no_docket\" the cluster carries no docket_id, so nothing can be resolved; \"lookup_failed\" a request was spent on the docket and it yielded no court; \"over_budget\" no request was spent because max_court_lookups ran out or the walk stopped on a rate limit — raise max_court_lookups or fetch that docket directly."
},
"precedential_status": {
"type": [
"string",
"null"
],
"description": "Publication status (e.g. \"Published\", \"Unpublished\"); null if not recorded."
}
},
"description": "An opinion cluster this citation resolved to.",
"additionalProperties": false
},
"description": "Cases this citation resolved to — empty when status is not 200 or 300, and more than one when status is 300."
},
"status_label": {
"type": "string",
"description": "status decoded to a label."
},
"error_message": {
"type": "string",
"description": "CourtListener's explanation when status is not 200; empty string otherwise."
},
"normalized_citation": {
"type": [
"string",
"null"
],
"description": "Canonical citation form used by CourtListener; null if not resolved."
}
},
"description": "One citation found in the submitted text and everything it resolved to.",
"additionalProperties": false
},
"description": "One entry per citation CourtListener extracted from the input, in the order they appear."
},
"queriedCitation": {
"type": "string",
"description": "The citation string that was looked up."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}courtlistener_search_dockets — Search Federal Court Dockets
Search RECAP federal court dockets. Query terms match case name, docket number, party, and attorney names; filters narrow by party name, court, and filing date. RECAP is a crowd-sourced mirror of PACER (the federal court filing system) — coverage varies by court and date. Returns docket metadata with the parties, attorneys, and firms of record, plus up to 3 sample document entries per docket. Use courtlistener_lookup_courts to find court IDs.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"description": "Query terms matched against case name, docket number, party names, and attorney names. Example: \"Apple Inc patent infringement\"."
},
"court": {
"type": "string",
"description": "Filter to a specific federal court ID (e.g., \"dnd\", \"cacd\", \"deb\" for Delaware Bankruptcy). Use courtlistener_lookup_courts to find court IDs."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a previous response's next_cursor field."
},
"page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested page size (default 20), bounded to 20. Upstream search has a 20-row minimum; empty and final pages can be smaller. Full pages and continuation are preserved; page_sizing reports actual sizes."
},
"party_name": {
"type": "string",
"description": "Filter to dockets listing a specific party by name — applied in addition to (AND with) the q query. More precise than including party names in q when the party name is known."
},
"filed_after": {
"type": "string",
"description": "Earliest case filing date (ISO 8601)."
},
"filed_before": {
"type": "string",
"description": "Latest case filing date (ISO 8601)."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results",
"next_cursor",
"coverage_note",
"totalCount"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_query",
"rate_limited",
"empty_query",
"invalid_date"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_query`: CourtListener rejects caller-authored query or filter syntax with a recognized diagnostic. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `empty_query`: q is empty or whitespace-only after trimming — no request is sent. `invalid_date`: filed_after or filed_before is not a valid ISO 8601 calendar date. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Recovery hint when results are empty — echoes filters and suggests how to broaden."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"docket_id",
"case_name",
"case_name_full",
"court",
"court_id",
"date_filed",
"date_terminated",
"docket_number",
"pacer_case_id",
"assigned_to",
"referred_to",
"cause",
"jury_demand",
"suit_nature",
"jurisdiction_type",
"parties",
"attorneys",
"firms",
"sample_documents"
],
"properties": {
"cause": {
"type": "string",
"description": "Legal cause of action."
},
"court": {
"type": "string",
"description": "Court display name."
},
"firms": {
"type": "array",
"items": {
"type": "string"
},
"description": "Law firm names of record on this docket; empty when none are recorded."
},
"parties": {
"type": "array",
"items": {
"type": "string"
},
"description": "Party names listed in this docket."
},
"court_id": {
"type": "string",
"description": "Court identifier."
},
"attorneys": {
"type": "array",
"items": {
"type": "string"
},
"description": "Attorney names of record on this docket; empty when none are recorded."
},
"case_name": {
"type": "string",
"description": "Case name."
},
"docket_id": {
"type": "number",
"description": "Docket ID — pass to courtlistener_get_docket for full entry list."
},
"date_filed": {
"type": "string",
"description": "Date the case was filed."
},
"assigned_to": {
"type": [
"string",
"null"
],
"description": "Assigned judge name; null if not recorded."
},
"jury_demand": {
"type": "string",
"description": "Jury demand status."
},
"referred_to": {
"type": [
"string",
"null"
],
"description": "Referred magistrate judge name; null if not recorded."
},
"suit_nature": {
"type": "string",
"description": "Nature-of-suit label, usually prefixed with its PACER code (e.g. \"830 Patent\"); empty string when not recorded."
},
"docket_number": {
"type": "string",
"description": "Docket number."
},
"pacer_case_id": {
"type": [
"string",
"null"
],
"description": "PACER case ID; null if not available in RECAP."
},
"case_name_full": {
"type": "string",
"description": "Full case name with all parties; empty string when not recorded."
},
"date_terminated": {
"type": [
"string",
"null"
],
"description": "Date the case was terminated; null if still active."
},
"sample_documents": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"description",
"date_filed",
"document_number",
"entry_number",
"document_type",
"page_count",
"filepath_local",
"is_available"
],
"properties": {
"id": {
"type": "number",
"description": "Document ID."
},
"date_filed": {
"type": "string",
"description": "Date the parent docket entry was filed; empty string when not recorded."
},
"page_count": {
"type": [
"number",
"null"
],
"description": "Page count; null if not recorded."
},
"description": {
"type": "string",
"description": "Document description or title."
},
"entry_number": {
"type": [
"number",
"null"
],
"description": "Docket entry number this document belongs to; null if unnumbered."
},
"is_available": {
"type": "boolean",
"description": "True if the document is available via RECAP without a PACER account."
},
"document_type": {
"type": "string",
"description": "Document classification (e.g. \"PACER Document\", \"RECAP Document\"); empty string when not recorded."
},
"filepath_local": {
"type": [
"string",
"null"
],
"description": "Fully-qualified RECAP storage URL (https://storage.courtlistener.com/...) for the document; null when no copy is stored."
},
"document_number": {
"type": [
"number",
"null"
],
"description": "PACER document number; null if not assigned."
}
},
"description": "Sample document entry.",
"additionalProperties": false
},
"description": "Up to 3 sample filings matched on this docket — a search excerpt, not the docket's full filing list. Call courtlistener_get_docket for every entry."
},
"jurisdiction_type": {
"type": "string",
"description": "Basis of federal jurisdiction (e.g. \"Federal Question\"); empty string when not recorded."
}
},
"description": "Docket search result.",
"additionalProperties": false
},
"description": "Matching docket records."
},
"totalCount": {
"type": "number",
"description": "Total matching dockets."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Pagination cursor for the next page; null when no more results."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
},
"coverage_note": {
"type": "string",
"description": "Note about RECAP coverage limitations."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_get_docket — Get Docket
Fetch docket metadata and one entries page by docket ID. Omit document_ids for the docket listing, or select RECAP document IDs embedded on entries_page to retrieve their extracted text without further upstream requests. Selected text uses bounded full/outline/page responses; continue retrieval.next_cursor as cursor with the same docket_id, entries_page and document_ids. Top-level next_cursor remains entries pagination. File availability and extracted-text status are independent. Obtain docket IDs from courtlistener_search_dockets or opinion results.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"docket_id"
],
"properties": {
"cursor": {
"type": "string",
"maxLength": 1024,
"description": "Retrieval next_cursor from the previous response. Repeat the original ID and sections/categories selection unchanged; omit to start."
},
"docket_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Docket ID from a search result's docket_id field or from an opinion cluster result."
},
"document_ids": {
"type": "array",
"items": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"minItems": 1,
"description": "Select RECAP document IDs embedded on entries_page. No other pages or document endpoints are fetched; omit for the unchanged docket listing."
},
"entries_page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Page of docket entries to fetch (1-indexed). Docket entries are page-paginated at 20 per page; pass the next_cursor from a previous response here to page through large cases."
},
"entries_page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Requested docket entries per page. NOTE: CourtListener ignores this value — /docket-entries/ always returns a fixed 20-entry page regardless of what is passed. Use entries_page to reach entries beyond the first 20 (large cases can have hundreds)."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"docket_id",
"entries_page",
"next_cursor"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"kind": {
"enum": [
"full",
"outline",
"page"
],
"type": "string",
"description": "Bounded selected-document retrieval mode."
},
"cause": {
"type": "string",
"description": "Legal cause of action."
},
"court": {
"type": "string",
"description": "Court display name for major federal courts; the court identifier otherwise."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"document_not_on_page",
"document_ownership_unverified",
"selection_required",
"invalid_cursor",
"stale_cursor",
"not_found",
"rate_limited"
],
"description": "Machine-readable failure mode. Declared by this tool: `document_not_on_page`: A selected document ID is absent from the requested entries page. `document_ownership_unverified`: The selected document entry has no explicit matching docket relation. `selection_required`: A text retrieval cursor is supplied without document_ids. `invalid_cursor`: A cursor is malformed, out of range or bound to another page or selection. `stale_cursor`: Selected source records changed since retrieval began. `not_found`: Docket ID does not exist in CourtListener. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"entries": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"entry_number",
"date_filed",
"description",
"documents"
],
"properties": {
"id": {
"type": "number",
"description": "Docket entry ID."
},
"documents": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"document_number",
"attachment_number",
"description",
"is_available",
"page_count",
"filepath_local"
],
"properties": {
"id": {
"type": "number",
"description": "Document ID."
},
"page_count": {
"type": [
"number",
"null"
],
"description": "Page count; null if not recorded."
},
"description": {
"type": "string",
"description": "Document description."
},
"is_available": {
"type": "boolean",
"description": "True if the document is available via RECAP without a PACER account."
},
"filepath_local": {
"type": [
"string",
"null"
],
"description": "Fully-qualified RECAP storage URL (https://storage.courtlistener.com/...) for the document; null if not available."
},
"document_number": {
"type": [
"string",
"null"
],
"description": "PACER document number as a string (e.g. \"1\"); attachments can be non-integer like \"70-1\". Null if not assigned."
},
"attachment_number": {
"type": [
"number",
"null"
],
"description": "Attachment number; null for the main document."
}
},
"description": "Document attached to a docket entry.",
"additionalProperties": false
},
"description": "Documents attached to this docket entry."
},
"date_filed": {
"type": "string",
"description": "Date this entry was filed."
},
"description": {
"type": "string",
"description": "Entry description or filing type."
},
"entry_number": {
"type": [
"number",
"null"
],
"description": "PACER entry number; null if not assigned."
}
},
"description": "Docket entry with attached documents.",
"additionalProperties": false
},
"description": "Docket entries for this page (fixed at 20 per page; entries_page_size is not honored by upstream)."
},
"court_id": {
"type": "string",
"description": "Court identifier — the stable value for filtering."
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"bytes"
],
"properties": {
"name": {
"type": "string",
"description": "Deferred field group."
},
"bytes": {
"type": "number",
"description": "Serialized source bytes."
}
},
"description": "Deferred field group and source size.",
"additionalProperties": false
},
"description": "Deferred selected-document groups."
},
"case_name": {
"type": "string",
"description": "Short case name."
},
"docket_id": {
"type": "number",
"description": "Requested docket ID."
},
"retrieval": {
"type": "object",
"required": [
"next_cursor",
"ranges",
"text_chunks"
],
"properties": {
"ranges": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"unit",
"start",
"end",
"total"
],
"properties": {
"end": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Exclusive absolute end."
},
"path": {
"type": "string",
"description": "JSON Pointer into the normalized unsliced selected view."
},
"unit": {
"enum": [
"rows",
"code_points",
"sections"
],
"type": "string",
"description": "Coordinate unit."
},
"start": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Inclusive absolute start."
},
"total": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Length of the complete normalized collection or text field."
}
},
"description": "Source range.",
"additionalProperties": false
},
"description": "Absolute source coordinates; merge typed rows by index rather than appending duplicates."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Continue with cursor and the same ID/selection; null when this fetched view is exhausted."
},
"text_chunks": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"text"
],
"properties": {
"path": {
"type": "string",
"description": "JSON Pointer of the original string field or string-array element."
},
"text": {
"type": "string",
"description": "Unescaped normalized substring, matching its code_points range."
}
},
"description": "Readable string slice.",
"additionalProperties": false
},
"description": "Text omitted from partial rows/metadata, recoverable exactly using the matching ranges."
}
},
"description": "Caller retrieval completion, separate from upstream source completion.",
"additionalProperties": false
},
"date_filed": {
"type": "string",
"description": "Date the case was filed."
},
"assigned_to": {
"type": [
"string",
"null"
],
"description": "Assigned judge name; null if not recorded."
},
"jury_demand": {
"type": "string",
"description": "Jury demand status."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Next entries page; independent of retrieval.next_cursor."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
},
"referred_to": {
"type": [
"string",
"null"
],
"description": "Referred judge name; null if not recorded."
},
"document_ids": {
"type": "array",
"items": {
"type": "number"
},
"description": "Normalized selected document IDs; deferred oversized selections are recovered through retrieval ranges."
},
"entries_page": {
"type": "number",
"description": "Entries page containing the selected documents."
},
"docket_number": {
"type": "string",
"description": "Docket number."
},
"pacer_case_id": {
"type": [
"string",
"null"
],
"description": "PACER case ID; null if not in RECAP."
},
"total_entries": {
"type": [
"number",
"null"
],
"description": "Total number of docket entries available; null when upstream supplies no numeric total. May exceed the returned entries list."
},
"case_name_full": {
"type": "string",
"description": "Full case name."
},
"date_terminated": {
"type": [
"string",
"null"
],
"description": "Date the case was terminated; null if active."
},
"retrieval_notice": {
"type": "string",
"description": "Instructions for reconstructing selected source records."
},
"jurisdiction_type": {
"type": "string",
"description": "Jurisdiction type."
},
"selected_documents": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "RECAP document ID."
},
"entry_id": {
"type": "number",
"description": "Owning entry ID, verified against the requested docket."
},
"page_count": {
"type": [
"number",
"null"
],
"description": "Source page count, or null."
},
"plain_text": {
"type": [
"string",
"null"
],
"description": "Unmodified extracted source text; omitted if absent upstream or deferred to retrieval.text_chunks."
},
"source_url": {
"type": [
"string",
"null"
],
"description": "CourtListener document source link, or null."
},
"description": {
"type": "string",
"description": "Source document description."
},
"text_status": {
"enum": [
"available",
"unavailable",
"not_extracted",
"unknown"
],
"type": "string",
"description": "Text availability independently of source file availability."
},
"is_available": {
"type": [
"boolean",
"null"
],
"description": "Source file availability; null means unknown."
},
"filepath_local": {
"type": [
"string",
"null"
],
"description": "RECAP storage URL, or null."
},
"document_number": {
"type": [
"string",
"null"
],
"description": "PACER document number."
},
"attachment_number": {
"type": [
"number",
"null"
],
"description": "Attachment number, or null."
}
},
"description": "Selected document or a recoverable partial record.",
"additionalProperties": false
},
"description": "Selected source records; partial fields are recovered by retrieval ranges and text_chunks."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}courtlistener_get_parties — Get Parties
Fetch a page of parties and their attorneys of record for a RECAP federal docket by docket ID. Returns each party's name, role (Plaintiff, Defendant, Petitioner, Respondent, etc.), and their attorneys with contact information, scoped to this docket. Costs one party request plus up to five attorney roster requests. A later roster page blocked by the local request budget returns fetched detail with capped resolution, unresolved IDs, and the remaining roster cursor. Obtain docket IDs from courtlistener_search_dockets or courtlistener_get_docket.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"docket_id"
],
"properties": {
"cursor": {
"type": "string",
"description": "Pagination cursor from a previous response's next_cursor field. Omit for the first page. This is an opaque token, not a page number — CourtListener cursor-paginates this endpoint, so a numeric value selects nothing and re-serves the first page."
},
"docket_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Docket ID from a courtlistener_search_dockets or courtlistener_get_docket result's docket_id field."
},
"page_size": {
"type": "integer",
"default": 10,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested party page size (default 10), bounded to 10 before retrieval. CourtListener uses fixed 20-row pages and ignores this request; final pages can be smaller. page_sizing reports requested, bounded and actual sizes."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"docket_id",
"total_parties",
"next_cursor",
"parties"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"rate_limited"
],
"description": "Machine-readable failure mode. Declared by this tool: `not_found`: Docket ID does not exist in CourtListener or has no RECAP party data. `rate_limited`: 429 from CourtListener, or no request slot opened before any attorney roster page completed. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"parties": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name",
"role",
"extra_info",
"attorneys"
],
"properties": {
"id": {
"type": "number",
"description": "Party record ID."
},
"name": {
"type": "string",
"description": "Party display name (e.g., \"Jane Doe\", \"Acme Corporation\")."
},
"role": {
"type": [
"string",
"null"
],
"description": "Role on this docket (e.g., \"Plaintiff\", \"Defendant\", \"Petitioner\", \"Respondent\"); null if not recorded."
},
"attorneys": {
"type": "array",
"items": {
"type": "object",
"required": [
"attorney_id",
"name",
"contact_raw",
"role_code",
"role",
"date_action"
],
"properties": {
"name": {
"type": "string",
"description": "Attorney display name. Empty string when attorney detail is unavailable."
},
"role": {
"type": "string",
"description": "role_code decoded to a label (e.g., \"Lead attorney\"). Codes 5–9 (\"Self-terminated\" through \"Disbarred\") mean the attorney is no longer of record. The stringified code when upstream sends a value outside the documented enum, \"Unrecorded\" when it sends none."
},
"role_code": {
"type": [
"number",
"null"
],
"description": "Numeric attorney role code from the party–attorney relationship (1 = Attorney to be noticed, 2 = Lead attorney, 3 = Attorney in sealed group, 4 = Pro hac vice, 5 = Self-terminated, 6 = Terminated, 7 = Suspended, 8 = Inactive, 9 = Disbarred, 10 = Unknown); null when upstream recorded no code."
},
"resolution": {
"enum": [
"resolved",
"not_found",
"not_fetched"
],
"type": "string",
"description": "Whether detail was resolved (possibly with empty source fields), absent from an exhausted roster, or unknown after the cap."
},
"attorney_id": {
"type": "number",
"description": "Attorney record ID."
},
"contact_raw": {
"type": "string",
"description": "Raw address/phone block from the attorney record. Empty string when unavailable."
},
"date_action": {
"type": [
"string",
"null"
],
"description": "Date the attorney–party relationship ended; null while the attorney is still of record."
}
},
"description": "Attorney of record for this party.",
"additionalProperties": false
},
"description": "Attorneys of record for this party on this docket."
},
"extra_info": {
"type": "string",
"description": "Additional metadata from upstream (e.g., pro se status, date range)."
}
},
"description": "A party and their attorneys for this docket.",
"additionalProperties": false
},
"description": "Parties on this page."
},
"docket_id": {
"type": "number",
"description": "Docket ID these parties belong to."
},
"totalCount": {
"type": "number",
"description": "Total parties on this docket across all pages — this endpoint reports its count as a URL rather than a number, so the total is only derivable when the first page is also the last, and is absent for any list spanning more than one page."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Opaque pagination cursor for the next page — pass it back as the `cursor` argument; null when this is the last page."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
},
"total_parties": {
"type": [
"number",
"null"
],
"description": "Total parties on this docket across all pages; null when no total is derivable — CourtListener serves the count as a URL rather than a number here, so it is only known when the first page is also the last."
},
"attorney_resolution": {
"type": "object",
"required": [
"status",
"unresolved_ids",
"next_cursor"
],
"properties": {
"status": {
"enum": [
"resolved",
"exhausted",
"capped"
],
"type": "string",
"description": "Resolved all needed IDs, exhausted roster with misses, or stopped at the page cap."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Remaining attorney-roster cursor; null when exhausted."
},
"unresolved_ids": {
"type": "array",
"items": {
"type": "number"
},
"description": "Attorney IDs still unresolved on this parties page."
}
},
"description": "Attorney lookup completeness; no additional automatic requests are made.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}courtlistener_search_judges — Search Judges
Search judge/person records by name, appointing president, court, political affiliation, or demographic. Returns biographical data, current position, and appointment summary. Use courtlistener_get_judge for full appointment history and education records.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"description": "Search query — judge name, court, city, or relevant keywords."
},
"court": {
"type": "string",
"description": "Filter to judges who have held a position at this court (e.g., \"scotus\", \"ca9\"). Use court_id strings from courtlistener_lookup_courts."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a previous response's next_cursor field."
},
"appointer": {
"type": "string",
"description": "Filter by appointing president's last name (e.g., \"Obama\", \"Trump\", \"Biden\"). Matches against the appointer field in position records."
},
"page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested page size (default 20), bounded to 20. Upstream search has a 20-row minimum; empty and final pages can be smaller. Full pages and continuation are preserved; page_sizing reports actual sizes."
},
"political_affiliation": {
"enum": [
"d",
"r",
"i",
"l",
"g",
"u"
],
"type": "string",
"description": "Filter by political affiliation: d=Democrat, r=Republican, i=Independent, l=Libertarian, g=Green Party, u=Unknown/unconfirmed. Based on party of the appointing president or election affiliation."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results",
"next_cursor",
"totalCount"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_query",
"rate_limited",
"empty_query"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_query`: CourtListener rejects caller-authored query or filter syntax with a recognized diagnostic. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `empty_query`: q is empty or whitespace-only after trimming — no request is sent. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Recovery hint when results are empty — echoes filters and suggests how to broaden."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"person_id",
"name",
"gender",
"dob",
"dob_city",
"dob_state",
"political_affiliation",
"aba_rating",
"schools",
"current_position"
],
"properties": {
"dob": {
"type": [
"string",
"null"
],
"description": "Date of birth; null if not recorded."
},
"name": {
"type": "string",
"description": "Full judge name."
},
"gender": {
"type": "string",
"description": "Gender."
},
"schools": {
"type": "array",
"items": {
"type": "string"
},
"description": "Educational institutions attended."
},
"dob_city": {
"type": [
"string",
"null"
],
"description": "City of birth; null if not recorded."
},
"dob_state": {
"type": [
"string",
"null"
],
"description": "State of birth; null if not recorded."
},
"person_id": {
"type": "number",
"description": "Person ID — pass to courtlistener_get_judge for full biography."
},
"aba_rating": {
"type": "array",
"items": {
"type": "string"
},
"description": "ABA qualification labels (e.g. \"Well Qualified\", \"Qualified\"), one per rating on record — not the rating codes."
},
"current_position": {
"anyOf": [
{
"type": "object",
"required": [
"court",
"court_id",
"position_type",
"job_title",
"organization_name",
"appointer",
"selection_method",
"date_start",
"date_termination",
"termination_reason"
],
"properties": {
"court": {
"type": [
"string",
"null"
],
"description": "Court full name; null for non-judicial positions."
},
"court_id": {
"type": [
"string",
"null"
],
"description": "Court identifier for use in filter parameters; null for non-judicial positions."
},
"appointer": {
"type": [
"string",
"null"
],
"description": "Name of the appointing president (e.g. \"Obama, Barack Hussein, II\"); null if elected or not recorded."
},
"job_title": {
"type": [
"string",
"null"
],
"description": "Free-text title for non-judicial roles (e.g. \"Assistant district attorney\"); null for judicial positions."
},
"date_start": {
"type": [
"string",
"null"
],
"description": "Date the position started; null if not recorded."
},
"position_type": {
"type": [
"string",
"null"
],
"description": "Judicial position title (e.g. \"Judge\", \"Chief Judge\"); null for non-judicial positions — see job_title."
},
"date_termination": {
"type": [
"string",
"null"
],
"description": "Date the position ended; null while the judge still holds it."
},
"selection_method": {
"type": [
"string",
"null"
],
"description": "How the judge reached the position (e.g. \"Appointment (President)\", \"Election (Partisan)\"); null if not recorded."
},
"organization_name": {
"type": [
"string",
"null"
],
"description": "Employer for non-judicial roles; null for judicial positions."
},
"termination_reason": {
"type": [
"string",
"null"
],
"description": "Why the position ended (e.g. \"Appointed to Other Judgeship\", \"Retirement\"); null while still serving."
}
},
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "The position with no termination date, or — when several or none qualify — the one with the latest start date. Null when the record carries no positions. courtlistener_get_judge returns the full appointment history."
},
"political_affiliation": {
"type": "array",
"items": {
"type": "string"
},
"description": "Party labels (e.g. \"Democratic\", \"Republican\"), one per recorded affiliation — not the single-letter codes the political_affiliation input filter takes."
}
},
"description": "Judge search result.",
"additionalProperties": false
},
"description": "Matching judge records."
},
"totalCount": {
"type": "number",
"description": "Total matching judge records."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Pagination cursor for the next page; null when no more results."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_get_judge — Get Judge Profile
Fetch full biographical profile for a single judge: positions on record — judicial appointments across all courts plus non-judicial roles — education, political affiliations, and ABA ratings. The position list is paginated upstream and walked under a page bound; the response reports whether it was truncated. Obtain person IDs from courtlistener_search_judges results.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"person_id"
],
"properties": {
"person_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Judge person ID from a search result's person_id field. Identifies a specific judge across all courts they have served on."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"person_id",
"name",
"gender",
"dob",
"dob_granularity",
"dob_city",
"dob_state",
"dod",
"dod_granularity",
"fjc_id",
"aba_ratings",
"political_affiliations",
"education",
"positions",
"positionsShown",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"dob": {
"type": [
"string",
"null"
],
"description": "Date of birth as CourtListener stores it, always full ISO 8601 — but the month and day are placeholders unless dob_granularity is \"day\". Read dob_granularity before presenting this as an exact date. Null if not recorded."
},
"dod": {
"type": [
"string",
"null"
],
"description": "Date of death as CourtListener stores it, always full ISO 8601 — precision qualified by dod_granularity, as with dob. Null if living or not recorded."
},
"name": {
"type": "string",
"description": "Full name."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"rate_limited"
],
"description": "Machine-readable failure mode. Declared by this tool: `not_found`: Person ID does not exist in CourtListener. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"fjc_id": {
"type": [
"number",
"null"
],
"description": "Federal Judicial Center ID for cross-referencing with FJC data; null if not available."
},
"gender": {
"type": "string",
"description": "Gender."
},
"notice": {
"type": "string",
"description": "Present only when positions[] was truncated: what was withheld."
},
"dob_city": {
"type": [
"string",
"null"
],
"description": "City of birth; null if not recorded."
},
"dob_state": {
"type": [
"string",
"null"
],
"description": "State of birth; null if not recorded."
},
"education": {
"type": "array",
"items": {
"type": "object",
"required": [
"school",
"degree",
"degree_label",
"year"
],
"properties": {
"year": {
"type": [
"number",
"null"
],
"description": "Graduation year; null if not recorded."
},
"degree": {
"type": [
"string",
"null"
],
"description": "Raw CourtListener degree-level code (e.g. \"ba\"); null if not recorded."
},
"school": {
"type": "string",
"description": "Educational institution name."
},
"degree_label": {
"type": [
"string",
"null"
],
"description": "Degree level expanded to a readable label (e.g. \"Juris Doctor (J.D.)\"). An unmapped code passes through as the code itself; null if not recorded."
}
},
"description": "Education record.",
"additionalProperties": false
},
"description": "Educational history."
},
"person_id": {
"type": "number",
"description": "Person ID."
},
"positions": {
"type": "array",
"items": {
"type": "object",
"required": [
"court",
"court_id",
"position_type",
"position_type_label",
"job_title",
"organization_name",
"appointer",
"nomination_process",
"date_nominated",
"date_confirmation",
"date_start",
"date_start_granularity",
"date_termination",
"date_termination_granularity",
"termination_reason",
"termination_reason_label"
],
"properties": {
"court": {
"type": "string",
"description": "Court name."
},
"court_id": {
"type": "string",
"description": "Court identifier — use to filter opinions by this judge."
},
"appointer": {
"type": [
"string",
"null"
],
"description": "Position URI of the appointing authority (e.g., \".../positions/123/\"), not resolved to a name; null if elected or not recorded."
},
"job_title": {
"type": "string",
"description": "Free-text title for a role with no position_type code (e.g. \"Assistant district attorney\"); empty on judicial rows."
},
"date_start": {
"type": [
"string",
"null"
],
"description": "Date the position started as CourtListener stores it, always full ISO 8601 — the month and day are placeholders unless date_start_granularity is \"day\". Null if not recorded."
},
"position_type": {
"type": "string",
"description": "Raw CourtListener position-type code (e.g. \"jud\", \"c-jud\") — the value the /positions/ position_type filter takes. Empty for non-judicial roles, which describe themselves in job_title."
},
"date_nominated": {
"type": [
"string",
"null"
],
"description": "Date nominated; null if not recorded."
},
"date_termination": {
"type": [
"string",
"null"
],
"description": "Date the position ended as CourtListener stores it, always full ISO 8601 — precision qualified by date_termination_granularity. Null if current."
},
"date_confirmation": {
"type": [
"string",
"null"
],
"description": "Date confirmed; null if not recorded."
},
"organization_name": {
"type": "string",
"description": "Employer for a non-judicial role; empty on judicial rows, which use court."
},
"nomination_process": {
"type": [
"string",
"null"
],
"description": "Selection method, expanded to a readable label (e.g., \"Appointment (President)\"); null if not recorded."
},
"termination_reason": {
"type": [
"string",
"null"
],
"description": "Raw CourtListener termination-reason code (e.g. \"other_pos\"); null if still serving."
},
"position_type_label": {
"type": "string",
"description": "Position type expanded to a readable label (e.g. \"Judge\", \"Chief Judge\"). An unmapped code passes through as the code itself; empty for non-judicial roles."
},
"date_start_granularity": {
"type": [
"string",
"null"
],
"description": "Precision actually recorded for date_start: \"year\", \"month\", or \"day\". Null when CourtListener recorded no precision."
},
"termination_reason_label": {
"type": [
"string",
"null"
],
"description": "Termination reason expanded to a readable label (e.g. \"Appointed to Other Judgeship\"). An unmapped code passes through as the code itself; null if still serving."
},
"date_termination_granularity": {
"type": [
"string",
"null"
],
"description": "Precision actually recorded for date_termination: \"year\", \"month\", or \"day\". Null when CourtListener recorded no precision."
}
},
"description": "Position record — judicial or otherwise.",
"additionalProperties": false
},
"description": "Positions on record, across all courts — judicial appointments plus non-judicial roles (private practice, prosecutor, professor), which carry no court and describe themselves in job_title. CourtListener paginates this list and the walk is bounded, so read the truncated flag before treating it as a complete career."
},
"truncated": {
"type": "boolean",
"description": "True when the bounded /positions/ page walk stopped with pages outstanding — positions[] is then a prefix of the person's record, not the whole of it. False when the walk reached the end."
},
"aba_ratings": {
"type": "array",
"items": {
"type": "string"
},
"description": "ABA qualification ratings, expanded to readable labels (e.g., \"Well Qualified\")."
},
"positionsShown": {
"type": "number",
"description": "Number of position records returned."
},
"dob_granularity": {
"type": [
"string",
"null"
],
"description": "Precision actually recorded for dob: \"year\", \"month\", or \"day\". Null when CourtListener recorded no precision. An unrecognized upstream value passes through unchanged."
},
"dod_granularity": {
"type": [
"string",
"null"
],
"description": "Precision actually recorded for dod: \"year\", \"month\", or \"day\". Null when CourtListener recorded no precision."
},
"political_affiliations": {
"type": "array",
"items": {
"type": "object",
"required": [
"affiliation",
"date_start",
"date_end"
],
"properties": {
"date_end": {
"type": [
"string",
"null"
],
"description": "End date of this affiliation; null if current."
},
"date_start": {
"type": [
"string",
"null"
],
"description": "Start date of this affiliation."
},
"affiliation": {
"type": "string",
"description": "Political party, expanded to a readable label (e.g., \"Democratic\")."
}
},
"description": "Political affiliation entry.",
"additionalProperties": false
},
"description": "Political affiliation history."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}courtlistener_lookup_courts — Lookup Courts
List courts with optional filtering by jurisdiction type, active/inactive status, and scraper coverage. Primarily used to discover court IDs for use in search and filter parameters across all other courtlistener tools. Defaults to the active bench — the courts CourtListener still scrapes; pass status:'inactive' for historical courts or status:'any' for every court. A bundled snapshot returns the complete list of matching court IDs without paging whenever the filtered set fits the response budget, which covers the default bench and every jurisdiction filter. Full court records — names, citation strings, scraper status — come live from CourtListener at a fixed 20 rows per page, so pull those only when a court ID alone is not enough.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Page number (1-indexed). CourtListener serves /courts/ at a fixed 20 rows per page and ignores any requested page size, so the number of pages is the enrichment totalCount divided by 20 — there is no way to pull a larger page. Pass the next_cursor from a previous response here to walk them one call at a time."
},
"status": {
"enum": [
"active",
"inactive",
"any"
],
"type": "string",
"default": "active",
"description": "Which bench to return. 'active' (default) returns only courts CourtListener currently scrapes; 'inactive' returns only the historical and defunct courts it no longer scrapes; 'any' returns both. The two filtered sets are disjoint, so 'any' is the only value that reaches the whole list — but reaching all of it means paging, one call per 20 courts, and the inactive bench is several times larger than the active one. Prefer the narrowest value that answers the question, and narrow with jurisdiction rather than paging the full list."
},
"jurisdiction": {
"enum": [
"F",
"FD",
"FB",
"FBP",
"FS",
"S",
"SA",
"ST",
"SS",
"SAG",
"TRS",
"TRA",
"TRT",
"TRX",
"TS",
"TA",
"TT",
"TSP",
"MA",
"MT",
"C",
"I"
],
"type": "string",
"description": "Jurisdiction type — CourtListener's own court classification, one code per court: F=Federal Appellate, FD=Federal District, FB=Federal Bankruptcy, FBP=Federal Bankruptcy Panel, FS=Federal Special, S=State Supreme, SA=State Appellate, ST=State Trial, SS=State Special, SAG=State Attorney General, TRS=Tribal Supreme, TRA=Tribal Appellate, TRT=Tribal Trial, TRX=Tribal Special, TS=Territory Supreme, TA=Territory Appellate, TT=Territory Trial, TSP=Territory Special, MA=Military Appellate, MT=Military Trial, C=Committee, I=International. Omit to list all. SCOTUS and the numbered circuits are F; USITC and FISC are FS. Upstream's Testing code is not offered here: /courts/ excludes testing courts from every response, so a filter on it can only ever return nothing. Accepted but matching no court as of the 2026-07-30 snapshot: TSP, MT. Courts whose stored jurisdiction is not one of these codes (njcirctsussex, ohctapp1) are unreachable through this filter at any value — the value they store is not one the filter accepts. Pass those ids straight to the tool that needs them, or list with no jurisdiction filter."
},
"has_opinion_scraper": {
"type": "boolean",
"description": "Filter to courts with active opinion scraping. Useful when planning search queries — courts without scrapers have sparse coverage."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"page",
"next_cursor",
"courts",
"all_matching_court_ids",
"all_matching_court_ids_complete",
"totalCount"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"page": {
"type": "number",
"description": "Current page number (1-indexed)."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"rate_limited"
],
"description": "Machine-readable failure mode. Declared by this tool: `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"courts": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"full_name",
"short_name",
"citation_string",
"jurisdiction",
"has_opinion_scraper",
"has_oral_argument_scraper"
],
"properties": {
"id": {
"type": "string",
"description": "Court identifier for use in search filter parameters."
},
"full_name": {
"type": "string",
"description": "Full court name."
},
"short_name": {
"type": "string",
"description": "Abbreviated court name."
},
"jurisdiction": {
"type": "string",
"description": "Jurisdiction type code."
},
"citation_string": {
"type": "string",
"description": "Citation abbreviation (e.g., \"9th Cir.\", \"SCOTUS\")."
},
"has_opinion_scraper": {
"type": "boolean",
"description": "True if CourtListener actively scrapes opinions from this court."
},
"has_oral_argument_scraper": {
"type": "boolean",
"description": "True if CourtListener actively scrapes oral arguments from this court."
}
},
"description": "Court record.",
"additionalProperties": false
},
"description": "Matching courts on this page."
},
"notice": {
"type": "string",
"description": "Recovery hint when no courts match the applied filters."
},
"totalCount": {
"type": "number",
"description": "Total courts returned."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Next page number to pass as the `page` argument (this list is page-paginated at a fixed 20 rows/page); null when this is the last page — a non-null value means the courts shown are a partial view of the filtered set."
},
"all_matching_court_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Every court id matching the same filters, from a snapshot of /courts/ bundled with this server (taken 2026-07-30) — the complete set, not just this page, and free of any request. Paging `courts` is only needed for the fields a court id alone does not carry (full_name, citation_string, scraper flags). Empty when more than 1000 courts match, since a prefix of the set would be indistinguishable from the whole of it — check all_matching_court_ids_complete before reading emptiness as \"no courts match\". A court added or retired upstream since the snapshot date appears in `courts` but may be missing here."
},
"all_matching_court_ids_complete": {
"type": "boolean",
"description": "True when all_matching_court_ids holds every matching court id. False when more than 1000 courts match: the list is withheld whole rather than truncated, and the notice gives the count and how to narrow."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_search_oral_arguments — Search Oral Arguments
Search appellate oral argument audio recordings — the largest public collection of oral argument audio. Returns recording metadata with two direct MP3 links per result (download_url at the originating court, local_path for CourtListener's durable copy), panel judge IDs, and transcript snippets where available. Panel judge IDs can be passed to courtlistener_get_judge for biographical context.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"description": "Query terms matched against case name and transcribed argument text (where available)."
},
"court": {
"type": "string",
"description": "Filter to a specific court (e.g., \"scotus\", \"ca9\")."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a previous response's next_cursor field."
},
"page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested page size (default 20), bounded to 20. Upstream search has a 20-row minimum; empty and final pages can be smaller. Full pages and continuation are preserved; page_sizing reports actual sizes."
},
"argued_after": {
"type": "string",
"description": "Earliest date the case was argued (ISO 8601) — filters by argument date, not publication date."
},
"argued_before": {
"type": "string",
"description": "Latest date the case was argued (ISO 8601)."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results",
"next_cursor",
"totalCount"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_query",
"rate_limited",
"empty_query",
"invalid_date"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_query`: CourtListener rejects caller-authored query or filter syntax with a recognized diagnostic. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `empty_query`: q is empty or whitespace-only after trimming — no request is sent. `invalid_date`: argued_after or argued_before is not a valid ISO 8601 calendar date. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Recovery hint when results are empty — echoes filters and suggests how to broaden."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"audio_id",
"case_name",
"court",
"court_id",
"date_argued",
"docket_id",
"docket_number",
"judges",
"panel_ids",
"duration_seconds",
"download_url",
"local_path",
"snippet"
],
"properties": {
"court": {
"type": "string",
"description": "Court display name."
},
"judges": {
"type": "string",
"description": "Judge names on the panel."
},
"snippet": {
"type": "string",
"description": "Transcript excerpt where available; empty string if no transcript."
},
"audio_id": {
"type": "number",
"description": "Audio recording ID."
},
"court_id": {
"type": "string",
"description": "Court identifier."
},
"case_name": {
"type": "string",
"description": "Case name."
},
"docket_id": {
"type": "number",
"description": "Associated docket ID."
},
"panel_ids": {
"type": "array",
"items": {
"type": "number"
},
"description": "Person IDs of panel judges — pass to courtlistener_get_judge."
},
"local_path": {
"type": [
"string",
"null"
],
"description": "CourtListener-hosted copy of the recording (https://storage.courtlistener.com/...); null if not stored."
},
"date_argued": {
"type": [
"string",
"null"
],
"description": "Date the case was argued; null if not recorded."
},
"download_url": {
"type": [
"string",
"null"
],
"description": "MP3 URL at the originating court; null if not recorded. Often plain HTTP and prone to rot as courts reorganize — prefer local_path, CourtListener's durable copy."
},
"docket_number": {
"type": "string",
"description": "Docket number."
},
"duration_seconds": {
"type": "number",
"description": "Recording duration in seconds."
}
},
"description": "Oral argument recording.",
"additionalProperties": false
},
"description": "Matching oral argument recordings."
},
"totalCount": {
"type": "number",
"description": "Total matching oral argument recordings."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Pagination cursor for the next page; null when no more results."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_get_oral_argument — Get Oral Argument
Fetch an oral argument recording by audio_id from courtlistener_search_oral_arguments. Returns case metadata, panel IDs, duration, MP3 URL, docket and available transcript. Oversized text or metadata returns outline then page responses; continue retrieval.next_cursor as cursor with the unchanged ID/sections selection until null. The argument date comes from search or the linked docket.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Audio recording ID — the audio_id field from a courtlistener_search_oral_arguments result."
},
"cursor": {
"type": "string",
"maxLength": 1024,
"description": "Retrieval next_cursor from the previous response. Repeat the original ID and sections/categories selection unchanged; omit to start."
},
"sections": {
"type": "array",
"items": {
"type": "string"
},
"description": "Selected record fields. Metadata is always selected; a nonempty selection omitting transcript excludes it. Omit for the whole record. Oversized selections page; keep this selection unchanged while following cursor."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"kind"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"kind": {
"enum": [
"full",
"outline",
"page"
],
"type": "string",
"description": "'full' carries a small selected record; 'outline' pages the section catalog; 'page' carries fields and text chunks. Bounded identity remains present throughout retrieval."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_cursor",
"stale_cursor",
"not_found",
"rate_limited",
"unknown_section"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_cursor`: Retrieval cursor is malformed, out of range or belongs to another request. `stale_cursor`: The normalized selected source changed since the previous page. `not_found`: Audio ID does not exist in CourtListener. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. `unknown_section`: A requested sections name is not a field of the oral argument record. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"judges": {
"type": "string",
"description": "Free-text judge names; often empty on this endpoint."
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"bytes"
],
"properties": {
"name": {
"type": "string",
"description": "Section identifier — pass in `sections` to retrieve it"
},
"bytes": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Serialized byte size of the section"
}
},
"description": "A withheld section of the record and its serialized byte size.",
"additionalProperties": false
},
"description": "Section catalog: transcript and paged metadata fields. Follow retrieval.next_cursor to finish the catalog and retrieve data."
},
"case_name": {
"type": "string",
"description": "Case name."
},
"docket_id": {
"type": "number",
"description": "Associated docket ID; 0 if not linked."
},
"panel_ids": {
"type": "array",
"items": {
"type": "number"
},
"description": "Person IDs of panel judges — pass to courtlistener_get_judge."
},
"retrieval": {
"type": "object",
"required": [
"next_cursor",
"ranges",
"text_chunks"
],
"properties": {
"ranges": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"unit",
"start",
"end",
"total"
],
"properties": {
"end": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Exclusive absolute end."
},
"path": {
"type": "string",
"description": "JSON Pointer into the normalized unsliced selected view."
},
"unit": {
"enum": [
"rows",
"code_points",
"sections"
],
"type": "string",
"description": "Coordinate unit."
},
"start": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Inclusive absolute start."
},
"total": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Length of the complete normalized collection or text field."
}
},
"description": "Source range.",
"additionalProperties": false
},
"description": "Absolute source coordinates; merge typed rows by index rather than appending duplicates."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Continue with cursor and the same ID/selection; null when this fetched view is exhausted."
},
"text_chunks": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"text"
],
"properties": {
"path": {
"type": "string",
"description": "JSON Pointer of the original string field or string-array element."
},
"text": {
"type": "string",
"description": "Unescaped normalized substring, matching its code_points range."
}
},
"description": "Readable string slice.",
"additionalProperties": false
},
"description": "Text omitted from partial rows/metadata, recoverable exactly using the matching ranges."
}
},
"description": "Caller retrieval completion, separate from upstream source completion.",
"additionalProperties": false
},
"transcript": {
"type": "string",
"description": "Speech-to-text transcript; empty if transcription has not completed. Oversized text is recovered through retrieval.text_chunks at /transcript."
},
"download_url": {
"type": [
"string",
"null"
],
"description": "Direct MP3 download URL; null if not available."
},
"case_name_full": {
"type": "string",
"description": "Full case name with parties."
},
"has_transcript": {
"type": "boolean",
"description": "True if a speech-to-text transcript is available."
},
"duration_seconds": {
"type": "number",
"description": "Recording duration in seconds."
},
"oral_argument_id": {
"type": "number",
"description": "Audio recording ID."
},
"retrieval_notice": {
"type": "string",
"description": "How to continue bounded retrieval using the unchanged ID and selection."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}courtlistener_search_financial_disclosures — Search Financial Disclosures
Search federal judicial financial disclosure filings — the annual reports judges file on investments, gifts, debts, outside positions, and income. Filter by judge (person ID from courtlistener_search_judges) and/or filing year; the year filter is applied to the fetched page only (CourtListener has no server-side year filter), so page through with cursor to reach a judge's filings for a year that fall on later pages. Returns per-filing metadata, category counts, itemized gifts, and a link to the source PDF. Line-item investments (often hundreds per filing, with coded values) are summarized as counts; the linked PDF carries the full itemization. Use this for judicial-ethics and recusal research after identifying a judge's person ID.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"year": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Filing year to filter by (e.g., 2022). Applied client-side to the fetched page only — CourtListener rejects a server-side year param, so filings for this year on later pages are not included. When a page has no match for the year but more pages remain, next_cursor is returned; pass it as cursor to check the next page. Omit to return all years on the page."
},
"cursor": {
"type": "string",
"description": "Pagination cursor from a previous response's next_cursor field."
},
"judge_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Person ID of the judge whose disclosures to return — obtain from courtlistener_search_judges (the person_id field). Omit to browse across all filers."
},
"page_size": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Positive requested page size (default 20), bounded to 20. Upstream has a minimum of 20; final pages and page-local year filtering can return fewer. Full fetched pages and continuation are preserved; page_sizing reports returned sizes."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results",
"next_cursor"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"rate_limited"
],
"description": "Machine-readable failure mode. Declared by this tool: `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Recovery hint when no filings are found — echoes filters and suggests next steps."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"disclosure_id",
"person_id",
"year",
"report_type",
"page_count",
"has_been_extracted",
"is_amended",
"pdf_url",
"counts",
"gifts"
],
"properties": {
"year": {
"type": "number",
"description": "Filing year."
},
"gifts": {
"type": "array",
"items": {
"type": "object",
"required": [
"description",
"source",
"value"
],
"properties": {
"value": {
"type": "string",
"description": "Reported dollar value; empty if not stated."
},
"source": {
"type": "string",
"description": "Who provided the gift."
},
"description": {
"type": "string",
"description": "What the gift was."
}
},
"description": "A reported gift.",
"additionalProperties": false
},
"description": "Itemized gifts (the most ethics-relevant category; usually few)."
},
"counts": {
"type": "object",
"required": [
"investments",
"gifts",
"debts",
"positions",
"reimbursements",
"agreements",
"non_investment_incomes",
"spouse_incomes"
],
"properties": {
"debts": {
"type": "number",
"description": "Number of reported debts/liabilities."
},
"gifts": {
"type": "number",
"description": "Number of reported gifts."
},
"positions": {
"type": "number",
"description": "Number of reported outside positions."
},
"agreements": {
"type": "number",
"description": "Number of reported agreements."
},
"investments": {
"type": "number",
"description": "Number of reported investments."
},
"reimbursements": {
"type": "number",
"description": "Number of reported reimbursements."
},
"spouse_incomes": {
"type": "number",
"description": "Number of reported spouse income sources."
},
"non_investment_incomes": {
"type": "number",
"description": "Number of reported non-investment income sources."
}
},
"description": "Count of line items in each disclosure category.",
"additionalProperties": false
},
"pdf_url": {
"type": [
"string",
"null"
],
"description": "URL to the source disclosure PDF; null if unavailable."
},
"person_id": {
"type": [
"number",
"null"
],
"description": "Person ID of the filer — pass to courtlistener_get_judge; null if absent."
},
"is_amended": {
"type": "boolean",
"description": "True if this filing is an amendment."
},
"page_count": {
"type": [
"number",
"null"
],
"description": "Page count of the source filing; null if not recorded."
},
"report_type": {
"type": "string",
"description": "Report type (Nomination, Initial, Annual, Final, or Unknown)."
},
"disclosure_id": {
"type": "number",
"description": "Financial disclosure ID."
},
"has_been_extracted": {
"type": "boolean",
"description": "True if line items were parsed from the PDF; counts are 0 when false."
}
},
"description": "A judicial financial disclosure filing.",
"additionalProperties": false
},
"description": "Matching financial disclosure filings."
},
"totalCount": {
"type": "number",
"description": "Total matching disclosure filings — present only when the API reports a numeric count (this endpoint returns it as a URL by default, so it is usually absent)."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Pagination cursor for the next page; null when no more results."
},
"page_sizing": {
"type": "object",
"required": [
"requested",
"bounded",
"actual",
"upstream"
],
"properties": {
"actual": {
"type": "number",
"description": "Rows returned to the caller after any page-local filters."
},
"bounded": {
"type": "number",
"description": "Size sent upstream or used for the cited-ID slice."
},
"upstream": {
"enum": [
"minimum_20",
"fixed_20",
"cited_id_slice"
],
"type": "string",
"description": "Upstream minimum, fixed page, or cited-ID slicing policy; final pages may contain fewer rows."
},
"requested": {
"type": "number",
"description": "Caller-requested page size."
}
},
"description": "Requested, bounded, and actual page sizes.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": false
}courtlistener_get_financial_disclosure — Get Financial Disclosure
Fetch a judicial financial disclosure by disclosure_id from courtlistener_search_financial_disclosures. Returns metadata, counts and typed line items with coded values decoded to dollar ranges. Select categories or omit for all. Oversized selections return outline then page responses; continue retrieval.next_cursor as cursor with the unchanged ID/categories selection until null. Large individual row fields remain recoverable through text_chunks.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"disclosure_id"
],
"properties": {
"cursor": {
"type": "string",
"maxLength": 1024,
"description": "Retrieval next_cursor from the previous response. Repeat the original ID and sections/categories selection unchanged; omit to start."
},
"categories": {
"type": "array",
"items": {
"enum": [
"investments",
"debts",
"positions",
"reimbursements",
"non_investment_incomes",
"spouse_incomes",
"agreements",
"gifts"
],
"type": "string"
},
"description": "Line-item categories to select. Omit for all. Oversized selections page; keep this selection unchanged while following cursor."
},
"disclosure_id": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Financial disclosure ID — the disclosure_id field from a courtlistener_search_financial_disclosures result."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"disclosure_id",
"person_id",
"year",
"page_count",
"has_been_extracted",
"is_amended",
"counts",
"kind"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"kind": {
"enum": [
"full",
"outline",
"page"
],
"type": "string",
"description": "'full' carries a small selected record; 'outline' pages the section catalog; 'page' carries typed rows and field-path text chunks. Filing identity and counts remain present."
},
"year": {
"type": "number",
"description": "Filing year."
},
"debts": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Debt row ID."
},
"creditor": {
"type": "string",
"description": "Creditor name (e.g. \"Wells Fargo Bank, NA\")."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
},
"description": {
"type": "string",
"description": "Description of the liability."
},
"value_range": {
"type": "string",
"description": "Value of the debt as a dollar range; empty if none."
}
},
"description": "A debt or liability (Part VII); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Debts and liabilities."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_cursor",
"stale_cursor",
"not_found",
"rate_limited"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_cursor`: Retrieval cursor is malformed, out of range or belongs to another request. `stale_cursor`: The normalized selected source changed since the previous page. `not_found`: Disclosure ID does not exist in CourtListener. `rate_limited`: 429 from CourtListener, or no request slot opened within the wait budget. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"gifts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Reported dollar value; empty if not stated."
},
"source": {
"type": "string",
"description": "Who provided the gift."
},
"description": {
"type": "string",
"description": "What the gift was."
}
},
"description": "A reported gift (Part VI); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Reported gifts."
},
"counts": {
"type": "object",
"required": [
"investments",
"gifts",
"debts",
"positions",
"reimbursements",
"agreements",
"non_investment_incomes",
"spouse_incomes"
],
"properties": {
"debts": {
"type": "number",
"description": "Number of reported debts/liabilities."
},
"gifts": {
"type": "number",
"description": "Number of reported gifts."
},
"positions": {
"type": "number",
"description": "Number of reported outside positions."
},
"agreements": {
"type": "number",
"description": "Number of reported agreements."
},
"investments": {
"type": "number",
"description": "Number of reported investments."
},
"reimbursements": {
"type": "number",
"description": "Number of reported reimbursements."
},
"spouse_incomes": {
"type": "number",
"description": "Number of reported spouse income sources."
},
"non_investment_incomes": {
"type": "number",
"description": "Number of reported non-investment income sources."
}
},
"description": "Count of line items in each disclosure category.",
"additionalProperties": false
},
"pdf_url": {
"type": [
"string",
"null"
],
"description": "URL to the source disclosure PDF; null if unavailable."
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"bytes"
],
"properties": {
"name": {
"type": "string",
"description": "Section identifier — pass in `sections` to retrieve it"
},
"bytes": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Serialized byte size of the section"
}
},
"description": "A retrievable category (by name) and its serialized byte size.",
"additionalProperties": false
},
"description": "Category catalog in declared order, with paged metadata fields. Follow retrieval.next_cursor to finish the catalog and retrieve data."
},
"person_id": {
"type": [
"number",
"null"
],
"description": "Person ID of the filer — pass to courtlistener_get_judge; null if absent."
},
"positions": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Position row ID."
},
"position": {
"type": "string",
"description": "Position title (e.g. \"Governing Director\")."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
},
"organization": {
"type": "string",
"description": "Organization or entity name."
}
},
"description": "An outside position held by the filer (Part I); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Outside positions."
},
"retrieval": {
"type": "object",
"required": [
"next_cursor",
"ranges",
"text_chunks"
],
"properties": {
"ranges": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"unit",
"start",
"end",
"total"
],
"properties": {
"end": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Exclusive absolute end."
},
"path": {
"type": "string",
"description": "JSON Pointer into the normalized unsliced selected view."
},
"unit": {
"enum": [
"rows",
"code_points",
"sections"
],
"type": "string",
"description": "Coordinate unit."
},
"start": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Inclusive absolute start."
},
"total": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "Length of the complete normalized collection or text field."
}
},
"description": "Source range.",
"additionalProperties": false
},
"description": "Absolute source coordinates; merge typed rows by index rather than appending duplicates."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Continue with cursor and the same ID/selection; null when this fetched view is exhausted."
},
"text_chunks": {
"type": "array",
"items": {
"type": "object",
"required": [
"path",
"text"
],
"properties": {
"path": {
"type": "string",
"description": "JSON Pointer of the original string field or string-array element."
},
"text": {
"type": "string",
"description": "Unescaped normalized substring, matching its code_points range."
}
},
"description": "Readable string slice.",
"additionalProperties": false
},
"description": "Text omitted from partial rows/metadata, recoverable exactly using the matching ranges."
}
},
"description": "Caller retrieval completion, separate from upstream source completion.",
"additionalProperties": false
},
"agreements": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Agreement row ID."
},
"date": {
"type": "string",
"description": "Date of the agreement as filed."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
},
"parties_and_terms": {
"type": "string",
"description": "Parties to and terms of the agreement."
}
},
"description": "A continuing agreement or arrangement (Part VIII); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Continuing agreements."
},
"is_amended": {
"type": "boolean",
"description": "True if this filing is an amendment."
},
"page_count": {
"type": [
"number",
"null"
],
"description": "Page count of the source filing; null if not recorded."
},
"investments": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Investment row ID."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
},
"description": {
"type": "string",
"description": "Name of the holding (e.g. \"Citibank, N.A. Accounts\")."
},
"income_type": {
"type": "string",
"description": "Income type (e.g. \"Interest\", \"Dividend\", \"Rent\"); empty if none."
},
"transaction": {
"type": "string",
"description": "Transaction during the period (e.g. \"Buy\", \"Sold\"); empty if none."
},
"value_range": {
"type": "string",
"description": "Gross value at period end as a dollar range (e.g. \"$250,001 - $500,000\"); empty if none."
},
"income_range": {
"type": "string",
"description": "Income during the reporting period as a dollar range (e.g. \"$1 - $1,000\"); empty if none."
},
"value_method": {
"type": "string",
"description": "Valuation method (e.g. \"Cash/market value\", \"Appraisal\"); empty if none."
},
"transaction_date": {
"type": "string",
"description": "Transaction date as filed; empty if none."
},
"transaction_partner": {
"type": "string",
"description": "Identity of the transaction partner; empty if none."
},
"transaction_gain_range": {
"type": "string",
"description": "Gain realized on the transaction as a dollar range; empty if none."
},
"transaction_value_range": {
"type": "string",
"description": "Transaction value as a dollar range; empty if none."
}
},
"description": "An investment holding (Part VII); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Investment holdings."
},
"report_type": {
"type": "string",
"description": "Report type (Nomination, Initial, Annual, Final, or Unknown)."
},
"disclosure_id": {
"type": "number",
"description": "Financial disclosure ID."
},
"reimbursements": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Reimbursement row ID."
},
"date": {
"type": "string",
"description": "Dates as filed (e.g. \"April 3-5, 2022\")."
},
"items": {
"type": "string",
"description": "Items reimbursed (e.g. \"Transportation, Lodging and Meals\")."
},
"source": {
"type": "string",
"description": "Who provided the reimbursement (e.g. a law school)."
},
"purpose": {
"type": "string",
"description": "Purpose of the reimbursement."
},
"location": {
"type": "string",
"description": "Location of the reimbursed event."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
}
},
"description": "A travel/event reimbursement (Part IV); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Reimbursements."
},
"spouse_incomes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Spouse income row ID."
},
"date": {
"type": "string",
"description": "Date as filed."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
},
"source_type": {
"type": "string",
"description": "Source and type of the spousal income."
}
},
"description": "The filer's spouse income (Part III); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Spouse income sources."
},
"retrieval_notice": {
"type": "string",
"description": "How to continue bounded retrieval using the unchanged ID and selection."
},
"has_been_extracted": {
"type": "boolean",
"description": "True if line items were parsed from the PDF; category arrays are empty when false."
},
"non_investment_incomes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"redacted"
],
"properties": {
"id": {
"type": "number",
"description": "Non-investment income row ID."
},
"date": {
"type": "string",
"description": "Date as filed (e.g. \"3/10/2022\")."
},
"amount": {
"type": "string",
"description": "Amount as filed — usually a dollar string (e.g. \"$10,116.00\")."
},
"redacted": {
"type": "boolean",
"description": "True if the source row was partially redacted."
},
"source_type": {
"type": "string",
"description": "Source and type of the income."
}
},
"description": "The filer's non-investment income (Part II); omitted partial strings remain reachable through retrieval.",
"additionalProperties": false
},
"description": "Non-investment income sources."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"idempotentHint": true
}Prompts
1 advertised
courtlistener_research_topic
Generate a structured legal research plan for a given legal topic or question. Produces a step-by-step workflow using CourtListener tools to find relevant case law, trace precedent chains, and surface key opinions.
- topic
- Legal topic, question, or issue to research (e.g., "Fourth Amendment cell phone search", "Title VII hostile work environment", "Section 1983 qualified immunity"). (required)
- jurisdiction
- Optional jurisdiction to focus on (e.g., "scotus" for Supreme Court, "ca9" for Ninth Circuit, "nysd" for SDNY). Omit for nationwide research.
- depth
- "overview" (default): find 3–5 key cases. "deep": include citation network traversal and judge lookup. Note: deep research uses more of the free tier's daily budget, and each citation-network call spends three upstream requests.
Resources
2 advertised
CourtListener Reference — CourtListener Reference
Static reference guide for CourtListener court IDs, jurisdiction type codes, search type codes, and rate limit information. Read this before building queries to find the correct court ID and jurisdiction filter values.
courtlistener://reference/courtscourtlistener-guide
Resolve identifiers and assess completeness when using courtlistener_* tools for US case-law research, precedent tracing, federal RECAP dockets, or judicial disclosures. Use before drawing conclusions from citation links, partial text, or missing records.
skill://courtlistener-guide/SKILL.mdio.modelcontextprotocol/skills
skill://{+path}90-day uptime
A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.
- 2026-11-07: 1 of 1 checks answered
30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 679 ms
- 95th percentile latency
- 679 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 679 ms · metadata changed · 14 tool(s), 2 resource(s), 1 resource template(s), 1 prompt(s)
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http courtlistener-mcp-server https://courtlistener.caseyjhand.com/mcpCodex
codex mcp add courtlistener-mcp-server --url https://courtlistener.caseyjhand.com/mcpCursor
{
"mcpServers": {
"courtlistener-mcp-server": {
"url": "https://courtlistener.caseyjhand.com/mcp"
}
}
}Cline
{
"mcpServers": {
"courtlistener-mcp-server": {
"type": "streamableHttp",
"url": "https://courtlistener.caseyjhand.com/mcp",
"disabled": false
}
}
}VS Code
{
"servers": {
"courtlistener-mcp-server": {
"type": "http",
"url": "https://courtlistener.caseyjhand.com/mcp"
}
}
}Gemini CLI
gemini mcp add --transport http courtlistener-mcp-server https://courtlistener.caseyjhand.com/mcpClaude Desktop
https://courtlistener.caseyjhand.com/mcpWindsurf
{
"mcpServers": {
"courtlistener-mcp-server": {
"serverUrl": "https://courtlistener.caseyjhand.com/mcp"
}
}
}Let your agent find its tools
Find servers like courtlistener-mcp-server from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.