Skip to content

FLP/CourtListener: initial outreach — heads-up, API-budget standing, and two upstream bug reports #154

Description

@modelmirror

Maintainer action (manual, not a pipeline task). This is the single initial
outreach to Free Law Project / CourtListener
— folding the courtesy heads-up,
the API-budget confirmation, and the two upstream courtlistener-api-client bug
reports into one contact so we reach out once, with a plan, rather than
piecemeal. Do these together around the public flip.

Consolidates what were three separate issues (the courtesy heads-up here, plus the
two upstream bug reports previously tracked apart). The bug reports are kept below
as self-contained items with paste-ready drafts.

Why one outreach

Good citizenship and it de-risks the relationship: a public, automated project
that builds on CourtListener / FLP data should introduce itself. And a concrete,
helpful bug report is a good opener — leading with two well-diagnosed fixes to
their own MCP client makes the first contact a contribution, not just a
notification. The data-terms position is already written down in
docs/data-sources.md; this issue is the outreach around it.


Item 1 — Courtesy heads-up

  • Send FLP a short note: what the project is, that it runs an automated
    consumer against their API + bulk exports, that the derived corpus stays
    access-gated (only model-generated judgments are public), and that we
    attribute them (README + NOTICE).

Item 2 — Confirm our API-budget standing

  • Confirm our token's standing on the API budget. As of May 2026 FLP folded
    full API access into paid memberships (free EDU tier for academics), with
    grandfathering for tokens that have made 1,000+ requests. Our budget assumes
    the standard free authenticated tier (5/min · 50/hr · 125/day); confirm that
    still holds for our token, or obtain a membership tier if more throughput is
    needed (no code change — config/tracking.yaml + the governor already cap
    us).

Item 3 — Upstream bug report A: missing MCP assets in the 1.0.0 wheel

File on
freelawproject/courtlistener-api-client,
or hand it over as part of the outreach above.

Context. Our agent cells launch the official CourtListener MCP server from the
pinned courtlistener-api-client[mcp]==1.0.0. It crashed at startup on every
engine; we launch it through a missing-assets shim in fedcourtsai.mcp (keyed to
this exact pin, self-retiring on a pin bump). Once upstream ships a fixed release,
bump the manifest pin in config/predictors.yaml / config/evaluators.yaml and
delete the shim.

  • File the report below.
Draft report — ready to paste upstream

Title: courtlistener-mcp entry point crashes at startup: courtlistener/mcp/assets/ missing from the 1.0.0 wheel and sdist

Body:

The courtlistener-mcp console script from courtlistener-api-client[mcp]==1.0.0 crashes immediately on launch:

$ uvx --from 'courtlistener-api-client[mcp]==1.0.0' courtlistener-mcp
...
FileNotFoundError: [Errno 2] No such file or directory:
'.../site-packages/courtlistener/mcp/assets/favicon.svg'

Cause: create_mcp_server() (courtlistener/mcp/server.py, ~line 68) unconditionally reads assets/favicon.svg and assets/apple-touch-icon.png to embed as server icons, but the courtlistener/mcp/assets/ directory is not shipped in the 1.0.0 wheel or sdist (verified by listing both artifacts from PyPI — no assets/ entries). So every stdio launch of the published package fails before the MCP handshake; MCP clients surface it only as a generic startup failure (e.g. Gemini CLI's "MCP issues detected").

Fix suggestions:

  1. Include courtlistener/mcp/assets/ in the package data (e.g. package-data / MANIFEST.in + include_package_data) and cut a patch release; and/or
  2. Make the icon loading tolerant of missing files (skip the icons=[...] metadata rather than crash) so the server still starts if packaging regresses.

Repro: any machine with uv: uvx --from 'courtlistener-api-client[mcp]==1.0.0' courtlistener-mcp — crashes as above. With the two files present (any bytes), the server starts and serves its 14 tools normally, which is how we're working around it.

Happy to provide more detail — we're using the MCP server headless in CI (stdio transport, token via env) and it works well once past this.

Item 4 — Upstream bug report B: stdio mode needs REDIS_URL for every call

Sibling of Item 3 — the two reports can go up together. File on
freelawproject/courtlistener-api-client.

Context. Once the missing-assets shim got the pinned server starting, every
predict cell then hit a second stdio-mode bug: every search / call_endpoint
call failed server-side with REDIS_URL is not set; cannot access session store.
Agents flagged it across the 2026-07-11 predict runs and fell back to the REST
API. We work around it by pre-seeding the server's module-level Redis client with
an in-process fakeredis instance in the same shim (fedcourtsai.mcp, keyed to
this exact pin, self-retiring on a pin bump). Once upstream ships a fixed release,
bump the manifest pin and delete the shim.

  • File the report below.
Draft report — ready to paste upstream

Title: stdio mode is unusable in 1.0.0: every search/call_endpoint call fails with "REDIS_URL is not set; cannot access session store."

Body:

Running the MCP server from courtlistener-api-client[mcp]==1.0.0 over stdio (the courtlistener-mcp entry point / main()), the server starts and completes the MCP handshake, but every call to search or call_endpoint fails with:

RuntimeError: REDIS_URL is not set; cannot access session store.

Cause: the tools unconditionally persist pagination state (the query_id resume mechanism) through the Redis-backed session store — search_tool.py and call_endpoint_tool.py both call prepare_query_id()store_session_query()get_redis() (courtlistener/mcp/tools/utils.py, ~line 186), which raises when REDIS_URL is unset. HTTP mode requires REDIS_URL at startup (create_http_app()), but stdio mode configures no session store at all, so the entry point boots cleanly and then fails on every retrieval call — there is no working configuration of 1.0.0 stdio mode short of running a real Redis next to it.

Fix suggestions:

  1. Default stdio mode to an in-memory session store (a dict with TTL, or fakeredis) when REDIS_URL is unset — a single-process stdio session only ever holds its own resume state; and/or
  2. Fail fast at startup in stdio mode when the store is unavailable, rather than per-call, so clients surface a clear configuration error instead of tool-level failures mid-session.

Repro: launch courtlistener-mcp over stdio with REDIS_URL unset (any MCP client), call search with any query — the tool call errors as above. Pre-seeding courtlistener.mcp.tools.utils.redis_client with fakeredis.aioredis.FakeRedis(decode_responses=True) before main() fully restores stdio operation, which is how we're working around it.

(Same deployment context as our other report: headless CI, stdio transport, API token via env.)


Reference

  • docs/data-sources.md — terms, redistribution, API budget, PII stance.
  • CourtListener terms: https://www.courtlistener.com/terms/
  • Both shims live in fedcourtsai.mcp, keyed to courtlistener-api-client[mcp]==1.0.0
    and self-retiring on a pin bump — so landing a fixed upstream release lets us
    delete both.

Metadata

Metadata

Assignees

No one assigned

    Labels

    manualHuman action required; triggers no workflow

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions