mcp-lyricscom 1.4.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +141 -0
- package/LICENSE +1 -1
- package/PRIVACY.md +152 -0
- package/README.md +391 -268
- package/dist/index.js +326 -120
- package/dist/index.js.map +1 -1
- package/dist/lyricscom/client.js +130 -48
- package/dist/lyricscom/client.js.map +1 -1
- package/package.json +19 -11
- package/server.json +4 -4
package/README.md
CHANGED
|
@@ -5,18 +5,26 @@
|
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.smeet666/mcp-lyricscom)
|
|
7
7
|
[](https://glama.ai/mcp/servers/smeet666/mcp-lyricscom)
|
|
8
|
+
[](https://m8ven.ai/mcp/smeet666-mcp-lyricscom-pptp4t)
|
|
8
9
|
[](https://cursor.com/en/install-mcp?name=lyricscom&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1seXJpY3Njb20iXX0%3D)
|
|
9
10
|
[](https://insiders.vscode.dev/redirect/mcp/install?name=lyricscom&config=%7B%22name%22%3A%22lyricscom%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-lyricscom%22%5D%7D)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
Search songs by a word in their lyrics, by title, and read the full text.
|
|
13
|
-
**No API key, no account, no configuration.**
|
|
12
|
+
<!-- m8ven-verify: 3c4d434dcafaac3c25dc86631fb1393b -->
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
[lyrics.com](https://www.lyrics.com) is a large public catalogue of song lyrics.
|
|
15
|
+
It files a song under its title, its artist, the album it appeared on and the
|
|
16
|
+
year, and it holds the words themselves. Its search reaches inside those words.
|
|
17
|
+
|
|
18
|
+
This server connects a chat client to that catalogue. You can search for a song
|
|
19
|
+
by a line you remember, search by title and artist, and read the words of one
|
|
20
|
+
song, a slice at a time, with the words you were looking for located in the text.
|
|
21
|
+
It needs no API key and no account.
|
|
22
|
+
|
|
23
|
+
_[Version française](#mcp-lyricscom-français)_
|
|
16
24
|
|
|
17
25
|
---
|
|
18
26
|
|
|
19
|
-
##
|
|
27
|
+
## Install
|
|
20
28
|
|
|
21
29
|
**One-click install**
|
|
22
30
|
|
|
@@ -42,176 +50,216 @@ claude mcp add lyricscom -- npx -y mcp-lyricscom
|
|
|
42
50
|
}
|
|
43
51
|
```
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
**Bundle, without npm**
|
|
48
|
-
|
|
49
|
-
Download `mcp-lyricscom-<version>.mcpb` from
|
|
50
|
-
[the latest release](https://github.com/smeet666/mcp-lyricscom/releases/latest) and open
|
|
51
|
-
it. A client that supports MCP bundles installs it on its own, with no npm and
|
|
52
|
-
no configuration file to edit. The bundle carries its dependencies, so nothing
|
|
53
|
-
is fetched at install time.
|
|
54
|
-
|
|
55
|
-
## Tools
|
|
56
|
-
|
|
57
|
-
| Tool | What it does | Key parameters |
|
|
58
|
-
| --------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
|
59
|
-
| `search_lyrics` | Finds songs whose **lyrics contain a word or phrase**, with the matching line as an excerpt. | `query`, `limit`, `page`, `verify`, `include_excerpt` |
|
|
60
|
-
| `search_songs` | Finds songs **by title**, optionally narrowed by artist. | `title`, `artist`, `limit`, `page`, `match` |
|
|
61
|
-
| `get_lyrics` | Reads the **full lyrics** of one song, by id or URL. | `id`, `url`, `max_chars`, `offset`, `highlight` |
|
|
62
|
-
|
|
63
|
-
The two search tools return a lyrics.com `id` for every result; `get_lyrics` takes that id.
|
|
64
|
-
That is the intended chain: search, then read.
|
|
65
|
-
|
|
66
|
-
### Things worth knowing
|
|
67
|
-
|
|
68
|
-
**Search really checks the lyrics.** lyrics.com's own search also returns title
|
|
69
|
-
matches and loose matches. `search_lyrics` filters them out locally, using a
|
|
70
|
-
word-boundary matcher, so a result is a song where the word genuinely appears.
|
|
71
|
-
`coup` does not match `beaucoup`, but `enfant` does match `enfants`. Set
|
|
72
|
-
`verify: "none"` to see the raw, unfiltered list.
|
|
73
|
-
|
|
74
|
-
**Pagination is yours to drive.** One call fetches one page (24 rows on
|
|
75
|
-
lyrics.com). The response carries `has_more` and `next_page`. Raising `limit`
|
|
76
|
-
does not fetch more pages, on purpose: chaining several fetches inside a single
|
|
77
|
-
tool call is the fastest way to get rate limited.
|
|
78
|
-
|
|
79
|
-
**Some songs have no lyrics.** A valid lyrics.com page can simply have no text
|
|
80
|
-
on file. That comes back as `status: "no_lyrics"` with a successful result, not
|
|
81
|
-
an error, so there is nothing to retry.
|
|
82
|
-
|
|
83
|
-
**Rate limiting is visible, not silent.** lyrics.com answers a throttled request
|
|
84
|
-
with an empty body rather than a normal error code. This server detects that and
|
|
85
|
-
returns an explicit `throttled` error telling you to wait and try again. It never
|
|
86
|
-
reports throttling as "no results found", which would be indistinguishable from a
|
|
87
|
-
genuine answer.
|
|
88
|
-
|
|
89
|
-
## Configuration
|
|
53
|
+
Node 24 or later is required, and no environment variable has to be set.
|
|
90
54
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
| Variable | Default | Purpose |
|
|
94
|
-
| ----------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
95
|
-
| `LYRICSCOM_USER_AGENT` | `mcp-lyricscom/<version> (+repo url)` | User-Agent sent to lyrics.com. See below. |
|
|
96
|
-
| `LYRICSCOM_MIN_INTERVAL_MS` | `1100` | Minimum gap between requests. Raise it if you hit throttling. Values below 500 ms are ignored, see below. |
|
|
97
|
-
| `LYRICSCOM_TIMEOUT_MS` | `15000` | Per-request timeout. |
|
|
98
|
-
| `LYRICSCOM_MAX_RETRIES` | `3` | Retries on throttling and transient errors. |
|
|
99
|
-
| `LYRICSCOM_CACHE_TTL_MS` | `900000` | In-memory page cache lifetime (15 minutes). |
|
|
100
|
-
| `LYRICSCOM_CACHE_MAX_ENTRIES` | `200` | In-memory page cache size. |
|
|
101
|
-
| `LYRICSCOM_LOG_LEVEL` | `error` | `silent`, `error`, `info` or `debug`. Logs go to stderr. |
|
|
55
|
+
### With Docker
|
|
102
56
|
|
|
103
57
|
```json
|
|
104
58
|
{
|
|
105
59
|
"mcpServers": {
|
|
106
60
|
"lyricscom": {
|
|
107
|
-
"command": "
|
|
108
|
-
"args": ["-
|
|
109
|
-
"env": { "LYRICSCOM_MIN_INTERVAL_MS": "1500" }
|
|
61
|
+
"command": "docker",
|
|
62
|
+
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-lyricscom:2.0.1"]
|
|
110
63
|
}
|
|
111
64
|
}
|
|
112
65
|
}
|
|
113
66
|
```
|
|
114
67
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
to this repository. lyrics.com serves that fine today.
|
|
119
|
-
|
|
120
|
-
It does block some generic tool agents outright: a plain `curl/8.5.0` gets a 403.
|
|
121
|
-
If you ever see a `blocked_user_agent` error, set `LYRICSCOM_USER_AGENT` to a
|
|
122
|
-
value of your choosing. That override exists so you are not stuck, and what you
|
|
123
|
-
put in it is your call and your responsibility.
|
|
68
|
+
`-i` keeps stdin open, which is where the protocol travels, and `-t` is left out
|
|
69
|
+
because a TTY rewrites the stream. The container needs outbound HTTPS to
|
|
70
|
+
`www.lyrics.com`, and nothing else: no volume, no port, no credential.
|
|
124
71
|
|
|
125
|
-
|
|
72
|
+
### Bundle, without npm
|
|
126
73
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
error does not mean your query has no results.
|
|
74
|
+
Download `mcp-lyricscom-2.0.1.mcpb` from
|
|
75
|
+
[the latest release](https://github.com/smeet666/mcp-lyricscom/releases/latest)
|
|
76
|
+
and open it. A client that supports MCP bundles installs it on its own, with no
|
|
77
|
+
npm and no configuration file to edit. The bundle carries its dependencies, so
|
|
78
|
+
nothing is fetched at install time.
|
|
133
79
|
|
|
134
|
-
|
|
80
|
+
## What you can ask
|
|
135
81
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
82
|
+
- "Which song goes 'I've got a hand for you'?"
|
|
83
|
+
- "Find me the lyrics of Wichita Lineman by Glen Campbell."
|
|
84
|
+
- "Read me the second half of those words."
|
|
85
|
+
- "Where does the word 'lineman' appear in that song?"
|
|
86
|
+
- "What albums is that song on?"
|
|
140
87
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
Try `verify: "none"` to see them anyway.
|
|
88
|
+
The ordinary path runs from a search to a reading: a row carries an `id`, and
|
|
89
|
+
`get_lyrics` takes that id.
|
|
144
90
|
|
|
145
|
-
##
|
|
91
|
+
## Tools
|
|
146
92
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
the
|
|
93
|
+
| Tool | What it does |
|
|
94
|
+
| --------------- | ----------------------------------------------- |
|
|
95
|
+
| `search_lyrics` | Finds a song from a line inside its words. |
|
|
96
|
+
| `search_songs` | Finds songs by title, narrowed by artist. |
|
|
97
|
+
| `get_lyrics` | Reads the words of one song, a slice at a time. |
|
|
98
|
+
|
|
99
|
+
### `search_lyrics`
|
|
100
|
+
|
|
101
|
+
Finds a song from words inside its lyrics. The site ranks loosely, so a match is
|
|
102
|
+
checked before it is served.
|
|
103
|
+
|
|
104
|
+
| Argument | Type | Required | What it does |
|
|
105
|
+
| ----------------- | ---------------------------------------------- | -------- | --------------------------------------- |
|
|
106
|
+
| `query` | string, 1 to 120 characters | yes | The line, or part of it, to look for. |
|
|
107
|
+
| `limit` | integer, 1 to 50, default `10` | no | Rows to serve. |
|
|
108
|
+
| `page` | integer, 1 to 20, default `1` | no | Which page of rows. |
|
|
109
|
+
| `verify` | `snippet`, `full` or `none`, default `snippet` | no | How to confirm the words really appear. |
|
|
110
|
+
| `include_excerpt` | boolean, default `true` | no | Carry the matching line with each row. |
|
|
111
|
+
|
|
112
|
+
`verify` decides what a row is worth. `snippet` checks the excerpt the site
|
|
113
|
+
already returned and costs nothing. `full` fetches up to five song pages and
|
|
114
|
+
checks the complete words, which is slow and can bring on rate limiting. `none`
|
|
115
|
+
serves what the site ranked, unchecked.
|
|
116
|
+
|
|
117
|
+
**In return:** rows carrying `id`, which `get_lyrics` takes; `title`; `artist`;
|
|
118
|
+
`album` and `year`, `null` where the catalogue states none; `source_url`; and
|
|
119
|
+
`excerpt`, the matching line. `raw_result_count` is what the site returned and
|
|
120
|
+
`filtered_out` how many rows the check removed, so the two together say how loose
|
|
121
|
+
the ranking was. `has_more` and `next_page` continue.
|
|
122
|
+
|
|
123
|
+
### `search_songs`
|
|
124
|
+
|
|
125
|
+
Finds songs by title, narrowed by artist.
|
|
126
|
+
|
|
127
|
+
| Argument | Type | Required | What it does |
|
|
128
|
+
| -------- | ------------------------------------ | -------- | --------------------------------------- |
|
|
129
|
+
| `title` | string, 1 to 120 characters | yes | The song title, or part of it. |
|
|
130
|
+
| `artist` | string, up to 120 characters | no | Keep the songs credited to this artist. |
|
|
131
|
+
| `limit` | integer, 1 to 50, default `10` | no | Rows to serve. |
|
|
132
|
+
| `page` | integer, 1 to 20, default `1` | no | Which page of rows. |
|
|
133
|
+
| `match` | `loose` or `strict`, default `loose` | no | How closely the artist has to match. |
|
|
134
|
+
|
|
135
|
+
**In return:** the rows `search_lyrics` returns, with `artist_filter` echoing
|
|
136
|
+
what was asked for and `filtered_out` counting what the artist restriction
|
|
137
|
+
removed. `strict` keeps the artists whose name matches as written; `loose`
|
|
138
|
+
accepts a name written differently.
|
|
139
|
+
|
|
140
|
+
### `get_lyrics`
|
|
141
|
+
|
|
142
|
+
Reads the words of one song. Long lyrics are served a slice at a time.
|
|
143
|
+
|
|
144
|
+
| Argument | Type | Required | What it does |
|
|
145
|
+
| ----------- | ------------------------------------- | ---------- | ----------------------------------------- |
|
|
146
|
+
| `id` | string | one of two | The song id a search row carries. |
|
|
147
|
+
| `url` | a lyrics.com URL | one of two | The address of the song page. |
|
|
148
|
+
| `max_chars` | integer, 200 to 20000, default `6000` | no | Characters of text to serve in this call. |
|
|
149
|
+
| `offset` | integer, 0 or more, default `0` | no | Character offset to resume from. |
|
|
150
|
+
| `highlight` | string, up to 120 characters | no | Words to locate inside the text. |
|
|
151
|
+
|
|
152
|
+
**In return:** `status`, reading `ok` or `no_lyrics` for a page the site holds
|
|
153
|
+
without words; `title`, `artist` and `source_url`; and `lyrics`, the slice
|
|
154
|
+
itself. The reading is described by `total_chars`, `returned_chars`, `offset`,
|
|
155
|
+
`next_offset` and `truncated`: pass `next_offset` back to read on, and `null`
|
|
156
|
+
there means the end. `line_count` counts the lines of the slice, and `highlight`
|
|
157
|
+
answers for each word whether it was `found` and on which `line_number`, which is
|
|
158
|
+
`null` when it was not.
|
|
152
159
|
|
|
153
|
-
##
|
|
160
|
+
## Configuration
|
|
154
161
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
Every variable is optional. Set them in the `env` block of your client config.
|
|
163
|
+
|
|
164
|
+
| Variable | Default | What it does |
|
|
165
|
+
| ----------------------------- | -------------------- | ---------------------------------------------------------------------------------- |
|
|
166
|
+
| `LYRICSCOM_USER_AGENT` | the project identity | Names your application to the site, with an address where a person can be reached. |
|
|
167
|
+
| `LYRICSCOM_MIN_INTERVAL_MS` | `1100` | Gap between two requests, from 500 to 60000. |
|
|
168
|
+
| `LYRICSCOM_TIMEOUT_MS` | `15000` | Deadline for one request, from 1000 to 120000. |
|
|
169
|
+
| `LYRICSCOM_MAX_RETRIES` | `3` | Attempts after a transient failure, from 0 to 10. |
|
|
170
|
+
| `LYRICSCOM_CACHE_TTL_MS` | `900000` | How long an answer stays in memory, from 0 to 86400000. |
|
|
171
|
+
| `LYRICSCOM_CACHE_MAX_ENTRIES` | `200` | Answers held in memory at once, from 0 to 10000. |
|
|
172
|
+
| `LYRICSCOM_LOG_LEVEL` | `error` | `silent`, `error`, `info` or `debug`, written to stderr. |
|
|
173
|
+
|
|
174
|
+
A value outside its range falls back to the default, and the reason is written to
|
|
175
|
+
stderr.
|
|
176
|
+
|
|
177
|
+
**On the User-Agent.** This server names the project and links to its repository,
|
|
178
|
+
and the site serves that. It does refuse some generic tool agents outright: a
|
|
179
|
+
plain `curl` gets a 403. A `blocked_user_agent` error means the identity was
|
|
180
|
+
refused, and `LYRICSCOM_USER_AGENT` lets you set one of your choosing. What you
|
|
181
|
+
put there is your call and your responsibility.
|
|
182
|
+
|
|
183
|
+
## Errors
|
|
184
|
+
|
|
185
|
+
Every failure carries one of these codes, a message, and where it helps a hint
|
|
186
|
+
naming the next move.
|
|
187
|
+
|
|
188
|
+
| Code | What happened | What to do |
|
|
189
|
+
| -------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
190
|
+
| `not_found` | The site answered, and holds no such song. | Check the id with `search_songs`. |
|
|
191
|
+
| `invalid_input` | The arguments were refused before any request went out. | Read the message, which names the argument. |
|
|
192
|
+
| `throttled` | The site asked this client to slow down. | Wait, then call again with the same arguments. The song is still there. |
|
|
193
|
+
| `blocked_user_agent` | The site refused the identity this client sent. | Set `LYRICSCOM_USER_AGENT`. |
|
|
194
|
+
| `parse_failure` | The page loaded and the expected content was absent. | Report it at [the issue tracker](https://github.com/smeet666/mcp-lyricscom/issues). |
|
|
195
|
+
| `network_error` | The request did not complete. | Try again shortly. |
|
|
196
|
+
| `timeout` | The request passed its deadline. | Raise `LYRICSCOM_TIMEOUT_MS`, or ask for a smaller `max_chars`. |
|
|
197
|
+
|
|
198
|
+
`throttled` and `blocked_user_agent` are this server's two names for a refusal to
|
|
199
|
+
serve, and a caller reading several sources normalises them onto whatever it
|
|
200
|
+
calls rate limiting.
|
|
201
|
+
|
|
202
|
+
## As a library
|
|
203
|
+
|
|
204
|
+
The layer reading the site is published on its own, with its pacing, its cache
|
|
205
|
+
and its errors, and with no protocol attached.
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { LyricsComClient } from "mcp-lyricscom/client";
|
|
209
|
+
|
|
210
|
+
const client = new LyricsComClient();
|
|
211
|
+
const { data, cached } = await client.getSong({ id: "1234567" });
|
|
212
|
+
console.log(data.title, data.artist, cached);
|
|
163
213
|
```
|
|
164
214
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
215
|
+
`search` and `getSong` each answer `{ data, cached }`, and throw an error
|
|
216
|
+
carrying one of the codes above. The floor between two requests holds here as
|
|
217
|
+
well.
|
|
168
218
|
|
|
169
|
-
|
|
170
|
-
is published separately as `mcp-lyricscom/client`, so it can be used as a plain
|
|
171
|
-
library.
|
|
219
|
+
## Pacing and attribution
|
|
172
220
|
|
|
173
|
-
|
|
221
|
+
Requests go out one at a time with at least a second between them, and the floor
|
|
222
|
+
of half a second holds however the server is configured. A `verify: "full"`
|
|
223
|
+
search fetches up to five song pages, which is the most expensive thing this
|
|
224
|
+
server does.
|
|
174
225
|
|
|
175
|
-
|
|
176
|
-
|
|
226
|
+
Every result carries the artist, the title and the address of the song page. Song
|
|
227
|
+
lyrics are the work of their authors and publishers. This project claims no
|
|
228
|
+
rights over them, ships no database of them, and writes nothing to disk.
|
|
177
229
|
|
|
178
|
-
This server is
|
|
179
|
-
open in a browser, on demand, one request at a time, in response to an explicit
|
|
180
|
-
request from you or your assistant. It does not crawl the site, does not build a
|
|
181
|
-
lyrics database, and does not write anything to disk. Pages are held in memory
|
|
182
|
-
for a few minutes so that repeated questions do not hit the site again.
|
|
230
|
+
This MCP server is an unofficial project, with no affiliation to lyrics.com.
|
|
183
231
|
|
|
184
|
-
|
|
185
|
-
reuse anything this server returns, keep that attribution and link back to the
|
|
186
|
-
source page.
|
|
232
|
+
## Privacy
|
|
187
233
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
234
|
+
This server collects nothing about you and sends nothing to its author. It runs
|
|
235
|
+
on your machine, contacts `www.lyrics.com` and nothing else, holds its answers in memory
|
|
236
|
+
while it runs, and writes nothing to disk.
|
|
237
|
+
[PRIVACY.md](PRIVACY.md) states what a request carries and which settings change
|
|
238
|
+
any of it.
|
|
193
239
|
|
|
194
|
-
|
|
195
|
-
sponsorship from lyrics.com or STANDS4 Ltd. Use it in accordance with lyrics.com's
|
|
196
|
-
terms of service and the copyright law that applies to you.
|
|
240
|
+
## Development
|
|
197
241
|
|
|
198
|
-
|
|
242
|
+
```bash
|
|
243
|
+
npm install
|
|
244
|
+
npm run build:fixtures
|
|
245
|
+
npm test
|
|
246
|
+
npm run check
|
|
247
|
+
```
|
|
199
248
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
answer is before you write it. [CONTRIBUTING.md](CONTRIBUTING.md) has the
|
|
204
|
-
detail, and [SECURITY.md](SECURITY.md) covers anything exploitable.
|
|
249
|
+
Tests run against generated fixtures and make no network request. The live suite,
|
|
250
|
+
`npm run test:live`, makes one request per route and runs nightly against the
|
|
251
|
+
site itself.
|
|
205
252
|
|
|
206
|
-
##
|
|
253
|
+
## Contributing
|
|
207
254
|
|
|
208
|
-
|
|
209
|
-
|
|
255
|
+
Bugs, questions and ideas belong in
|
|
256
|
+
[the issue tracker](https://github.com/smeet666/mcp-lyricscom/issues). Pull
|
|
257
|
+
requests are welcome; opening an issue first helps agree on the shape of the
|
|
258
|
+
change. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
210
259
|
|
|
211
260
|
## License
|
|
212
261
|
|
|
213
|
-
MIT
|
|
214
|
-
lyrics retrieved through it.
|
|
262
|
+
MIT, see [LICENSE](LICENSE). The lyrics belong to their authors and publishers.
|
|
215
263
|
|
|
216
264
|
---
|
|
217
265
|
|
|
@@ -219,11 +267,19 @@ lyrics retrieved through it.
|
|
|
219
267
|
|
|
220
268
|
# mcp-lyricscom (français)
|
|
221
269
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
270
|
+
_[English version](#mcp-lyricscom)_
|
|
271
|
+
|
|
272
|
+
[lyrics.com](https://www.lyrics.com) est un grand catalogue public de paroles de
|
|
273
|
+
chansons. Il classe une chanson sous son titre, son artiste, l'album où elle a
|
|
274
|
+
paru et l'année, et il contient les paroles elles-mêmes. Sa recherche va à
|
|
275
|
+
l'intérieur de ces paroles.
|
|
225
276
|
|
|
226
|
-
|
|
277
|
+
Ce serveur relie un client de conversation à ce catalogue. On peut y chercher une
|
|
278
|
+
chanson par un vers dont on se souvient, chercher par titre et par artiste, et
|
|
279
|
+
lire les paroles d'une chanson par tranches, avec les mots cherchés localisés
|
|
280
|
+
dans le texte. Aucune clé d'API, aucun compte.
|
|
281
|
+
|
|
282
|
+
## Installation
|
|
227
283
|
|
|
228
284
|
**Installation en un clic**
|
|
229
285
|
|
|
@@ -236,7 +292,7 @@ texte complet. **Sans clé d'API, sans compte, sans configuration.**
|
|
|
236
292
|
claude mcp add lyricscom -- npx -y mcp-lyricscom
|
|
237
293
|
```
|
|
238
294
|
|
|
239
|
-
**Claude Desktop, Cursor, et tout client
|
|
295
|
+
**Claude Desktop, Cursor, et tout client au format de configuration standard**
|
|
240
296
|
|
|
241
297
|
```json
|
|
242
298
|
{
|
|
@@ -249,152 +305,219 @@ claude mcp add lyricscom -- npx -y mcp-lyricscom
|
|
|
249
305
|
}
|
|
250
306
|
```
|
|
251
307
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
**Bundle, sans npm**
|
|
255
|
-
|
|
256
|
-
Téléchargez `mcp-lyricscom-<version>.mcpb` depuis
|
|
257
|
-
[la dernière release](https://github.com/smeet666/mcp-lyricscom/releases/latest) et
|
|
258
|
-
ouvrez-le. Un client compatible avec les bundles MCP l'installe seul, sans npm
|
|
259
|
-
ni fichier de configuration à modifier. Le bundle embarque ses dépendances,
|
|
260
|
-
donc rien n'est téléchargé à l'installation.
|
|
261
|
-
|
|
262
|
-
## Outils
|
|
263
|
-
|
|
264
|
-
| Outil | Rôle | Paramètres principaux |
|
|
265
|
-
| --------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
|
266
|
-
| `search_lyrics` | Trouve les chansons dont les **paroles contiennent un mot ou une phrase**, avec la ligne correspondante en extrait. | `query`, `limit`, `page`, `verify`, `include_excerpt` |
|
|
267
|
-
| `search_songs` | Trouve des chansons **par titre**, éventuellement restreintes à un artiste. | `title`, `artist`, `limit`, `page`, `match` |
|
|
268
|
-
| `get_lyrics` | Lit les **paroles complètes** d'une chanson, par id ou par URL. | `id`, `url`, `max_chars`, `offset`, `highlight` |
|
|
308
|
+
Node 24 ou plus récent est nécessaire, et aucune variable d'environnement n'est à
|
|
309
|
+
renseigner.
|
|
269
310
|
|
|
270
|
-
|
|
271
|
-
`get_lyrics` prend cet id. C'est l'enchaînement prévu : chercher, puis lire.
|
|
311
|
+
### Avec Docker
|
|
272
312
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
lyrics.com). La réponse porte `has_more` et `next_page`. Augmenter `limit` ne va
|
|
284
|
-
pas chercher plus de pages, volontairement : enchaîner plusieurs requêtes dans un
|
|
285
|
-
seul appel d'outil est le meilleur moyen de se faire limiter.
|
|
286
|
-
|
|
287
|
-
**Certaines chansons n'ont pas de paroles.** Une page lyrics.com valide peut
|
|
288
|
-
simplement n'avoir aucun texte enregistré. Cela revient en `status: "no_lyrics"`
|
|
289
|
-
avec un résultat réussi, pas une erreur : inutile de réessayer.
|
|
313
|
+
```json
|
|
314
|
+
{
|
|
315
|
+
"mcpServers": {
|
|
316
|
+
"lyricscom": {
|
|
317
|
+
"command": "docker",
|
|
318
|
+
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-lyricscom:2.0.1"]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
290
323
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
324
|
+
`-i` garde l'entrée standard ouverte, qui est le canal du protocole, et `-t` est
|
|
325
|
+
omis parce qu'un TTY réécrit le flux. Le conteneur a besoin d'un accès HTTPS
|
|
326
|
+
sortant vers `www.lyrics.com`, et de rien d'autre : aucun volume, aucun port,
|
|
327
|
+
aucun identifiant.
|
|
328
|
+
|
|
329
|
+
### Bundle, sans npm
|
|
330
|
+
|
|
331
|
+
Téléchargez `mcp-lyricscom-2.0.1.mcpb` depuis
|
|
332
|
+
[la dernière publication](https://github.com/smeet666/mcp-lyricscom/releases/latest)
|
|
333
|
+
et ouvrez-le. Un client qui gère les bundles MCP l'installe seul, sans npm et
|
|
334
|
+
sans fichier de configuration à modifier. Le bundle emporte ses dépendances, donc
|
|
335
|
+
rien n'est téléchargé à l'installation.
|
|
336
|
+
|
|
337
|
+
## Ce qu'on peut demander
|
|
338
|
+
|
|
339
|
+
- « Quelle est la chanson qui dit "I've got a hand for you" ? »
|
|
340
|
+
- « Trouve-moi les paroles de Wichita Lineman par Glen Campbell. »
|
|
341
|
+
- « Lis-moi la seconde moitié de ces paroles. »
|
|
342
|
+
- « Où apparaît le mot "lineman" dans cette chanson ? »
|
|
343
|
+
- « Sur quels albums cette chanson figure-t-elle ? »
|
|
344
|
+
|
|
345
|
+
Le chemin ordinaire va d'une recherche à une lecture : une ligne porte un `id`,
|
|
346
|
+
et `get_lyrics` reprend cet identifiant.
|
|
347
|
+
|
|
348
|
+
## Les outils
|
|
349
|
+
|
|
350
|
+
| Outil | Ce qu'il fait |
|
|
351
|
+
| --------------- | ------------------------------------------------------ |
|
|
352
|
+
| `search_lyrics` | Trouve une chanson à partir d'un vers de ses paroles. |
|
|
353
|
+
| `search_songs` | Trouve des chansons par titre, resserrées par artiste. |
|
|
354
|
+
| `get_lyrics` | Lit les paroles d'une chanson, par tranches. |
|
|
355
|
+
|
|
356
|
+
### `search_lyrics`
|
|
357
|
+
|
|
358
|
+
Trouve une chanson à partir de mots contenus dans ses paroles. Le site classe
|
|
359
|
+
largement, donc une correspondance est vérifiée avant d'être servie.
|
|
360
|
+
|
|
361
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
362
|
+
| ----------------- | --------------------------------------------- | ------ | ---------------------------------------------- |
|
|
363
|
+
| `query` | chaîne, 1 à 120 caractères | oui | Le vers, ou une partie, à chercher. |
|
|
364
|
+
| `limit` | entier, 1 à 50, défaut `10` | non | Lignes à servir. |
|
|
365
|
+
| `page` | entier, 1 à 20, défaut `1` | non | Quelle page de lignes. |
|
|
366
|
+
| `verify` | `snippet`, `full` ou `none`, défaut `snippet` | non | Comment confirmer que les mots y figurent. |
|
|
367
|
+
| `include_excerpt` | booléen, défaut `true` | non | Porter le vers correspondant sur chaque ligne. |
|
|
368
|
+
|
|
369
|
+
`verify` décide de ce que vaut une ligne. `snippet` vérifie l'extrait que le site
|
|
370
|
+
a déjà rendu et ne coûte rien. `full` va chercher jusqu'à cinq pages de chansons
|
|
371
|
+
et vérifie les paroles entières, ce qui est lent et peut déclencher une
|
|
372
|
+
limitation. `none` sert ce que le site a classé, sans vérification.
|
|
373
|
+
|
|
374
|
+
**En retour :** des lignes portant `id`, que `get_lyrics` reprend ; `title` ;
|
|
375
|
+
`artist` ; `album` et `year`, `null` là où le catalogue n'indique rien ;
|
|
376
|
+
`source_url` ; et `excerpt`, le vers correspondant. `raw_result_count` est ce que
|
|
377
|
+
le site a rendu et `filtered_out` le nombre de lignes que la vérification a
|
|
378
|
+
retirées, si bien que les deux ensemble disent à quel point le classement était
|
|
379
|
+
large. `has_more` et `next_page` poursuivent.
|
|
380
|
+
|
|
381
|
+
### `search_songs`
|
|
382
|
+
|
|
383
|
+
Trouve des chansons par titre, resserrées par artiste.
|
|
384
|
+
|
|
385
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
386
|
+
| -------- | ----------------------------------- | ------ | ---------------------------------------------- |
|
|
387
|
+
| `title` | chaîne, 1 à 120 caractères | oui | Le titre de la chanson, ou une partie. |
|
|
388
|
+
| `artist` | chaîne, jusqu'à 120 caractères | non | Ne garder que les chansons de cet artiste. |
|
|
389
|
+
| `limit` | entier, 1 à 50, défaut `10` | non | Lignes à servir. |
|
|
390
|
+
| `page` | entier, 1 à 20, défaut `1` | non | Quelle page de lignes. |
|
|
391
|
+
| `match` | `loose` ou `strict`, défaut `loose` | non | La rigueur de la correspondance sur l'artiste. |
|
|
392
|
+
|
|
393
|
+
**En retour :** les lignes que rend `search_lyrics`, avec `artist_filter` qui
|
|
394
|
+
redonne ce qui a été demandé et `filtered_out` qui compte ce que la restriction
|
|
395
|
+
sur l'artiste a retiré. `strict` garde les artistes dont le nom correspond tel
|
|
396
|
+
qu'écrit ; `loose` accepte un nom écrit autrement.
|
|
397
|
+
|
|
398
|
+
### `get_lyrics`
|
|
399
|
+
|
|
400
|
+
Lit les paroles d'une chanson. Des paroles longues sont servies par tranches.
|
|
401
|
+
|
|
402
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
403
|
+
| ----------- | ---------------------------------- | ------------- | -------------------------------------------- |
|
|
404
|
+
| `id` | chaîne | l'un des deux | L'identifiant que porte une ligne. |
|
|
405
|
+
| `url` | une adresse lyrics.com | l'un des deux | L'adresse de la page de la chanson. |
|
|
406
|
+
| `max_chars` | entier, 200 à 20000, défaut `6000` | non | Caractères de texte à servir dans cet appel. |
|
|
407
|
+
| `offset` | entier, 0 ou plus, défaut `0` | non | Position en caractères où reprendre. |
|
|
408
|
+
| `highlight` | chaîne, jusqu'à 120 caractères | non | Des mots à localiser dans le texte. |
|
|
409
|
+
|
|
410
|
+
**En retour :** `status`, valant `ok` ou `no_lyrics` pour une page que le site
|
|
411
|
+
contient sans paroles ; `title`, `artist` et `source_url` ; et `lyrics`, la
|
|
412
|
+
tranche elle-même. La lecture est décrite par `total_chars`, `returned_chars`,
|
|
413
|
+
`offset`, `next_offset` et `truncated` : redonnez `next_offset` pour poursuivre,
|
|
414
|
+
et `null` marque la fin. `line_count` compte les lignes de la tranche, et
|
|
415
|
+
`highlight` répond pour chaque mot s'il a été `found` et à quel `line_number`,
|
|
416
|
+
`null` quand il ne l'a pas été.
|
|
296
417
|
|
|
297
418
|
## Configuration
|
|
298
419
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
| Variable | Défaut
|
|
303
|
-
| ----------------------------- |
|
|
304
|
-
| `LYRICSCOM_USER_AGENT` |
|
|
305
|
-
| `LYRICSCOM_MIN_INTERVAL_MS` | `1100`
|
|
306
|
-
| `LYRICSCOM_TIMEOUT_MS` | `15000`
|
|
307
|
-
| `LYRICSCOM_MAX_RETRIES` | `3`
|
|
308
|
-
| `LYRICSCOM_CACHE_TTL_MS` | `900000`
|
|
309
|
-
| `LYRICSCOM_CACHE_MAX_ENTRIES` | `200`
|
|
310
|
-
| `LYRICSCOM_LOG_LEVEL` | `error`
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
420
|
+
Chaque variable est facultative. Elles se posent dans le bloc `env` de la
|
|
421
|
+
configuration du client.
|
|
422
|
+
|
|
423
|
+
| Variable | Défaut | Ce qu'elle fait |
|
|
424
|
+
| ----------------------------- | -------------------- | --------------------------------------------------------------------------------- |
|
|
425
|
+
| `LYRICSCOM_USER_AGENT` | l'identité du projet | Nomme votre application auprès du site, avec une adresse où joindre une personne. |
|
|
426
|
+
| `LYRICSCOM_MIN_INTERVAL_MS` | `1100` | Écart entre deux requêtes, de 500 à 60000. |
|
|
427
|
+
| `LYRICSCOM_TIMEOUT_MS` | `15000` | Délai d'une requête, de 1000 à 120000. |
|
|
428
|
+
| `LYRICSCOM_MAX_RETRIES` | `3` | Tentatives après un échec passager, de 0 à 10. |
|
|
429
|
+
| `LYRICSCOM_CACHE_TTL_MS` | `900000` | Durée pendant laquelle une réponse reste en mémoire, de 0 à 86400000. |
|
|
430
|
+
| `LYRICSCOM_CACHE_MAX_ENTRIES` | `200` | Réponses gardées en mémoire à la fois, de 0 à 10000. |
|
|
431
|
+
| `LYRICSCOM_LOG_LEVEL` | `error` | `silent`, `error`, `info` ou `debug`, écrit sur la sortie d'erreur. |
|
|
432
|
+
|
|
433
|
+
Une valeur hors de sa plage retombe sur le défaut, et la raison est écrite sur la
|
|
434
|
+
sortie d'erreur.
|
|
435
|
+
|
|
436
|
+
**À propos du User-Agent.** Ce serveur nomme le projet et renvoie vers son dépôt,
|
|
437
|
+
et le site le sert. Il refuse en revanche certains agents d'outils génériques :
|
|
438
|
+
un `curl` nu reçoit un 403. Une erreur `blocked_user_agent` signifie que
|
|
439
|
+
l'identité envoyée a été refusée, et `LYRICSCOM_USER_AGENT` permet d'en poser une
|
|
440
|
+
de votre choix. Ce que vous y mettez relève de votre décision et de votre
|
|
441
|
+
responsabilité.
|
|
442
|
+
|
|
443
|
+
## Erreurs
|
|
444
|
+
|
|
445
|
+
Chaque échec porte un de ces codes, un message, et quand cela aide une indication
|
|
446
|
+
du geste suivant.
|
|
447
|
+
|
|
448
|
+
| Code | Ce qui s'est passé | Que faire |
|
|
449
|
+
| -------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
450
|
+
| `not_found` | Le site a répondu, et n'a pas cette chanson. | Vérifiez l'identifiant avec `search_songs`. |
|
|
451
|
+
| `invalid_input` | Les arguments ont été refusés avant toute requête. | Lisez le message, qui nomme l'argument. |
|
|
452
|
+
| `throttled` | Le site demande à ce client de ralentir. | Attendez, puis rappelez avec les mêmes arguments. La chanson est toujours là. |
|
|
453
|
+
| `blocked_user_agent` | Le site a refusé l'identité envoyée par ce client. | Posez `LYRICSCOM_USER_AGENT`. |
|
|
454
|
+
| `parse_failure` | La page a chargé et le contenu attendu est absent. | Signalez-le sur [le suivi d'incidents](https://github.com/smeet666/mcp-lyricscom/issues). |
|
|
455
|
+
| `network_error` | La requête n'a pas abouti. | Réessayez sous peu. |
|
|
456
|
+
| `timeout` | La requête a dépassé son délai. | Augmentez `LYRICSCOM_TIMEOUT_MS`, ou demandez un `max_chars` plus petit. |
|
|
457
|
+
|
|
458
|
+
`throttled` et `blocked_user_agent` sont les deux noms que ce serveur donne à un
|
|
459
|
+
refus de servir, et un appelant qui lit plusieurs sources les ramène sur ce qu'il
|
|
460
|
+
appelle une limitation de débit.
|
|
461
|
+
|
|
462
|
+
## Comme bibliothèque
|
|
463
|
+
|
|
464
|
+
La couche qui lit le site est publiée seule, avec son rythme, son cache et ses
|
|
465
|
+
erreurs, sans protocole attaché.
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
import { LyricsComClient } from "mcp-lyricscom/client";
|
|
469
|
+
|
|
470
|
+
const client = new LyricsComClient();
|
|
471
|
+
const { data, cached } = await client.getSong({ id: "1234567" });
|
|
472
|
+
console.log(data.title, data.artist, cached);
|
|
473
|
+
```
|
|
322
474
|
|
|
323
|
-
|
|
475
|
+
`search` et `getSong` répondent chacun `{ data, cached }`, et lèvent une erreur
|
|
476
|
+
portant un des codes ci-dessus. Le plancher entre deux requêtes tient également
|
|
477
|
+
ici.
|
|
324
478
|
|
|
325
|
-
|
|
326
|
-
backoff et ralentit tout seul : voir cette erreur signifie que ces tentatives ont
|
|
327
|
-
été épuisées. Une fois la limitation déclenchée, la fenêtre dure couramment
|
|
328
|
-
plusieurs minutes, pas quelques secondes : attendez une minute ou plus avant de
|
|
329
|
-
réessayer, et augmentez `LYRICSCOM_MIN_INTERVAL_MS` si cela persiste. Une erreur
|
|
330
|
-
`throttled` ne signifie pas que votre requête n'a pas de résultats.
|
|
479
|
+
## Rythme et attribution
|
|
331
480
|
|
|
332
|
-
|
|
481
|
+
Les requêtes partent une à une avec au moins une seconde entre elles, et le
|
|
482
|
+
plancher d'une demi-seconde tient quelle que soit la configuration. Une recherche
|
|
483
|
+
en `verify: "full"` va chercher jusqu'à cinq pages de chansons, ce qui est la
|
|
484
|
+
chose la plus coûteuse que fait ce serveur.
|
|
333
485
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
486
|
+
Chaque résultat porte l'artiste, le titre et l'adresse de la page de la chanson.
|
|
487
|
+
Les paroles sont l'œuvre de leurs auteurs et de leurs éditeurs. Ce projet ne
|
|
488
|
+
revendique aucun droit dessus, n'embarque aucune base de paroles et n'écrit rien
|
|
489
|
+
sur le disque.
|
|
338
490
|
|
|
339
|
-
|
|
340
|
-
`results` est vide, lyrics.com a bien renvoyé des lignes mais aucune ne contient
|
|
341
|
-
réellement votre mot. Essayez `verify: "none"` pour les voir quand même.
|
|
491
|
+
Ce MCP est un projet non officiel, sans affiliation à lyrics.com.
|
|
342
492
|
|
|
343
|
-
##
|
|
493
|
+
## Confidentialité
|
|
344
494
|
|
|
345
|
-
|
|
346
|
-
que
|
|
347
|
-
|
|
348
|
-
requête
|
|
349
|
-
cache mémoire pour ne pas redemander deux fois la même page.
|
|
495
|
+
Ce serveur ne collecte rien sur vous et n'envoie rien à son auteur. Il tourne sur
|
|
496
|
+
votre machine, ne joint que `www.lyrics.com`, garde ses réponses en mémoire le temps qu'il
|
|
497
|
+
tourne, et n'écrit rien sur le disque. [PRIVACY.md](PRIVACY.md) dit ce qu'une
|
|
498
|
+
requête emporte et quels réglages changent cela.
|
|
350
499
|
|
|
351
500
|
## Développement
|
|
352
501
|
|
|
353
502
|
```bash
|
|
354
503
|
npm install
|
|
355
|
-
npm run build:fixtures
|
|
356
|
-
npm test
|
|
357
|
-
npm run
|
|
358
|
-
npm run build
|
|
359
|
-
LYRICSCOM_LIVE=1 npm run test:live # touche le vrai site, exclu de la CI
|
|
360
|
-
npm run inspector # explorer les outils dans le MCP Inspector
|
|
504
|
+
npm run build:fixtures
|
|
505
|
+
npm test
|
|
506
|
+
npm run check
|
|
361
507
|
```
|
|
362
508
|
|
|
363
|
-
Les
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
La couche de scraping (`src/lyricscom`, `src/text`) n'importe pas le SDK MCP et
|
|
368
|
-
est publiée séparément sous `mcp-lyricscom/client`, utilisable comme simple
|
|
369
|
-
bibliothèque.
|
|
370
|
-
|
|
371
|
-
## Paroles et droits d'auteur
|
|
372
|
-
|
|
373
|
-
Les paroles de chansons sont des œuvres protégées, propriété de leurs auteurs et
|
|
374
|
-
éditeurs. Ce projet ne revendique aucun droit dessus.
|
|
375
|
-
|
|
376
|
-
Ce serveur est un client. Il va chercher les mêmes pages publiques de lyrics.com
|
|
377
|
-
que celles que vous pourriez ouvrir dans un navigateur, à la demande, une requête
|
|
378
|
-
à la fois, en réponse à une demande explicite de votre part ou de celle de votre
|
|
379
|
-
assistant. Il ne parcourt pas le site, ne constitue aucune base de paroles, et
|
|
380
|
-
n'écrit rien sur le disque. Les pages restent en mémoire quelques minutes pour ne
|
|
381
|
-
pas solliciter le site inutilement.
|
|
382
|
-
|
|
383
|
-
Chaque résultat porte l'artiste, le titre et l'URL source. Si vous affichez ou
|
|
384
|
-
réutilisez ce que renvoie ce serveur, conservez cette attribution et le lien vers
|
|
385
|
-
la page d'origine.
|
|
509
|
+
Les tests s'exécutent sur des fixtures engendrées et n'émettent aucune requête.
|
|
510
|
+
La suite en direct, `npm run test:live`, émet une requête par route et tourne
|
|
511
|
+
chaque nuit contre le site lui-même.
|
|
386
512
|
|
|
387
|
-
|
|
388
|
-
utilise n'y est interdit, et il s'impose environ une requête par seconde. Ce
|
|
389
|
-
rythme est contraint : `LYRICSCOM_MIN_INTERVAL_MS` est refusé en dessous de
|
|
390
|
-
500 ms, une valeur plus basse retombant sur l'intervalle standard avec un
|
|
391
|
-
avertissement sur stderr. Augmentez-le pour ralentir davantage.
|
|
513
|
+
## Contribuer
|
|
392
514
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
515
|
+
Les anomalies, les questions et les idées ont leur place dans
|
|
516
|
+
[le suivi d'incidents](https://github.com/smeet666/mcp-lyricscom/issues). Les
|
|
517
|
+
propositions de modification sont bienvenues ; ouvrir un ticket d'abord aide à
|
|
518
|
+
s'accorder sur la forme du changement. Voir [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
396
519
|
|
|
397
520
|
## Licence
|
|
398
521
|
|
|
399
|
-
MIT, voir [LICENSE](
|
|
400
|
-
|
|
522
|
+
MIT, voir [LICENSE](LICENSE). Les paroles appartiennent à leurs auteurs et à
|
|
523
|
+
leurs éditeurs.
|