
Connects Claude directly to Wikipedia's MediaWiki REST and Action APIs across all language editions. Exposes full-text search, article summaries with Wikidata QIDs, targeted section reads, geospatial article lookup, and language edition enumeration. Built on cyanheads' mcp-ts-core framework, so you get declarative tool definitions, structured error handling with recovery hints, and dual transport support (stdio and streamable HTTP). The wikitext stripping pipeline uses wtf_wikipedia to deliver clean plain text while preserving section structure. Reach for this when you need encyclopedic lookups without API keys, want to cross-reference Wikidata entities, or need to work across non-English Wikipedia editions in a single session.
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 toolquery (an empty one fails with empty_query), limit 1–50, and offset paging, passing back enrichment nextOffset. Wikipedia serves no result past the 10,000th: an offset at or beyond it fails with offset_too_large, and a page ending on that window carries enrichment truncateddescription and Wikidata QID (wikibase_item); enrichment suggestion carries Wikipedia's spelling correction (einstien → einstein)wikipedia_get_summary tooltitle; returns the REST summary extract — a fragment from the start of the lead (wikipedia_get_article with section_index: 0 reads the whole lead) — plus the short description, thumbnail URL, Wikidata QID (wikibase_item), and, for a geotagged article, latitude / longitude to pass straight to wikipedia_search_nearbypage_type discriminates standard / disambiguation / no-extract (on disambiguation, re-query with wikipedia_search_articles); url, revision_id, and last_modified name the revision read, and ?oldid=<revision_id> is a permanent link to itwikipedia_get_article toolsection_index: the full article with == Section == markers, or a section outline (truncated: true) when it exceeds WIKIPEDIA_ARTICLE_OVERFLOW_BYTES (default 80,000 bytes). With a section_index from wikipedia_get_sections (0 is the lead): that section plus its nested subsectionsurl and revision_id (?oldid=<revision_id> is a permanent link to the text read); a full read, outline included, also returns last_modified. With WIKIPEDIA_BASE_URL set, a section read omits urllabel: value lines, which the full-article extract strips; a table over 40,000 rendered bytes leaves a [table omitted: N rows] markerwikipedia_get_sections tooltitle; returns section titles, heading levels, hierarchical numbering (e.g. "2.1"), and the section_index to pass to wikipedia_get_article — the first entry is the lead (index: 0, titled Introduction)no_sections on a stub or very short article — read it with wikipedia_get_article insteadwikipedia_search_nearby toollatitude / longitude (WGS 84), radius_meters 10–10,000 (default 1000), and limit 1–500 (default 10), with no pagination past limit; enrichment truncated flags more matches than limit allowed — at 500, Wikipedia's ceiling, sweep narrower radii insteaddistance_meters, with coordinates, short description, and Wikidata QID (wikibase_item). Each is placed by the article's own GeoData coordinate tag, not its Wikidata item's coordinate, so a mistagged article appears where the tag puts itwikipedia_get_languages tooltitle; returns each edition's language_code, edition_code, article title, and URL, plus source_title, the resolved title. Pass edition_code — not language_code — as language on other tools; the two can differ (gsw vs als)editions narrows the list to the codes asked for: codes with no article come back under missing, and total_languages stays the unfiltered count. Fails with no_other_languages when the article has no translations; a filter matching nothing is an empty list, not a failureBuilt 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 (default en) — all Wikipedia language editions accessible in a single session; every title read follows redirectsaction=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.6 (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 |
LOG_TOOL_FAILURE_PAYLOADS | Log each failed tool call's arguments and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). A secret inside a free-form value is not redacted. | false |
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.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.