mcp-courtwatch
This server provides access to U.S. case law, court dockets, citations, and judge data via the free CourtListener API — a free alternative to services like Westlaw or PACER.
opinion_search: Full-text search of U.S. court opinions, with filters for court, date range, and sort order (relevance, newest, oldest, most cited). Returns case name, court, date, citations, snippets, and links. Supports cursor-based pagination.docket_lookup: Search court dockets by case name, free text, and/or docket number, optionally filtered by court. Returns case name, docket number, filed/terminated dates, nature of suit, and a direct link.court_list: List all CourtListener courts and their IDs, filterable by jurisdiction type (e.g.,Ffor federal,Sfor state) or name substring. Court IDs are used as filters in other tools.case_detail: Fetch full details for a case cluster (name, citations, date, judges, opinion IDs) or the full text of a specific opinion by ID. Requires an API token.citation_lookup: Verify legal citations from free text (up to 64,000 characters) against CourtListener's database. Each citation is flagged asFOUND,NOT_FOUND,UNKNOWN_REPORTER, orNOT_CHECKED_OVER_CAP— useful for catching fabricated or mis-cited authorities. Requires an API token.judge_lookup: Search for judges by first and/or last name. Returns judge ID, full name, birth/death dates and place, gender, and number of court positions on record.
Authentication: case_detail and citation_lookup require a COURTLISTENER_API_TOKEN. Other tools work without a token but benefit from higher rate limits when one is provided.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-courtwatchsearch for tenant rights opinions in California"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-courtwatch
MCP server for free U.S. case-law and court-docket search, over CourtListener (the Free Law Project's open legal database). Built for legal-aid orgs, tenant-defense and pro-se litigants, and public-interest lawyers who cannot afford Westlaw or PACER.
It wraps CourtListener's REST API v4, normalizing the raw JSON (caseName, dateFiled, cluster_id, docket_absolute_url, and so on) rather than passing the envelope through — see the field map below.
Tools
Tool | Arguments | Returns |
|
| Full-text case-law search ( |
|
| Docket search ( |
|
| Courts and their ids ( |
|
| Full case by id. A cluster ( |
|
| Verify citations ( |
|
| Judges / people ( |
order_by for opinion_search is one of relevance (default), newest, oldest, most_cited. Court jurisdiction codes include F (federal appellate and other), FD (federal district), FB (bankruptcy), S (state), SA (state appellate), SS (state supreme).
Related MCP server: courtlistener-mcp
Data source
Base URL:
https://www.courtlistener.com/api/rest/v4Auth: a free API token, sent as the header
Authorization: Token <token>.Envelope: search and list endpoints return the DRF shape
{ count, next, previous, results: [...] }./search/and/people/paginate by opaquecursor;/courts/paginates by page number (?page=N). Detail endpoints return a bare object.POST /citation-lookup/returns a bare JSON array (one item per citation recognized in the text).Access:
/search/,/courts/, and/people/answer without a token at a low rate limit, so those tools attach the token only when it is set (a token raises the limit)./clusters/{id}/,/opinions/{id}/, andPOST /citation-lookup/return HTTP 401 without a token, socase_detailandcitation_lookuprequire one.Citation-lookup limits (server-side):
textmax 64,000 characters (enforced pre-flight here with a clear error; the tool never truncates, since a dropped tail would mean unchecked citations); the first 250 citations per call are looked up and any beyond that come back flagged per-item as not checked; rate limit 60 citations/min.
Sources:
REST API v4 overview and auth: https://www.courtlistener.com/help/api/rest/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/overview)
Search API (params,
typeenum, response fields): https://www.courtlistener.com/help/api/rest/search/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/search)Case Law API (clusters, opinions): https://www.courtlistener.com/help/api/rest/case-law/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/case-law)
Citation Lookup API: https://www.courtlistener.com/help/api/rest/citation-lookup/ (redirects to https://wiki.free.law/c/courtlistener/help/api/rest/v4/citation-lookup), plus the endpoint's source in the CourtListener repo:
cl/citations/api_views.pyandapi_serializers.py(request/response fields, per-citation status codes) andcl/settings/project/citations.py(the 250-citations-per-request cap). The endpoint returns HTTP 401 without a token.The live API itself, for the search / courts / people field names:
/search/?type=o,/search/?type=r,/courts/,/people/(all answer unauthenticated GETs).
Field map (CourtListener to normalized output)
CourtListener field | Normalized field | Where |
|
| opinion_search, docket_lookup |
|
| search hits |
|
| search hits |
|
| opinion_search |
|
| search hits |
|
| opinion_search |
|
| search hits |
|
| search hits |
|
| docket_lookup |
|
| court_list |
|
| case_detail (cluster) |
|
| case_detail (cluster) |
|
| case_detail (opinion) |
| same names | citation_lookup (per citation) |
|
| citation_lookup (per citation) |
|
| citation_lookup (per citation) |
Install
Nothing to clone. Point your MCP client at it and npm fetches it on first run:
{
"mcpServers": {
"courtwatch": {
"command": "npx",
"args": ["-y", "@haksanlulz/mcp-courtwatch"],
"env": { "COURTLISTENER_API_TOKEN": "your-courtlistener-token" }
}
}
}git clone https://github.com/haksanlulz/mcp-courtwatch
cd mcp-courtwatch
npm install
npm run build # emits dist/; the published bin is dist/index.jsnpm start runs the TypeScript directly via tsx without building.
API token
case_detail and citation_lookup need a free CourtListener token, and the other tools run faster (higher rate limit) with one. Create a free account, open Profile then the API page, and copy the token. Docs: https://www.courtlistener.com/help/api/rest/
Expose it as COURTLISTENER_API_TOKEN:
export COURTLISTENER_API_TOKEN=your-token-here # macOS / Linux
setx COURTLISTENER_API_TOKEN your-token-here # Windows (new shells)Without the token, opinion_search, docket_lookup, court_list, and judge_lookup still work at CourtListener's unauthenticated rate limit. case_detail and citation_lookup return a clear error telling you to set the token. The token is never logged.
Example
Call opinion_search with { "q": "warrantless search", "court": "scotus", "order_by": "most_cited", "limit": 1 } (output captured live, 2026-07; counts drift as CourtListener grows):
{
"query": { "q": "warrantless search", "court": "scotus", "filed_after": null, "filed_before": null, "order_by": "most_cited", "cursor": null },
"total_matches": 282,
"returned": 1,
"next_cursor": "cz01MTI3JnM9MTA5NjkzJnQ9byZkPTIwMjYtMDctMTcmcD0y",
"results": [
{
"case_name": "Monell v. New York City Dept. of Social Servs.",
"court": "Supreme Court of the United States",
"court_id": "scotus",
"date_filed": "1978-06-06",
"citations": ["56 L. Ed. 2d 611", "98 S. Ct. 2018", "436 U.S. 658", "1978 U.S. LEXIS 100", "16 Empl. Prac. Dec. (CCH) 8345", "17 Fair Empl. Prac. Cas. (BNA) 873"],
"docket_number": "75-1914",
"cite_count": 42298,
"status": "Published",
"snippet": "436 U.S. 658 (1978)\nMONELL ET AL.\nv.\nDEPARTMENT OF SOCIAL SERVICES OF THE CITY OF NEW YORK ET AL.\nNo. 75-1914.\nSupreme Court of the United States. ...",
"cluster_id": 109881,
"docket_id": 266243,
"absolute_url": "https://www.courtlistener.com/opinion/109881/monell-v-new-york-city-dept-of-social-servs/"
}
],
"disclaimer": "Raw public court records from CourtListener, reproduced as published. This is not legal advice and is not a substitute for a lawyer. Docket entries record filings, not rulings; the absence of a record is not evidence that nothing happened."
}The disclaimer is attached to every response, in the payload rather than only
in the tool description — a model composing an answer has the payload in hand
and may no longer be holding the description.
Then pass the cluster_id to case_detail ({ "id": 109881 }) for the citations, judges, and opinion ids, or case_detail with { "id": <opinion id>, "type": "opinion" } for the full opinion text. For the next page, pass next_cursor back as cursor.
Example: verifying citations before filing
Courts have sanctioned filings built on citations that do not exist. Run a draft's citations through citation_lookup before filing.
Call citation_lookup with { "text": "Tenants are protected here. See Roe v. Wade, 410 U.S. 113 (1973); Smith v. Imaginary, 999 U.S. 9999 (2099)." }. This endpoint requires a token this repo was built without, so unlike the example above the output here is constructed from the documented response shape, not captured from a live call (see Caveats):
{
"query": { "text_chars": 107 },
"citations_checked": 2,
"found": 1,
"not_found": 1,
"invalid": 0,
"not_checked": 0,
"all_verified": false,
"warning": "1 of 2 citation(s) did NOT verify: 1 not found in CourtListener (likely fabricated or mis-cited). Do not cite unverified authorities — check them by hand before filing.",
"results": [
{
"citation": "410 U.S. 113",
"verified": true,
"verdict": "FOUND",
"status": 200,
"error_message": null,
"normalized_citations": ["410 U.S. 113"],
"start_index": 45,
"end_index": 57,
"matches": [
{
"cluster_id": 108713,
"case_name": "Roe v. Wade",
"date_filed": "1973-01-22",
"citations": ["410 U.S. 113", "93 S. Ct. 705", "35 L. Ed. 2d 147"],
"precedential_status": "Published",
"citation_count": 12030,
"judges": "Blackmun",
"docket_id": 4463,
"absolute_url": "https://www.courtlistener.com/opinion/108713/roe-v-wade/"
}
]
},
{
"citation": "999 U.S. 9999",
"verified": false,
"verdict": "NOT_FOUND",
"status": 404,
"error_message": "Citation not found: '999 U.S. 9999'",
"normalized_citations": ["999 U.S. 9999"],
"start_index": 86,
"end_index": 99,
"matches": []
}
],
"disclaimer": "Raw public court records from CourtListener, reproduced as published. This is not legal advice and is not a substitute for a lawyer. Docket entries record filings, not rulings; the absence of a record is not evidence that nothing happened."
}The fabricated citation comes back NOT_FOUND with a top-level warning. Per-citation status mirrors the API's own codes: 200 found, 300 found with multiple matching clusters (FOUND_MULTIPLE — a real citation, ambiguous mapping), 400 unknown reporter, 404 not found, 429 past the 250-citations-per-call cap (NOT_CHECKED_OVER_CAP — split the text and re-run the rest). A lookup that recognizes zero citations says so in a note instead of pretending to have verified anything.
Caveats
Built without a token, so:
The
case_detailfield names (cluster and opinion objects) come from the Case Law API docs plus the search-result shape, not from a live authenticated GET (the/clusters/and/opinions/endpoints return HTTP 401 without a token). The normalizer is defensive: unknown or missing values coerce tonull(or empty arrays) rather than throwing, and citations accept either string or object form. Runnpm run smokewith a real token to confirm these end to end.The
citation_lookupresponse shape (per-citation fields, the 200/300/400/404/429 status codes, the serializer-level 64,000-char text cap, the 250-citation per-request cap) comes from the CourtListener source (cl/citations/api_views.py,api_serializers.py,cl/settings/project/citations.py) and the Citation Lookup docs, not from a live authenticated POST (the endpoint returns HTTP 401 without a token). The normalizer is defensive like the rest. Runnpm run smokewith a token: it checks one real citation (410 U.S. 113, Roe v. Wade) plus one fabricated one and fails unless the real one resolves and the fake comes backNOT_FOUND.The clusters returned by
citation_lookupdo not include the court (in CourtListener's model the court hangs off the docket, not the cluster). For the court, follow the match'sabsolute_urlor pass itscluster_idtocase_detailand thedocket_idonward. Deliberately not auto-fetched here: a 250-citation brief would fan out into hundreds of extra docket calls.docket_numberis folded into the free-textqterm rather than sent as a dedicated field, so matching is best-effort. If a known docket number under-returns, also pass the case name inq.court_listapplies itsqname filter across the full courts table, walked one page at a time server-side (the/courts/endpoint ignorespage_size, so the ~3,400 courts span ~170 pages of ~20 up to a safety cap). Scope byjurisdictionto page less; a token is recommended for the unfiltered full-table scan.opinion_searchanddocket_lookupreturn one fixed/search/page of ~20 results; for more, pass the response'snext_cursorback as thecursorargument. The endpoint ignorespage_size, solimitcannot exceed one page (it is capped at 20 rather than advertising an unreachable number).The
order_byvalues, thecourt/filed_after/filed_beforefilters, and the search / courts / people field names match the live API, as does the fixed ~20-row page size of/search/and/courts/(both ignorepage_size). The token-gated behavior ofcase_detailis the main thing the keyed smoke should confirm.
Develop
npm test # vitest, fetch mocked with the documented response shapes (no token needed)
npm run smoke # one live call per tool (needs COURTLISTENER_API_TOKEN; skips cleanly without)
npm run typecheckAI assistance
This project was built with AI assistance (Claude). Correctness was established by the test suite and typecheck (npm test, npm run typecheck): every tool is driven through a real MCP client over an in-memory transport with fetch stubbed to the documented CourtListener response shapes, and the unauthenticated search / courts / people surfaces were additionally checked against the live API. The token-gated endpoints are verified only to the extent the Caveats state, with npm run smoke as the live confirmation path. The author is accountable for what ships here.
License
MIT. See LICENSE. Data from CourtListener / the Free Law Project (public court records and openly licensed legal data). Unofficial, not affiliated with CourtListener or the Free Law Project.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP Server providing AI agents access to over 3 million US court decisions via CourtListener and EU legislation via EUR-Lex, with tools for searching cases, citations, judges, and court information.Last updated6MIT
- Alicense-qualityCmaintenanceAn MCP server providing AI agents access to CourtListener's comprehensive legal database, featuring semantic search, hybrid search, citation verification, and research tools.Last updated7MIT
- Alicense-qualityCmaintenanceA remotely callable MCP server for US legal research that provides tools to search, retrieve, and analyze US case law from the CourtListener API, enabling agents to build evidence packs from primary sources without generating legal content.Last updatedMIT
- AlicenseAqualityDmaintenanceAn MCP server that provides AI assistants access to the CourtListener legal database (US court opinions, dockets, RECAP, PACER, oral arguments, judges) and the full eCFR federal regulations via the official CourtListener API v4. It supports bring-your-own-key authentication and is designed for use with MCP-compatible clients like Claude, VS Code, and Cursor.Last updated342MIT
Related MCP Connectors
MCP for CourtListener: US federal and state opinions, dockets, judges, plus eCFR regulations.
CourtListener MCP — Free Law Project's CourtListener API (free, no auth required for basic access)
Search US court opinions, federal dockets, judges, citations, and oral arguments via CourtListener.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/haksanlulz/mcp-courtwatch'
If you have feedback or need assistance with the MCP directory API, please join our Discord server