{
  "markdown": "# mcp-lrclib\n\n[![npm](https://img.shields.io/npm/v/mcp-lrclib.svg)](https://www.npmjs.com/package/mcp-lrclib)\n[![CI](https://github.com/smeet666/mcp-lrclib/actions/workflows/ci.yml/badge.svg)](https://github.com/smeet666/mcp-lrclib/actions/workflows/ci.yml)\n[![license](https://img.shields.io/npm/l/mcp-lrclib.svg)](./LICENSE)\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-6E56CF)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.smeet666/mcp-lrclib)\n[![Glama](https://glama.ai/mcp/servers/smeet666/mcp-lrclib/badges/score.svg)](https://glama.ai/mcp/servers/smeet666/mcp-lrclib)\n[![M8ven](https://m8ven.ai/badge/mcp/smeet666-mcp-lrclib-1gu2op?variant=verified)](https://m8ven.ai/mcp/smeet666-mcp-lrclib-1gu2op)\n[![LobeHub](https://lobehub.com/badge/mcp/smeet666-mcp-lrclib)](https://lobehub.com/mcp/smeet666-mcp-lrclib)\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lrclib&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1scmNsaWIiXX0%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=lrclib&config=%7B%22name%22%3A%22lrclib%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lrclib%22%5D%7D)\n\n<!-- m8ven-verify: a556ead8f1e452af912eefc4f7d5fcc3 -->\n\n[LRCLIB](https://lrclib.net) is a free, open database of song lyrics, built by\nthe people who use it and offered to anyone without a key or an account. It holds\ntwo forms of the words: the plain text of a song, and the LRC form, where every\nline carries the moment it is sung, which is what a karaoke display or a lyrics\npanel follows along with. A track is filed there by its title, its artist, its\nalbum and its duration, so the several releases of one song sit side by side.\n\nThis server connects a chat client to that database. You can search for a track\nby title, artist or album, read the plain words of a song, read its time-synced\nlines with their timestamps, and check the metadata of one release before\nreading it. It needs no API key and no account.\n\n_[Version française](#mcp-lrclib-français)_\n\n---\n\n## Install\n\n**One-click install**\n\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lrclib&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1scmNsaWIiXX0%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=lrclib&config=%7B%22name%22%3A%22lrclib%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lrclib%22%5D%7D)\n\n**Claude Code**\n\n```bash\nclaude mcp add lrclib -- npx -y mcp-lrclib\n```\n\n**Claude Desktop, Cursor, and any client using the standard config format**\n\n```json\n{\n  \"mcpServers\": {\n    \"lrclib\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-lrclib\"]\n    }\n  }\n}\n```\n\nNode 24 or later is required, and no environment variable has to be set.\n\n### With Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"lrclib\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"ghcr.io/smeet666/mcp-lrclib:2.0.1\"]\n    }\n  }\n}\n```\n\n`-i` keeps stdin open, which is where the protocol travels, and `-t` is left out\nbecause a TTY rewrites the stream. The container needs outbound HTTPS to\n`lrclib.net`, and nothing else: no volume, no port, no credential.\n\n### Bundle, without npm\n\nDownload `mcp-lrclib-2.0.1.mcpb` from\n[the latest release](https://github.com/smeet666/mcp-lrclib/releases/latest) and\nopen it. A client that supports MCP bundles installs it on its own, with no npm\nand no configuration file to edit. The bundle carries its dependencies, so\nnothing is fetched at install time.\n\n## What you can ask\n\n- \"Find me the lyrics of Le Sud by Nino Ferrer.\"\n- \"Give me the timed lyrics of Bohemian Rhapsody so I can follow along.\"\n- \"Which version of Hallelujah is on LRCLIB, and how long is each one?\"\n- \"Read me the second half of those lyrics.\"\n- \"Does track 3396226 have synced lyrics?\"\n\nThe ordinary path runs from a search to a reading: `search_tracks` names an `id`,\nand `get_lyrics` takes that id.\n\n## Tools\n\n| Tool            | What it does                                                  |\n| --------------- | ------------------------------------------------------------- |\n| `search_tracks` | Finds tracks by title, artist or album, with their metadata.  |\n| `get_lyrics`    | Reads the words of one track, plain or with their timestamps. |\n| `get_track`     | Reads the metadata of one track by its id, without the words. |\n\nLRCLIB files a track by its metadata, so a search reaches a song through its\ntitle, its artist or its album. A word remembered from inside a song finds\nnothing there.\n\n### `search_tracks`\n\nFinds the tracks whose metadata matches, in one free-text search or in fields of\ntheir own. Several releases of one song come back side by side, and their album\nand duration tell them apart.\n\n| Argument      | Type                           | Required | What it does                                       |\n| ------------- | ------------------------------ | -------- | -------------------------------------------------- |\n| `query`       | string, 1 to 200 characters    | no       | Free-text search, as in `nino ferrer le sud`.      |\n| `track_name`  | string, up to 200 characters   | no       | Song title, for a search by field.                 |\n| `artist_name` | string, up to 200 characters   | no       | Artist name, for a search by field.                |\n| `album_name`  | string, up to 200 characters   | no       | Album name, to narrow a search by field.           |\n| `limit`       | integer, 1 to 50, default `10` | no       | Rows to serve. LRCLIB answers up to 20 per search. |\n\nPass `query`, or one of the three fields.\n\n**In return:** rows carrying `id`, which `get_lyrics` and `get_track` take;\n`track_name` and `artist_name`; `album_name` and `duration_seconds`, which tell\ntwo releases of one song apart; `instrumental`; `has_plain_lyrics` and\n`has_synced_lyrics`, so timed lines can be checked for before they are asked\nfor; and `source_url`. Alongside come `result_count` and `total_available`, the\ntracks LRCLIB served before `limit` was applied. `album_name` and\n`duration_seconds` are `null` on a track filed without them, and the rows carry\nno words at all: `get_lyrics` reads those.\n\n### `get_lyrics`\n\nReads the words of one track, either as plain text or as LRC lines carrying the\nmoment each one is sung. Long lyrics are served a slice at a time, resuming at a\nline boundary.\n\n| Argument           | Type                                         | Required | What it does                                                  |\n| ------------------ | -------------------------------------------- | -------- | ------------------------------------------------------------- |\n| `id`               | integer, positive                            | no       | The LRCLIB track id, as `search_tracks` returned it.          |\n| `artist_name`      | string, up to 200 characters                 | no       | Artist name, matched exactly. Needed when `id` is absent.     |\n| `track_name`       | string, up to 200 characters                 | no       | Song title, matched exactly. Needed when `id` is absent.      |\n| `album_name`       | string, up to 200 characters                 | no       | Album name, to pick between releases.                         |\n| `duration_seconds` | number, positive                             | no       | Track duration, to pick between versions of differing length. |\n| `format`           | `plain`, `synced` or `both`, default `plain` | no       | Which form of the words to serve.                             |\n| `max_chars`        | integer, 200 to 20000, default `6000`        | no       | Characters of text to serve in this call.                     |\n| `offset`           | integer, 0 or more, default `0`              | no       | Character offset to resume from.                              |\n\n**In return:** `status`, which reads `ok`, `instrumental` for a track with no\nwords to sing, or `no_lyrics` for one filed without them; `track` with its id,\ntitle, artist, album, duration and `source_url`; `plain_lyrics`; `synced_lyrics`\nas raw LRC text and `synced_lines` as a list of `{ time_seconds, text }`, with\n`synced_lines_truncated` when the slice cut them. The reading is described by\n`paginated_form`, `total_chars`, `returned_chars`, `offset`, `next_offset` and\n`truncated`: pass `next_offset` back to read on, and `null` there means the end.\n`attribution` is the line to cite when the words are shown. A `status` of\n`instrumental` is a complete answer.\n\n### `get_track`\n\nReads the metadata of one track from its id, leaving the words aside. It confirms\na release before the words are asked for, and it resolves an id carried over from\nearlier in a conversation.\n\n| Argument | Type              | Required | What it does                                         |\n| -------- | ----------------- | -------- | ---------------------------------------------------- |\n| `id`     | integer, positive | yes      | The LRCLIB track id, as `search_tracks` returned it. |\n\n**In return:** `track`, holding the fields a search row carries, and\n`duration_formatted` as `m:ss`, which is `null` when the track is filed without a\nduration. `has_plain_lyrics` and `has_synced_lyrics` say which forms\n`get_lyrics` can serve for it.\n\n## Configuration\n\nEvery variable is optional. Set them in the `env` block of your client config.\n\n| Variable                   | Default              | What it does                                                                                        |\n| -------------------------- | -------------------- | --------------------------------------------------------------------------------------------------- |\n| `LRCLIB_USER_AGENT`        | the project identity | Names your application to LRCLIB, with an address where a person can be reached.                    |\n| `LRCLIB_MIN_INTERVAL_MS`   | `500`                | Gap between two requests, from 200 to 60000. A figure under the floor is refused and this one used. |\n| `LRCLIB_TIMEOUT_MS`        | `15000`              | Deadline for one request, from 1000 to 120000.                                                      |\n| `LRCLIB_MAX_RETRIES`       | `3`                  | Attempts after a transient failure, from 0 to 10.                                                   |\n| `LRCLIB_CACHE_TTL_MS`      | `900000`             | How long an answer stays in memory, from 0 to 86400000.                                             |\n| `LRCLIB_CACHE_MAX_ENTRIES` | `200`                | Answers held in memory at once, from 0 to 10000.                                                    |\n| `LRCLIB_LOG_LEVEL`         | `error`              | `silent`, `error`, `info` or `debug`, written to stderr.                                            |\n\nA value outside its range falls back to the default, and the reason is written to\nstderr.\n\n## Errors\n\nEvery failure carries one of six codes, a message, and where it helps a hint\nnaming the next move.\n\n| Code             | What happened                                           | What to do                                                                                                  |\n| ---------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| `not_found`      | LRCLIB answered, and it holds no such track.            | Check the spelling with `search_tracks`.                                                                    |\n| `invalid_input`  | The arguments were refused before any request went out. | Read the message, which names the argument.                                                                 |\n| `rate_limited`   | LRCLIB asked this client to slow down.                  | Wait the number of seconds the hint names and call again with the same arguments. The track is still there. |\n| `upstream_error` | LRCLIB answered in a shape this client cannot read.     | Report it at [the issue tracker](https://github.com/smeet666/mcp-lrclib/issues).                            |\n| `network_error`  | The request did not complete.                           | Try again shortly.                                                                                          |\n| `timeout`        | The request passed its deadline.                        | Raise `LRCLIB_TIMEOUT_MS`, or ask for a smaller `max_chars`.                                                |\n\n## As a library\n\nThe layer reading LRCLIB is published on its own, with its pacing, its cache and\nits errors, and with no protocol attached.\n\n```ts\nimport { LrclibClient } from \"mcp-lrclib/client\";\n\nconst client = new LrclibClient();\nconst { data, cached } = await client.getById(3396226);\nconsole.log(data.track_name, data.synced_lyrics !== null, cached);\n```\n\n`search`, `get` and `getById` each answer `{ data, cached }`, and throw an error\ncarrying one of the six codes. The floor between two requests holds here as well.\n\n## Pacing and attribution\n\nRequests go out one at a time with a minimum gap between them, and that floor\nholds however the server is configured. The `User-Agent` always ends with the\nproject identity and an address where a person can be reached. LRCLIB is a free\nservice and publishes its API for machines to read, and this server reads it on\ndemand, one call at a time, in answer to something you asked for.\n\nEvery result carries the artist, the title and the address of its LRCLIB page,\nand `get_lyrics` carries `attribution`, the three of them written as one line.\n\nSong lyrics are the work of their authors and publishers. This project claims no\nrights over them, ships no database of them, writes nothing to disk, and\ncontributes nothing back to LRCLIB. This MCP server is an unofficial project,\nwith no affiliation to LRCLIB.\n\n## Privacy\n\nThis server collects nothing about you and sends nothing to its author. It runs\non your machine, contacts `lrclib.net` and nothing else, holds its answers in memory\nwhile it runs, and writes nothing to disk.\n[PRIVACY.md](PRIVACY.md) states what a request carries and which settings change\nany of it.\n\n## Development\n\n```bash\nnpm install\nnpm run build:fixtures\nnpm test\nnpm run check\n```\n\nTests run against generated fixtures and make no network request. The live suite,\n`npm run test:live`, makes one request per route and runs nightly against the\nservice itself.\n\n## Contributing\n\nBugs, questions and ideas belong in\n[the issue tracker](https://github.com/smeet666/mcp-lrclib/issues). Pull requests\nare welcome; opening an issue first helps agree on the shape of the change. See\n[CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nMIT, see [LICENSE](LICENSE). The lyrics belong to their authors and publishers,\nand the database to LRCLIB and its contributors.\n\n---\n\n<a name=\"mcp-lrclib-français\"></a>\n\n# mcp-lrclib (français)\n\n_[English version](#mcp-lrclib)_\n\n[LRCLIB](https://lrclib.net) est une base de paroles de chansons libre et\nouverte, alimentée par ceux qui s'en servent et offerte à tous sans clé ni\ncompte. Elle contient deux formes des paroles : le texte simple d'une chanson, et\nla forme LRC, où chaque ligne porte le moment où elle est chantée, ce que suit un\naffichage karaoké ou un panneau de paroles. Un titre y est classé par son nom,\nson artiste, son album et sa durée, si bien que les différentes parutions d'une\nmême chanson y voisinent.\n\nCe serveur relie un client de conversation à cette base. On peut y chercher un\ntitre par son nom, son artiste ou son album, lire les paroles simples d'une\nchanson, lire ses lignes horodatées avec leurs marques de temps, et vérifier la\nfiche d'une parution avant de la lire. Aucune clé d'API, aucun compte.\n\n## Installation\n\n**Installation en un clic**\n\n[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=lrclib&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1scmNsaWIiXX0%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=lrclib&config=%7B%22name%22%3A%22lrclib%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lrclib%22%5D%7D)\n\n**Claude Code**\n\n```bash\nclaude mcp add lrclib -- npx -y mcp-lrclib\n```\n\n**Claude Desktop, Cursor, et tout client au format de configuration standard**\n\n```json\n{\n  \"mcpServers\": {\n    \"lrclib\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-lrclib\"]\n    }\n  }\n}\n```\n\nNode 24 ou plus récent est nécessaire, et aucune variable d'environnement n'est à\nrenseigner.\n\n### Avec Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"lrclib\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"ghcr.io/smeet666/mcp-lrclib:2.0.1\"]\n    }\n  }\n}\n```\n\n`-i` garde l'entrée standard ouverte, qui est le canal du protocole, et `-t` est\nomis parce qu'un TTY réécrit le flux. Le conteneur a besoin d'un accès HTTPS\nsortant vers `lrclib.net`, et de rien d'autre : aucun volume, aucun port, aucun\nidentifiant.\n\n### Bundle, sans npm\n\nTéléchargez `mcp-lrclib-2.0.1.mcpb` depuis\n[la dernière publication](https://github.com/smeet666/mcp-lrclib/releases/latest)\net ouvrez-le. Un client qui gère les bundles MCP l'installe seul, sans npm et\nsans fichier de configuration à modifier. Le bundle emporte ses dépendances, donc\nrien n'est téléchargé à l'installation.\n\n## Ce qu'on peut demander\n\n- « Trouve-moi les paroles du Sud de Nino Ferrer. »\n- « Donne-moi les paroles horodatées de Bohemian Rhapsody pour que je suive. »\n- « Quelles versions de Hallelujah y a-t-il sur LRCLIB, et quelle est leur durée ? »\n- « Lis-moi la seconde moitié de ces paroles. »\n- « Est-ce que le titre 3396226 a des paroles synchronisées ? »\n\nLe chemin ordinaire va d'une recherche à une lecture : `search_tracks` nomme un\n`id`, et `get_lyrics` reprend cet identifiant.\n\n## Les outils\n\n| Outil           | Ce qu'il fait                                                   |\n| --------------- | --------------------------------------------------------------- |\n| `search_tracks` | Trouve des titres par nom, artiste ou album, avec leurs fiches. |\n| `get_lyrics`    | Lit les paroles d'un titre, simples ou horodatées.              |\n| `get_track`     | Lit la fiche d'un titre par son identifiant, sans les paroles.  |\n\nLRCLIB classe un titre par sa fiche, donc une recherche atteint une chanson par\nson nom, son artiste ou son album. Un mot retenu de l'intérieur d'une chanson n'y\ntrouve rien.\n\n### `search_tracks`\n\nTrouve les titres dont la fiche correspond, en une recherche libre ou par champs.\nPlusieurs parutions d'une même chanson reviennent côte à côte, et leur album et\nleur durée les distinguent.\n\n| Argument      | Type                           | Requis | Ce qu'il fait                                             |\n| ------------- | ------------------------------ | ------ | --------------------------------------------------------- |\n| `query`       | chaîne, 1 à 200 caractères     | non    | Recherche libre, par exemple `nino ferrer le sud`.        |\n| `track_name`  | chaîne, jusqu'à 200 caractères | non    | Nom de la chanson, pour une recherche par champs.         |\n| `artist_name` | chaîne, jusqu'à 200 caractères | non    | Nom de l'artiste, pour une recherche par champs.          |\n| `album_name`  | chaîne, jusqu'à 200 caractères | non    | Nom de l'album, pour resserrer une recherche par champs.  |\n| `limit`       | entier, 1 à 50, défaut `10`    | non    | Lignes à servir. LRCLIB en rend jusqu'à 20 par recherche. |\n\nPassez `query`, ou l'un des trois champs.\n\n**En retour :** des lignes portant `id`, que `get_lyrics` et `get_track`\nreprennent ; `track_name` et `artist_name` ; `album_name` et `duration_seconds`,\nqui distinguent deux parutions d'une même chanson ; `instrumental` ;\n`has_plain_lyrics` et `has_synced_lyrics`, qui permettent de vérifier l'existence\ndes lignes horodatées avant de les demander ; et `source_url`. Viennent aussi\n`result_count` et `total_available`, les titres que LRCLIB a servis avant\nl'application de `limit`. `album_name` et `duration_seconds` valent `null` sur un\ntitre classé sans eux, et les lignes ne portent aucune parole : `get_lyrics` les\nlit.\n\n### `get_lyrics`\n\nLit les paroles d'un titre, en texte simple ou en lignes LRC portant le moment où\nchacune est chantée. Des paroles longues sont servies par tranches, coupées sur\nune fin de ligne.\n\n| Argument           | Type                                        | Requis | Ce qu'il fait                                                             |\n| ------------------ | ------------------------------------------- | ------ | ------------------------------------------------------------------------- |\n| `id`               | entier, positif                             | non    | L'identifiant LRCLIB rendu par `search_tracks`.                           |\n| `artist_name`      | chaîne, jusqu'à 200 caractères              | non    | Nom de l'artiste, correspondance exacte. Nécessaire sans `id`.            |\n| `track_name`       | chaîne, jusqu'à 200 caractères              | non    | Nom de la chanson, correspondance exacte. Nécessaire sans `id`.           |\n| `album_name`       | chaîne, jusqu'à 200 caractères              | non    | Nom de l'album, pour choisir entre des parutions.                         |\n| `duration_seconds` | nombre, positif                             | non    | Durée du titre, pour choisir entre des versions de longueurs différentes. |\n| `format`           | `plain`, `synced` ou `both`, défaut `plain` | non    | La forme des paroles à servir.                                            |\n| `max_chars`        | entier, 200 à 20000, défaut `6000`          | non    | Caractères de texte à servir dans cet appel.                              |\n| `offset`           | entier, 0 ou plus, défaut `0`               | non    | Position en caractères où reprendre.                                      |\n\n**En retour :** `status`, qui vaut `ok`, `instrumental` pour un titre sans\nparoles à chanter, ou `no_lyrics` pour un titre classé sans elles ; `track` avec\nson identifiant, son nom, son artiste, son album, sa durée et son `source_url` ;\n`plain_lyrics` ; `synced_lyrics` en texte LRC brut et `synced_lines` en liste de\n`{ time_seconds, text }`, avec `synced_lines_truncated` quand la tranche les a\ncoupées. La lecture est décrite par `paginated_form`, `total_chars`,\n`returned_chars`, `offset`, `next_offset` et `truncated` : redonnez `next_offset`\npour poursuivre, et `null` marque la fin. `attribution` est la ligne à citer\nquand les paroles sont montrées. Un `status` à `instrumental` est une réponse\ncomplète.\n\n### `get_track`\n\nLit la fiche d'un titre depuis son identifiant, sans les paroles. Elle confirme\nune parution avant qu'on demande les paroles, et elle résout un identifiant venu\nd'un échange précédent.\n\n| Argument | Type            | Requis | Ce qu'il fait                                   |\n| -------- | --------------- | ------ | ----------------------------------------------- |\n| `id`     | entier, positif | oui    | L'identifiant LRCLIB rendu par `search_tracks`. |\n\n**En retour :** `track`, qui porte les champs d'une ligne de recherche, et\n`duration_formatted` sous la forme `m:ss`, `null` pour un titre classé sans\ndurée. `has_plain_lyrics` et `has_synced_lyrics` disent quelles formes\n`get_lyrics` peut servir.\n\n## Configuration\n\nChaque variable est facultative. Elles se posent dans le bloc `env` de la\nconfiguration du client.\n\n| Variable                   | Défaut               | Ce qu'elle fait                                                                                           |\n| -------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------- |\n| `LRCLIB_USER_AGENT`        | l'identité du projet | Nomme votre application auprès de LRCLIB, avec une adresse où joindre une personne.                       |\n| `LRCLIB_MIN_INTERVAL_MS`   | `500`                | Écart entre deux requêtes, de 200 à 60000. Une valeur sous le plancher est refusée au profit de celle-ci. |\n| `LRCLIB_TIMEOUT_MS`        | `15000`              | Délai d'une requête, de 1000 à 120000.                                                                    |\n| `LRCLIB_MAX_RETRIES`       | `3`                  | Tentatives après un échec passager, de 0 à 10.                                                            |\n| `LRCLIB_CACHE_TTL_MS`      | `900000`             | Durée pendant laquelle une réponse reste en mémoire, de 0 à 86400000.                                     |\n| `LRCLIB_CACHE_MAX_ENTRIES` | `200`                | Réponses gardées en mémoire à la fois, de 0 à 10000.                                                      |\n| `LRCLIB_LOG_LEVEL`         | `error`              | `silent`, `error`, `info` ou `debug`, écrit sur la sortie d'erreur.                                       |\n\nUne valeur hors de sa plage retombe sur le défaut, et la raison est écrite sur la\nsortie d'erreur.\n\n## Erreurs\n\nChaque échec porte un des six codes, un message, et quand cela aide une\nindication du geste suivant.\n\n| Code             | Ce qui s'est passé                                        | Que faire                                                                                       |\n| ---------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |\n| `not_found`      | LRCLIB a répondu, et ne contient pas ce titre.            | Vérifiez l'orthographe avec `search_tracks`.                                                    |\n| `invalid_input`  | Les arguments ont été refusés avant toute requête.        | Lisez le message, qui nomme l'argument.                                                         |\n| `rate_limited`   | LRCLIB demande à ce client de ralentir.                   | Attendez les secondes indiquées et rappelez avec les mêmes arguments. Le titre est toujours là. |\n| `upstream_error` | LRCLIB a répondu dans une forme que ce client ne lit pas. | Signalez-le sur [le suivi d'incidents](https://github.com/smeet666/mcp-lrclib/issues).          |\n| `network_error`  | La requête n'a pas abouti.                                | Réessayez sous peu.                                                                             |\n| `timeout`        | La requête a dépassé son délai.                           | Augmentez `LRCLIB_TIMEOUT_MS`, ou demandez un `max_chars` plus petit.                           |\n\n## Comme bibliothèque\n\nLa couche qui lit LRCLIB est publiée seule, avec son rythme, son cache et ses\nerreurs, sans protocole attaché.\n\n```ts\nimport { LrclibClient } from \"mcp-lrclib/client\";\n\nconst client = new LrclibClient();\nconst { data, cached } = await client.getById(3396226);\nconsole.log(data.track_name, data.synced_lyrics !== null, cached);\n```\n\n`search`, `get` et `getById` répondent chacun `{ data, cached }`, et lèvent une\nerreur portant un des six codes. Le plancher entre deux requêtes tient également\nici.\n\n## Rythme et attribution\n\nLes requêtes partent une à une avec un écart minimal entre elles, et ce plancher\ntient quelle que soit la configuration. Le `User-Agent` se termine toujours par\nl'identité du projet et une adresse où joindre une personne. LRCLIB est un\nservice gratuit et publie son API pour être lue par des machines, et ce serveur\nla lit à la demande, un appel à la fois, en réponse à ce que vous avez demandé.\n\nChaque résultat porte l'artiste, le titre et l'adresse de sa page LRCLIB, et\n`get_lyrics` porte `attribution`, ces trois éléments écrits en une ligne.\n\nLes paroles sont l'œuvre de leurs auteurs et de leurs éditeurs. Ce projet ne\nrevendique aucun droit dessus, n'embarque aucune base de paroles, n'écrit rien\nsur le disque et ne contribue rien à LRCLIB. Ce MCP est un projet non officiel,\nsans affiliation à LRCLIB.\n\n## Confidentialité\n\nCe serveur ne collecte rien sur vous et n'envoie rien à son auteur. Il tourne sur\nvotre machine, ne joint que `lrclib.net`, garde ses réponses en mémoire le temps qu'il\ntourne, et n'écrit rien sur le disque. [PRIVACY.md](PRIVACY.md) dit ce qu'une\nrequête emporte et quels réglages changent cela.\n\n## Développement\n\n```bash\nnpm install\nnpm run build:fixtures\nnpm test\nnpm run check\n```\n\nLes tests s'exécutent sur des fixtures engendrées et n'émettent aucune requête.\nLa suite en direct, `npm run test:live`, émet une requête par route et tourne\nchaque nuit contre le service lui-même.\n\n## Contribuer\n\nLes anomalies, les questions et les idées ont leur place dans\n[le suivi d'incidents](https://github.com/smeet666/mcp-lrclib/issues). Les\npropositions de modification sont bienvenues ; ouvrir un ticket d'abord aide à\ns'accorder sur la forme du changement. Voir [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Licence\n\nMIT, voir [LICENSE](LICENSE). Les paroles appartiennent à leurs auteurs et à\nleurs éditeurs, et la base à LRCLIB et à ses contributeurs.\n",
  "bytes": 29358,
  "sha": "9230410d3d236b396cf02b2e4e6b218c80ad79d90d971e16869e5827de01fcc5",
  "repo_slug": "smeet666/mcp-lrclib",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_smeet666_mcp_lrclib_16943fae/readme"
}