mcp-metacritic 1.1.1 → 1.2.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/README.md +1 -0
- package/dist/index.js +168 -113
- package/dist/index.js.map +1 -1
- package/dist/mc/client.js +9 -5
- package/dist/mc/client.js.map +1 -1
- package/package.json +2 -2
- package/server.json +10 -6
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/mcp-metacritic)
|
|
4
4
|
[](https://github.com/smeet666/mcp-metacritic/actions/workflows/ci.yml)
|
|
5
5
|
[](./LICENSE)
|
|
6
|
+
[](https://glama.ai/mcp/servers/smeet666/mcp-metacritic)
|
|
6
7
|
|
|
7
8
|
An [MCP](https://modelcontextprotocol.io) server for
|
|
8
9
|
[Metacritic](https://www.metacritic.com). Search films, shows and games, read
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
|
-
var PKG_VERSION = "1.
|
|
7
|
+
var PKG_VERSION = "1.2.0";
|
|
8
8
|
var REPO_URL = "https://github.com/smeet666/mcp-metacritic";
|
|
9
9
|
|
|
10
10
|
// src/config.ts
|
|
@@ -129,7 +129,7 @@ function createLogger(level) {
|
|
|
129
129
|
|
|
130
130
|
// src/server.ts
|
|
131
131
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
132
|
-
import { z as
|
|
132
|
+
import { z as z7 } from "zod";
|
|
133
133
|
|
|
134
134
|
// src/mc/cache.ts
|
|
135
135
|
var TtlLruCache = class {
|
|
@@ -542,6 +542,10 @@ var intOf = (value) => {
|
|
|
542
542
|
const parsed = num(value);
|
|
543
543
|
return parsed === null ? null : Math.trunc(parsed);
|
|
544
544
|
};
|
|
545
|
+
var aggregate = (value) => {
|
|
546
|
+
const parsed = num(value);
|
|
547
|
+
return parsed === 0 ? null : parsed;
|
|
548
|
+
};
|
|
545
549
|
function kindOf(value) {
|
|
546
550
|
const type = str(value);
|
|
547
551
|
if (type === SEARCH_TYPE.movie) return "movie";
|
|
@@ -559,7 +563,7 @@ function toSummary(node) {
|
|
|
559
563
|
const critic = isObject(node.criticScoreSummary) ? node.criticScoreSummary : {};
|
|
560
564
|
const userSummary = isObject(node.userScoreSummary) ? node.userScoreSummary : {};
|
|
561
565
|
const userObject = isObject(node.userScore) ? node.userScore : {};
|
|
562
|
-
const userScore =
|
|
566
|
+
const userScore = aggregate(userSummary.score) ?? aggregate(userObject.score) ?? aggregate(node.userScore);
|
|
563
567
|
return {
|
|
564
568
|
id,
|
|
565
569
|
kind,
|
|
@@ -568,7 +572,7 @@ function toSummary(node) {
|
|
|
568
572
|
year: intOf(node.premiereYear),
|
|
569
573
|
releaseDate: str(node.releaseDate),
|
|
570
574
|
rating: str(node.rating),
|
|
571
|
-
metascore:
|
|
575
|
+
metascore: aggregate(critic.score),
|
|
572
576
|
userScore,
|
|
573
577
|
sourceUrl: titlePageUrl(kind, slug)
|
|
574
578
|
};
|
|
@@ -652,7 +656,7 @@ function parseDetail(raw, url, kind, slug) {
|
|
|
652
656
|
description: str(item.description),
|
|
653
657
|
tagline: str(item.tagline),
|
|
654
658
|
genres: toStringList(item.genres),
|
|
655
|
-
duration: intOf(item.duration),
|
|
659
|
+
duration: aggregate(intOf(item.duration)),
|
|
656
660
|
imdbId: str(item.imdbId),
|
|
657
661
|
networks: toStringList(item.networks),
|
|
658
662
|
production: toCompanies(item.production),
|
|
@@ -668,7 +672,7 @@ function parseScore(raw, url, what) {
|
|
|
668
672
|
const max = num(item.max);
|
|
669
673
|
if (max === null) throw parseFailure(url, "the score carries no scale");
|
|
670
674
|
return {
|
|
671
|
-
score:
|
|
675
|
+
score: aggregate(item.score),
|
|
672
676
|
max,
|
|
673
677
|
reviewCount: intOf(item.reviewCount),
|
|
674
678
|
positiveCount: intOf(item.positiveCount),
|
|
@@ -894,24 +898,75 @@ var McClient = class {
|
|
|
894
898
|
};
|
|
895
899
|
|
|
896
900
|
// src/tools/browseTitles.ts
|
|
897
|
-
import { z as
|
|
901
|
+
import { z as z3 } from "zod";
|
|
898
902
|
|
|
899
|
-
// src/tools/
|
|
903
|
+
// src/tools/arguments.ts
|
|
900
904
|
import { z } from "zod";
|
|
905
|
+
var INVALID_INPUT = "invalid_input";
|
|
906
|
+
function strictInput(shape) {
|
|
907
|
+
const declared = Object.keys(shape);
|
|
908
|
+
const errorMap = (issue, ctx) => issue.code === z.ZodIssueCode.unrecognized_keys ? { message: unknownArgumentMessage(issue.keys, declared) } : { message: ctx.defaultError };
|
|
909
|
+
return z.strictObject(shape, { errorMap });
|
|
910
|
+
}
|
|
911
|
+
function unknownArgumentMessage(keys, declared) {
|
|
912
|
+
const named = keys.map((key) => {
|
|
913
|
+
const near = nearestArgument(key, declared);
|
|
914
|
+
return near ? `'${key}' (did you mean '${near}'?)` : `'${key}'`;
|
|
915
|
+
}).join(", ");
|
|
916
|
+
return `[${INVALID_INPUT}] Unknown ${keys.length > 1 ? "arguments" : "argument"} ${named}. This tool takes: ${declared.join(", ")}.`;
|
|
917
|
+
}
|
|
918
|
+
function nearestArgument(key, declared) {
|
|
919
|
+
const flatten = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
920
|
+
const flat = flatten(key);
|
|
921
|
+
if (flat.length === 0) return void 0;
|
|
922
|
+
const sameName = declared.find((name) => flatten(name) === flat);
|
|
923
|
+
if (sameName) return sameName;
|
|
924
|
+
const overlapping = declared.find((name) => {
|
|
925
|
+
const other = flatten(name);
|
|
926
|
+
const [shorter, longer] = other.length < flat.length ? [other, flat] : [flat, other];
|
|
927
|
+
return shorter.length >= 3 && (longer.startsWith(shorter) || longer.endsWith(shorter));
|
|
928
|
+
});
|
|
929
|
+
if (overlapping) return overlapping;
|
|
930
|
+
let closest;
|
|
931
|
+
let shortest = Number.POSITIVE_INFINITY;
|
|
932
|
+
for (const name of declared) {
|
|
933
|
+
const distance = editDistance(flat, flatten(name));
|
|
934
|
+
if (distance < shortest) {
|
|
935
|
+
shortest = distance;
|
|
936
|
+
closest = name;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return shortest <= Math.max(1, Math.floor(flat.length / 3)) ? closest : void 0;
|
|
940
|
+
}
|
|
941
|
+
function editDistance(left, right) {
|
|
942
|
+
let previous = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
943
|
+
for (let row = 1; row <= left.length; row += 1) {
|
|
944
|
+
const current = [row];
|
|
945
|
+
for (let column = 1; column <= right.length; column += 1) {
|
|
946
|
+
const substitution = previous[column - 1] + (left[row - 1] === right[column - 1] ? 0 : 1);
|
|
947
|
+
current[column] = Math.min(substitution, previous[column] + 1, current[column - 1] + 1);
|
|
948
|
+
}
|
|
949
|
+
previous = current;
|
|
950
|
+
}
|
|
951
|
+
return previous[right.length];
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/tools/shared.ts
|
|
955
|
+
import { z as z2 } from "zod";
|
|
901
956
|
var MAX_TEXT_MIRROR_CHARS = 2e3;
|
|
902
957
|
var ATTRIBUTION = "Source: Metacritic";
|
|
903
|
-
var kindSchema =
|
|
904
|
-
var titleSummarySchema =
|
|
905
|
-
id:
|
|
906
|
-
kind:
|
|
907
|
-
title:
|
|
908
|
-
slug:
|
|
909
|
-
year:
|
|
910
|
-
release_date:
|
|
911
|
-
rating:
|
|
912
|
-
metascore:
|
|
913
|
-
user_score:
|
|
914
|
-
source_url:
|
|
958
|
+
var kindSchema = z2.enum(["movie", "show", "game"]).describe("Which catalogue the entry belongs to. Pass it back with the slug.");
|
|
959
|
+
var titleSummarySchema = z2.object({
|
|
960
|
+
id: z2.number().int(),
|
|
961
|
+
kind: z2.enum(["movie", "show", "game"]),
|
|
962
|
+
title: z2.string(),
|
|
963
|
+
slug: z2.string().describe("Identifier to pass to get_title and get_reviews, with 'kind'."),
|
|
964
|
+
year: z2.number().int().nullable(),
|
|
965
|
+
release_date: z2.string().nullable(),
|
|
966
|
+
rating: z2.string().nullable().describe("Age rating as published, such as R or TV-MA."),
|
|
967
|
+
metascore: z2.number().nullable().describe("Critic score, out of 100. Not comparable to user_score without rescaling."),
|
|
968
|
+
user_score: z2.number().nullable().describe("Audience score, out of 10. Not comparable to metascore without rescaling."),
|
|
969
|
+
source_url: z2.string().describe("Metacritic page. Show this when citing the entry.")
|
|
915
970
|
});
|
|
916
971
|
function toTitleSummaryOut(title) {
|
|
917
972
|
return {
|
|
@@ -927,14 +982,14 @@ function toTitleSummaryOut(title) {
|
|
|
927
982
|
source_url: title.sourceUrl
|
|
928
983
|
};
|
|
929
984
|
}
|
|
930
|
-
var scoreSchema =
|
|
931
|
-
score:
|
|
932
|
-
max:
|
|
933
|
-
review_count:
|
|
934
|
-
positive_count:
|
|
935
|
-
neutral_count:
|
|
936
|
-
negative_count:
|
|
937
|
-
sentiment:
|
|
985
|
+
var scoreSchema = z2.object({
|
|
986
|
+
score: z2.number().nullable(),
|
|
987
|
+
max: z2.number().describe("Scale this score is on: 100 for critics, 10 for users."),
|
|
988
|
+
review_count: z2.number().int().nullable(),
|
|
989
|
+
positive_count: z2.number().int().nullable(),
|
|
990
|
+
neutral_count: z2.number().int().nullable(),
|
|
991
|
+
negative_count: z2.number().int().nullable(),
|
|
992
|
+
sentiment: z2.string().nullable().describe("Metacritic's own wording for the verdict.")
|
|
938
993
|
});
|
|
939
994
|
function toScoreOut(score) {
|
|
940
995
|
return {
|
|
@@ -1023,26 +1078,26 @@ var browseTitlesDescription = [
|
|
|
1023
1078
|
"Scores come back on their own scales, 100 for critics and 10 for users.",
|
|
1024
1079
|
"Paging is approximate: Metacritic does not order tied entries stably, so an entry can appear on two consecutive pages. Deduplicate by slug rather than counting rows."
|
|
1025
1080
|
].join(" ");
|
|
1026
|
-
var
|
|
1027
|
-
kind:
|
|
1028
|
-
sort:
|
|
1081
|
+
var browseTitlesInput = strictInput({
|
|
1082
|
+
kind: z3.enum(["movie", "show", "game"]).default("movie").describe("Which catalogue to list."),
|
|
1083
|
+
sort: z3.enum(["score", "recent", "popular"]).default("score").describe(
|
|
1029
1084
|
"'score' is the critic ranking, 'recent' is by release date, 'popular' is current attention."
|
|
1030
1085
|
),
|
|
1031
|
-
genre:
|
|
1032
|
-
limit:
|
|
1033
|
-
offset:
|
|
1034
|
-
};
|
|
1086
|
+
genre: z3.string().optional().describe("Single genre name, such as Horror. Omit for all genres."),
|
|
1087
|
+
limit: z3.number().int().min(1).max(50).default(20).describe("How many rows to return."),
|
|
1088
|
+
offset: z3.number().int().min(0).default(0).describe("How many rows to skip, for paging.")
|
|
1089
|
+
});
|
|
1035
1090
|
var browseTitlesOutputShape = {
|
|
1036
|
-
kind:
|
|
1037
|
-
sort:
|
|
1038
|
-
genre:
|
|
1039
|
-
results:
|
|
1040
|
-
total_available:
|
|
1041
|
-
offset:
|
|
1042
|
-
next_offset:
|
|
1091
|
+
kind: z3.string(),
|
|
1092
|
+
sort: z3.string(),
|
|
1093
|
+
genre: z3.string().nullable(),
|
|
1094
|
+
results: z3.array(titleSummarySchema),
|
|
1095
|
+
total_available: z3.number().int().describe("How many entries match upstream, which is the size of what this samples."),
|
|
1096
|
+
offset: z3.number().int(),
|
|
1097
|
+
next_offset: z3.number().int().nullable().describe(
|
|
1043
1098
|
"Pass as 'offset' for the next page. Tied entries are not ordered stably upstream, so deduplicate by slug across pages."
|
|
1044
1099
|
),
|
|
1045
|
-
notes:
|
|
1100
|
+
notes: z3.array(z3.string())
|
|
1046
1101
|
};
|
|
1047
1102
|
async function runBrowseTitles(client, args) {
|
|
1048
1103
|
try {
|
|
@@ -1094,7 +1149,7 @@ ${renderTitleList(results)}`;
|
|
|
1094
1149
|
}
|
|
1095
1150
|
|
|
1096
1151
|
// src/tools/getReviews.ts
|
|
1097
|
-
import { z as
|
|
1152
|
+
import { z as z4 } from "zod";
|
|
1098
1153
|
var MAX_QUOTE_CHARS = 600;
|
|
1099
1154
|
var getReviewsDescription = [
|
|
1100
1155
|
"Read individual reviews of a Metacritic entry, from critics or from users.",
|
|
@@ -1104,34 +1159,34 @@ var getReviewsDescription = [
|
|
|
1104
1159
|
"Critic reviews carry the publication and a link to the original article: quote them with both.",
|
|
1105
1160
|
"Critic scores run to 100 and user scores to 10, so do not average the two together."
|
|
1106
1161
|
].join(" ");
|
|
1107
|
-
var
|
|
1108
|
-
slug:
|
|
1162
|
+
var getReviewsInput = strictInput({
|
|
1163
|
+
slug: z4.string().min(1).describe("Identifier from search_titles, such as 'the-matrix'."),
|
|
1109
1164
|
kind: kindSchema,
|
|
1110
|
-
source:
|
|
1111
|
-
sentiment:
|
|
1112
|
-
limit:
|
|
1113
|
-
offset:
|
|
1114
|
-
};
|
|
1115
|
-
var reviewSchema =
|
|
1116
|
-
quote:
|
|
1117
|
-
score:
|
|
1118
|
-
max:
|
|
1119
|
-
publication:
|
|
1120
|
-
author:
|
|
1121
|
-
url:
|
|
1122
|
-
date:
|
|
1165
|
+
source: z4.enum(["critic", "user"]).default("critic").describe("'critic' is the professional press, 'user' is the audience."),
|
|
1166
|
+
sentiment: z4.enum(["all", "positive", "neutral", "negative"]).default("all").describe("Which slice to read. Metacritic groups reviews this way itself."),
|
|
1167
|
+
limit: z4.number().int().min(1).max(50).default(10).describe("How many reviews to return from the sample Metacritic publishes."),
|
|
1168
|
+
offset: z4.number().int().min(0).default(0).describe("How many of the sampled reviews to skip. The sample itself cannot be paged past.")
|
|
1169
|
+
});
|
|
1170
|
+
var reviewSchema = z4.object({
|
|
1171
|
+
quote: z4.string().nullable().describe("Excerpt as published, truncated if long."),
|
|
1172
|
+
score: z4.number().nullable(),
|
|
1173
|
+
max: z4.number().describe("Scale for this review's score: 100 for critics, 10 for users."),
|
|
1174
|
+
publication: z4.string().nullable().describe("Who ran it. Name it when quoting."),
|
|
1175
|
+
author: z4.string().nullable(),
|
|
1176
|
+
url: z4.string().nullable().describe("Original article. Link it when quoting."),
|
|
1177
|
+
date: z4.string().nullable()
|
|
1123
1178
|
});
|
|
1124
1179
|
var getReviewsOutputShape = {
|
|
1125
|
-
slug:
|
|
1126
|
-
kind:
|
|
1127
|
-
source_url:
|
|
1128
|
-
source:
|
|
1129
|
-
sentiment:
|
|
1130
|
-
reviews:
|
|
1131
|
-
total_available:
|
|
1132
|
-
offset:
|
|
1133
|
-
next_offset:
|
|
1134
|
-
notes:
|
|
1180
|
+
slug: z4.string(),
|
|
1181
|
+
kind: z4.string(),
|
|
1182
|
+
source_url: z4.string().describe("Metacritic page these reviews belong to. Cite it when an article link is missing."),
|
|
1183
|
+
source: z4.string(),
|
|
1184
|
+
sentiment: z4.string(),
|
|
1185
|
+
reviews: z4.array(reviewSchema),
|
|
1186
|
+
total_available: z4.number().int().describe("How many reviews Metacritic counts in total. Usually far more than it serves here."),
|
|
1187
|
+
offset: z4.number().int(),
|
|
1188
|
+
next_offset: z4.number().int().nullable().describe("Pass as 'offset' for the next page."),
|
|
1189
|
+
notes: z4.array(z4.string())
|
|
1135
1190
|
};
|
|
1136
1191
|
async function runGetReviews(client, args) {
|
|
1137
1192
|
try {
|
|
@@ -1215,7 +1270,7 @@ ${listing}`;
|
|
|
1215
1270
|
}
|
|
1216
1271
|
|
|
1217
1272
|
// src/tools/getTitle.ts
|
|
1218
|
-
import { z as
|
|
1273
|
+
import { z as z5 } from "zod";
|
|
1219
1274
|
var SECTIONS = ["basic", "scores", "awards", "production", "networks", "where_to_watch"];
|
|
1220
1275
|
var getTitleDescription = [
|
|
1221
1276
|
"Read one Metacritic entry by slug and kind, both from search_titles.",
|
|
@@ -1225,38 +1280,38 @@ var getTitleDescription = [
|
|
|
1225
1280
|
"'networks' lists the broadcasters of a show; 'where_to_watch' costs an extra request and covers films and shows only.",
|
|
1226
1281
|
"A long description paginates: when 'truncated' is true, call again with 'offset' set to 'next_offset'."
|
|
1227
1282
|
].join(" ");
|
|
1228
|
-
var
|
|
1229
|
-
slug:
|
|
1283
|
+
var getTitleInput = strictInput({
|
|
1284
|
+
slug: z5.string().min(1).describe("Identifier from search_titles, such as 'the-matrix'."),
|
|
1230
1285
|
kind: kindSchema,
|
|
1231
|
-
sections:
|
|
1232
|
-
max_chars:
|
|
1233
|
-
offset:
|
|
1234
|
-
};
|
|
1286
|
+
sections: z5.array(z5.enum(SECTIONS)).default(["basic", "scores"]).describe("Which parts to return. Each extra section beyond the default costs a request."),
|
|
1287
|
+
max_chars: z5.number().int().min(200).max(2e4).default(4e3).describe("Character budget for the description."),
|
|
1288
|
+
offset: z5.number().int().min(0).default(0).describe("Where to resume the description.")
|
|
1289
|
+
});
|
|
1235
1290
|
var getTitleOutputShape = {
|
|
1236
1291
|
title: titleSummarySchema,
|
|
1237
|
-
description:
|
|
1238
|
-
tagline:
|
|
1239
|
-
genres:
|
|
1240
|
-
duration_minutes:
|
|
1241
|
-
imdb_id:
|
|
1242
|
-
total_chars:
|
|
1243
|
-
returned_chars:
|
|
1244
|
-
offset:
|
|
1245
|
-
next_offset:
|
|
1246
|
-
truncated:
|
|
1292
|
+
description: z5.string().nullable(),
|
|
1293
|
+
tagline: z5.string().nullable(),
|
|
1294
|
+
genres: z5.array(z5.string()),
|
|
1295
|
+
duration_minutes: z5.number().int().nullable().describe("Runtime in minutes for a film, or the length of a typical episode for a show."),
|
|
1296
|
+
imdb_id: z5.string().nullable().describe("IMDb identifier, usable to cross-reference other sources."),
|
|
1297
|
+
total_chars: z5.number().int().describe("Length of the full description."),
|
|
1298
|
+
returned_chars: z5.number().int(),
|
|
1299
|
+
offset: z5.number().int(),
|
|
1300
|
+
next_offset: z5.number().int().nullable().describe("Pass as 'offset' to read the rest."),
|
|
1301
|
+
truncated: z5.boolean(),
|
|
1247
1302
|
critic_score: scoreSchema.nullable(),
|
|
1248
1303
|
user_score: scoreSchema.nullable(),
|
|
1249
|
-
awards:
|
|
1250
|
-
|
|
1251
|
-
ceremony:
|
|
1252
|
-
wins:
|
|
1253
|
-
nominations:
|
|
1304
|
+
awards: z5.array(
|
|
1305
|
+
z5.object({
|
|
1306
|
+
ceremony: z5.string().describe("Awards body, such as 'Academy Awards, USA'."),
|
|
1307
|
+
wins: z5.number().int().nullable().describe("Null when the source records no win."),
|
|
1308
|
+
nominations: z5.number().int().nullable()
|
|
1254
1309
|
})
|
|
1255
1310
|
).optional().describe("One tally per ceremony. Metacritic publishes no per-category detail."),
|
|
1256
|
-
networks:
|
|
1257
|
-
production:
|
|
1258
|
-
where_to_watch:
|
|
1259
|
-
notes:
|
|
1311
|
+
networks: z5.array(z5.string()).optional().describe("Broadcasters, for shows."),
|
|
1312
|
+
production: z5.array(z5.object({ name: z5.string(), id: z5.number().int().nullable() })).optional(),
|
|
1313
|
+
where_to_watch: z5.array(z5.object({ provider: z5.string(), kind: z5.string(), url: z5.string().nullable() })).optional(),
|
|
1314
|
+
notes: z5.array(z5.string())
|
|
1260
1315
|
};
|
|
1261
1316
|
async function runGetTitle(client, args) {
|
|
1262
1317
|
try {
|
|
@@ -1412,7 +1467,7 @@ function render(item, description, critic, user, wanted, offers, production) {
|
|
|
1412
1467
|
}
|
|
1413
1468
|
|
|
1414
1469
|
// src/tools/searchTitles.ts
|
|
1415
|
-
import { z as
|
|
1470
|
+
import { z as z6 } from "zod";
|
|
1416
1471
|
var searchTitlesDescription = [
|
|
1417
1472
|
"Search Metacritic for films, shows and games by title.",
|
|
1418
1473
|
"Returns one compact row per match, carrying the critic Metascore, so a question about the critical verdict needs no second call.",
|
|
@@ -1421,18 +1476,18 @@ var searchTitlesDescription = [
|
|
|
1421
1476
|
"There is no paging: 'limit' is the only lever, and results always start from the most relevant match.",
|
|
1422
1477
|
"This searches titles only. It cannot find an entry from a plot detail, a person or a studio."
|
|
1423
1478
|
].join(" ");
|
|
1424
|
-
var
|
|
1425
|
-
query:
|
|
1426
|
-
kind:
|
|
1427
|
-
limit:
|
|
1428
|
-
};
|
|
1479
|
+
var searchTitlesInput = strictInput({
|
|
1480
|
+
query: z6.string().min(1).describe("Title or part of one, for example 'the matrix'."),
|
|
1481
|
+
kind: z6.enum(["movie", "show", "game", "any"]).default("any").describe("Restrict results to one catalogue. Metacritic searches all three at once."),
|
|
1482
|
+
limit: z6.number().int().min(1).max(50).default(10).describe("How many rows to return.")
|
|
1483
|
+
});
|
|
1429
1484
|
var searchTitlesOutputShape = {
|
|
1430
|
-
query:
|
|
1431
|
-
results:
|
|
1432
|
-
total_available:
|
|
1485
|
+
query: z6.string(),
|
|
1486
|
+
results: z6.array(titleSummarySchema),
|
|
1487
|
+
total_available: z6.number().int().describe(
|
|
1433
1488
|
"How many entries Metacritic counted. For a query of several words it counts entries matching any one of them, so the number is far larger than the useful matches and should not be read as a match count."
|
|
1434
1489
|
),
|
|
1435
|
-
notes:
|
|
1490
|
+
notes: z6.array(z6.string())
|
|
1436
1491
|
};
|
|
1437
1492
|
async function runSearchTitles(client, args) {
|
|
1438
1493
|
try {
|
|
@@ -1498,8 +1553,8 @@ function createServer(options = {}) {
|
|
|
1498
1553
|
{
|
|
1499
1554
|
title: "Search Metacritic",
|
|
1500
1555
|
description: searchTitlesDescription,
|
|
1501
|
-
inputSchema:
|
|
1502
|
-
outputSchema:
|
|
1556
|
+
inputSchema: searchTitlesInput,
|
|
1557
|
+
outputSchema: z7.object(searchTitlesOutputShape),
|
|
1503
1558
|
annotations: READ_ONLY
|
|
1504
1559
|
},
|
|
1505
1560
|
async (args) => runSearchTitles(client, args)
|
|
@@ -1509,8 +1564,8 @@ function createServer(options = {}) {
|
|
|
1509
1564
|
{
|
|
1510
1565
|
title: "Read an entry",
|
|
1511
1566
|
description: getTitleDescription,
|
|
1512
|
-
inputSchema:
|
|
1513
|
-
outputSchema:
|
|
1567
|
+
inputSchema: getTitleInput,
|
|
1568
|
+
outputSchema: z7.object(getTitleOutputShape),
|
|
1514
1569
|
annotations: READ_ONLY
|
|
1515
1570
|
},
|
|
1516
1571
|
async (args) => runGetTitle(client, args)
|
|
@@ -1520,8 +1575,8 @@ function createServer(options = {}) {
|
|
|
1520
1575
|
{
|
|
1521
1576
|
title: "Read reviews",
|
|
1522
1577
|
description: getReviewsDescription,
|
|
1523
|
-
inputSchema:
|
|
1524
|
-
outputSchema:
|
|
1578
|
+
inputSchema: getReviewsInput,
|
|
1579
|
+
outputSchema: z7.object(getReviewsOutputShape),
|
|
1525
1580
|
annotations: READ_ONLY
|
|
1526
1581
|
},
|
|
1527
1582
|
async (args) => runGetReviews(client, args)
|
|
@@ -1531,8 +1586,8 @@ function createServer(options = {}) {
|
|
|
1531
1586
|
{
|
|
1532
1587
|
title: "Browse rankings",
|
|
1533
1588
|
description: browseTitlesDescription,
|
|
1534
|
-
inputSchema:
|
|
1535
|
-
outputSchema:
|
|
1589
|
+
inputSchema: browseTitlesInput,
|
|
1590
|
+
outputSchema: z7.object(browseTitlesOutputShape),
|
|
1536
1591
|
annotations: READ_ONLY
|
|
1537
1592
|
},
|
|
1538
1593
|
async (args) => runBrowseTitles(client, args)
|