@xiedada/nodemw-mcp-server 0.0.6 → 0.0.8

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.
Files changed (2) hide show
  1. package/dist/index.js +168 -125
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
37
37
  // package.json
38
38
  var package_default = {
39
39
  name: "@xiedada/nodemw-mcp-server",
40
- version: "0.0.6",
40
+ version: "0.0.8",
41
41
  description: "MCP server for nodemw - MediaWiki API client",
42
42
  type: "module",
43
43
  main: "dist/index.js",
@@ -554,7 +554,7 @@ function getPagesInNamespaceTool(server) {
554
554
  "get-pages-in-namespace",
555
555
  "Get all non-redirect pages in a specific namespace",
556
556
  {
557
- namespace: z7.number().describe("Namespace number to filter pages")
557
+ namespace: z7.number().describe("Namespace number (0=Main, 2=User, 6=File, 10=Template, 14=Category)")
558
558
  },
559
559
  {
560
560
  title: "Get pages in namespace",
@@ -740,7 +740,7 @@ import { z as z12 } from "zod";
740
740
  function getArticlePropertiesTool(server) {
741
741
  const tool = server.tool(
742
742
  "get-article-properties",
743
- "Get page properties for a wiki article",
743
+ "Get page properties (page_props table data) for a wiki article",
744
744
  {
745
745
  title: z12.string().describe("Article title")
746
746
  },
@@ -783,7 +783,7 @@ function getArticleInfoTool(server) {
783
783
  z13.number(),
784
784
  z13.array(z13.union([z13.string(), z13.number()]))
785
785
  ]).describe("Article title, page ID, or array of titles/IDs"),
786
- properties: z13.array(z13.string()).optional().describe("Specific properties to retrieve")
786
+ properties: z13.array(z13.string()).optional().describe("Specific properties to retrieve (e.g. protection, talkid, url)")
787
787
  },
788
788
  {
789
789
  title: "Get article info",
@@ -865,6 +865,7 @@ async function handleGetUserContribsTool(username, namespace, limit = 50) {
865
865
  }
866
866
 
867
867
  // src/tools/ro/whoami.ts
868
+ import { z as z15 } from "zod";
868
869
  function whoamiTool(server) {
869
870
  const tool = server.tool(
870
871
  "whoami",
@@ -877,7 +878,17 @@ function whoamiTool(server) {
877
878
  },
878
879
  async () => handleWhoamiTool()
879
880
  );
880
- tool.update({ outputSchema: {} });
881
+ tool.update({ outputSchema: { user: z15.object({
882
+ name: z15.string(),
883
+ id: z15.number(),
884
+ groups: z15.array(z15.string()),
885
+ rights: z15.array(z15.string()),
886
+ ratelimits: z15.union([z15.record(z15.unknown()), z15.array(z15.unknown())]),
887
+ editcount: z15.number(),
888
+ realname: z15.string(),
889
+ email: z15.string(),
890
+ emailauthenticated: z15.string()
891
+ }) } });
881
892
  return tool;
882
893
  }
883
894
  async function handleWhoamiTool() {
@@ -887,20 +898,20 @@ async function handleWhoamiTool() {
887
898
  bot,
888
899
  "whoami"
889
900
  );
890
- return jsonResult(userInfo);
901
+ return jsonResult({ user: userInfo });
891
902
  } catch (error) {
892
903
  return errorResult("Failed to get current user info", error);
893
904
  }
894
905
  }
895
906
 
896
907
  // src/tools/ro/whois.ts
897
- import { z as z15 } from "zod";
908
+ import { z as z16 } from "zod";
898
909
  function whoisTool(server) {
899
910
  const tool = server.tool(
900
911
  "whois",
901
912
  "Get information about a specific user",
902
913
  {
903
- username: z15.string().describe("Username to look up")
914
+ username: z16.string().describe("Username to look up")
904
915
  },
905
916
  {
906
917
  title: "Whois",
@@ -909,7 +920,18 @@ function whoisTool(server) {
909
920
  },
910
921
  async ({ username }) => handleWhoisTool(username)
911
922
  );
912
- tool.update({ outputSchema: {} });
923
+ tool.update({ outputSchema: { user: z16.object({
924
+ userid: z16.number(),
925
+ name: z16.string(),
926
+ groups: z16.array(z16.string()),
927
+ implicitgroups: z16.array(z16.string()),
928
+ rights: z16.array(z16.string()),
929
+ editcount: z16.number(),
930
+ registration: z16.string(),
931
+ emailable: z16.string(),
932
+ gender: z16.string(),
933
+ blockinfo: z16.record(z16.unknown()).optional()
934
+ }) } });
913
935
  return tool;
914
936
  }
915
937
  async function handleWhoisTool(username) {
@@ -923,20 +945,20 @@ async function handleWhoisTool(username) {
923
945
  if (userInfo.missing) {
924
946
  return errorResult(`User "${username}" not found.`);
925
947
  }
926
- return jsonResult(userInfo);
948
+ return jsonResult({ user: userInfo });
927
949
  } catch (error) {
928
950
  return errorResult("Failed to get user info", error);
929
951
  }
930
952
  }
931
953
 
932
954
  // src/tools/ro/whoare.ts
933
- import { z as z16 } from "zod";
955
+ import { z as z17 } from "zod";
934
956
  function whoareTool(server) {
935
957
  const tool = server.tool(
936
958
  "whoare",
937
959
  "Get information about multiple wiki users",
938
960
  {
939
- usernames: z16.array(z16.string()).describe("Array of usernames to query")
961
+ usernames: z17.array(z17.string()).describe("Array of usernames to query")
940
962
  },
941
963
  {
942
964
  title: "Who are",
@@ -945,7 +967,18 @@ function whoareTool(server) {
945
967
  },
946
968
  async (params) => handleWhoareTool(params)
947
969
  );
948
- tool.update({ outputSchema: {} });
970
+ tool.update({ outputSchema: { users: z17.array(z17.object({
971
+ userid: z17.number(),
972
+ name: z17.string(),
973
+ groups: z17.array(z17.string()),
974
+ implicitgroups: z17.array(z17.string()),
975
+ rights: z17.array(z17.string()),
976
+ editcount: z17.number(),
977
+ registration: z17.string(),
978
+ emailable: z17.string(),
979
+ gender: z17.string(),
980
+ blockinfo: z17.record(z17.unknown()).optional()
981
+ })), count: z17.number() } });
949
982
  return tool;
950
983
  }
951
984
  async function handleWhoareTool(params) {
@@ -956,21 +989,21 @@ async function handleWhoareTool(params) {
956
989
  "whoare",
957
990
  params.usernames
958
991
  );
959
- return jsonResult(users);
992
+ return jsonResult({ users, count: users.length });
960
993
  } catch (error) {
961
994
  return errorResult("Failed to get user information", error);
962
995
  }
963
996
  }
964
997
 
965
998
  // src/tools/ro/get-images.ts
966
- import { z as z17 } from "zod";
999
+ import { z as z18 } from "zod";
967
1000
  function getImagesTool(server) {
968
1001
  const tool = server.tool(
969
1002
  "get-images",
970
1003
  "Get list of images starting from a specific name",
971
1004
  {
972
- startFrom: z17.string().optional().default("").describe("Start from this image name"),
973
- limit: z17.number().optional().default(50).describe("Maximum number of images to return")
1005
+ startFrom: z18.string().optional().default("").describe("Start from this image name"),
1006
+ limit: z18.number().optional().default(50).describe("Maximum number of images to return")
974
1007
  },
975
1008
  {
976
1009
  title: "Get images",
@@ -979,7 +1012,7 @@ function getImagesTool(server) {
979
1012
  },
980
1013
  async ({ startFrom, limit }) => handleGetImagesTool(startFrom, limit)
981
1014
  );
982
- tool.update({ outputSchema: { total: z17.number(), limit: z17.number(), startFrom: z17.string(), images: z17.array(z17.record(z17.unknown())) } });
1015
+ tool.update({ outputSchema: { total: z18.number(), limit: z18.number(), startFrom: z18.string(), images: z18.array(z18.record(z18.unknown())) } });
983
1016
  return tool;
984
1017
  }
985
1018
  async function handleGetImagesTool(startFrom, limit) {
@@ -1008,13 +1041,13 @@ async function handleGetImagesTool(startFrom, limit) {
1008
1041
  }
1009
1042
 
1010
1043
  // src/tools/ro/get-images-from-article.ts
1011
- import { z as z18 } from "zod";
1044
+ import { z as z19 } from "zod";
1012
1045
  function getImagesFromArticleTool(server) {
1013
1046
  const tool = server.tool(
1014
1047
  "get-images-from-article",
1015
1048
  "Get all images embedded in a specific article",
1016
1049
  {
1017
- title: z18.union([z18.string(), z18.number()]).describe("Article title or page ID")
1050
+ title: z19.union([z19.string(), z19.number()]).describe("Article title or page ID")
1018
1051
  },
1019
1052
  {
1020
1053
  title: "Get images from article",
@@ -1023,7 +1056,7 @@ function getImagesFromArticleTool(server) {
1023
1056
  },
1024
1057
  async ({ title }) => handleGetImagesFromArticleTool(title)
1025
1058
  );
1026
- tool.update({ outputSchema: { title: z18.string(), images: z18.array(z18.record(z18.unknown())), count: z18.number() } });
1059
+ tool.update({ outputSchema: { title: z19.string(), images: z19.array(z19.record(z19.unknown())), count: z19.number() } });
1027
1060
  return tool;
1028
1061
  }
1029
1062
  async function handleGetImagesFromArticleTool(title) {
@@ -1045,13 +1078,13 @@ async function handleGetImagesFromArticleTool(title) {
1045
1078
  }
1046
1079
 
1047
1080
  // src/tools/ro/get-image-usage.ts
1048
- import { z as z19 } from "zod";
1081
+ import { z as z20 } from "zod";
1049
1082
  function getImageUsageTool(server) {
1050
1083
  const tool = server.tool(
1051
1084
  "get-image-usage",
1052
1085
  "Get all pages that use a specific image",
1053
1086
  {
1054
- filename: z19.string().describe("Image filename with File: prefix")
1087
+ filename: z20.string().describe("Image filename with File: prefix")
1055
1088
  },
1056
1089
  {
1057
1090
  title: "Get image usage",
@@ -1060,7 +1093,7 @@ function getImageUsageTool(server) {
1060
1093
  },
1061
1094
  async ({ filename }) => handleGetImageUsageTool(filename)
1062
1095
  );
1063
- tool.update({ outputSchema: { filename: z19.string(), pages: z19.array(z19.record(z19.unknown())), count: z19.number() } });
1096
+ tool.update({ outputSchema: { filename: z20.string(), pages: z20.array(z20.record(z20.unknown())), count: z20.number() } });
1064
1097
  return tool;
1065
1098
  }
1066
1099
  async function handleGetImageUsageTool(filename) {
@@ -1082,13 +1115,13 @@ async function handleGetImageUsageTool(filename) {
1082
1115
  }
1083
1116
 
1084
1117
  // src/tools/ro/get-image-info.ts
1085
- import { z as z20 } from "zod";
1118
+ import { z as z21 } from "zod";
1086
1119
  function getImageInfoTool(server) {
1087
1120
  const tool = server.tool(
1088
1121
  "get-image-info",
1089
1122
  "Get detailed information about an image file",
1090
1123
  {
1091
- filename: z20.string().describe("Image filename with File: prefix")
1124
+ filename: z21.string().describe("Image filename with File: prefix")
1092
1125
  },
1093
1126
  {
1094
1127
  title: "Get image info",
@@ -1097,7 +1130,7 @@ function getImageInfoTool(server) {
1097
1130
  },
1098
1131
  async ({ filename }) => handleGetImageInfoTool(filename)
1099
1132
  );
1100
- tool.update({ outputSchema: { filename: z20.string(), info: z20.record(z20.unknown()) } });
1133
+ tool.update({ outputSchema: { filename: z21.string(), info: z21.record(z21.unknown()) } });
1101
1134
  return tool;
1102
1135
  }
1103
1136
  async function handleGetImageInfoTool(filename) {
@@ -1121,15 +1154,15 @@ async function handleGetImageInfoTool(filename) {
1121
1154
  }
1122
1155
 
1123
1156
  // src/tools/ro/get-log.ts
1124
- import { z as z21 } from "zod";
1157
+ import { z as z22 } from "zod";
1125
1158
  function getLogTool(server) {
1126
1159
  const tool = server.tool(
1127
1160
  "get-log",
1128
1161
  "Get log entries of a specific type",
1129
1162
  {
1130
- type: z21.string().describe("Log type (e.g. delete, block, move)"),
1131
- start: z21.string().optional().default("").describe("Start timestamp (YYYYMMDDHHMMSS format)"),
1132
- limit: z21.number().optional().default(50).describe("Maximum number of entries to return")
1163
+ type: z22.string().describe("Log type (e.g. delete, block, move)"),
1164
+ start: z22.string().optional().default("").describe("Start timestamp (YYYYMMDDHHMMSS format)"),
1165
+ limit: z22.number().optional().default(50).describe("Maximum number of entries to return")
1133
1166
  },
1134
1167
  {
1135
1168
  title: "Get log entries",
@@ -1138,7 +1171,7 @@ function getLogTool(server) {
1138
1171
  },
1139
1172
  async ({ type, start, limit }) => handleGetLogTool(type, start, limit)
1140
1173
  );
1141
- tool.update({ outputSchema: { type: z21.string(), start: z21.string(), limit: z21.number(), total: z21.number(), displayed: z21.number(), entries: z21.array(z21.record(z21.unknown())) } });
1174
+ tool.update({ outputSchema: { type: z22.string(), start: z22.string(), limit: z22.number(), total: z22.number(), displayed: z22.number(), entries: z22.array(z22.record(z22.unknown())) } });
1142
1175
  return tool;
1143
1176
  }
1144
1177
  async function handleGetLogTool(type, start, limit) {
@@ -1169,14 +1202,14 @@ async function handleGetLogTool(type, start, limit) {
1169
1202
  }
1170
1203
 
1171
1204
  // src/tools/ro/expand-templates.ts
1172
- import { z as z22 } from "zod";
1205
+ import { z as z23 } from "zod";
1173
1206
  function expandTemplatesTool(server) {
1174
1207
  return server.tool(
1175
1208
  "expand-templates",
1176
1209
  "Expand templates in wikitext",
1177
1210
  {
1178
- text: z22.string().describe("Wikitext with templates to expand"),
1179
- title: z22.string().optional().describe("Context page title")
1211
+ text: z23.string().describe("Wikitext with templates to expand"),
1212
+ title: z23.string().optional().describe("Context page title (for resolving {{PAGENAME}} and similar magic words)")
1180
1213
  },
1181
1214
  {
1182
1215
  title: "Expand templates",
@@ -1213,14 +1246,14 @@ async function handleExpandTemplatesTool(text, title) {
1213
1246
  }
1214
1247
 
1215
1248
  // src/tools/ro/parse.ts
1216
- import { z as z23 } from "zod";
1249
+ import { z as z24 } from "zod";
1217
1250
  function parseTool(server) {
1218
1251
  return server.tool(
1219
1252
  "parse",
1220
1253
  "Parse wikitext to HTML",
1221
1254
  {
1222
- text: z23.string().describe("Wikitext to parse"),
1223
- title: z23.string().optional().describe("Context page title")
1255
+ text: z24.string().describe("Wikitext to parse"),
1256
+ title: z24.string().optional().describe("Context page title (for resolving {{PAGENAME}} and similar magic words)")
1224
1257
  },
1225
1258
  {
1226
1259
  title: "Parse wikitext",
@@ -1260,14 +1293,14 @@ async function handleParseTool(text, title) {
1260
1293
  }
1261
1294
 
1262
1295
  // src/tools/ro/get-recent-changes.ts
1263
- import { z as z24 } from "zod";
1296
+ import { z as z25 } from "zod";
1264
1297
  function getRecentChangesTool(server) {
1265
1298
  const tool = server.tool(
1266
1299
  "get-recent-changes",
1267
1300
  "Get recent changes on the wiki",
1268
1301
  {
1269
- start: z24.string().optional().describe("Start timestamp"),
1270
- limit: z24.number().optional().default(50).describe("Maximum number of changes to return")
1302
+ start: z25.string().optional().describe("Start timestamp (YYYYMMDDHHMMSS format)"),
1303
+ limit: z25.number().optional().default(50).describe("Maximum number of changes to return")
1271
1304
  },
1272
1305
  {
1273
1306
  title: "Get recent changes",
@@ -1276,7 +1309,7 @@ function getRecentChangesTool(server) {
1276
1309
  },
1277
1310
  async ({ start, limit }) => handleGetRecentChangesTool(start, limit)
1278
1311
  );
1279
- tool.update({ outputSchema: { total: z24.number(), limit: z24.number(), start: z24.string(), changes: z24.array(z24.record(z24.unknown())) } });
1312
+ tool.update({ outputSchema: { total: z25.number(), limit: z25.number(), start: z25.string(), changes: z25.array(z25.record(z25.unknown())) } });
1280
1313
  return tool;
1281
1314
  }
1282
1315
  async function handleGetRecentChangesTool(start, limit = 50) {
@@ -1305,13 +1338,13 @@ async function handleGetRecentChangesTool(start, limit = 50) {
1305
1338
  }
1306
1339
 
1307
1340
  // src/tools/ro/get-site-info.ts
1308
- import { z as z25 } from "zod";
1341
+ import { z as z26 } from "zod";
1309
1342
  function getSiteInfoTool(server) {
1310
1343
  const tool = server.tool(
1311
1344
  "get-site-info",
1312
1345
  "Get site information from MediaWiki",
1313
1346
  {
1314
- properties: z25.array(z25.string()).describe("List of site information properties to retrieve")
1347
+ properties: z26.array(z26.string()).describe("List of site information properties to retrieve")
1315
1348
  },
1316
1349
  {
1317
1350
  title: "Get site info",
@@ -1320,7 +1353,7 @@ function getSiteInfoTool(server) {
1320
1353
  },
1321
1354
  async ({ properties }) => handleGetSiteInfoTool(properties)
1322
1355
  );
1323
- tool.update({ outputSchema: {} });
1356
+ tool.update({ outputSchema: { siteinfo: z26.record(z26.unknown()) } });
1324
1357
  return tool;
1325
1358
  }
1326
1359
  async function handleGetSiteInfoTool(properties) {
@@ -1331,13 +1364,14 @@ async function handleGetSiteInfoTool(properties) {
1331
1364
  "getSiteInfo",
1332
1365
  properties
1333
1366
  );
1334
- return jsonResult(info || {});
1367
+ return jsonResult({ siteinfo: info || {} });
1335
1368
  } catch (error) {
1336
1369
  return errorResult("Failed to get site info", error);
1337
1370
  }
1338
1371
  }
1339
1372
 
1340
1373
  // src/tools/ro/get-site-stats.ts
1374
+ import { z as z27 } from "zod";
1341
1375
  function getSiteStatsTool(server) {
1342
1376
  const tool = server.tool(
1343
1377
  "get-site-stats",
@@ -1350,7 +1384,16 @@ function getSiteStatsTool(server) {
1350
1384
  },
1351
1385
  async () => handleGetSiteStatsTool()
1352
1386
  );
1353
- tool.update({ outputSchema: {} });
1387
+ tool.update({ outputSchema: { statistics: z27.object({
1388
+ pages: z27.number(),
1389
+ articles: z27.number(),
1390
+ edits: z27.number(),
1391
+ images: z27.number(),
1392
+ users: z27.number(),
1393
+ activeusers: z27.number(),
1394
+ admins: z27.number(),
1395
+ jobs: z27.number()
1396
+ }) } });
1354
1397
  return tool;
1355
1398
  }
1356
1399
  async function handleGetSiteStatsTool() {
@@ -1360,14 +1403,14 @@ async function handleGetSiteStatsTool() {
1360
1403
  bot,
1361
1404
  "getSiteStats"
1362
1405
  );
1363
- return jsonResult(stats);
1406
+ return jsonResult({ statistics: stats });
1364
1407
  } catch (error) {
1365
1408
  return errorResult("Failed to get site stats", error);
1366
1409
  }
1367
1410
  }
1368
1411
 
1369
1412
  // src/tools/ro/get-mediawiki-version.ts
1370
- import { z as z26 } from "zod";
1413
+ import { z as z28 } from "zod";
1371
1414
  function getMediaWikiVersionTool(server) {
1372
1415
  const tool = server.tool(
1373
1416
  "get-mediawiki-version",
@@ -1380,7 +1423,7 @@ function getMediaWikiVersionTool(server) {
1380
1423
  },
1381
1424
  async () => handleGetMediaWikiVersionTool()
1382
1425
  );
1383
- tool.update({ outputSchema: { version: z26.string() } });
1426
+ tool.update({ outputSchema: { version: z28.string() } });
1384
1427
  return tool;
1385
1428
  }
1386
1429
  async function handleGetMediaWikiVersionTool() {
@@ -1397,13 +1440,13 @@ async function handleGetMediaWikiVersionTool() {
1397
1440
  }
1398
1441
 
1399
1442
  // src/tools/ro/get-query-page.ts
1400
- import { z as z27 } from "zod";
1443
+ import { z as z29 } from "zod";
1401
1444
  function getQueryPageTool(server) {
1402
1445
  const tool = server.tool(
1403
1446
  "get-query-page",
1404
- "Get results from a query page (special page)",
1447
+ "Get results from a query page (e.g. Ancientpages, Lonelypages, Wantedpages)",
1405
1448
  {
1406
- name: z27.string().describe("Name of the query page")
1449
+ name: z29.string().describe("Name of the query page")
1407
1450
  },
1408
1451
  {
1409
1452
  title: "Get query page results",
@@ -1412,7 +1455,7 @@ function getQueryPageTool(server) {
1412
1455
  },
1413
1456
  async ({ name }) => handleGetQueryPageTool(name)
1414
1457
  );
1415
- tool.update({ outputSchema: { name: z27.string(), results: z27.array(z27.record(z27.unknown())), count: z27.number() } });
1458
+ tool.update({ outputSchema: { name: z29.string(), results: z29.array(z29.record(z29.unknown())), count: z29.number() } });
1416
1459
  return tool;
1417
1460
  }
1418
1461
  async function handleGetQueryPageTool(name) {
@@ -1434,13 +1477,13 @@ async function handleGetQueryPageTool(name) {
1434
1477
  }
1435
1478
 
1436
1479
  // src/tools/ro/get-external-links.ts
1437
- import { z as z28 } from "zod";
1480
+ import { z as z30 } from "zod";
1438
1481
  function getExternalLinksTool(server) {
1439
1482
  const tool = server.tool(
1440
1483
  "get-external-links",
1441
1484
  "Get all external links from an article",
1442
1485
  {
1443
- title: z28.union([z28.string(), z28.number()]).describe("Article title or page ID")
1486
+ title: z30.union([z30.string(), z30.number()]).describe("Article title or page ID")
1444
1487
  },
1445
1488
  {
1446
1489
  title: "Get external links",
@@ -1449,7 +1492,7 @@ function getExternalLinksTool(server) {
1449
1492
  },
1450
1493
  async ({ title }) => handleGetExternalLinksTool(title)
1451
1494
  );
1452
- tool.update({ outputSchema: { title: z28.string(), links: z28.array(z28.record(z28.unknown())), count: z28.number() } });
1495
+ tool.update({ outputSchema: { title: z30.string(), links: z30.array(z30.record(z30.unknown())), count: z30.number() } });
1453
1496
  return tool;
1454
1497
  }
1455
1498
  async function handleGetExternalLinksTool(title) {
@@ -1471,13 +1514,13 @@ async function handleGetExternalLinksTool(title) {
1471
1514
  }
1472
1515
 
1473
1516
  // src/tools/ro/get-backlinks.ts
1474
- import { z as z29 } from "zod";
1517
+ import { z as z31 } from "zod";
1475
1518
  function getBacklinksTool(server) {
1476
1519
  const tool = server.tool(
1477
1520
  "get-backlinks",
1478
1521
  "Get all backlinks to a specific page",
1479
1522
  {
1480
- title: z29.string().describe("Target page title to find backlinks for")
1523
+ title: z31.string().describe("Target page title to find backlinks for")
1481
1524
  },
1482
1525
  {
1483
1526
  title: "Get backlinks",
@@ -1486,7 +1529,7 @@ function getBacklinksTool(server) {
1486
1529
  },
1487
1530
  async ({ title }) => handleGetBacklinksTool(title)
1488
1531
  );
1489
- tool.update({ outputSchema: { target: z29.string(), backlinks: z29.array(z29.record(z29.unknown())), count: z29.number() } });
1532
+ tool.update({ outputSchema: { target: z31.string(), backlinks: z31.array(z31.record(z31.unknown())), count: z31.number() } });
1490
1533
  return tool;
1491
1534
  }
1492
1535
  async function handleGetBacklinksTool(title) {
@@ -1508,19 +1551,19 @@ async function handleGetBacklinksTool(title) {
1508
1551
  }
1509
1552
 
1510
1553
  // src/tools/editing/edit.ts
1511
- import { z as z30 } from "zod";
1554
+ import { z as z32 } from "zod";
1512
1555
  function editTool(server) {
1513
1556
  const tool = server.tool(
1514
1557
  "edit",
1515
1558
  "Replace the ENTIRE content of a wiki page (requires authentication). CRITICAL: This is a FULL replacement \u2014 content you provide becomes the complete page, not an addition. There is NO undelete/undo tool \u2014 any damage you cause must be manually reverted by a human. To add a category or make a small change, you MUST first call get-article to retrieve the current content, modify it as needed, then pass the FULL modified content here. For appending or prepending without fetching the full page first, use the append/prepend tools instead.",
1516
1559
  {
1517
- title: z30.string().describe("Page title to edit"),
1518
- content: z30.string().describe("COMPLETE new wikitext for the ENTIRE page \u2014 not a snippet, not a prefix, not an appendage. This replaces everything. Always fetch the current content with get-article first, then modify and resubmit the full text."),
1519
- intent: z30.enum(["add", "revise", "delete"]).describe(
1560
+ title: z32.string().describe("Page title to edit"),
1561
+ content: z32.string().describe("COMPLETE new wikitext for the ENTIRE page \u2014 not a snippet, not a prefix, not an appendage. This replaces everything. Always fetch the current content with get-article first, then modify and resubmit the full text."),
1562
+ intent: z32.enum(["add", "revise", "delete"]).describe(
1520
1563
  'Your editing intent: "add" = adding content (page should grow), "revise" = modifying content (small net change, must keep \u22653/4 of existing bytes), "delete" = removing significant content (page should shrink significantly)'
1521
1564
  ),
1522
- summary: z30.string().describe("Edit summary describing what was changed and why"),
1523
- minor: z30.boolean().optional().default(false).describe("Mark as minor edit")
1565
+ summary: z32.string().describe("Edit summary describing what was changed and why"),
1566
+ minor: z32.boolean().optional().default(false).describe("Mark as minor edit")
1524
1567
  },
1525
1568
  {
1526
1569
  title: "Edit page",
@@ -1529,7 +1572,7 @@ function editTool(server) {
1529
1572
  },
1530
1573
  async (params) => handleEditTool(params)
1531
1574
  );
1532
- tool.update({ outputSchema: {} });
1575
+ tool.update({ outputSchema: { result: z32.string(), pageid: z32.number(), title: z32.string(), contentmodel: z32.string(), newrevid: z32.number(), newtimestamp: z32.string(), oldrevid: z32.number().optional() } });
1533
1576
  return tool;
1534
1577
  }
1535
1578
  async function handleEditTool(params) {
@@ -1583,15 +1626,15 @@ async function handleEditTool(params) {
1583
1626
  }
1584
1627
 
1585
1628
  // src/tools/editing/append.ts
1586
- import { z as z31 } from "zod";
1629
+ import { z as z33 } from "zod";
1587
1630
  function appendTool(server) {
1588
1631
  const tool = server.tool(
1589
1632
  "append",
1590
1633
  "Append content to the END of a wiki page without changing existing content (requires authentication). Safe for adding categories, interwiki links, or any content that belongs at the bottom of a page.",
1591
1634
  {
1592
- title: z31.string().describe("Page title"),
1593
- content: z31.string().describe('Content to append to the end of the page (e.g., "\\n[[Category:MyCategory]]")'),
1594
- summary: z31.string().describe("Edit summary")
1635
+ title: z33.string().describe("Page title"),
1636
+ content: z33.string().describe('Content to append to the end of the page (e.g., "\\n[[Category:MyCategory]]")'),
1637
+ summary: z33.string().describe("Edit summary")
1595
1638
  },
1596
1639
  {
1597
1640
  title: "Append to page",
@@ -1600,7 +1643,7 @@ function appendTool(server) {
1600
1643
  },
1601
1644
  async (params) => handleAppendTool(params)
1602
1645
  );
1603
- tool.update({ outputSchema: { success: z31.boolean(), title: z31.string() } });
1646
+ tool.update({ outputSchema: { success: z33.boolean(), title: z33.string() } });
1604
1647
  return tool;
1605
1648
  }
1606
1649
  async function handleAppendTool(params) {
@@ -1622,15 +1665,15 @@ async function handleAppendTool(params) {
1622
1665
  }
1623
1666
 
1624
1667
  // src/tools/editing/prepend.ts
1625
- import { z as z32 } from "zod";
1668
+ import { z as z34 } from "zod";
1626
1669
  function prependTool(server) {
1627
1670
  const tool = server.tool(
1628
1671
  "prepend",
1629
1672
  "Prepend content to the TOP of a wiki page without changing existing content (requires authentication). Useful for adding notices, templates, or cleanup tags that belong at the top of a page.",
1630
1673
  {
1631
- title: z32.string().describe("Page title to prepend to"),
1632
- content: z32.string().describe('Content to prepend to the top of the page (e.g., "{{Cleanup}}\\n")'),
1633
- summary: z32.string().describe("Edit summary")
1674
+ title: z34.string().describe("Page title to prepend to"),
1675
+ content: z34.string().describe('Content to prepend to the top of the page (e.g., "{{Cleanup}}\\n")'),
1676
+ summary: z34.string().describe("Edit summary")
1634
1677
  },
1635
1678
  {
1636
1679
  title: "Prepend to page",
@@ -1639,7 +1682,7 @@ function prependTool(server) {
1639
1682
  },
1640
1683
  async (params) => handlePrependTool(params)
1641
1684
  );
1642
- tool.update({ outputSchema: {} });
1685
+ tool.update({ outputSchema: { result: z34.string(), pageid: z34.number(), title: z34.string(), contentmodel: z34.string(), newrevid: z34.number(), newtimestamp: z34.string(), oldrevid: z34.number().optional() } });
1643
1686
  return tool;
1644
1687
  }
1645
1688
  async function handlePrependTool(params) {
@@ -1661,15 +1704,15 @@ async function handlePrependTool(params) {
1661
1704
  }
1662
1705
 
1663
1706
  // src/tools/editing/move.ts
1664
- import { z as z33 } from "zod";
1707
+ import { z as z35 } from "zod";
1665
1708
  function moveTool(server) {
1666
1709
  const tool = server.tool(
1667
1710
  "move",
1668
1711
  "Move (rename) a wiki page \u2014 changes the page title and creates a redirect from the old name (requires authentication). The old page title becomes a redirect to the new title. All page history moves with the page.",
1669
1712
  {
1670
- from: z33.string().describe("Current/existing page title to rename"),
1671
- to: z33.string().describe("New target page title \u2014 must not already exist (unless moving to overwrite)"),
1672
- summary: z33.string().describe("Reason for the move (visible in move log)")
1713
+ from: z35.string().describe("Current/existing page title to rename"),
1714
+ to: z35.string().describe("New target page title \u2014 must not already exist (unless moving to overwrite)"),
1715
+ summary: z35.string().describe("Reason for the move (visible in move log)")
1673
1716
  },
1674
1717
  {
1675
1718
  title: "Move page",
@@ -1678,7 +1721,7 @@ function moveTool(server) {
1678
1721
  },
1679
1722
  async (params) => handleMoveTool(params)
1680
1723
  );
1681
- tool.update({ outputSchema: {} });
1724
+ tool.update({ outputSchema: { from: z35.string(), to: z35.string(), reason: z35.string(), redirectcreated: z35.boolean().optional() } });
1682
1725
  return tool;
1683
1726
  }
1684
1727
  async function handleMoveTool(params) {
@@ -1700,14 +1743,14 @@ async function handleMoveTool(params) {
1700
1743
  }
1701
1744
 
1702
1745
  // src/tools/editing/delete.ts
1703
- import { z as z34 } from "zod";
1746
+ import { z as z36 } from "zod";
1704
1747
  function deleteTool(server) {
1705
1748
  const tool = server.tool(
1706
1749
  "delete",
1707
1750
  "PERMANENTLY delete a wiki page (requires authentication). CRITICAL: This action is IRREVERSIBLE \u2014 there is NO undelete/undo tool available. Any deletion must be manually restored by a human administrator. Only delete a page when the user explicitly asks for it. Always verify the title is correct before proceeding.",
1708
1751
  {
1709
- title: z34.string().describe("Exact page title to permanently delete \u2014 double-check this is correct"),
1710
- reason: z34.string().describe("Detailed reason for deletion (visible in deletion log)")
1752
+ title: z36.string().describe("Exact page title to permanently delete \u2014 double-check this is correct"),
1753
+ reason: z36.string().describe("Detailed reason for deletion (visible in deletion log)")
1711
1754
  },
1712
1755
  {
1713
1756
  title: "Delete page",
@@ -1716,7 +1759,7 @@ function deleteTool(server) {
1716
1759
  },
1717
1760
  async (params) => handleDeleteTool(params)
1718
1761
  );
1719
- tool.update({ outputSchema: {} });
1762
+ tool.update({ outputSchema: { title: z36.string(), reason: z36.string(), logid: z36.number() } });
1720
1763
  return tool;
1721
1764
  }
1722
1765
  async function handleDeleteTool(params) {
@@ -1737,24 +1780,24 @@ async function handleDeleteTool(params) {
1737
1780
  }
1738
1781
 
1739
1782
  // src/tools/editing/protect.ts
1740
- import { z as z35 } from "zod";
1783
+ import { z as z37 } from "zod";
1741
1784
  function protectTool(server) {
1742
1785
  const tool = server.tool(
1743
1786
  "protect",
1744
1787
  'Protect or unprotect a wiki page to restrict editing/moving (requires authentication). CRITICAL: Protection can lock out legitimate editors \u2014 only protect pages when there is a clear need (ongoing vandalism, edit war, high-risk template, policy page). To remove protection, set level to "all". Available levels: "all" (anyone), "autoconfirmed" (trusted users), "sysop" (admins only).',
1745
1788
  {
1746
- title: z35.string().describe("Page title to protect or unprotect"),
1747
- protections: z35.array(
1748
- z35.object({
1749
- type: z35.enum(["edit", "move"]).describe('Action to restrict: "edit" or "move"'),
1750
- level: z35.enum(["all", "autoconfirmed", "sysop"]).optional().default("all").describe(
1789
+ title: z37.string().describe("Page title to protect or unprotect"),
1790
+ protections: z37.array(
1791
+ z37.object({
1792
+ type: z37.enum(["edit", "move"]).describe('Action to restrict: "edit" or "move"'),
1793
+ level: z37.enum(["all", "autoconfirmed", "sysop"]).optional().default("all").describe(
1751
1794
  'Who can perform this action: "all" = no restriction, "autoconfirmed" = trusted users only, "sysop" = admins only'
1752
1795
  ),
1753
- expiry: z35.string().optional().describe('How long protection lasts (e.g. "1 day", "1 week", "infinite"). Default is indefinite.')
1796
+ expiry: z37.string().optional().describe('How long protection lasts (e.g. "1 day", "1 week", "infinite"). Default is indefinite.')
1754
1797
  })
1755
1798
  ).describe('Protection rules \u2014 typically one entry for "edit" and optionally one for "move". Example: [{type:"edit",level:"sysop",expiry:"1 week"}]'),
1756
- reason: z35.string().optional().describe("Reason for changing protection, visible in the page log"),
1757
- cascade: z35.boolean().optional().default(false).describe("If true, transcluded templates/pages inherit this protection. Only works with full sysop protection on edit. Use with caution.")
1799
+ reason: z37.string().optional().describe("Reason for changing protection, visible in the page log"),
1800
+ cascade: z37.boolean().optional().default(false).describe("If true, transcluded templates/pages inherit this protection. Only works with full sysop protection on edit. Use with caution.")
1758
1801
  },
1759
1802
  {
1760
1803
  title: "Protect page",
@@ -1763,7 +1806,7 @@ function protectTool(server) {
1763
1806
  },
1764
1807
  async (params) => handleProtectTool(params)
1765
1808
  );
1766
- tool.update({ outputSchema: {} });
1809
+ tool.update({ outputSchema: { title: z37.string(), reason: z37.string().optional(), protections: z37.array(z37.record(z37.unknown())), cascade: z37.boolean() } });
1767
1810
  return tool;
1768
1811
  }
1769
1812
  async function handleProtectTool(params) {
@@ -1791,13 +1834,13 @@ async function handleProtectTool(params) {
1791
1834
  }
1792
1835
 
1793
1836
  // src/tools/editing/purge.ts
1794
- import { z as z36 } from "zod";
1837
+ import { z as z38 } from "zod";
1795
1838
  function purgeTool(server) {
1796
1839
  const tool = server.tool(
1797
1840
  "purge",
1798
1841
  "Purge the server-side cache for one or more wiki pages (requires authentication). Forces MediaWiki to regenerate the page from current wikitext. This is a safe, non-destructive action.",
1799
1842
  {
1800
- titles: z36.union([z36.string(), z36.array(z36.string())]).describe("Page title(s) or category name to purge")
1843
+ titles: z38.union([z38.string(), z38.array(z38.string())]).describe("Page title(s) or category name to purge")
1801
1844
  },
1802
1845
  {
1803
1846
  title: "Purge pages",
@@ -1806,7 +1849,7 @@ function purgeTool(server) {
1806
1849
  },
1807
1850
  async (params) => handlePurgeTool(params)
1808
1851
  );
1809
- tool.update({ outputSchema: {} });
1852
+ tool.update({ outputSchema: { pages: z38.array(z38.record(z38.unknown())) } });
1810
1853
  return tool;
1811
1854
  }
1812
1855
  async function handlePurgeTool(params) {
@@ -1817,22 +1860,22 @@ async function handlePurgeTool(params) {
1817
1860
  "purge",
1818
1861
  params.titles
1819
1862
  );
1820
- return jsonResult(result);
1863
+ return jsonResult({ pages: result });
1821
1864
  } catch (error) {
1822
1865
  return errorResult("Failed to purge pages", error);
1823
1866
  }
1824
1867
  }
1825
1868
 
1826
1869
  // src/tools/editing/send-email.ts
1827
- import { z as z37 } from "zod";
1870
+ import { z as z39 } from "zod";
1828
1871
  function sendEmailTool(server) {
1829
1872
  const tool = server.tool(
1830
1873
  "send-email",
1831
1874
  "Send an ACTUAL email to a wiki user via the wiki's built-in email system (requires authentication). CRITICAL: This sends a real email to the user's registered address \u2014 it is NOT a simulation. The recipient will see it came from the authenticated bot operator's wiki account. Abuse (spam, harassment, unsolicited messages) WILL result in the bot account being blocked. ONLY use this when the human user has explicitly asked you to send an email.",
1832
1875
  {
1833
- username: z37.string().describe("Target wiki username \u2014 email goes to their registered email address"),
1834
- subject: z37.string().describe("Email subject line \u2014 be clear and professional, no misleading subjects"),
1835
- text: z37.string().describe("Plain text email body \u2014 will be delivered as-is to the recipient's inbox")
1876
+ username: z39.string().describe("Target wiki username \u2014 email goes to their registered email address"),
1877
+ subject: z39.string().describe("Email subject line \u2014 be clear and professional, no misleading subjects"),
1878
+ text: z39.string().describe("Plain text email body \u2014 will be delivered as-is to the recipient's inbox")
1836
1879
  },
1837
1880
  {
1838
1881
  title: "Send email",
@@ -1841,7 +1884,7 @@ function sendEmailTool(server) {
1841
1884
  },
1842
1885
  async (params) => handleSendEmailTool(params)
1843
1886
  );
1844
- tool.update({ outputSchema: {} });
1887
+ tool.update({ outputSchema: { result: z39.string(), message: z39.string().optional() } });
1845
1888
  return tool;
1846
1889
  }
1847
1890
  async function handleSendEmailTool(params) {
@@ -1861,15 +1904,15 @@ async function handleSendEmailTool(params) {
1861
1904
  }
1862
1905
 
1863
1906
  // src/tools/editing/upload.ts
1864
- import { z as z38 } from "zod";
1907
+ import { z as z40 } from "zod";
1865
1908
  function uploadTool(server) {
1866
1909
  const tool = server.tool(
1867
1910
  "upload",
1868
1911
  "Upload a file to the wiki (requires authentication). CRITICAL: If a file with the same name already exists, it WILL BE OVERWRITTEN. Ensure you have the right to upload the content. Use only when explicitly requested.",
1869
1912
  {
1870
- filename: z38.string().describe('Destination filename on wiki (e.g., "MyImage.png") \u2014 existing file will be overwritten!'),
1871
- content: z38.string().describe("File content encoded as base64 string"),
1872
- comment: z38.string().optional().describe("Upload comment describing the file")
1913
+ filename: z40.string().describe('Destination filename on wiki (e.g., "MyImage.png") \u2014 existing file will be overwritten!'),
1914
+ content: z40.string().describe("File content encoded as base64 string"),
1915
+ comment: z40.string().optional().describe("Upload comment describing the file")
1873
1916
  },
1874
1917
  {
1875
1918
  title: "Upload file",
@@ -1878,7 +1921,7 @@ function uploadTool(server) {
1878
1921
  },
1879
1922
  async (params) => handleUploadTool(params)
1880
1923
  );
1881
- tool.update({ outputSchema: {} });
1924
+ tool.update({ outputSchema: { result: z40.string(), filename: z40.string(), imageinfo: z40.record(z40.unknown()).optional() } });
1882
1925
  return tool;
1883
1926
  }
1884
1927
  async function handleUploadTool(params) {
@@ -1900,15 +1943,15 @@ async function handleUploadTool(params) {
1900
1943
  }
1901
1944
 
1902
1945
  // src/tools/editing/upload-by-url.ts
1903
- import { z as z39 } from "zod";
1946
+ import { z as z41 } from "zod";
1904
1947
  function uploadByUrlTool(server) {
1905
1948
  const tool = server.tool(
1906
1949
  "upload-by-url",
1907
1950
  "Upload a file to the wiki by downloading it from a URL (requires authentication). CRITICAL: If a file with the same name already exists, it WILL BE OVERWRITTEN. Ensure you have the right to upload the content from the source URL.",
1908
1951
  {
1909
- filename: z39.string().describe('Destination filename on wiki (e.g., "Diagram.png") \u2014 existing file will be overwritten!'),
1910
- url: z39.string().url().describe("Source URL to download the file from \u2014 must be publicly accessible"),
1911
- summary: z39.string().optional().describe("Upload summary")
1952
+ filename: z41.string().describe('Destination filename on wiki (e.g., "Diagram.png") \u2014 existing file will be overwritten!'),
1953
+ url: z41.string().url().describe("Source URL to download the file from \u2014 must be publicly accessible"),
1954
+ summary: z41.string().optional().describe("Upload summary")
1912
1955
  },
1913
1956
  {
1914
1957
  title: "Upload file by URL",
@@ -1917,7 +1960,7 @@ function uploadByUrlTool(server) {
1917
1960
  },
1918
1961
  async (params) => handleUploadByUrlTool(params)
1919
1962
  );
1920
- tool.update({ outputSchema: {} });
1963
+ tool.update({ outputSchema: { result: z41.string(), filename: z41.string(), imageinfo: z41.record(z41.unknown()).optional() } });
1921
1964
  return tool;
1922
1965
  }
1923
1966
  async function handleUploadByUrlTool(params) {
@@ -1938,15 +1981,15 @@ async function handleUploadByUrlTool(params) {
1938
1981
  }
1939
1982
 
1940
1983
  // src/tools/editing/add-flow-topic.ts
1941
- import { z as z40 } from "zod";
1984
+ import { z as z42 } from "zod";
1942
1985
  function addFlowTopicTool(server) {
1943
1986
  const tool = server.tool(
1944
1987
  "add-flow-topic",
1945
1988
  "Add a new Flow/Structured Discussions topic to a wiki talk page (requires authentication). Creates a publicly visible discussion thread on the wiki. Ensure the content is appropriate and relevant.",
1946
1989
  {
1947
- title: z40.string().describe('Talk page title to add the topic to (e.g., "Talk:Main Page")'),
1948
- subject: z40.string().describe("Topic title/heading \u2014 should summarize the discussion topic"),
1949
- content: z40.string().describe("Topic body content in wikitext format")
1990
+ title: z42.string().describe('Talk page title to add the topic to (e.g., "Talk:Main Page")'),
1991
+ subject: z42.string().describe("Topic title/heading \u2014 should summarize the discussion topic"),
1992
+ content: z42.string().describe("Topic body content in wikitext format")
1950
1993
  },
1951
1994
  {
1952
1995
  title: "Add Flow topic",
@@ -1955,7 +1998,7 @@ function addFlowTopicTool(server) {
1955
1998
  },
1956
1999
  async (params) => handleAddFlowTopicTool(params)
1957
2000
  );
1958
- tool.update({ outputSchema: {} });
2001
+ tool.update({ outputSchema: { "new-topic": z42.record(z42.unknown()) } });
1959
2002
  return tool;
1960
2003
  }
1961
2004
  async function handleAddFlowTopicTool(params) {
@@ -1975,14 +2018,14 @@ async function handleAddFlowTopicTool(params) {
1975
2018
  }
1976
2019
 
1977
2020
  // src/tools/editing/create-account.ts
1978
- import { z as z41 } from "zod";
2021
+ import { z as z43 } from "zod";
1979
2022
  function createAccountTool(server) {
1980
2023
  const tool = server.tool(
1981
2024
  "create-account",
1982
2025
  "Create a NEW user account on the wiki (requires authentication). CRITICAL: This creates a real user account. Do NOT create accounts for yourself or without explicit user request. The account will be permanently registered on the wiki.",
1983
2026
  {
1984
- username: z41.string().describe("Desired username for the new account \u2014 must follow wiki username rules"),
1985
- password: z41.string().describe("Password for the new account \u2014 use a strong, unique password")
2027
+ username: z43.string().describe("Desired username for the new account \u2014 must follow wiki username rules"),
2028
+ password: z43.string().describe("Password for the new account \u2014 use a strong, unique password")
1986
2029
  },
1987
2030
  {
1988
2031
  title: "Create user account",
@@ -1991,7 +2034,7 @@ function createAccountTool(server) {
1991
2034
  },
1992
2035
  async (params) => handleCreateAccountTool(params)
1993
2036
  );
1994
- tool.update({ outputSchema: {} });
2037
+ tool.update({ outputSchema: { account: z43.record(z43.unknown()) } });
1995
2038
  return tool;
1996
2039
  }
1997
2040
  async function handleCreateAccountTool(params) {
@@ -2003,7 +2046,7 @@ async function handleCreateAccountTool(params) {
2003
2046
  params.username,
2004
2047
  params.password
2005
2048
  );
2006
- return jsonResult(result);
2049
+ return jsonResult({ account: result });
2007
2050
  } catch (error) {
2008
2051
  return errorResult("Failed to create account", error);
2009
2052
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiedada/nodemw-mcp-server",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "MCP server for nodemw - MediaWiki API client",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",