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
Item 2 — Confirm our API-budget standing
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.
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:
- Include
courtlistener/mcp/assets/ in the package data (e.g. package-data / MANIFEST.in + include_package_data) and cut a patch release; and/or
- 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.
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:
- 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
- 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.
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-clientbugreports 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
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
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 capus).
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 everyengine; we launch it through a missing-assets shim in
fedcourtsai.mcp(keyed tothis exact pin, self-retiring on a pin bump). Once upstream ships a fixed release,
bump the manifest pin in
config/predictors.yaml/config/evaluators.yamlanddelete the shim.
Draft report — ready to paste upstream
Title:
courtlistener-mcpentry point crashes at startup:courtlistener/mcp/assets/missing from the 1.0.0 wheel and sdistBody:
The
courtlistener-mcpconsole script fromcourtlistener-api-client[mcp]==1.0.0crashes immediately on launch:Cause:
create_mcp_server()(courtlistener/mcp/server.py, ~line 68) unconditionally readsassets/favicon.svgandassets/apple-touch-icon.pngto embed as server icons, but thecourtlistener/mcp/assets/directory is not shipped in the 1.0.0 wheel or sdist (verified by listing both artifacts from PyPI — noassets/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:
courtlistener/mcp/assets/in the package data (e.g.package-data/MANIFEST.in+include_package_data) and cut a patch release; and/oricons=[...]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_URLfor every callSibling 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_endpointcall 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
fakeredisinstance in the same shim (fedcourtsai.mcp, keyed tothis exact pin, self-retiring on a pin bump). Once upstream ships a fixed release,
bump the manifest pin and delete the shim.
Draft report — ready to paste upstream
Title: stdio mode is unusable in 1.0.0: every
search/call_endpointcall fails with "REDIS_URL is not set; cannot access session store."Body:
Running the MCP server from
courtlistener-api-client[mcp]==1.0.0over stdio (thecourtlistener-mcpentry point /main()), the server starts and completes the MCP handshake, but every call tosearchorcall_endpointfails with:Cause: the tools unconditionally persist pagination state (the
query_idresume mechanism) through the Redis-backed session store —search_tool.pyandcall_endpoint_tool.pyboth callprepare_query_id()→store_session_query()→get_redis()(courtlistener/mcp/tools/utils.py, ~line 186), which raises whenREDIS_URLis unset. HTTP mode requiresREDIS_URLat 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:
fakeredis) whenREDIS_URLis unset — a single-process stdio session only ever holds its own resume state; and/orRepro: launch
courtlistener-mcpover stdio withREDIS_URLunset (any MCP client), callsearchwith any query — the tool call errors as above. Pre-seedingcourtlistener.mcp.tools.utils.redis_clientwithfakeredis.aioredis.FakeRedis(decode_responses=True)beforemain()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.fedcourtsai.mcp, keyed tocourtlistener-api-client[mcp]==1.0.0and self-retiring on a pin bump — so landing a fixed upstream release lets us
delete both.