PSLRA Case Tracker
Reads Business Wire securities class action announcements through the Google News index, since Business Wire's own site refuses automated readers; used to collect headlines from that source.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PSLRA Case Trackerrefresh the tracker, then show deadlines due in the next 14 days"
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.
PSLRA Case Tracker
An open-source tracker for newly filed US securities class actions and their PSLRA lead plaintiff deadlines, with an MCP server so Claude can query it.
One securities class action is announced separately by eight to fifteen plaintiffs' firms. This tool reads those announcements from free public sources, recognises when many of them describe one lawsuit, and keeps one case per lawsuit with its ticker, class period, deadline, every firm that announced it, and the court docket when one can be found.
Runs with no API keys: extraction and classification are plain regular expressions. Optionally, set a TypeSafe key and the classification decisions are made by the Jev model instead (see Optional: Jev).
Not legal advice. Deadlines are read by regex from law firm press releases and can be wrong. Verify against the published notice or the court docket before relying on a date.
Quick start
uv sync # or: pip install -e .
uv run pslra-tracker run # one pass over the live sources (first run takes a few minutes)
uv run pslra-tracker cases --due-within 14run also writes output/report.html, cases.csv and cases.json. The record itself lives in SQLite at ~/.pslra-tracker/tracker.db (override with --db or PSLRA_DB).
Related MCP server: CourtListener MCP Server
Connect it to Claude
Claude Code (this repo ships a .mcp.json, or add it anywhere):
claude mcp add pslra-tracker -- uv run --directory /path/to/pslra-tracker pslra-tracker serveClaude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"pslra-tracker": {
"command": "uv",
"args": ["run", "--directory", "/path/to/pslra-tracker", "pslra-tracker", "serve"]
}
}
}Remote connector (claude.ai and Claude Desktop "custom connector"): see Remote connector with sign-in.
Then ask things like "refresh the tracker, then which lead plaintiff deadlines fall in the next two weeks?" or "which securities dockets were filed this week that no firm has announced yet?"
Tools
Tool | What it does |
| One pass over the sources. The only tool that touches the network. |
| Cases by status, deadline window, ticker, company, or first-seen date. |
| One case in full: deadline votes, class period, firms, docket, every source announcement and how it was matched. |
| Every announcement ever read, including those set aside, with the decision made about each. |
| Federal securities dockets from CourtListener, matched or not yet matched to a case. |
| Each source's last success, last error and newest item reached, plus record counts. |
Remote connector with sign-in
Custom connectors are reached from Anthropic's servers, not from your computer, so the tracker needs a public https address and a login.
export PSLRA_AUTH_PASSWORD='a long passphrase'
pslra-tracker serve --http --port 8765 --public-url https://tracker.example.com--public-url is the address Claude will use. It switches on OAuth 2.1: Claude registers itself, opens a sign-in page in your browser, and you approve by typing the password. In Claude, add a custom connector with the URL https://tracker.example.com/mcp.
Put TLS in front (a reverse proxy, or a tunnel such as
cloudflared tunnel --url http://127.0.0.1:8765for testing; pass the tunnel's https address as--public-url).Access tokens last an hour and refresh automatically for 30 days. Only token hashes are stored, in the tracker's SQLite file.
PSLRA_API_TOKENoptionally sets a static bearer token for scripts (Authorization: Bearer ...).Without
--public-urlthe server only binds to localhost and has no login. It refuses to bind to any other address without sign-in.One password, one operator. There are no per-user accounts; anyone with the password can read and refresh the tracker.
Optional: Jev for classification
Regex is good at copying a date or a ticker out of a release. It is poor at deciding what a release is. With a TypeSafe key, two judgments go to Jev, a small model that returns a typed answer with a confidence rather than text:
uv sync --extra jev # or: pip install -e ".[jev]"
export TYPESAFE_API_KEY=...Judgment | Without a key | With Jev |
Filing, reminder, investigation, settlement or noise? | Keyword rules on the headline and body | One Choice per announcement; taken over the keyword rule at confidence ≥ 0.60 (≥ 0.80 to discard on the headline alone) |
What kind of case is this docket? | Caption keywords: SEC and derivative ruled out | One Choice on caption and cause of action; taken at ≥ 0.70, so short-swing 16(b) suits and the like are also ruled out |
Jev never extracts values. Dates, tickers and class periods still come from regex. Below the confidence floor, or on any API error, the keyword rule decides, so behaviour degrades rather than breaks. When Jev and the rule disagree, both verdicts are stored (search_announcements shows jev: investigation (0.95); regex said reminder).
Cost at the time of writing is $0.042 per million input tokens; a first run over a week of wires is a few cents. --no-jev or PSLRA_JEV=0 forces regex only.
Sources
All checked live on 5 October 2026.
Source | Kind | Default | How it is read |
PR Newswire | wire | on | Its own search page, phrase "securities class action". Highest volume, noisiest. |
Business Wire | wire | on | Its site refuses automated readers (HTTP 403), so it is reached through the Google News index. Headlines only. |
GlobeNewswire | wire | on | Its "class action" tag page. |
CourtListener | court | on | Free Law Project's archive of federal dockets, searched by filing date for nature-of-suit code 850. Works without a key; anonymous access is rate-limited, so the sweep pauses between pages. A free |
Only public distribution channels are read: the newswires every firm publishes through, and the court record. Individual law firm websites are deliberately left out.
Pick sources per run with --sources prnewswire globenewswire, skip the docket sweep with --no-courts.
How it works
Collect. Read each source's current listing.
Skip what is already read. A web address already in the record costs nothing further.
Keep real cases. Investigations, settlements and unrelated news are set aside, from the headline alone where possible. They are still recorded, with the reason.
Read the detail. Ticker, exchange, company, deadline, class period, firm, and the docket number when the release quotes one.
Match or create. Compare against existing cases, strongest rule first. Nothing below 0.85 is merged.
Rule | Confidence |
Ticker + same deadline | 0.98 |
Ticker + same class period | 0.96 |
Ticker + deadline within 10 days (recorded as a conflict) | 0.92 |
Ticker + same class period end | 0.90 |
Company name + same deadline | 0.88 |
Ticker, where one side has no deadline yet | 0.86 |
Company name alone | 0.75, never merged |
A case's facts are a majority vote over its announcements, so one firm's typo does not move the deadline, and disagreement is reported (deadline_conflict, deadline_votes, class_period_conflict).
Safeguards
Silence is not an answer. A source that cannot be reached is recorded as an error and retried next run. Its watermark does not move.
Nothing is lost. Announcements over a run's reading cap (
--max-fetch, per source) are deferred, not dropped. Bare headlines with no deadline never open a case; they are held and retried each run until their case exists.In doubt, do not merge. A weak resemblance opens a separate case. An announcement naming no company and no ticker is refused.
Impossible dates are dropped. A "deadline" inside the class period, or weeks before the release, is a misread.
One run at a time. A file lock stops two passes colliding.
Every decision is recorded.
search_announcementsshows what happened to each announcement and why.
Court dockets
A lawsuit appears on the docket the day it is filed, typically weeks before any press release. Two caveats are built in:
A filing code is not a classification. Code 850 also carries derivative suits, SEC enforcement and individual investor suits. Dockets are labelled from the caption and cover sheet only:
regulatory_enforcement,derivativeand (with Jev)not_class_actionare ruled out, and everything else stays asecurities_candidate, meaning not ruled out, not confirmed.classified_byrecords whether a keyword rule or Jev decided. Nothing reads the complaint.A docket does not state the deadline. The 60-day window runs from publication of the notice, not from filing. Where
get_caseoffers a date computed from a docket it is markedestimated.
Dockets are linked to a case by the docket number a release quotes, or by company name plus a filing date within 100 days before the deadline. Unlinked candidates stay visible through list_court_dockets.
Configuration
Variable | Purpose |
| SQLite file. Default |
| How the tracker identifies itself to sources. |
| Optional. Lifts CourtListener's anonymous rate limit. |
| Optional. Turns on Jev classification. |
| Required with |
| Same as |
| Optional static bearer token for scripts, HTTP mode only. |
| Keeps the key but forces regex only. |
Project layout
pslra_tracker/
sources.py newswire readers and the CourtListener docket search
extract.py regex extraction: ticker, company, deadline, class period, firm, docket number
judge.py optional Jev judgments, with regex fallback
pipeline.py collect, skip seen, set aside, extract, match or create
store.py SQLite record of announcements, cases, dockets and watermarks
server.py MCP server
auth.py OAuth sign-in for the HTTP transport
cli.py command line
report.py HTML and CSV report
tests/ unit tests and 19 real releases used as a benchmarkTests
uv run --extra dev pytest
uv run pslra-tracker run --from-json tests/data/real_items.json --benchmark tests/data/bench.txtThe suite runs offline with no keys (Jev is replaced by a stub). tests/data/real_items.json holds 19 real releases from September 2026; bench.txt lists the 16 true tickers. Current result: 16/16 cases, no false cases, the Pentair class-period discrepancy flagged.
Known limits
Extraction is regex with or without Jev. Company names are heuristic and sometimes truncated.
Business Wire items are headlines only, so they rarely carry a class period.
Press releases trail the filing; the docket sweep narrows that gap but its candidates need a human or a complaint-reading step before they count as cases.
Securities cases only. Other practice areas would need their own nature-of-suit codes and classifiers.
Sources change their pages. A layout change surfaces as a source error in
source_status, not as an empty result.Be polite: the tracker identifies itself (
PSLRA_USER_AGENT) and pauses between requests. Keep it that way.
Licence
MIT
Available Tools
6 toolsget_caseARead-only
Full detail for one case by id, or every case for a ticker: the deadline and how many announcements voted for each date, the class period, every firm that announced it, the linked court docket when one was found, and every source announcement with how it was matched.
| Name | Required | Description | Default |
|---|---|---|---|
| ticker | No | ||
| case_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds real behavioral value beyond that by disclosing the returned contents (deadline, vote counts per date, class period, announcing firms, linked docket, matched source announcements), which matters because there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that leads with the two retrieval modes before the field list. The trailing enumeration is long but every item is informative about the return payload, so little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameter descriptions, the description is the sole source of contract information. It documents return fields well, but omits ambiguous-case handling (both params supplied, neither supplied) and any pagination or volume limits for the ticker-wide mode.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameter burden, and it does clarify that case_id selects one case while ticker selects all cases for a ticker. It does not explain precedence when both are supplied or behavior when neither is given, leaving a real gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource clearly: returns full detail for one case by id, or all cases for a ticker, and enumerates what detail means. An agent can tell it apart from a bulk lister without opening the schema, though it never names the sibling tools (list_cases, search_announcements) it is distinct from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the usage modes (by id vs by ticker) but gives no explicit when-to-use guidance, no exclusions, and no routing to alternatives such as list_cases for browsing. An agent must infer that this is the detail-retrieval endpoint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_casesARead-only
List tracked securities class actions, soonest lead plaintiff deadline first.
status: open (deadline today or later), expired, no_deadline_found, or all. due_within_days: only cases whose deadline falls within this many days. ticker: exact stock ticker. query: substring of the company name. first_seen_since: ISO date; only cases first seen on or after it (what is new).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | No | ||
| status | No | open | |
| ticker | No | ||
| due_within_days | No | ||
| first_seen_since | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a read-only, closed-world operation. The description adds genuinely useful behavioral context: the result ordering and the meaning of the default status=open. It says nothing about result size or how the limit interacts with ordering, which for a 6-param list tool would be worth one line.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One lead sentence plus a tight bullet list, front-loaded with the resource and ordering. Each line earns its place; the only minor cost is abstracting the filters as a glossary rather than prose, which is still easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-param, no-output-schema listing tool, the description covers filtering and ordering adequately, but omits anything about the limit/pagination dimension even though limit is a top-level parameter with a default of 50. An agent can call it correctly, but cannot reason about result-set size.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it documents 5 of 6 parameters with real differentiation: ticker is an exact match while query is a substring match, status enumerates the accepted values with their meaning, and first_seen_since is scoped as an ISO date. Only limit is left undocumented (its default 50 is visible in the schema).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List tracked securities class actions') plus the ordering ('soonest lead plaintiff deadline first'), which distinguishes it from get_case (single case) and search_announcements. It does not explicitly contrast with the siblings, but the resource scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The bullets explain how each filter narrows results, including the useful hint that first_seen_since answers 'what is new', so usage is implied through parameter semantics. There is no explicit when-to-use-this-vs-get_case/search_announcements guidance or statement of default behavior beyond the status enum.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_court_docketsARead-only
Federal dockets filed under nature-of-suit code 850 (Securities/Commodities), from CourtListener. These appear the day a case is filed, typically weeks before any press release.
A filing code is not a classification: code 850 also carries derivative suits, SEC enforcement
and individual investor suits. classification is read from the caption and cover sheet only
(classified_by says whether a keyword rule or the Jev model decided), so securities_candidate
means "not ruled out", and even securities_class_action is unconfirmed until the complaint is read.
unmatched_only: dockets not yet linked to a tracked case (possible cases no firm has announced).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| classification | No | ||
| unmatched_only | No | ||
| filed_within_days | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true, so the description is free to spend its words on subtler behavior, and it does: it warns that a filing code is not a classification, that `securities_candidate` means 'not ruled out' and even `securities_class_action` is unconfirmed. That is real epistemic context an agent needs before trusting the output. It omits ordering, pagination, and rate-limit behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then layered caveats. Dense but each sentence adds information; the only slight drag is the stacked disclaimers in the middle paragraph.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and only two annotations, the description does the heavy lifting well, covering provenance, timing, classification caveats, and the unmatched case use. Still missing what a returned docket record looks like beyond the classification fields and how results are ordered or paged.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the parameter burden. It richly explains the `classification` enum semantics and the meaning of `unmatched_only`, but leaves `limit` and `filed_within_days` (only obliquely implied by the 'weeks before' framing) undocumented. Partial compensation for a 4-param tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: listing federal dockets under nature-of-suit code 850 (Securities/Commodities) from CourtListener. The scope is unusually precise, but it never names a sibling (list_cases, search_announcements), so an agent must infer the boundary itself.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied rather than stated: the timing note ('appear the day a case is filed, weeks before any press release') and the 'unmatched_only' gloss ('possible cases no firm has announced') hint at when the tool is useful. But there is no explicit when-to-use/when-not or routing to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_casesAIdempotent
Run one pass: read the newswires, set aside what is not a filed case, extract ticker / class period / deadline, and merge each announcement into its lawsuit.
sources: any of prnewswire, businesswire, globenewswire (default: all three). days: look-back window. max_fetch: cap on article bodies read per source this run; anything over the cap is deferred to the next run, not dropped. include_courts: also sweep CourtListener for securities dockets (nature of suit 850) and link them to cases. A source that cannot be reached is reported under its name with an error and retried next time.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| sources | No | ||
| max_fetch | No | ||
| include_courts | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only declaring readOnlyHint=false, openWorldHint=true and idempotentHint=true, the description adds real behavioral value: it discloses that cap-exceeding articles are deferred rather than dropped, that unreachable sources are reported by name and retried, and that it merges into existing lawsuits (a mutation). It stops short of describing result/output shape beyond the error-reporting note.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the pipeline in the first sentence, then compact per-parameter clauses. It is longer than a typical description but every clause corresponds to an undocumented parameter or a behavior (deferral, retry) that an agent needs, so the length is earned.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter mutation tool with no output schema and 0% schema coverage, the description covers parameters, external I/O, failure handling, and partial result reporting. The main remaining gap is a fuller account of what a run returns or how progress is observed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does so: it defines sources with the concrete allowed values (prnewswire, businesswire, globenewswire) plus the 'all three' default, days as a look-back window, max_fetch as a per-source body cap, and include_courts as a CourtListener sweep limited to nature of suit 850. This supplies semantics the schema's bare typed properties entirely lack.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb+resource pipeline: read newswires, discard non-filed cases, extract ticker/class period/deadline, and merge announcements into lawsuits. An agent can tell this is the ingest/refresh job rather than a read tool like list_cases or search_announcements, though the description never names a sibling to sharpen the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied by 'Run one pass' and by the parameter semantics, but there is no explicit statement of when to call this versus get_case/list_cases/search_announcements, nor any prerequisite or exclusion. The operational notes (deferred over cap, retried on failure) hint at usage but do not route the agent among alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_announcementsBRead-only
Search every announcement the tracker has read, including those set aside, with the decision made about each (why it was set aside, or which case it joined and by which rule). kind: filing, reminder, investigation, settlement or other. source: e.g. prnewswire.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | ||
| limit | No | ||
| query | No | ||
| source | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuinely useful scope detail (includes set-aside announcements, reports why each was set aside or which case/rule absorbed it), but says nothing about ordering, pagination, or how 'limit' behaves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Compact and front-loaded: the return scope is stated first, then the two filtered fields. The kind/source glosses are terse but justified given zero schema description coverage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does decent work describing what comes back (announcement plus the decision about it). However, two of four parameters lack any semantics and there is no note on result volume or default limit behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameters. It usefully enumerates kind values (filing, reminder, investigation, settlement, other) and gives a source example (prnewswire), but 'query' and 'limit' are left entirely unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Search every announcement the tracker has read') and clarifies scope, including set-aside items and the decision attached to each. It does not explicitly distinguish itself from siblings like list_cases or get_case, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to reach for this tool versus list_cases/get_case, nor any prerequisite or exclusion. Usage is only inferable from the fact that it searches announcements and their decisions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
source_statusARead-only
Whether the Jev classifier is active, and every source with whether it is switched on, when it last succeeded, its last error, and the newest announcement reached, plus record counts. A source whose newest announcement has not moved for days while others are current has quietly stalled.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, and the description adds substantial value on top: it discloses the exact fields returned, the presence of error history, and a staleness heuristic for interpreting the output. It doesn't cover refresh cadence or whether the classifier status is live vs cached, but the diagnostic context is genuinely useful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the classifier state, then the per-source field list, then a single diagnostic sentence that earns its place by telling the agent how to read the data. Slightly dense in the middle enumeration but no wasted filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations describing returns, the description carries the burden of explaining the payload, and it does so reasonably: it lists the reported fields and gives a staleness interpretation. It stops short of describing the structure/shape of the response, but is adequate for a zero-arg status tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline is 4 — there is no parameter surface for the description to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete resource (sources) and enumerates exactly what is reported: classifier active state, on/off, last success, last error, newest announcement, and record counts. It's a monitoring/status tool, clearly distinct in intent from case/announcement siblings, though it never explicitly differentiates itself from them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied — the diagnostic note that a source whose newest announcement hasn't moved 'has quietly stalled' hints at when to consult this (health checking), but there is no explicit when-to-use, prerequisite, or alternative tool guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.2.0- First observed
get_case - First observed
list_cases - First observed
list_court_dockets - First observed
refresh_cases - First observed
search_announcements - First observed
source_status
TDQS
Scored across 6 tools
Most tools have clearly distinct purposes: ingestion, case lookup, case listing, announcement search, docket listing, and source health. The main ambiguity is between get_case and list_cases, since get_case with a ticker returns every case for that ticker while list_cases also lists cases with ticker/filter options.
Five of six tools follow a clear verb_noun snake_case pattern: refresh_cases, get_case, list_cases, search_announcements, list_court_dockets. The only deviation is source_status, which is a noun phrase rather than a verb-led action, but the overall convention remains readable and consistent.
Six tools is well-scoped for a focused PSLRA case-tracking server. Each tool covers a distinct part of the workflow: ingestion, case detail, listing, announcement search, docket discovery, and source health.
The surface covers ingestion, lookup, listing, announcement search, court docket discovery, and source diagnostics, which is strong for the domain. Minor gaps remain, such as no direct tool to manually create or update a case, but the automated refresh and query tools cover the core lifecycle.
Maintenance
Related MCP Connectors
Search U.S. case law, fetch opinions, and ask matter-aware legal questions over your documents.
Judge-level filing rules, court holidays and enforcement data for US federal and state courts.
Search public U.S. federal litigation: companies, cases, dockets and document metadata.
Primary-source SEC filing intelligence and financial/disclosure reconciliation for AI agents.
Related MCP Servers
- AlicenseCqualityAmaintenanceEnables Claude to access and manage your law firm's MyCase account, including cases, clients, tasks, invoices, and more.1001MIT
- FlicenseNot gradedqualityBmaintenanceEnables LLM-friendly access to the CourtListener legal database and eCFR for searching legal opinions, court cases, judges, documents, and federal regulations.12-

CourtAPI MCP Serverofficial
AlicenseAqualityDmaintenanceSearch and retrieve US federal court cases, dockets, claims, and documents via PACER — directly from Claude and other MCP-compatible AI assistants.1047 npmMIT- AlicenseNot gradedqualityBmaintenanceConnects Claude to MyCase legal practice management, enabling natural language queries for cases, contacts, calendar, billing, and more.55 npm5MIT