@cyanheads/wikipedia-mcp-server 0.1.3
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/AGENTS.md +394 -0
- package/CLAUDE.md +394 -0
- package/Dockerfile +99 -0
- package/LICENSE +201 -0
- package/README.md +294 -0
- package/changelog/0.1.x/0.1.0.md +18 -0
- package/changelog/0.1.x/0.1.1.md +22 -0
- package/changelog/0.1.x/0.1.2.md +13 -0
- package/changelog/0.1.x/0.1.3.md +31 -0
- package/changelog/template.md +119 -0
- package/dist/config/server-config.d.ts +13 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +25 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/index.d.ts +168 -0
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/index.js +19 -0
- package/dist/mcp-server/tools/definitions/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-article.tool.d.ts +34 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-article.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-article.tool.js +153 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-article.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-languages.tool.d.ts +35 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-languages.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-languages.tool.js +105 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-languages.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-sections.tool.d.ts +37 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-sections.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-sections.tool.js +109 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-sections.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-summary.tool.d.ts +30 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-summary.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-summary.tool.js +107 -0
- package/dist/mcp-server/tools/definitions/wikipedia-get-summary.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search-nearby.tool.d.ts +42 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search-nearby.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search-nearby.tool.js +127 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search-nearby.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search.tool.d.ts +32 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search.tool.js +91 -0
- package/dist/mcp-server/tools/definitions/wikipedia-search.tool.js.map +1 -0
- package/dist/services/wikipedia/types.d.ts +110 -0
- package/dist/services/wikipedia/types.d.ts.map +1 -0
- package/dist/services/wikipedia/types.js +6 -0
- package/dist/services/wikipedia/types.js.map +1 -0
- package/dist/services/wikipedia/wikipedia-service.d.ts +81 -0
- package/dist/services/wikipedia/wikipedia-service.d.ts.map +1 -0
- package/dist/services/wikipedia/wikipedia-service.js +577 -0
- package/dist/services/wikipedia/wikipedia-service.js.map +1 -0
- package/package.json +86 -0
- package/server.json +99 -0
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wikipedia service — wraps the MediaWiki REST API and Action API.
|
|
3
|
+
* @module services/wikipedia/wikipedia-service
|
|
4
|
+
*/
|
|
5
|
+
import { JsonRpcErrorCode, McpError, notFound, serviceUnavailable, validationError, } from '@cyanheads/mcp-ts-core/errors';
|
|
6
|
+
import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
|
|
7
|
+
import wtf from 'wtf_wikipedia';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Wikitext stripping pipeline
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/**
|
|
12
|
+
* Strip MediaWiki markup from raw wikitext and return clean plain text.
|
|
13
|
+
* Uses wtf_wikipedia for the heavy lifting, then applies heading-preservation
|
|
14
|
+
* and blank-line normalization as a post-pass.
|
|
15
|
+
*/
|
|
16
|
+
function stripWikitext(wikitext) {
|
|
17
|
+
// wtf_wikipedia handles links, templates, refs, bold/italic
|
|
18
|
+
const doc = wtf(wikitext);
|
|
19
|
+
let text = doc.text();
|
|
20
|
+
// Preserve section headings — wtf strips them, but we want structure.
|
|
21
|
+
// Re-inject from the raw wikitext using a simple regex pass.
|
|
22
|
+
const headingPattern = /^(={2,6})\s*(.+?)\s*\1\s*$/gm;
|
|
23
|
+
const headings = [...wikitext.matchAll(headingPattern)]
|
|
24
|
+
.filter((m) => m[1] && m[2])
|
|
25
|
+
.map((m) => ({ level: m[1].length, title: m[2] }));
|
|
26
|
+
// Prepend headings as == Heading == markers when present and not already in text.
|
|
27
|
+
if (headings[0] && !text.startsWith(headings[0].title)) {
|
|
28
|
+
const headingMarkers = headings
|
|
29
|
+
.map(({ level, title }) => `${'='.repeat(level)} ${title} ${'='.repeat(level)}`)
|
|
30
|
+
.join('\n\n');
|
|
31
|
+
text = `${headingMarkers}\n\n${text}`;
|
|
32
|
+
}
|
|
33
|
+
// Remove HTML comments that may have survived.
|
|
34
|
+
text = text.replace(/<!--[\s\S]*?-->/g, '');
|
|
35
|
+
// Collapse multiple blank lines to a single blank line.
|
|
36
|
+
text = text.replace(/\n{3,}/g, '\n\n');
|
|
37
|
+
return text.trim();
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Strip HTML snippet markup from Action API search results
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
function stripSnippetHtml(html) {
|
|
43
|
+
const stripped = html.replace(/<[^>]+>/g, '');
|
|
44
|
+
// Decode the most common HTML entities that the Action API leaves in snippets.
|
|
45
|
+
return stripped
|
|
46
|
+
.replace(/&/g, '&')
|
|
47
|
+
.replace(/</g, '<')
|
|
48
|
+
.replace(/>/g, '>')
|
|
49
|
+
.replace(/"/g, '"')
|
|
50
|
+
.replace(/'/g, "'")
|
|
51
|
+
.replace(/'/g, "'")
|
|
52
|
+
.trim();
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Language code validation
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Known Wikipedia language edition codes (subdomains that exist as wikipedia.org editions).
|
|
59
|
+
* Sourced from https://meta.wikimedia.org/wiki/List_of_Wikipedias — stable set of ~300 codes.
|
|
60
|
+
* A structurally valid BCP 47 code that is NOT in this set will time out after 4 retries (~60s)
|
|
61
|
+
* and leak the full API URL in the error message, so we validate eagerly.
|
|
62
|
+
*/
|
|
63
|
+
const KNOWN_WIKIPEDIA_EDITIONS = new Set([
|
|
64
|
+
'en',
|
|
65
|
+
'de',
|
|
66
|
+
'fr',
|
|
67
|
+
'ja',
|
|
68
|
+
'es',
|
|
69
|
+
'ru',
|
|
70
|
+
'zh',
|
|
71
|
+
'pt',
|
|
72
|
+
'ar',
|
|
73
|
+
'it',
|
|
74
|
+
'fa',
|
|
75
|
+
'pl',
|
|
76
|
+
'nl',
|
|
77
|
+
'uk',
|
|
78
|
+
'he',
|
|
79
|
+
'sv',
|
|
80
|
+
'ko',
|
|
81
|
+
'vi',
|
|
82
|
+
'ca',
|
|
83
|
+
'no',
|
|
84
|
+
'fi',
|
|
85
|
+
'cs',
|
|
86
|
+
'hu',
|
|
87
|
+
'ro',
|
|
88
|
+
'tr',
|
|
89
|
+
'id',
|
|
90
|
+
'th',
|
|
91
|
+
'sr',
|
|
92
|
+
'ms',
|
|
93
|
+
'eo',
|
|
94
|
+
'eu',
|
|
95
|
+
'da',
|
|
96
|
+
'bg',
|
|
97
|
+
'sk',
|
|
98
|
+
'min',
|
|
99
|
+
'hr',
|
|
100
|
+
'et',
|
|
101
|
+
'lt',
|
|
102
|
+
'simple',
|
|
103
|
+
'sl',
|
|
104
|
+
'az',
|
|
105
|
+
'la',
|
|
106
|
+
'ur',
|
|
107
|
+
'be',
|
|
108
|
+
'ce',
|
|
109
|
+
'nn',
|
|
110
|
+
'cy',
|
|
111
|
+
'hy',
|
|
112
|
+
'ka',
|
|
113
|
+
'el',
|
|
114
|
+
'uz',
|
|
115
|
+
'gl',
|
|
116
|
+
'lv',
|
|
117
|
+
'bn',
|
|
118
|
+
'ta',
|
|
119
|
+
'mk',
|
|
120
|
+
'sh',
|
|
121
|
+
'hi',
|
|
122
|
+
'af',
|
|
123
|
+
'bs',
|
|
124
|
+
'kk',
|
|
125
|
+
'war',
|
|
126
|
+
'mg',
|
|
127
|
+
'te',
|
|
128
|
+
'sq',
|
|
129
|
+
'oc',
|
|
130
|
+
'mr',
|
|
131
|
+
'tl',
|
|
132
|
+
'ml',
|
|
133
|
+
'ceb',
|
|
134
|
+
'br',
|
|
135
|
+
'ast',
|
|
136
|
+
'be-tarask',
|
|
137
|
+
'azb',
|
|
138
|
+
'pa',
|
|
139
|
+
'zh-yue',
|
|
140
|
+
'an',
|
|
141
|
+
'lb',
|
|
142
|
+
'is',
|
|
143
|
+
'ba',
|
|
144
|
+
'my',
|
|
145
|
+
'fy',
|
|
146
|
+
'wuu',
|
|
147
|
+
'sw',
|
|
148
|
+
'yo',
|
|
149
|
+
'ga',
|
|
150
|
+
'new',
|
|
151
|
+
'tt',
|
|
152
|
+
'gu',
|
|
153
|
+
'kn',
|
|
154
|
+
'io',
|
|
155
|
+
'ia',
|
|
156
|
+
'or',
|
|
157
|
+
'su',
|
|
158
|
+
'ne',
|
|
159
|
+
'ckb',
|
|
160
|
+
'si',
|
|
161
|
+
'cv',
|
|
162
|
+
'ps',
|
|
163
|
+
'fo',
|
|
164
|
+
'scn',
|
|
165
|
+
'nds',
|
|
166
|
+
'bpy',
|
|
167
|
+
'qu',
|
|
168
|
+
'diq',
|
|
169
|
+
'li',
|
|
170
|
+
'bar',
|
|
171
|
+
'als',
|
|
172
|
+
'mn',
|
|
173
|
+
'sa',
|
|
174
|
+
'jv',
|
|
175
|
+
'sco',
|
|
176
|
+
'roa-tara',
|
|
177
|
+
'as',
|
|
178
|
+
'mzn',
|
|
179
|
+
'nah',
|
|
180
|
+
'ace',
|
|
181
|
+
'pnb',
|
|
182
|
+
'am',
|
|
183
|
+
'wa',
|
|
184
|
+
'lmo',
|
|
185
|
+
'tg',
|
|
186
|
+
'pms',
|
|
187
|
+
'nds-nl',
|
|
188
|
+
'ku',
|
|
189
|
+
'ky',
|
|
190
|
+
'vec',
|
|
191
|
+
'sc',
|
|
192
|
+
'os',
|
|
193
|
+
'arz',
|
|
194
|
+
'vls',
|
|
195
|
+
'rue',
|
|
196
|
+
'frr',
|
|
197
|
+
'hif',
|
|
198
|
+
'zh-min-nan',
|
|
199
|
+
'crh',
|
|
200
|
+
'sd',
|
|
201
|
+
'bo',
|
|
202
|
+
'vep',
|
|
203
|
+
'hak',
|
|
204
|
+
'hat',
|
|
205
|
+
'se',
|
|
206
|
+
'bcl',
|
|
207
|
+
'km',
|
|
208
|
+
'tk',
|
|
209
|
+
'krc',
|
|
210
|
+
'gag',
|
|
211
|
+
'nso',
|
|
212
|
+
'ab',
|
|
213
|
+
'xmf',
|
|
214
|
+
'sah',
|
|
215
|
+
'map-bms',
|
|
216
|
+
'mi',
|
|
217
|
+
'hsb',
|
|
218
|
+
'szl',
|
|
219
|
+
'nrm',
|
|
220
|
+
'pcd',
|
|
221
|
+
'ksh',
|
|
222
|
+
'lij',
|
|
223
|
+
'mhr',
|
|
224
|
+
'ug',
|
|
225
|
+
'bxr',
|
|
226
|
+
'glk',
|
|
227
|
+
'zh-classical',
|
|
228
|
+
'roa-rup',
|
|
229
|
+
'stq',
|
|
230
|
+
'co',
|
|
231
|
+
'frp',
|
|
232
|
+
'kv',
|
|
233
|
+
'so',
|
|
234
|
+
'kw',
|
|
235
|
+
'mwl',
|
|
236
|
+
'to',
|
|
237
|
+
'csb',
|
|
238
|
+
'myv',
|
|
239
|
+
'lad',
|
|
240
|
+
'rm',
|
|
241
|
+
'ie',
|
|
242
|
+
'bjn',
|
|
243
|
+
'ln',
|
|
244
|
+
'fur',
|
|
245
|
+
'ang',
|
|
246
|
+
'ext',
|
|
247
|
+
'cbk-zam',
|
|
248
|
+
'mt',
|
|
249
|
+
'xh',
|
|
250
|
+
'eml',
|
|
251
|
+
'ilo',
|
|
252
|
+
'wo',
|
|
253
|
+
'sn',
|
|
254
|
+
'za',
|
|
255
|
+
'pfl',
|
|
256
|
+
'gd',
|
|
257
|
+
'nap',
|
|
258
|
+
'ig',
|
|
259
|
+
'tw',
|
|
260
|
+
'tet',
|
|
261
|
+
'fiu-vro',
|
|
262
|
+
'ay',
|
|
263
|
+
'got',
|
|
264
|
+
'bm',
|
|
265
|
+
'chy',
|
|
266
|
+
'kl',
|
|
267
|
+
'tpi',
|
|
268
|
+
'bh',
|
|
269
|
+
'aa',
|
|
270
|
+
'ki',
|
|
271
|
+
'ff',
|
|
272
|
+
'cu',
|
|
273
|
+
'sm',
|
|
274
|
+
'gn',
|
|
275
|
+
'ts',
|
|
276
|
+
'tn',
|
|
277
|
+
'cr',
|
|
278
|
+
'sg',
|
|
279
|
+
'ty',
|
|
280
|
+
'ss',
|
|
281
|
+
've',
|
|
282
|
+
'iu',
|
|
283
|
+
'ch',
|
|
284
|
+
'st',
|
|
285
|
+
'hz',
|
|
286
|
+
'rw',
|
|
287
|
+
'ee',
|
|
288
|
+
'lg',
|
|
289
|
+
'pi',
|
|
290
|
+
'ii',
|
|
291
|
+
]);
|
|
292
|
+
/**
|
|
293
|
+
* Validate that `language` is a structurally valid BCP 47 code AND a known Wikipedia edition.
|
|
294
|
+
* Returns the normalised base URL or throws a `validationError` with a descriptive message.
|
|
295
|
+
*
|
|
296
|
+
* This is a pure utility — it cannot call `ctx.fail`. Callers that want a typed error contract
|
|
297
|
+
* should validate using `ctx.fail('invalid_language', ...)` before calling service methods.
|
|
298
|
+
*/
|
|
299
|
+
function buildBaseUrl(language) {
|
|
300
|
+
// Structure check — must look like a BCP 47 code.
|
|
301
|
+
if (!/^[a-z]{2,3}(-[a-z0-9]+)*$/i.test(language)) {
|
|
302
|
+
throw validationError(`Invalid language code "${language}". Use a BCP 47 language code such as "fr", "de", or "ja".`, { recovery: { hint: 'Use a valid BCP 47 language code such as "fr", "de", or "ja".' } });
|
|
303
|
+
}
|
|
304
|
+
const normalized = language.toLowerCase();
|
|
305
|
+
// Edition check — structurally valid codes may not correspond to an existing Wikipedia edition.
|
|
306
|
+
// Without this check a non-existent subdomain causes 4 retries × 15s timeout and URL leakage.
|
|
307
|
+
if (!KNOWN_WIKIPEDIA_EDITIONS.has(normalized)) {
|
|
308
|
+
throw validationError(`Language edition "${language}" does not exist on Wikipedia. Use a valid Wikipedia language code such as "fr", "de", or "ja".`, {
|
|
309
|
+
language,
|
|
310
|
+
recovery: {
|
|
311
|
+
hint: 'Use a Wikipedia language code that has an active edition, such as "fr", "de", or "ja".',
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
return `https://${normalized}.wikipedia.org`;
|
|
316
|
+
}
|
|
317
|
+
// ---------------------------------------------------------------------------
|
|
318
|
+
// WikipediaService
|
|
319
|
+
// ---------------------------------------------------------------------------
|
|
320
|
+
export class WikipediaService {
|
|
321
|
+
userAgent;
|
|
322
|
+
constructor(_config, _storage, userAgent) {
|
|
323
|
+
this.userAgent = userAgent;
|
|
324
|
+
}
|
|
325
|
+
/** Shared fetch headers for all requests. */
|
|
326
|
+
headers() {
|
|
327
|
+
return {
|
|
328
|
+
'User-Agent': this.userAgent,
|
|
329
|
+
Accept: 'application/json',
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
/** GET from the REST API (`/api/rest_v1/`). */
|
|
333
|
+
async restGet(language, path, ctx) {
|
|
334
|
+
const base = buildBaseUrl(language);
|
|
335
|
+
const url = `${base}/api/rest_v1${path}`;
|
|
336
|
+
const signal = ctx.signal;
|
|
337
|
+
return withRetry(async () => {
|
|
338
|
+
const response = await fetchWithTimeout(url, 15_000, ctx, {
|
|
339
|
+
headers: this.headers(),
|
|
340
|
+
...(signal && { signal }),
|
|
341
|
+
});
|
|
342
|
+
const text = await response.text();
|
|
343
|
+
if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
|
|
344
|
+
throw serviceUnavailable('Wikipedia REST API returned HTML instead of JSON — likely rate-limited or under maintenance.');
|
|
345
|
+
}
|
|
346
|
+
return JSON.parse(text);
|
|
347
|
+
}, { operation: 'WikipediaService.restGet', context: ctx, baseDelayMs: 1000 });
|
|
348
|
+
}
|
|
349
|
+
/** GET from the Action API (`/w/api.php`). */
|
|
350
|
+
async actionGet(language, params, ctx) {
|
|
351
|
+
const base = buildBaseUrl(language);
|
|
352
|
+
const qs = new URLSearchParams({ format: 'json', formatversion: '2', ...params }).toString();
|
|
353
|
+
const url = `${base}/w/api.php?${qs}`;
|
|
354
|
+
const signal = ctx.signal;
|
|
355
|
+
return withRetry(async () => {
|
|
356
|
+
const response = await fetchWithTimeout(url, 15_000, ctx, {
|
|
357
|
+
headers: this.headers(),
|
|
358
|
+
...(signal && { signal }),
|
|
359
|
+
});
|
|
360
|
+
const text = await response.text();
|
|
361
|
+
if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
|
|
362
|
+
throw serviceUnavailable('Wikipedia Action API returned HTML instead of JSON — likely rate-limited or under maintenance.');
|
|
363
|
+
}
|
|
364
|
+
return JSON.parse(text);
|
|
365
|
+
}, { operation: 'WikipediaService.actionGet', context: ctx, baseDelayMs: 1000 });
|
|
366
|
+
}
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
// Domain methods
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
/** Fetch the REST summary for an article. */
|
|
371
|
+
async getSummary(title, language, ctx) {
|
|
372
|
+
const encodedTitle = encodeURIComponent(title.replace(/ /g, '_'));
|
|
373
|
+
let raw;
|
|
374
|
+
try {
|
|
375
|
+
raw = await this.restGet(language, `/page/summary/${encodedTitle}`, ctx);
|
|
376
|
+
}
|
|
377
|
+
catch (err) {
|
|
378
|
+
// fetchWithTimeout throws a McpError with code NotFound for 404 responses.
|
|
379
|
+
// Match by error code (reliable) rather than message text (fragile).
|
|
380
|
+
if (err instanceof McpError && err.code === JsonRpcErrorCode.NotFound) {
|
|
381
|
+
throw notFound(`No Wikipedia article found for "${title}" in language "${language}". Use wikipedia_search to find the correct title.`, {
|
|
382
|
+
title,
|
|
383
|
+
language,
|
|
384
|
+
recovery: { hint: 'Use wikipedia_search to find the correct article title.' },
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
throw err;
|
|
388
|
+
}
|
|
389
|
+
if (!raw.extract) {
|
|
390
|
+
throw notFound(`Article "${title}" exists but has no readable content.`, { title, language });
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
title: raw.title ?? title,
|
|
394
|
+
pageType: raw.type ?? 'article',
|
|
395
|
+
pageid: raw.pageid,
|
|
396
|
+
wikidataQid: raw.wikibase_item,
|
|
397
|
+
description: raw.description,
|
|
398
|
+
extract: raw.extract,
|
|
399
|
+
thumbnailUrl: raw.thumbnail?.source,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/** Full-text search across Wikipedia articles. */
|
|
403
|
+
async search(query, limit, language, ctx) {
|
|
404
|
+
const raw = await this.actionGet(language, {
|
|
405
|
+
action: 'query',
|
|
406
|
+
list: 'search',
|
|
407
|
+
srsearch: query,
|
|
408
|
+
srlimit: String(Math.min(limit, 50)),
|
|
409
|
+
srprop: 'snippet|wordcount',
|
|
410
|
+
}, ctx);
|
|
411
|
+
const results = raw.query?.search?.map((r) => ({
|
|
412
|
+
title: r.title,
|
|
413
|
+
pageid: r.pageid,
|
|
414
|
+
snippet: stripSnippetHtml(r.snippet),
|
|
415
|
+
wordcount: r.wordcount ?? 0,
|
|
416
|
+
})) ?? [];
|
|
417
|
+
return {
|
|
418
|
+
results,
|
|
419
|
+
totalResults: raw.query?.searchinfo?.totalhits ?? results.length,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
/** Fetch full article plain text via Action API extracts. */
|
|
423
|
+
async getArticleFull(title, language, ctx) {
|
|
424
|
+
const raw = await this.actionGet(language, {
|
|
425
|
+
action: 'query',
|
|
426
|
+
titles: title,
|
|
427
|
+
prop: 'extracts',
|
|
428
|
+
explaintext: 'true',
|
|
429
|
+
exsectionformat: 'wiki',
|
|
430
|
+
}, ctx);
|
|
431
|
+
const pages = raw.query?.pages;
|
|
432
|
+
// When `pages` is absent the API received an empty or invalid title rather than a valid
|
|
433
|
+
// (but missing) article. Map this to not_found — same user-visible outcome.
|
|
434
|
+
if (!pages) {
|
|
435
|
+
throw notFound(`No Wikipedia article found for "${title}" in language "${language}". Use wikipedia_search to find the correct title.`, { title, language });
|
|
436
|
+
}
|
|
437
|
+
const page = Object.values(pages)[0];
|
|
438
|
+
if (!page || page.missing !== undefined) {
|
|
439
|
+
throw notFound(`No Wikipedia article found for "${title}" in language "${language}". Use wikipedia_search to find the correct title.`, { title, language });
|
|
440
|
+
}
|
|
441
|
+
if (!page.extract) {
|
|
442
|
+
throw notFound(`Article "${title}" exists but has no readable content.`, { title, language });
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
title: page.title ?? title,
|
|
446
|
+
pageid: page.pageid,
|
|
447
|
+
content: page.extract,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
/** Fetch a single section's wikitext and strip it to plain text. */
|
|
451
|
+
async getArticleSection(title, sectionIndex, language, ctx) {
|
|
452
|
+
const raw = await this.actionGet(language, {
|
|
453
|
+
action: 'parse',
|
|
454
|
+
page: title,
|
|
455
|
+
prop: 'wikitext',
|
|
456
|
+
section: String(sectionIndex),
|
|
457
|
+
}, ctx);
|
|
458
|
+
if (raw.error) {
|
|
459
|
+
const errCode = raw.error.code ?? '';
|
|
460
|
+
if (errCode === 'nosuchsection') {
|
|
461
|
+
throw validationError(`Section index ${sectionIndex} does not exist in "${title}". Call wikipedia_get_sections to get valid index values.`, {
|
|
462
|
+
title,
|
|
463
|
+
sectionIndex,
|
|
464
|
+
recovery: { hint: 'Call wikipedia_get_sections to obtain valid section_index values.' },
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
if (errCode === 'missingtitle') {
|
|
468
|
+
throw notFound(`No Wikipedia article found for "${title}" in language "${language}". Use wikipedia_search to find the correct title.`, { title, language });
|
|
469
|
+
}
|
|
470
|
+
throw serviceUnavailable(`Wikipedia API error: ${raw.error.info ?? errCode}`);
|
|
471
|
+
}
|
|
472
|
+
// formatversion=2: wikitext is a plain string, not { '*': string }.
|
|
473
|
+
const wikitext = raw.parse?.wikitext ?? '';
|
|
474
|
+
const content = stripWikitext(wikitext);
|
|
475
|
+
// Derive section title from the first heading in the wikitext.
|
|
476
|
+
const headingMatch = /^={2,6}\s*(.+?)\s*={2,6}/m.exec(wikitext);
|
|
477
|
+
const sectionTitle = headingMatch?.[1] ?? `Section ${sectionIndex}`;
|
|
478
|
+
return {
|
|
479
|
+
title: raw.parse?.title ?? title,
|
|
480
|
+
pageid: raw.parse?.pageid,
|
|
481
|
+
sectionTitle,
|
|
482
|
+
content,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
/** Fetch section table of contents for an article. */
|
|
486
|
+
async getSections(title, language, ctx) {
|
|
487
|
+
const raw = await this.actionGet(language, { action: 'parse', page: title, prop: 'sections' }, ctx);
|
|
488
|
+
if (raw.error) {
|
|
489
|
+
const errCode = raw.error.code ?? '';
|
|
490
|
+
if (errCode === 'missingtitle') {
|
|
491
|
+
throw notFound(`No Wikipedia article found for "${title}" in language "${language}". Use wikipedia_search to find the correct title.`, { title, language });
|
|
492
|
+
}
|
|
493
|
+
throw serviceUnavailable(`Wikipedia API error: ${raw.error.info ?? errCode}`);
|
|
494
|
+
}
|
|
495
|
+
const rawSections = raw.parse?.sections ?? [];
|
|
496
|
+
// Fallback: if sections is empty, parse == headers from full-article text.
|
|
497
|
+
if (rawSections.length === 0) {
|
|
498
|
+
const fullArticle = await this.getArticleFull(title, language, ctx);
|
|
499
|
+
const headerPattern = /^(={2,6})\s*(.+?)\s*\1\s*$/gm;
|
|
500
|
+
let idx = 0;
|
|
501
|
+
const fallbackSections = [...fullArticle.content.matchAll(headerPattern)]
|
|
502
|
+
.filter((m) => m[1] && m[2])
|
|
503
|
+
.map((m) => {
|
|
504
|
+
const i = ++idx;
|
|
505
|
+
return { index: i, number: String(i), title: m[2], level: m[1].length };
|
|
506
|
+
});
|
|
507
|
+
return { pageid: fullArticle.pageid, sections: fallbackSections };
|
|
508
|
+
}
|
|
509
|
+
const sections = rawSections
|
|
510
|
+
.filter((s) => s.index !== undefined)
|
|
511
|
+
.map((s) => ({
|
|
512
|
+
index: parseInt(s.index ?? '0', 10),
|
|
513
|
+
number: s.number ?? '',
|
|
514
|
+
title: s.line ?? '',
|
|
515
|
+
level: parseInt(s.level ?? '2', 10),
|
|
516
|
+
}));
|
|
517
|
+
return { pageid: raw.parse?.pageid, sections };
|
|
518
|
+
}
|
|
519
|
+
/** List language editions available for an article. */
|
|
520
|
+
async getLanguages(title, sourceLanguage, ctx) {
|
|
521
|
+
const raw = await this.actionGet(sourceLanguage, {
|
|
522
|
+
action: 'query',
|
|
523
|
+
titles: title,
|
|
524
|
+
prop: 'langlinks',
|
|
525
|
+
lllimit: '500',
|
|
526
|
+
llprop: 'url',
|
|
527
|
+
}, ctx);
|
|
528
|
+
const pages = raw.query?.pages;
|
|
529
|
+
if (!pages)
|
|
530
|
+
throw serviceUnavailable('Unexpected response shape from Wikipedia langlinks API.');
|
|
531
|
+
const page = Object.values(pages)[0];
|
|
532
|
+
if (!page || page.missing !== undefined) {
|
|
533
|
+
throw notFound(`No Wikipedia article found for "${title}" in language "${sourceLanguage}". Use wikipedia_search to find the correct title.`, { title, language: sourceLanguage });
|
|
534
|
+
}
|
|
535
|
+
const languages = page.langlinks?.map((ll) => ({
|
|
536
|
+
languageCode: ll.lang,
|
|
537
|
+
// formatversion=2: title is a plain key, not '*'.
|
|
538
|
+
title: ll.title,
|
|
539
|
+
// url is populated because we pass llprop=url in the request.
|
|
540
|
+
url: ll.url ??
|
|
541
|
+
`https://${ll.lang}.wikipedia.org/wiki/${encodeURIComponent(ll.title.replace(/ /g, '_'))}`,
|
|
542
|
+
})) ?? [];
|
|
543
|
+
return { languages };
|
|
544
|
+
}
|
|
545
|
+
/** Find geotagged Wikipedia articles near a coordinate. */
|
|
546
|
+
async searchNearby(latitude, longitude, radiusMeters, limit, language, ctx) {
|
|
547
|
+
const raw = await this.actionGet(language, {
|
|
548
|
+
action: 'query',
|
|
549
|
+
list: 'geosearch',
|
|
550
|
+
gscoord: `${latitude}|${longitude}`,
|
|
551
|
+
gsradius: String(Math.min(radiusMeters, 10_000)),
|
|
552
|
+
gslimit: String(Math.min(limit, 50)),
|
|
553
|
+
}, ctx);
|
|
554
|
+
const results = raw.query?.geosearch?.map((r) => ({
|
|
555
|
+
title: r.title,
|
|
556
|
+
pageid: r.pageid,
|
|
557
|
+
latitude: r.lat,
|
|
558
|
+
longitude: r.lon,
|
|
559
|
+
distance_meters: r.dist,
|
|
560
|
+
})) ?? [];
|
|
561
|
+
return { results };
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
// Init/accessor pattern
|
|
566
|
+
// ---------------------------------------------------------------------------
|
|
567
|
+
let _service;
|
|
568
|
+
export function initWikipediaService(config, storage, userAgent) {
|
|
569
|
+
_service = new WikipediaService(config, storage, userAgent);
|
|
570
|
+
}
|
|
571
|
+
export function getWikipediaService() {
|
|
572
|
+
if (!_service) {
|
|
573
|
+
throw new Error('WikipediaService not initialized — call initWikipediaService() in setup()');
|
|
574
|
+
}
|
|
575
|
+
return _service;
|
|
576
|
+
}
|
|
577
|
+
//# sourceMappingURL=wikipedia-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wikipedia-service.js","sourceRoot":"","sources":["../../../src/services/wikipedia/wikipedia-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cyanheads/wikipedia-mcp-server",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Search Wikipedia articles, read summaries and full text, target sections, find nearby pages, and list language editions via MCP. STDIO or Streamable HTTP.",
|
|
5
|
+
"mcpName": "io.github.cyanheads/wikipedia-mcp-server",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"wikipedia-mcp-server": "dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"changelog/",
|
|
14
|
+
"dist/",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"CLAUDE.md",
|
|
18
|
+
"AGENTS.md",
|
|
19
|
+
"Dockerfile",
|
|
20
|
+
"server.json"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsx scripts/build.ts",
|
|
24
|
+
"rebuild": "tsx scripts/clean.ts && tsx scripts/build.ts",
|
|
25
|
+
"clean": "tsx scripts/clean.ts",
|
|
26
|
+
"devcheck": "tsx scripts/devcheck.ts",
|
|
27
|
+
"audit:refresh": "rm -f bun.lock && bun install && bun audit",
|
|
28
|
+
"tree": "tsx scripts/tree.ts",
|
|
29
|
+
"list-skills": "tsx scripts/list-skills.ts",
|
|
30
|
+
"format": "biome check --write --unsafe .",
|
|
31
|
+
"lint:mcp": "tsx scripts/lint-mcp.ts",
|
|
32
|
+
"lint:packaging": "tsx scripts/lint-packaging.ts",
|
|
33
|
+
"bundle": "bun run build && npx -y @anthropic-ai/mcpb pack . dist/wikipedia-mcp-server.mcpb",
|
|
34
|
+
"changelog:build": "tsx scripts/build-changelog.ts",
|
|
35
|
+
"changelog:check": "tsx scripts/build-changelog.ts --check",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"start": "node dist/index.js",
|
|
38
|
+
"start:stdio": "MCP_TRANSPORT_TYPE=stdio node dist/index.js",
|
|
39
|
+
"start:http": "MCP_TRANSPORT_TYPE=http node dist/index.js"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"mcp",
|
|
43
|
+
"mcp-server",
|
|
44
|
+
"model-context-protocol",
|
|
45
|
+
"wikipedia",
|
|
46
|
+
"mediawiki",
|
|
47
|
+
"typescript",
|
|
48
|
+
"bun",
|
|
49
|
+
"stdio",
|
|
50
|
+
"streamable-http"
|
|
51
|
+
],
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/cyanheads/wikipedia-mcp-server.git"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/cyanheads/wikipedia-mcp-server#readme",
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/cyanheads/wikipedia-mcp-server/issues"
|
|
59
|
+
},
|
|
60
|
+
"author": "cyanheads <casey@caseyjhand.com> (https://github.com/cyanheads/wikipedia-mcp-server#readme)",
|
|
61
|
+
"license": "Apache-2.0",
|
|
62
|
+
"packageManager": "bun@1.3.11",
|
|
63
|
+
"engines": {
|
|
64
|
+
"bun": ">=1.3.0",
|
|
65
|
+
"node": ">=24.0.0"
|
|
66
|
+
},
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public"
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"@cyanheads/mcp-ts-core": "^0.9.9",
|
|
72
|
+
"pino-pretty": "^13.1.3",
|
|
73
|
+
"wtf_wikipedia": "^10.4.1",
|
|
74
|
+
"zod": "^4.4.3"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@biomejs/biome": "^2.4.7",
|
|
78
|
+
"@types/node": "^25.6.0",
|
|
79
|
+
"depcheck": "^1.4.7",
|
|
80
|
+
"ignore": "^7.0.5",
|
|
81
|
+
"tsc-alias": "^1.8.16",
|
|
82
|
+
"tsx": "^4.19.0",
|
|
83
|
+
"typescript": "^5.9.3",
|
|
84
|
+
"vitest": "^4.1.0"
|
|
85
|
+
}
|
|
86
|
+
}
|