
Search Wikipedia, read summaries and full text, target sections, find nearby pages, list languages.
Search Wikipedia articles, read summaries and full text, target sections, find nearby pages, and list language editions via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://wikipedia.caseyjhand.com/mcp
Wikipedia content via the MediaWiki REST API and Action API. Search articles, read summaries or targeted sections, find geotagged pages near a coordinate, and list language editions from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
wikipedia_search_articles | Full-text search across Wikipedia, returning ranked results with short descriptions, Wikidata QIDs, plain-text snippets, and page IDs, plus Wikipedia's spelling suggestion. |
wikipedia_get_summary | Short summary for any article — plain text, Wikidata QID, description, thumbnail URL, page type, canonical URL, revision, and coordinates. |
wikipedia_get_article | Full article or a targeted section as clean plain text, with section markers preserved, the canonical URL, and the revision it was read from. |
wikipedia_get_sections | Table of contents with section_index values for targeted section reads. |
wikipedia_search_nearby | Geotagged Wikipedia articles within a radius of a WGS 84 coordinate, sorted by distance, with short descriptions and Wikidata QIDs. |
wikipedia_get_languages | All language editions available for an article, with titles and URLs, or just the editions you ask for. |
wikipedia_search_articles tooldescription and Wikidata QID (wikibase_item) when it has them, from one follow-up lookup per page of results. That lookup is best-effort: if it fails, the results still come back without the two fields and the notice says sosuggestion carries Wikipedia's spelling correction whenever it has one (einstien → einstein), and a zero-hit first page names it in the notice — re-run with it as querylimit is 1–50; offset pages further results — enrichment nextOffset signals more remain and is passed back as offsetoffset at or beyond it fails with offset_too_large, and a page ending on the window carries enrichment truncated naming the matches no offset reaches — narrow the query to bring them into rangequery fails with empty_query; a whitespace-only query is a real search that simply matches nothinglanguage selects any Wikipedia edition (default en)wikipedia_get_summary toolwikibase_item), short description, and thumbnail URLurl is the canonical article URL, and revision_id / last_modified name the revision the extract was read from — ?oldid=<revision_id> is a permanent link to it10²³, H₂O), rendered the same way as on wikipedia_get_articlelatitude / longitude are present for a geotagged article and pass straight to wikipedia_search_nearby, whose inputs carry those names; both are absent otherwisewikipedia_get_article with section_index: 0page_type discriminates standard / disambiguation / no-extract — on disambiguation, re-query with wikipedia_search_articles for a more specific titlewikipedia_get_article for full depthwikipedia_get_article toolsection_index: full article with == Section == markers, unless it exceeds WIKIPEDIA_ARTICLE_OVERFLOW_BYTES (default 80,000 bytes) — then returns a section outline (truncated: true) pointing to wikipedia_get_sections plus a targeted section_index readsection_index (from wikipedia_get_sections): returns that section plus every nested subsection, each heading above its own bodysection_index: 0 is the lead section — the text above the first heading, returned under the title Introduction| --- |, then one line per row; rowspan cells repeated) and infoboxes as label: value lines; a table over 40,000 rendered bytes leaves a [table omitted: N rows] marker. The full-article path carries no tables or infoboxes — upstream extracts strip them — so read the section for those10²³, mol⁻¹, H₂O, or ^x / _x where a character has no Unicode form. An abbreviation's superscript stays joined, as the edition writes it in plain text (French XIXe siècle, 1er, Mme)url (the canonical article URL) and revision_id (the revision the text was read from — ?oldid=<revision_id> is a permanent link to it); a full read, outline included, also returns last_modified, that revision's timestamp. For a redirect, all three name the target article. With WIKIPEDIA_BASE_URL set, a section read omits url, since the mirror's article path is unknownwikipedia_get_sections tool"2.1"), and section_index valuesindex: 0, titled Introduction — Wikipedia's own table of contents starts at the first headingsection_index is the integer to pass to wikipedia_get_article for a targeted readno_sections on a stub or very short article — read it with wikipedia_get_article insteadwikipedia_search_nearby tooldistance_meters, and each article's short description and Wikidata QID (wikibase_item) when it has themradius_meters: 10–10,000 (default 1000); limit: 1–500 (default 10) — no pagination past limit, so raise it or sweep narrower radii for full coveragedescription usually gives it away (Palazzo Bernardo Nani — "Palace on the Grand Canal, Venice" — 161 m from the Eiffel Tower)truncated flags when more articles matched than limit allowed; at limit: 500, Wikipedia's ceiling, a full page reports truncated and the notice points to narrower sweeps rather than a higher limitwikipedia_get_languages toollanguage_code, tool-usable edition_code (can differ, e.g. gsw vs als), article title, and URLedition_code — not language_code — as the language parameter on other toolseditions narrows the answer to the codes asked for, matched against both edition_code and language_code; requested codes with no article come back under missing, and total_languages stays the unfiltered count. A popular article lists hundreds of editions, so the filter is the difference between a 40 KB reply and a 1 KB oneno_other_languages when the article has no translations — a filter that matches nothing is a normal response with an empty list, not a failuresource_title reports the resolved titleBuilt on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Wikipedia-specific:
/api/rest_v1/) for summaries, Action API (/w/api.php) for search, full text, sections, geo search, and language linksRetry-After honored and each request's retries bounded at 30 s. The best-effort description lookup on search results gets one short attempt; User-Agent header per Wikimedia API policy== Heading == markers, one list item per line, superscripts kept, code fenced: the full article from the Action API's HTML extract, a section from the parser's own HTML for that section, the summary from the REST extract_html. A section read additionally carries data tables, infoboxes, and the lists inside layout tables, none of which the extract carrieslanguage parameter on every tool — all Wikipedia language editions accessible in a single sessionaction=sitematrix endpoint (cached 24h) — catches structurally valid but nonexistent editions before they cause timeoutsAgent-friendly output:
page_type on summaries discriminates standard / disambiguation / no-extract — no string parsing neededwikibase_item (Wikidata QID) on summaries and on search and nearby results enables direct cross-referencing with wikidata-mcp-servercontent[] render, so an article that writes about markup or markdown syntax reads as itself instead of being interpreted by the client; structuredContent carries the same text unescaped. Fenced code blocks and table-row delimiters pass through unescaped, while table cells stay escapedsection_index on table-of-contents entries links directly to the targeted-read parameter on wikipedia_get_article, index 0 included< > [ ] { }, the | multi-title separator, percent escapes, magic tildes, relative paths — are refused before any request, with invalid_title; a trailing #fragment is accepted and resolves normallywikipedia_search_articles to find the correct title")A public instance is available at https://wikipedia.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"wikipedia-mcp-server": {
"type": "streamable-http",
"url": "https://wikipedia.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file.
{
"mcpServers": {
"wikipedia-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/wikipedia-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"wikipedia-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/wikipedia-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"wikipedia-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/wikipedia-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/wikipedia-mcp-server.git
cd wikipedia-mcp-server
bun install
cp .env.example .env
# edit .env if you want to customize WIKIPEDIA_USER_AGENT or logging
| Variable | Description | Default |
|---|---|---|
WIKIPEDIA_USER_AGENT | User-Agent header sent with every Wikimedia API request. Customize for your deployment. | wikipedia-mcp-server/0.2.5 (https://github.com/cyanheads/wikipedia-mcp-server) |
WIKIPEDIA_BASE_URL | Optional single-instance override. Unset (default): compose per-language hosts, language selects the edition per call. Set to a full base URL (e.g. a private MediaWiki mirror): route every call at that one fixed host — language no longer varies it. | (unset) |
WIKIPEDIA_ARTICLE_OVERFLOW_BYTES | Byte budget above which a full-article read (wikipedia_get_article without section_index) returns a section outline instead of the full text. Tuned for this domain — ordinary articles stay whole; only genuine mega-articles (World War II ~86 KB, United States ~94 KB) outline. Section-targeted reads are never affected. | 80000 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto (which resolves to stateful). The Docker image ships stateless. | auto |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry instrumentation (spans, metrics, completion logs). | false |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t wikipedia-mcp-server .
docker run --rm -p 3010:3010 wikipedia-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/wikipedia-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and inits the Wikipedia service. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts) — one file per tool. |
src/services/wikipedia | WikipediaService — REST API + Action API client with retry/backoff and language validation. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/mcp-server/tools/definitions/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.