Skip to main content
Glama
Rayyan011

maldives-statistics-mcp

by Rayyan011
README.md
# Maldives Statistics MCP

A read-only, standard-stdio [Model Context Protocol](https://modelcontextprotocol.io/) server for public information from the [Maldives Bureau of Statistics](https://statisticsmaldives.gov.mv/). The site is a WordPress installation; this server uses its public WordPress pages and REST endpoints, plus public PDF attachments, without authentication.

The server is written in **TypeScript** and runs on **Node.js** using the official `@modelcontextprotocol/sdk`. It is model- and harness-agnostic: the same built process can be registered with any MCP host that supports local stdio servers.

## Features

- Public reachability/status check for the Bureau of Statistics website.
- Search across WordPress posts and pages.
- Paginated page and post listings.
- Readable page content with links to public PDFs.
- Publication, press-release, statistics-section, jobs, and event discovery.
- Bounded inspection of same-host attachments, with optional built-in PDF text extraction (first 20,000 characters).
- Exact-host allowlisting for `statisticsmaldives.gov.mv`.
- Structured, machine-readable errors and JSON-serializable tool results.
- No credentials, cookies, authentication headers, or write operations.

## Tool reference

The server exposes exactly the following 18 tools. Parameter defaults are part of the public contract in [`SPEC.md`](SPEC.md).

| Tool | Description | Key parameters |
| --- | --- | --- |
| `mbs_status` | Check site reachability and return HTTP status, page title, and UTC check time. | None |
| `mbs_search` | Search the WordPress search endpoint across posts and pages. | `query: string`, `per_page: number = 10` |
| `mbs_list_pages` | List report and other WordPress pages, optionally filtered and paginated. | `search: string = ""`, `per_page: number = 20`, `page: number = 1` |
| `mbs_list_posts` | List news/release WordPress posts, optionally filtered and paginated. | `search: string = ""`, `per_page: number = 20`, `page: number = 1` |
| `mbs_get_page` | Fetch one page by WordPress slug or an allowlisted full URL; return readable text and PDF links. | `slug_or_url: string` |
| `mbs_publications` | Parse the public publications index and return report-page links. | None |
| `mbs_press_releases` | Parse the public press-release page and return release links and direct PDF file URLs when available. | `limit: number = 20` |
| `mbs_sections` | Return the curated list of public statistics sections and their full URLs. | None |
| `mbs_yearbook_editions` | List Statistical Yearbook editions (2005–present) with URLs. | None |
| `mbs_yearbook_tables` | List a yearbook edition's tables (chapter + label + PDF/XLS links), optionally filtered by keyword. | `year: number`, `query: string = ""` |
| `mbs_census_releases` | List census release pages (e.g. Census 2022 statistical releases). | `limit: number = 20` |
| `mbs_economic_survey` | List Economic Survey report pages and PDFs. | None |
| `mbs_downloads` | List public downloads (forms and documents). | `limit: number = 20` |
| `mbs_updates` | List dated update posts (latest statistical releases). | `limit: number = 10`, `page: number = 1` |
| `mbs_jobs` | Parse the jobs page for main-content job links. | `limit: number = 20` |
| `mbs_events` | List events from the public WordPress `event` endpoint, including available ACF fields. | `per_page: number = 10` |
| `mbs_attachment` | Inspect an allowlisted public file with bounded HEAD/GET behavior; optionally extract the first 20,000 characters of a PDF. | `url: string`, `extract_text: boolean = false` |
| `mbs_xlsx_table` | Download and parse an allowlisted .xlsx (e.g. yearbook table) into rows of cell values. | `url: string`, `max_rows: number = 200` |

Errors use the structured shape `{"error": "<machine-readable reason>", "detail": "<human message>"}`. The documented reasons include `unreachable`, `http_error`, `no_results`, `invalid_url`, `blocked_url`, `parse_failed`, and `too_large`.

## Quickstart

Requirements: Node.js 20+ and npm.

From the repository root:

```bash
npm install
npm run build
npm start        # runs node dist/server.js
```

`dist/server.js` speaks MCP over stdio. Keep stdout available for protocol traffic; diagnostics go to stderr. PDF text extraction in `mbs_attachment` uses a small built-in extractor (uncompressed or zlib-inflated text streams); PDFs without extractable text return `"text": null` rather than failing the tool.

The examples below use this placeholder:

- `<REPO_ROOT>` — the absolute path to this checkout, such as `/path/to/maldives-statistics-mcp`.

Replace the placeholder before using a configuration. Do not put credentials in any MCP configuration for this server.

## Registering with MCP hosts

All examples launch the same local stdio process: `node <REPO_ROOT>/dist/server.js` (use an absolute path to the `node` binary if it is not on the host's PATH). Client configuration schemas and command names can change between releases; consult the host's current documentation if your installed version differs.

### Claude Desktop — `claude_desktop_config.json`

Add the server under `mcpServers` in Claude Desktop's configuration file:

```json
{
  "mcpServers": {
    "maldives-statistics": {
      "command": "node",
      "args": ["<REPO_ROOT>/dist/server.js"]
    }
  }
}
```

Restart or reload Claude Desktop after saving the file.

### Claude Code

Register the command from a shell:

```bash
claude mcp add maldives-statistics -- node <REPO_ROOT>/dist/server.js
```

Use the host's MCP listing command to confirm that `maldives-statistics` is registered.

### Codex CLI

A local stdio server can be added with the Codex CLI command form:

```bash
codex mcp add maldives-statistics -- node <REPO_ROOT>/dist/server.js
```

The equivalent project/user configuration, where supported, is conceptually:

```toml
[mcp_servers.maldives-statistics]
command = "node"
args = ["<REPO_ROOT>/dist/server.js"]
```

### Cursor

In Cursor's MCP settings or `.cursor/mcp.json`, add:

```json
{
  "mcpServers": {
    "maldives-statistics": {
      "command": "node",
      "args": ["<REPO_ROOT>/dist/server.js"]
    }
  }
}
```

### Gemini CLI

In the applicable Gemini CLI `settings.json` (commonly `~/.gemini/settings.json`), add the server under `mcpServers`:

```json
{
  "mcpServers": {
    "maldives-statistics": {
      "command": "node",
      "args": ["<REPO_ROOT>/dist/server.js"]
    }
  }
}
```

Merge this object into an existing settings file rather than replacing unrelated settings.

### Windsurf

In Windsurf's MCP configuration (commonly `~/.codeium/windsurf/mcp_config.json`), use the standard `mcpServers` shape:

```json
{
  "mcpServers": {
    "maldives-statistics": {
      "command": "node",
      "args": ["<REPO_ROOT>/dist/server.js"]
    }
  }
}
```

### Cline / Roo Code

In the relevant MCP settings JSON for Cline or Roo Code, add this entry to `mcpServers`:

```json
{
  "mcpServers": {
    "maldives-statistics": {
      "command": "node",
      "args": ["<REPO_ROOT>/dist/server.js"],
      "disabled": false
    }
  }
}
```

The exact settings-file location is controlled by the extension and editor profile; the server entry itself is a local stdio command.

### VS Code

Create or edit `.vscode/mcp.json` (or the user MCP configuration) with VS Code's `servers` schema:

```json
{
  "servers": {
    "maldives-statistics": {
      "type": "stdio",
      "command": "node",
      "args": ["<REPO_ROOT>/dist/server.js"]
    }
  }
}
```

### Hermes Agent

Hermes Agent is one option among many MCP hosts. Register the same stdio command with:

```bash
hermes mcp add maldives-statistics --command /usr/bin/node --args <REPO_ROOT>/dist/server.js
```

After registration, use the host's MCP test/list facility and start a new session if the host injects tools only at session start.

### Generic stdio clients

For a client that accepts a command and argument array, use:

```json
{
  "name": "maldives-statistics",
  "transport": "stdio",
  "command": "node",
  "args": ["<REPO_ROOT>/dist/server.js"]
}
```

The equivalent shell command is:

```bash
node <REPO_ROOT>/dist/server.js
```

The client must own the process's stdin/stdout and speak the MCP stdio protocol. Do not pipe ordinary logs into stdout.

## Testing

Run the protocol tests from the repository root (build first):

```bash
npm run build
npm test
```

The default suite includes live checks against the public website. To skip live network checks while still exercising initialization, tool discovery, and the blocked-URL safety path:

```bash
MBS_OFFLINE=1 npm test
```

A successful live run verifies MCP initialization, discovery of all 18 tools, status, search, publications, a page lookup, attachment handling, yearbook tables, XLSX parsing, census releases, economic survey, downloads, and updates. Network availability and the remote site's current content can affect live checks.

## Limitations

- **Read-only:** this server only reads public content. It does not authenticate, submit forms, upload files, create or modify records, or write to the website.
- **The `.Stat` data portal is unavailable:** `https://data.statisticsmaldives.gov.mv/` currently has a broken TLS certificate and is intentionally not used.
- **Source format:** data is obtained from public WordPress pages, WordPress REST responses, and PDF attachments on the Bureau's site; it is not a replacement for the Bureau's official source documents.
- **Jobs may be sparse:** the jobs page may contain few or no extractable job links at a given time. In that case `mbs_jobs` returns an empty list and a note when available.
- **Remote dependency:** live results depend on the public site's reachability, HTTP behavior, page structure, and current content.
- **Bounded extraction:** attachment downloads and extracted PDF text are intentionally size-limited. PDF text extraction is minimal (uncompressed/inflated text streams only); scanned or exotic PDFs return `"text": null`.
- **Exact host allowlist:** only `statisticsmaldives.gov.mv` is accepted for fetches, including attachment inspection. Off-host links are not followed.

## License

This project is released under the [MIT License](LICENSE). Copyright 2026 Maldives Statistics MCP contributors.

TDQS

A3.8/5.0

Scored across 18 tools

Disambiguation5/5

Each tool targets a clearly distinct content type or action: status checks, search, page/post retrieval, and specialized lists for publications, press releases, yearbook tables, jobs, events, etc. Even overlapping list tools are differentiated by the specific section they address, such as census releases versus economic survey.

Naming Consistency4/5

All tools use the 'mbs_' prefix and snake_case, which is consistent. However, there is a mix of verb-led names (mbs_status, mbs_search, mbs_list_*, mbs_get_page) and noun-only names (mbs_publications, mbs_jobs, mbs_events, etc.), which is a minor inconsistency but not chaotic.

Tool Count4/5

With 18 tools, the server is on the heavier side but still well-scoped for a statistics portal that covers multiple content categories. The count is justified by the variety of distinct resources exposed, and there is no obvious bloat or redundancy.

Completeness5/5

The tool surface comprehensively covers the domain of browsing and retrieving content from the Maldives Bureau of Statistics site: search, page/post retrieval, specialized listings, attachment inspection, and XLSX parsing. It covers both metadata and data extraction, leaving no major dead ends for typical use cases.

Maintenance

ActivitySlowing
ResponsivenessNo issues