fplai-cli
v0.1.0
Published
Command-line client for the read-only FPLai agent API: health, content discovery, page Markdown, MCP and A2A.
Maintainers
Readme
fplai
Command-line client for the public, read-only agent API of FPLai, the AI assistant for Fantasy Premier League managers.
It wraps the same surface an agent would call over HTTP — the versioned REST endpoints, the MCP endpoint, and the A2A endpoint — so you can discover FPLai content and read pages as Markdown without writing any HTTP code.
Zero runtime dependencies. Node 18 or newer.
Install
npx fplai-cli health # no install
npm i -g fplai-cli # installs the `fplai` command globallyCommands
fplai health
Liveness of the public agent surface (GET /api/v1/agent/health).
$ fplai health
ok api v1
site https://fplai.app
mcp https://fplai.app/mcp
generatedAt 2026-09-09T20:15:45.647Zfplai content-index
Seasons, content families, and matching public routes (GET /api/v1/agent/content-index).
$ fplai content-index --season 2026-27 --family captain-picks --limit 3
4 of 4397 public routes match (showing 3)
seasons: 2027-28, 2026-27, 2025-26
families: best (56), best-xi (1), … +63 more (--json for all)
/fpl/2026-27/captain-picks/
2026 27 Captain Picks
...Options: --season <YYYY-YY>, --family <slug>, --q <text> (case-insensitive substring over path, title, family, season), --limit <1-100> (default 25).
fplai content-index --q haaland --limit 5
fplai content-index --family compare --json | jq '.matches[].path'fplai page <path-or-url>
Prints one public FPLai page as Markdown.
fplai page /fpl/2026-27/captain-picks/gw01/
fplai page https://fplai.app/pricingPages routed through the Worker negotiate on Accept: text/markdown (the acceptmarkdown.com convention). Statically served pSEO pages (player, team, season tables) return HTML only, so the CLI transparently falls back to the MCP tool get_page_markdown for those — you get Markdown either way. Use --verbose to see which path was taken.
fplai overview
Site entry points and discovery documents, via the MCP tool get_site_overview (POST /mcp).
$ fplai overview
site https://fplai.app
home https://fplai.app/
fplHub https://fplai.app/fpl/
llms https://fplai.app/llms.txt
...fplai ask "<text>"
Asks the A2A content agent (POST /a2a, message/send). It routes the text to one of three read-only skills — site-overview, find-fpl-content, page-markdown — and answers synchronously.
$ fplai ask "find captain picks for 2026-27"
Found 4 public FPLai routes for 2026-27 in captain-picks.
- Captain Picks Gw01: https://fplai.app/fpl/2026-27/captain-picks/gw01/
...--json prints the whole A2A message, including the structured data part.
fplai openapi
Prints the URL of the OpenAPI 3.1 description and a summary of its operations. --json prints the whole document.
fplai openapi
fplai openapi --json > agent-api.jsonGlobal options
| Flag | Meaning |
| --- | --- |
| --json | Print the raw JSON payload instead of the readable rendering |
| --base-url <url> | Origin to talk to (default https://fplai.app; also FPLAI_BASE_URL) |
| --verbose | Log each request, its status, and RateLimit-Remaining to stderr |
| --retry | On a 429, wait out Retry-After and retry once |
| --help, -h / --version, -v | Help / version |
Exit codes: 0 success, 1 API error, 2 usage error.
Errors
Every non-2xx REST response is an RFC 9457 problem detail (application/problem+json) with a stable machine-readable code. The CLI prints it as code: title — detail on stderr:
$ fplai content-index --limit 0
fplai: invalid_query: Invalid Query Parameter — Query parameter "limit" must be between 1 and 100; received "0".Codes: not_found, method_not_allowed, invalid_query, rate_limited, internal_error. Branch on code, not on the type URI text. /mcp and /a2a use JSON-RPC 2.0 error envelopes instead (printed as jsonrpc <code>: <message>), except for 429, which is a problem detail on every transport.
Rate limits
60 requests per 60 seconds per client IP across /api/v1/*, /api/agent/*, /mcp, and /a2a. Responses carry RateLimit-Policy / RateLimit (IETF structured fields) and the legacy RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset. Enforcement is best-effort and per edge isolate, not a hard global quota — treat the headers as cooperative signalling.
The CLI never retries in a loop. A 429 exits 1 and prints Retry-After; --retry waits that long and tries once more.
Versioning
The CLI talks to the versioned surface /api/v1/agent/*. The unversioned /api/agent/* paths still work but are deprecated (RFC 9745 Deprecation + Link: rel="successor-version"); a Sunset header will announce any removal at least 12 months in advance. Breaking changes ship as /api/v2/...; additive fields may appear inside v1.
What this is not
- No account data. Nothing here reads or writes an FPLai account, a saved plan, a linked FPL team, or a squad analysis. Those are only available to a signed-in human in the web or iOS app.
- Read-only. No transfers, no writes, no mutations of any kind.
- No auth, and no way to get any. The whole public agent surface is unauthenticated; agents cannot self-register. See auth.md.
- Not the FPL API. This serves FPLai's own published content, not the official Fantasy Premier League endpoints.
Docs
- Developer docs: https://fplai.app/developers
- Agent guide: https://fplai.app/.well-known/service-docs/agent-guide.md
- OpenAPI 3.1: https://fplai.app/openapi.json
- Agent Card (A2A): https://fplai.app/.well-known/agent-card.json
- Auth contract: https://fplai.app/auth.md
License
MIT © FPLai
