mcp-metacritic 2.0.0 → 2.1.0
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 +20 -0
- package/PRIVACY.md +160 -0
- package/README.md +398 -259
- package/dist/index.js +177 -79
- package/dist/index.js.map +1 -1
- package/dist/mc/client.d.ts +13 -3
- package/dist/mc/client.js +76 -26
- package/dist/mc/client.js.map +1 -1
- package/package.json +16 -11
- package/server.json +4 -4
package/README.md
CHANGED
|
@@ -6,21 +6,29 @@
|
|
|
6
6
|
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.smeet666/mcp-metacritic)
|
|
7
7
|
[](https://glama.ai/mcp/servers/smeet666/mcp-metacritic)
|
|
8
8
|
[](https://m8ven.ai/mcp/smeet666-mcp-metacritic-1yvblv)
|
|
9
|
+
[](https://lobehub.com/mcp/smeet666-mcp-metacritic)
|
|
9
10
|
[](https://cursor.com/en/install-mcp?name=metacritic&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1tZXRhY3JpdGljIl19)
|
|
10
11
|
[](https://insiders.vscode.dev/redirect/mcp/install?name=metacritic&config=%7B%22name%22%3A%22metacritic%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-metacritic%22%5D%7D)
|
|
12
|
+
|
|
11
13
|
<!-- m8ven-verify: 01151bc5a8514e55175f063339bedc6f -->
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
the
|
|
17
|
-
|
|
15
|
+
[Metacritic](https://www.metacritic.com) gathers what critics and audiences said
|
|
16
|
+
about films, television series and video games. Each entry carries the year, the
|
|
17
|
+
age rating, the genres, and two scores of its own: the Metascore, a weighted
|
|
18
|
+
average of the professional reviews, and the user score, out of ten, from the
|
|
19
|
+
people who signed up to rate it. Under each entry sit the reviews themselves,
|
|
20
|
+
with the publication that ran them and the quoted line.
|
|
21
|
+
|
|
22
|
+
This server connects a chat client to that catalogue. You can search for a title,
|
|
23
|
+
read its entry with its scores and its details, browse a catalogue by score,
|
|
24
|
+
recency or popularity, and read the reviews of one title, filtered by critic or
|
|
25
|
+
audience and by how favourable they were. It needs no API key and no account.
|
|
18
26
|
|
|
19
|
-
_
|
|
27
|
+
_[Version française](#mcp-metacritic-français)_
|
|
20
28
|
|
|
21
29
|
---
|
|
22
30
|
|
|
23
|
-
##
|
|
31
|
+
## Install
|
|
24
32
|
|
|
25
33
|
**One-click install**
|
|
26
34
|
|
|
@@ -46,6 +54,8 @@ claude mcp add metacritic -- npx -y mcp-metacritic
|
|
|
46
54
|
}
|
|
47
55
|
```
|
|
48
56
|
|
|
57
|
+
Node 24 or later is required, and no environment variable has to be set.
|
|
58
|
+
|
|
49
59
|
### With Docker
|
|
50
60
|
|
|
51
61
|
```json
|
|
@@ -53,168 +63,220 @@ claude mcp add metacritic -- npx -y mcp-metacritic
|
|
|
53
63
|
"mcpServers": {
|
|
54
64
|
"metacritic": {
|
|
55
65
|
"command": "docker",
|
|
56
|
-
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-metacritic:2.
|
|
66
|
+
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-metacritic:2.1.0"]
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
70
|
```
|
|
61
71
|
|
|
62
|
-
`-i` keeps stdin open, which is where the protocol travels, and
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
`-i` keeps stdin open, which is where the protocol travels, and `-t` is left out
|
|
73
|
+
because a TTY rewrites the stream. The container needs outbound HTTPS to
|
|
74
|
+
`backend.metacritic.com`, and nothing else: no volume, no port, no credential.
|
|
65
75
|
|
|
66
|
-
|
|
76
|
+
### Bundle, without npm
|
|
67
77
|
|
|
68
|
-
Download `mcp-metacritic
|
|
69
|
-
[the latest release](https://github.com/smeet666/mcp-metacritic/releases/latest)
|
|
70
|
-
it. A client that supports MCP bundles installs it on its own, with no
|
|
71
|
-
no configuration file to edit. The bundle carries its dependencies, so
|
|
72
|
-
is fetched at install time.
|
|
78
|
+
Download `mcp-metacritic-2.1.0.mcpb` from
|
|
79
|
+
[the latest release](https://github.com/smeet666/mcp-metacritic/releases/latest)
|
|
80
|
+
and open it. A client that supports MCP bundles installs it on its own, with no
|
|
81
|
+
npm and no configuration file to edit. The bundle carries its dependencies, so
|
|
82
|
+
nothing is fetched at install time.
|
|
73
83
|
|
|
74
|
-
##
|
|
84
|
+
## What you can ask
|
|
85
|
+
|
|
86
|
+
- "What did critics make of The Matrix?"
|
|
87
|
+
- "Read me a few negative reviews of that game."
|
|
88
|
+
- "What are the best-reviewed horror films?"
|
|
89
|
+
- "How does the user score compare to the Metascore?"
|
|
90
|
+
- "What came out recently that reviewed well?"
|
|
75
91
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
| `search_titles` | Finds films, shows and games by title. Compact rows. | `query`, `kind`, `limit` |
|
|
79
|
-
| `get_title` | Reads one entry, section by section. | `slug`, `kind`, `sections`, `max_chars`, `offset` |
|
|
80
|
-
| `get_reviews` | Individual critic or audience reviews, filtered by verdict. | `slug`, `kind`, `source`, `sentiment`, `limit` |
|
|
81
|
-
| `browse_titles` | Rankings: best rated, newest, most looked at. | `kind`, `sort`, `genre`, `limit`, `offset` |
|
|
92
|
+
The ordinary path runs from a search to an entry: a row carries a `slug` and a
|
|
93
|
+
`kind`, and `get_title` and `get_reviews` take both together.
|
|
82
94
|
|
|
83
|
-
|
|
84
|
-
both. That is the intended chain: search, then read.
|
|
95
|
+
## Tools
|
|
85
96
|
|
|
86
|
-
|
|
97
|
+
| Tool | What it does |
|
|
98
|
+
| --------------- | ----------------------------------------------------------- |
|
|
99
|
+
| `search_titles` | Finds films, series and games by title. |
|
|
100
|
+
| `get_title` | Reads one entry, its scores and its details. |
|
|
101
|
+
| `get_reviews` | Reads the reviews of one entry, by source and by sentiment. |
|
|
102
|
+
| `browse_titles` | Lists a catalogue by score, recency or popularity. |
|
|
103
|
+
|
|
104
|
+
A title is addressed by its `slug` together with its `kind`, since the same slug
|
|
105
|
+
can name a film and a game.
|
|
106
|
+
|
|
107
|
+
### `search_titles`
|
|
108
|
+
|
|
109
|
+
Finds films, series and games by title.
|
|
110
|
+
|
|
111
|
+
| Argument | Type | Required | What it does |
|
|
112
|
+
| -------- | ----------------------------------------------- | -------- | -------------------------- |
|
|
113
|
+
| `query` | string, at least 1 character | yes | A title, or part of one. |
|
|
114
|
+
| `kind` | `movie`, `show`, `game` or `any`, default `any` | no | Which catalogue to search. |
|
|
115
|
+
| `limit` | integer, 1 to 50, default `10` | no | Rows to serve. |
|
|
116
|
+
|
|
117
|
+
**In return:** rows carrying `slug` and `kind`, which `get_title` and
|
|
118
|
+
`get_reviews` take together; `title`; `year`; `release_date`; `rating`, the age
|
|
119
|
+
rating as published; `metascore`; `user_score`, which the search route publishes
|
|
120
|
+
for no row and which is null on every one of them; and `source_url`. **A score the
|
|
121
|
+
site has not computed is `null`, never `0`:** on a scale that starts at zero the
|
|
122
|
+
two would be indistinguishable, and a title with too few reviews carries none.
|
|
123
|
+
|
|
124
|
+
### `get_title`
|
|
125
|
+
|
|
126
|
+
Reads one entry. The heavier parts are asked for rather than served by default,
|
|
127
|
+
and each one beyond the default costs a request.
|
|
128
|
+
|
|
129
|
+
| Argument | Type | Required | What it does |
|
|
130
|
+
| ----------- | --------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------- |
|
|
131
|
+
| `slug` | string, at least 1 character | yes | The identifier a row carries. |
|
|
132
|
+
| `kind` | `movie`, `show` or `game` | yes | Which catalogue it belongs to. |
|
|
133
|
+
| `sections` | array of `basic`, `scores`, `awards`, `production`, `networks`, `where_to_watch`, default `["basic", "scores"]` | no | Which parts to return. |
|
|
134
|
+
| `max_chars` | integer, 200 to 20000, default `4000` | no | How much of the description to serve. |
|
|
135
|
+
| `offset` | integer, 0 or more, default `0` | no | Where to resume the description. |
|
|
136
|
+
|
|
137
|
+
**In return:** the entry a search row carries, plus `description`, `tagline`,
|
|
138
|
+
`genres`, `duration_minutes` and `imdb_id`, each `null` where the page states
|
|
139
|
+
nothing. `total_chars`, `returned_chars` and `offset` describe the slice of the
|
|
140
|
+
description served.
|
|
141
|
+
|
|
142
|
+
### `get_reviews`
|
|
143
|
+
|
|
144
|
+
Reads the reviews of one entry.
|
|
145
|
+
|
|
146
|
+
| Argument | Type | Required | What it does |
|
|
147
|
+
| ----------- | --------------------------------------------------------- | -------- | ---------------------------------- |
|
|
148
|
+
| `slug` | string, at least 1 character | yes | The identifier a row carries. |
|
|
149
|
+
| `kind` | `movie`, `show` or `game` | yes | Which catalogue it belongs to. |
|
|
150
|
+
| `source` | `critic` or `user`, default `critic` | no | Whose reviews to read. |
|
|
151
|
+
| `sentiment` | `all`, `positive`, `neutral` or `negative`, default `all` | no | How favourable a review has to be. |
|
|
152
|
+
| `limit` | integer, 1 to 50, default `10` | no | Reviews to serve. |
|
|
153
|
+
| `offset` | integer, 0 or more, default `0` | no | Reviews to skip, for paging. |
|
|
154
|
+
|
|
155
|
+
**In return:** `reviews`, each with its `quote` as published, its `score`, the
|
|
156
|
+
`max` that score is out of, which is 100 for a critic and 10 for a user, and the
|
|
157
|
+
`publication` that ran it. **Name the publication when quoting a review.**
|
|
158
|
+
`total_available` counts every review Metacritic holds from that source for the
|
|
159
|
+
entry, whatever `sentiment` was asked for, since the sentiment sorts the sample
|
|
160
|
+
this server received rather than the request that fetched it. `next_offset`
|
|
161
|
+
continues.
|
|
162
|
+
|
|
163
|
+
### `browse_titles`
|
|
164
|
+
|
|
165
|
+
Lists a catalogue.
|
|
166
|
+
|
|
167
|
+
| Argument | Type | Required | What it does |
|
|
168
|
+
| -------- | ----------------------------------------------- | -------- | -------------------------------------- |
|
|
169
|
+
| `kind` | `movie`, `show` or `game`, default `movie` | no | Which catalogue to list. |
|
|
170
|
+
| `sort` | `score`, `recent` or `popular`, default `score` | no | How the rows are ordered. |
|
|
171
|
+
| `genre` | string | no | A single genre name, such as `Horror`. |
|
|
172
|
+
| `limit` | integer, 1 to 50, default `20` | no | Rows to serve. |
|
|
173
|
+
| `offset` | integer, 0 or more, default `0` | no | Rows to skip, for paging. |
|
|
174
|
+
|
|
175
|
+
**In return:** the rows `search_titles` returns, with `total_available`,
|
|
176
|
+
`offset`, `next_offset` and the `kind`, `sort` and `genre` the listing was read
|
|
177
|
+
under.
|
|
178
|
+
|
|
179
|
+
## Two scores, two things measured
|
|
180
|
+
|
|
181
|
+
The Metascore is a weighted average of professional reviews, out of 100. The user
|
|
182
|
+
score is the average of what registered members gave, out of 10. They measure
|
|
183
|
+
different populations on different scales, and a title can carry one and not the
|
|
184
|
+
other. Read each with the `max` its reviews state, and report a missing score as
|
|
185
|
+
missing.
|
|
87
186
|
|
|
88
|
-
|
|
187
|
+
## Configuration
|
|
89
188
|
|
|
90
|
-
|
|
91
|
-
the audience score to 10, so 73 and 8.9 describe similar opinions. Every score
|
|
92
|
-
this server returns carries its own `max`, and the tool descriptions say so,
|
|
93
|
-
because averaging the two is the single easiest mistake to make with this data.
|
|
189
|
+
Every variable is optional. Set them in the `env` block of your client config.
|
|
94
190
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
`
|
|
98
|
-
|
|
191
|
+
| Variable | Default | What it does |
|
|
192
|
+
| ------------------------ | -------------------- | ---------------------------------------------------------------------------------- |
|
|
193
|
+
| `MC_USER_AGENT` | the project identity | Names your application to the site, with an address where a person can be reached. |
|
|
194
|
+
| `MC_MIN_INTERVAL_MS` | `1000` | Gap between two requests, from 500 to 60000. |
|
|
195
|
+
| `MC_TIMEOUT_MS` | `15000` | Deadline for one request, from 1000 to 120000. |
|
|
196
|
+
| `MC_MAX_RETRIES` | `3` | Attempts after a transient failure, from 0 to 10. |
|
|
197
|
+
| `MC_CACHE_TTL_MS` | `86400000` | How long a catalogue entry stays in memory, from 0 to 604800000. |
|
|
198
|
+
| `MC_SCORES_CACHE_TTL_MS` | `3600000` | How long scores and reviews stay in memory, from 0 to 86400000. |
|
|
199
|
+
| `MC_CACHE_MAX_ENTRIES` | `200` | Answers held in memory at once, from 0 to 10000. |
|
|
200
|
+
| `MC_LOG_LEVEL` | `error` | `silent`, `error`, `info` or `debug`, written to stderr. |
|
|
99
201
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
entry page where the rest can be read.
|
|
202
|
+
Scores move as reviews come in, especially around a release, so they are held for
|
|
203
|
+
an hour where a catalogue entry is held for a day. A value outside its range
|
|
204
|
+
falls back to the default, and the reason is written to stderr.
|
|
104
205
|
|
|
105
|
-
|
|
106
|
-
object or an `errors` array, and this server reads that distinction rather than
|
|
107
|
-
guessing. A missing entry produces an error with a code; a request that could
|
|
108
|
-
not be made says it could not be made, and never that Metacritic publishes
|
|
109
|
-
nothing. Those are very different answers and a model cannot tell them apart on
|
|
110
|
-
its own.
|
|
206
|
+
## Errors
|
|
111
207
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
the site counts matches loosely: "the matrix" reports over 55 000 entries
|
|
115
|
-
because it counts anything matching either word.
|
|
208
|
+
Every failure carries one of six codes, a message, and where it helps a hint
|
|
209
|
+
naming the next move.
|
|
116
210
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
211
|
+
| Code | What happened | What to do |
|
|
212
|
+
| --------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
213
|
+
| `not_found` | The site answered, and holds no such entry. | Check the slug and the kind with `search_titles`. |
|
|
214
|
+
| `invalid_input` | The arguments were refused before any request went out. | Read the message, which names the argument. |
|
|
215
|
+
| `rate_limited` | The site asked this client to slow down. | Wait the number of seconds the hint names and call again with the same arguments. The entry is still there. |
|
|
216
|
+
| `parse_failure` | The answer arrived in a shape this client cannot read. | Report it at [the issue tracker](https://github.com/smeet666/mcp-metacritic/issues). |
|
|
217
|
+
| `network_error` | The request did not complete. | Try again shortly. |
|
|
218
|
+
| `timeout` | The request passed its deadline. | Raise `MC_TIMEOUT_MS`, or ask for fewer rows. |
|
|
120
219
|
|
|
121
|
-
##
|
|
220
|
+
## As a library
|
|
122
221
|
|
|
123
|
-
|
|
222
|
+
The layer reading the site is published on its own, with its pacing, its cache
|
|
223
|
+
and its errors, and with no protocol attached.
|
|
124
224
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
| `MC_USER_AGENT` | `mcp-metacritic v<version> (<repo>)` | User-Agent sent to Metacritic. |
|
|
128
|
-
| `MC_MIN_INTERVAL_MS` | `1000` | Minimum gap between requests. Values below 500 ms are ignored. |
|
|
129
|
-
| `MC_TIMEOUT_MS` | `15000` | Per-request timeout. |
|
|
130
|
-
| `MC_MAX_RETRIES` | `3` | Retries on refusals and transient errors. |
|
|
131
|
-
| `MC_CACHE_TTL_MS` | `86400000` | Catalogue cache lifetime (24 hours). |
|
|
132
|
-
| `MC_SCORES_CACHE_TTL_MS` | `3600000` | Scores and reviews cache lifetime (1 hour). |
|
|
133
|
-
| `MC_CACHE_MAX_ENTRIES` | `200` | In-memory cache size. |
|
|
134
|
-
| `MC_LOG_LEVEL` | `error` | `silent`, `error`, `info` or `debug`. Logs go to stderr. |
|
|
225
|
+
```ts
|
|
226
|
+
import { McClient } from "mcp-metacritic/client";
|
|
135
227
|
|
|
136
|
-
|
|
137
|
-
|
|
228
|
+
const client = new McClient();
|
|
229
|
+
const { data, cached } = await client.getDetail("movie", "the-matrix");
|
|
230
|
+
console.log(data.title, data.metascore, cached);
|
|
231
|
+
```
|
|
138
232
|
|
|
139
|
-
|
|
233
|
+
Each read answers `{ data, cached }`, and throws an error carrying one of the six
|
|
234
|
+
codes. The floor between two requests holds here as well.
|
|
140
235
|
|
|
141
|
-
|
|
142
|
-
`backend.metacritic.com`, and this server calls the same routes its own pages
|
|
143
|
-
call. It sends one request at a time, paces itself, backs off when refused, and
|
|
144
|
-
keeps two in-memory caches: a day for catalogue entries, which change when
|
|
145
|
-
someone edits them, and an hour for scores and reviews, which move as reviews
|
|
146
|
-
land.
|
|
236
|
+
## Pacing and attribution
|
|
147
237
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
the
|
|
238
|
+
Requests go out one at a time with at least a second between them, and the floor
|
|
239
|
+
of half a second holds however the server is configured. The `User-Agent` always
|
|
240
|
+
ends with the project identity and an address where a person can be reached.
|
|
151
241
|
|
|
152
|
-
|
|
242
|
+
Every result carries the address of the Metacritic page, and every quoted review
|
|
243
|
+
carries the publication that ran it. The reviews belong to their authors and to
|
|
244
|
+
the publications that ran them.
|
|
153
245
|
|
|
154
|
-
|
|
155
|
-
This is worth stating plainly rather than leaving implicit.
|
|
246
|
+
This MCP server is an unofficial project, with no affiliation to Metacritic.
|
|
156
247
|
|
|
157
|
-
|
|
158
|
-
API key, and did not throttle ten consecutive requests during testing. Those
|
|
159
|
-
are the conditions this server operates under, and it does not take them as
|
|
160
|
-
permission to be greedy. It sends one request per second at most, identifies
|
|
161
|
-
itself, caches what it reads, and carries a link back to Metacritic on every
|
|
162
|
-
result, including on every quoted review.
|
|
248
|
+
## Privacy
|
|
163
249
|
|
|
164
|
-
|
|
250
|
+
This server collects nothing about you and sends nothing to its author. It runs
|
|
251
|
+
on your machine, contacts `backend.metacritic.com` and nothing else, holds its
|
|
252
|
+
answers in memory while it runs, and writes nothing to disk.
|
|
253
|
+
[PRIVACY.md](PRIVACY.md) states what a request carries and which settings change
|
|
254
|
+
any of it.
|
|
165
255
|
|
|
166
256
|
## Development
|
|
167
257
|
|
|
168
258
|
```bash
|
|
169
259
|
npm install
|
|
170
|
-
npm run build:fixtures
|
|
171
|
-
npm test
|
|
172
|
-
npm run
|
|
173
|
-
npm run build
|
|
174
|
-
MC_LIVE=1 npm run test:live # hits the real site, excluded from CI
|
|
175
|
-
npm run inspector # explore the tools in the MCP Inspector
|
|
260
|
+
npm run build:fixtures
|
|
261
|
+
npm test
|
|
262
|
+
npm run check
|
|
176
263
|
```
|
|
177
264
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
The API layer (`src/mc`) does not import the MCP SDK and is published
|
|
183
|
-
separately as `mcp-metacritic/client`, so it can be used as a plain library. It
|
|
184
|
-
enforces the pacing floor and the identifying User-Agent itself, so those hold
|
|
185
|
-
for a library consumer too.
|
|
186
|
-
|
|
187
|
-
## Reviews, scores and copyright
|
|
188
|
-
|
|
189
|
-
Metascores, review texts and the editorial work behind them belong to
|
|
190
|
-
Metacritic and to the publications it aggregates. This project claims no rights
|
|
191
|
-
over them and ships none of their content.
|
|
192
|
-
|
|
193
|
-
Review quotes are returned as excerpts, capped in length, always with the
|
|
194
|
-
publication named and with a link to the original article where the site
|
|
195
|
-
provides one. If you repeat a quote, keep both. If you cite a score, credit
|
|
196
|
-
Metacritic and link the entry: every result carries a `source_url`.
|
|
197
|
-
|
|
198
|
-
This is an unofficial project, with no affiliation to or endorsement by
|
|
199
|
-
Metacritic or Fandom.
|
|
265
|
+
Tests run against generated fixtures and make no network request. The live suite,
|
|
266
|
+
`npm run test:live`, makes one request per route and runs nightly against the
|
|
267
|
+
site itself.
|
|
200
268
|
|
|
201
269
|
## Contributing
|
|
202
270
|
|
|
203
|
-
Bugs, questions and ideas
|
|
204
|
-
[the issue tracker](https://github.com/smeet666/mcp-metacritic/issues). Pull
|
|
205
|
-
are welcome;
|
|
206
|
-
|
|
207
|
-
detail, and [SECURITY.md](SECURITY.md) covers anything exploitable.
|
|
208
|
-
|
|
209
|
-
## Support
|
|
210
|
-
|
|
211
|
-
These servers are free and stay free. If one of them saved you an afternoon,
|
|
212
|
-
you can [buy me a coffee](https://buymeacoffee.com/smeet666).
|
|
271
|
+
Bugs, questions and ideas belong in
|
|
272
|
+
[the issue tracker](https://github.com/smeet666/mcp-metacritic/issues). Pull
|
|
273
|
+
requests are welcome; opening an issue first helps agree on the shape of the
|
|
274
|
+
change. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
213
275
|
|
|
214
276
|
## License
|
|
215
277
|
|
|
216
|
-
MIT
|
|
217
|
-
|
|
278
|
+
MIT, see [LICENSE](LICENSE). The scores and the reviews belong to Metacritic and
|
|
279
|
+
to the publications it quotes.
|
|
218
280
|
|
|
219
281
|
---
|
|
220
282
|
|
|
@@ -222,13 +284,22 @@ data retrieved through it.
|
|
|
222
284
|
|
|
223
285
|
# mcp-metacritic (français)
|
|
224
286
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
287
|
+
_[English version](#mcp-metacritic)_
|
|
288
|
+
|
|
289
|
+
[Metacritic](https://www.metacritic.com) rassemble ce que la critique et le
|
|
290
|
+
public ont dit des films, des séries et des jeux vidéo. Chaque fiche porte
|
|
291
|
+
l'année, la classification par âge, les genres, et deux notes qui lui sont
|
|
292
|
+
propres : le Metascore, moyenne pondérée des critiques professionnelles, et la
|
|
293
|
+
note des utilisateurs, sur dix, donnée par les inscrits. Sous chaque fiche se
|
|
294
|
+
trouvent les critiques elles-mêmes, avec la publication qui les a signées et la
|
|
295
|
+
phrase citée.
|
|
230
296
|
|
|
231
|
-
|
|
297
|
+
Ce serveur relie un client de conversation à ce catalogue. On peut y chercher un
|
|
298
|
+
titre, lire sa fiche avec ses notes et ses détails, parcourir un catalogue par
|
|
299
|
+
note, par fraîcheur ou par popularité, et lire les critiques d'un titre, filtrées
|
|
300
|
+
par source et par tonalité. Aucune clé d'API, aucun compte.
|
|
301
|
+
|
|
302
|
+
## Installation
|
|
232
303
|
|
|
233
304
|
**Installation en un clic**
|
|
234
305
|
|
|
@@ -241,7 +312,7 @@ compte, sans configuration.**
|
|
|
241
312
|
claude mcp add metacritic -- npx -y mcp-metacritic
|
|
242
313
|
```
|
|
243
314
|
|
|
244
|
-
**Claude Desktop, Cursor, et tout client
|
|
315
|
+
**Claude Desktop, Cursor, et tout client au format de configuration standard**
|
|
245
316
|
|
|
246
317
|
```json
|
|
247
318
|
{
|
|
@@ -254,6 +325,9 @@ claude mcp add metacritic -- npx -y mcp-metacritic
|
|
|
254
325
|
}
|
|
255
326
|
```
|
|
256
327
|
|
|
328
|
+
Node 24 ou plus récent est nécessaire, et aucune variable d'environnement n'est à
|
|
329
|
+
renseigner.
|
|
330
|
+
|
|
257
331
|
### Avec Docker
|
|
258
332
|
|
|
259
333
|
```json
|
|
@@ -261,155 +335,220 @@ claude mcp add metacritic -- npx -y mcp-metacritic
|
|
|
261
335
|
"mcpServers": {
|
|
262
336
|
"metacritic": {
|
|
263
337
|
"command": "docker",
|
|
264
|
-
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-metacritic:2.
|
|
338
|
+
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-metacritic:2.1.0"]
|
|
265
339
|
}
|
|
266
340
|
}
|
|
267
341
|
}
|
|
268
342
|
```
|
|
269
343
|
|
|
270
|
-
`-i` garde l'entrée standard ouverte, qui est le canal du protocole, et
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
Téléchargez `mcp-metacritic
|
|
278
|
-
[la dernière
|
|
279
|
-
ouvrez-le. Un client
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
##
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
**
|
|
317
|
-
`
|
|
318
|
-
la
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
344
|
+
`-i` garde l'entrée standard ouverte, qui est le canal du protocole, et `-t` est
|
|
345
|
+
omis parce qu'un TTY réécrit le flux. Le conteneur a besoin d'un accès HTTPS
|
|
346
|
+
sortant vers `backend.metacritic.com`, et de rien d'autre : aucun volume, aucun
|
|
347
|
+
port, aucun identifiant.
|
|
348
|
+
|
|
349
|
+
### Bundle, sans npm
|
|
350
|
+
|
|
351
|
+
Téléchargez `mcp-metacritic-2.1.0.mcpb` depuis
|
|
352
|
+
[la dernière publication](https://github.com/smeet666/mcp-metacritic/releases/latest)
|
|
353
|
+
et ouvrez-le. Un client qui gère les bundles MCP l'installe seul, sans npm et
|
|
354
|
+
sans fichier de configuration à modifier. Le bundle emporte ses dépendances, donc
|
|
355
|
+
rien n'est téléchargé à l'installation.
|
|
356
|
+
|
|
357
|
+
## Ce qu'on peut demander
|
|
358
|
+
|
|
359
|
+
- « Qu'a pensé la critique de Matrix ? »
|
|
360
|
+
- « Lis-moi quelques critiques négatives de ce jeu. »
|
|
361
|
+
- « Quels sont les films d'horreur les mieux notés ? »
|
|
362
|
+
- « Comment la note du public se compare-t-elle au Metascore ? »
|
|
363
|
+
- « Qu'est-il sorti récemment qui a été bien reçu ? »
|
|
364
|
+
|
|
365
|
+
Le chemin ordinaire va d'une recherche à une fiche : une ligne porte un `slug` et
|
|
366
|
+
un `kind`, et `get_title` comme `get_reviews` reprennent les deux ensemble.
|
|
367
|
+
|
|
368
|
+
## Les outils
|
|
369
|
+
|
|
370
|
+
| Outil | Ce qu'il fait |
|
|
371
|
+
| --------------- | ------------------------------------------------------------- |
|
|
372
|
+
| `search_titles` | Trouve des films, des séries et des jeux par leur titre. |
|
|
373
|
+
| `get_title` | Lit une fiche, ses notes et ses détails. |
|
|
374
|
+
| `get_reviews` | Lit les critiques d'une fiche, par source et par tonalité. |
|
|
375
|
+
| `browse_titles` | Liste un catalogue par note, par fraîcheur ou par popularité. |
|
|
376
|
+
|
|
377
|
+
Un titre s'adresse par son `slug` accompagné de son `kind`, un même slug pouvant
|
|
378
|
+
nommer un film et un jeu.
|
|
379
|
+
|
|
380
|
+
### `search_titles`
|
|
381
|
+
|
|
382
|
+
Trouve des films, des séries et des jeux par leur titre.
|
|
383
|
+
|
|
384
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
385
|
+
| -------- | ---------------------------------------------- | ------ | ------------------------- |
|
|
386
|
+
| `query` | chaîne, au moins 1 caractère | oui | Un titre, ou une partie. |
|
|
387
|
+
| `kind` | `movie`, `show`, `game` ou `any`, défaut `any` | non | Le catalogue où chercher. |
|
|
388
|
+
| `limit` | entier, 1 à 50, défaut `10` | non | Lignes à servir. |
|
|
389
|
+
|
|
390
|
+
**En retour :** des lignes portant `slug` et `kind`, que `get_title` et
|
|
391
|
+
`get_reviews` reprennent ensemble ; `title` ; `year` ; `release_date` ; `rating`,
|
|
392
|
+
la classification par âge telle que publiée ; `metascore` ; `user_score`, que la
|
|
393
|
+
route de recherche ne publie pour aucune ligne et qui y vaut `null` partout ; et
|
|
394
|
+
`source_url`. **Une note que le site n'a pas calculée vaut `null`, jamais `0` :**
|
|
395
|
+
sur une échelle qui commence à zéro les deux seraient indiscernables, et un titre
|
|
396
|
+
avec trop peu de critiques n'en porte aucune.
|
|
397
|
+
|
|
398
|
+
### `get_title`
|
|
399
|
+
|
|
400
|
+
Lit une fiche. Les parties lourdes se demandent au lieu d'être servies par
|
|
401
|
+
défaut, et chacune au-delà du défaut coûte une requête.
|
|
402
|
+
|
|
403
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
404
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------------- | ------ | ------------------------------------ |
|
|
405
|
+
| `slug` | chaîne, au moins 1 caractère | oui | L'identifiant d'une ligne. |
|
|
406
|
+
| `kind` | `movie`, `show` ou `game` | oui | Le catalogue dont il relève. |
|
|
407
|
+
| `sections` | tableau de `basic`, `scores`, `awards`, `production`, `networks`, `where_to_watch`, défaut `["basic", "scores"]` | non | Les parties à rendre. |
|
|
408
|
+
| `max_chars` | entier, 200 à 20000, défaut `4000` | non | La longueur de description à servir. |
|
|
409
|
+
| `offset` | entier, 0 ou plus, défaut `0` | non | Où reprendre la description. |
|
|
410
|
+
|
|
411
|
+
**En retour :** la fiche que porte une ligne de recherche, plus `description`,
|
|
412
|
+
`tagline`, `genres`, `duration_minutes` et `imdb_id`, chacun `null` là où la page
|
|
413
|
+
n'indique rien. `total_chars`, `returned_chars` et `offset` décrivent la tranche
|
|
414
|
+
de description servie.
|
|
415
|
+
|
|
416
|
+
### `get_reviews`
|
|
417
|
+
|
|
418
|
+
Lit les critiques d'une fiche.
|
|
419
|
+
|
|
420
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
421
|
+
| ----------- | -------------------------------------------------------- | ------ | ---------------------------------- |
|
|
422
|
+
| `slug` | chaîne, au moins 1 caractère | oui | L'identifiant d'une ligne. |
|
|
423
|
+
| `kind` | `movie`, `show` ou `game` | oui | Le catalogue dont il relève. |
|
|
424
|
+
| `source` | `critic` ou `user`, défaut `critic` | non | De qui lire les critiques. |
|
|
425
|
+
| `sentiment` | `all`, `positive`, `neutral` ou `negative`, défaut `all` | non | La tonalité exigée d'une critique. |
|
|
426
|
+
| `limit` | entier, 1 à 50, défaut `10` | non | Critiques à servir. |
|
|
427
|
+
| `offset` | entier, 0 ou plus, défaut `0` | non | Critiques à sauter, pour paginer. |
|
|
428
|
+
|
|
429
|
+
**En retour :** `reviews`, chacune avec sa `quote` telle que publiée, son
|
|
430
|
+
`score`, le `max` sur lequel cette note est donnée, qui vaut 100 pour un critique
|
|
431
|
+
et 10 pour un utilisateur, et la `publication` qui l'a signée. **Nommez la
|
|
432
|
+
publication quand vous citez une critique.** `total_available` compte toutes les
|
|
433
|
+
critiques que Metacritic tient de cette source pour cette fiche, quelle que soit
|
|
434
|
+
la tonalité demandée, puisque la tonalité trie l'échantillon reçu et non la
|
|
435
|
+
requête qui l'a cherché. `next_offset` poursuit.
|
|
436
|
+
|
|
437
|
+
### `browse_titles`
|
|
438
|
+
|
|
439
|
+
Liste un catalogue.
|
|
440
|
+
|
|
441
|
+
| Argument | Type | Requis | Ce qu'il fait |
|
|
442
|
+
| -------- | ---------------------------------------------- | ------ | ------------------------------------- |
|
|
443
|
+
| `kind` | `movie`, `show` ou `game`, défaut `movie` | non | Le catalogue à lister. |
|
|
444
|
+
| `sort` | `score`, `recent` ou `popular`, défaut `score` | non | L'ordre des lignes. |
|
|
445
|
+
| `genre` | chaîne | non | Un seul nom de genre, comme `Horror`. |
|
|
446
|
+
| `limit` | entier, 1 à 50, défaut `20` | non | Lignes à servir. |
|
|
447
|
+
| `offset` | entier, 0 ou plus, défaut `0` | non | Lignes à sauter, pour paginer. |
|
|
448
|
+
|
|
449
|
+
**En retour :** les lignes que rend `search_titles`, avec `total_available`,
|
|
450
|
+
`offset`, `next_offset` et les `kind`, `sort` et `genre` sous lesquels la liste a
|
|
451
|
+
été lue.
|
|
452
|
+
|
|
453
|
+
## Deux notes, deux choses mesurées
|
|
454
|
+
|
|
455
|
+
Le Metascore est une moyenne pondérée des critiques professionnelles, sur 100. La
|
|
456
|
+
note des utilisateurs est la moyenne de ce qu'ont donné les membres inscrits, sur 10. Elles mesurent des populations différentes sur des échelles différentes, et
|
|
457
|
+
un titre peut porter l'une sans l'autre. Lisez chacune avec le `max` que ses
|
|
458
|
+
critiques indiquent, et rapportez une note absente comme absente.
|
|
331
459
|
|
|
332
460
|
## Configuration
|
|
333
461
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
|
338
|
-
|
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
| `
|
|
344
|
-
| `
|
|
345
|
-
| `
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
462
|
+
Chaque variable est facultative. Elles se posent dans le bloc `env` de la
|
|
463
|
+
configuration du client.
|
|
464
|
+
|
|
465
|
+
| Variable | Défaut | Ce qu'elle fait |
|
|
466
|
+
| ------------------------ | -------------------- | ---------------------------------------------------------------------------------- |
|
|
467
|
+
| `MC_USER_AGENT` | l'identité du projet | Nomme votre application auprès du site, avec une adresse où joindre une personne. |
|
|
468
|
+
| `MC_MIN_INTERVAL_MS` | `1000` | Écart entre deux requêtes, de 500 à 60000. |
|
|
469
|
+
| `MC_TIMEOUT_MS` | `15000` | Délai d'une requête, de 1000 à 120000. |
|
|
470
|
+
| `MC_MAX_RETRIES` | `3` | Tentatives après un échec passager, de 0 à 10. |
|
|
471
|
+
| `MC_CACHE_TTL_MS` | `86400000` | Durée pendant laquelle une fiche reste en mémoire, de 0 à 604800000. |
|
|
472
|
+
| `MC_SCORES_CACHE_TTL_MS` | `3600000` | Durée pendant laquelle les notes et critiques restent en mémoire, de 0 à 86400000. |
|
|
473
|
+
| `MC_CACHE_MAX_ENTRIES` | `200` | Réponses gardées en mémoire à la fois, de 0 à 10000. |
|
|
474
|
+
| `MC_LOG_LEVEL` | `error` | `silent`, `error`, `info` ou `debug`, écrit sur la sortie d'erreur. |
|
|
475
|
+
|
|
476
|
+
Les notes bougent au fil des critiques, surtout autour d'une sortie, donc elles
|
|
477
|
+
sont gardées une heure là où une fiche l'est un jour. Une valeur hors de sa plage
|
|
478
|
+
retombe sur le défaut, et la raison est écrite sur la sortie d'erreur.
|
|
479
|
+
|
|
480
|
+
## Erreurs
|
|
481
|
+
|
|
482
|
+
Chaque échec porte un des six codes, un message, et quand cela aide une
|
|
483
|
+
indication du geste suivant.
|
|
484
|
+
|
|
485
|
+
| Code | Ce qui s'est passé | Que faire |
|
|
486
|
+
| --------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
487
|
+
| `not_found` | Le site a répondu, et n'a pas cette fiche. | Vérifiez le slug et le type avec `search_titles`. |
|
|
488
|
+
| `invalid_input` | Les arguments ont été refusés avant toute requête. | Lisez le message, qui nomme l'argument. |
|
|
489
|
+
| `rate_limited` | Le site demande à ce client de ralentir. | Attendez les secondes indiquées et rappelez avec les mêmes arguments. La fiche est toujours là. |
|
|
490
|
+
| `parse_failure` | La réponse est arrivée dans une forme illisible ici. | Signalez-le sur [le suivi d'incidents](https://github.com/smeet666/mcp-metacritic/issues). |
|
|
491
|
+
| `network_error` | La requête n'a pas abouti. | Réessayez sous peu. |
|
|
492
|
+
| `timeout` | La requête a dépassé son délai. | Augmentez `MC_TIMEOUT_MS`, ou demandez moins de lignes. |
|
|
493
|
+
|
|
494
|
+
## Comme bibliothèque
|
|
495
|
+
|
|
496
|
+
La couche qui lit le site est publiée seule, avec son rythme, son cache et ses
|
|
497
|
+
erreurs, sans protocole attaché.
|
|
498
|
+
|
|
499
|
+
```ts
|
|
500
|
+
import { McClient } from "mcp-metacritic/client";
|
|
501
|
+
|
|
502
|
+
const client = new McClient();
|
|
503
|
+
const { data, cached } = await client.getDetail("movie", "the-matrix");
|
|
504
|
+
console.log(data.title, data.metascore, cached);
|
|
505
|
+
```
|
|
349
506
|
|
|
350
|
-
|
|
507
|
+
Chaque lecture répond `{ data, cached }`, et lève une erreur portant un des six
|
|
508
|
+
codes. Le plancher entre deux requêtes tient également ici.
|
|
351
509
|
|
|
352
|
-
|
|
353
|
-
et ce serveur appelle les mêmes routes que leurs propres pages. Il envoie une
|
|
354
|
-
requête à la fois, s'impose un rythme, ralentit en cas de refus, et garde deux
|
|
355
|
-
caches mémoire : un jour pour les fiches, qui ne bougent qu'à l'édition, et une
|
|
356
|
-
heure pour les notes et critiques, qui évoluent au fil des publications.
|
|
510
|
+
## Rythme et attribution
|
|
357
511
|
|
|
358
|
-
Les
|
|
359
|
-
d'
|
|
360
|
-
|
|
512
|
+
Les requêtes partent une à une avec au moins une seconde entre elles, et le
|
|
513
|
+
plancher d'une demi-seconde tient quelle que soit la configuration. Le
|
|
514
|
+
`User-Agent` se termine toujours par l'identité du projet et une adresse où
|
|
515
|
+
joindre une personne.
|
|
361
516
|
|
|
362
|
-
|
|
517
|
+
Chaque résultat porte l'adresse de la page Metacritic, et chaque critique citée
|
|
518
|
+
porte la publication qui l'a signée. Les critiques appartiennent à leurs auteurs
|
|
519
|
+
et aux publications qui les ont publiées.
|
|
363
520
|
|
|
364
|
-
|
|
365
|
-
être lues. Autant le dire clairement plutôt que de le passer sous silence.
|
|
521
|
+
Ce MCP est un projet non officiel, sans affiliation à Metacritic.
|
|
366
522
|
|
|
367
|
-
|
|
368
|
-
aucune clé, et n'a ralenti aucune de dix requêtes consécutives lors des tests.
|
|
369
|
-
Ce sont les conditions dans lesquelles ce serveur opère, et il n'y voit pas une
|
|
370
|
-
autorisation d'être gourmand. Il envoie au plus une requête par seconde,
|
|
371
|
-
s'identifie, met en cache ce qu'il lit, et porte un lien vers Metacritic sur
|
|
372
|
-
chaque résultat, y compris sur chaque critique citée.
|
|
523
|
+
## Confidentialité
|
|
373
524
|
|
|
374
|
-
|
|
525
|
+
Ce serveur ne collecte rien sur vous et n'envoie rien à son auteur. Il tourne sur
|
|
526
|
+
votre machine, ne joint que `backend.metacritic.com`, garde ses réponses en
|
|
527
|
+
mémoire le temps qu'il tourne, et n'écrit rien sur le disque.
|
|
528
|
+
[PRIVACY.md](PRIVACY.md) dit ce qu'une requête emporte et quels réglages changent
|
|
529
|
+
cela.
|
|
375
530
|
|
|
376
531
|
## Développement
|
|
377
532
|
|
|
378
533
|
```bash
|
|
379
534
|
npm install
|
|
380
|
-
npm run build:fixtures
|
|
381
|
-
npm test
|
|
382
|
-
npm run
|
|
383
|
-
npm run build
|
|
384
|
-
MC_LIVE=1 npm run test:live # touche le vrai site, exclu de la CI
|
|
385
|
-
npm run inspector # explorer les outils dans le MCP Inspector
|
|
535
|
+
npm run build:fixtures
|
|
536
|
+
npm test
|
|
537
|
+
npm run check
|
|
386
538
|
```
|
|
387
539
|
|
|
388
|
-
Les
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
La couche API (`src/mc`) n'importe pas le SDK MCP et est publiée séparément sous
|
|
393
|
-
`mcp-metacritic/client`, utilisable comme simple bibliothèque. Elle applique
|
|
394
|
-
elle-même le plancher de cadence et le User-Agent identifiant, qui valent donc
|
|
395
|
-
aussi pour qui l'utilise en bibliothèque.
|
|
396
|
-
|
|
397
|
-
## Critiques, notes et droits d'auteur
|
|
398
|
-
|
|
399
|
-
Les Metascores, les textes de critiques et le travail éditorial qui les
|
|
400
|
-
sous-tend appartiennent à Metacritic et aux publications qu'il agrège. Ce projet
|
|
401
|
-
ne revendique aucun droit dessus et n'embarque aucun de leurs contenus.
|
|
540
|
+
Les tests s'exécutent sur des fixtures engendrées et n'émettent aucune requête.
|
|
541
|
+
La suite en direct, `npm run test:live`, émet une requête par route et tourne
|
|
542
|
+
chaque nuit contre le site lui-même.
|
|
402
543
|
|
|
403
|
-
|
|
404
|
-
avec la publication nommée et un lien vers l'article d'origine quand le site en
|
|
405
|
-
fournit un. Si vous reprenez une citation, conservez les deux. Si vous citez une
|
|
406
|
-
note, créditez Metacritic et liez la fiche : chaque résultat porte un
|
|
407
|
-
`source_url`.
|
|
544
|
+
## Contribuer
|
|
408
545
|
|
|
409
|
-
|
|
410
|
-
|
|
546
|
+
Les anomalies, les questions et les idées ont leur place dans
|
|
547
|
+
[le suivi d'incidents](https://github.com/smeet666/mcp-metacritic/issues). Les
|
|
548
|
+
propositions de modification sont bienvenues ; ouvrir un ticket d'abord aide à
|
|
549
|
+
s'accorder sur la forme du changement. Voir [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
411
550
|
|
|
412
551
|
## Licence
|
|
413
552
|
|
|
414
|
-
MIT, voir [LICENSE](
|
|
415
|
-
|
|
553
|
+
MIT, voir [LICENSE](LICENSE). Les notes et les critiques appartiennent à
|
|
554
|
+
Metacritic et aux publications qu'il cite.
|