Skip to main content
Glama
manamurah

ManaMurah MCP Server

by manamurah

manamurah-mcp-server

Remote Model Context Protocol (MCP) server for Malaysian PriceCatcher consumer price data. Deployed on Cloudflare Workers. 15 strongly-typed tools for AI agents.

Live endpoint: https://mcp.manamurah.com/mcp (POST, JSON-RPC 2.0)

Data source: data.gov.my PriceCatcher β€” ~3,800 premises Γ— ~756 items across all 16 Malaysian states/territories, collected daily and published as weekly averages. 100% public government data. No credentials needed anywhere in the stack.


Install

The server speaks streamable HTTP at https://mcp.manamurah.com/mcp. Pick the block for your client:

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json on macOS (or %APPDATA%\Claude\claude_desktop_config.json on Windows):

{
  "mcpServers": {
    "manamurah": {
      "command": "npx",
      "args": ["mcp-remote", "https://mcp.manamurah.com/mcp"]
    }
  }
}

Claude Desktop only speaks stdio, so the mcp-remote shim is the bridge. Restart the app β€” you'll see the 15 tools under the πŸ”Œ icon. Ask "harga tembikai di Selangor?" or "what's the cheapest chicken in KL this week?" and Claude will chain search_items β†’ find_cheapest automatically.

Claude Code (CLI)

One command, native streamable HTTP β€” no shim:

claude mcp add manamurah --transport http https://mcp.manamurah.com/mcp

Confirm with claude mcp list. Tools become available the next time you start a Claude Code session. Add --scope user to make it available across every project.

Cursor

User-level (every project): create or edit ~/.cursor/mcp.json. Project-level: <project-root>/.cursor/mcp.json.

{
  "mcpServers": {
    "manamurah": {
      "url": "https://mcp.manamurah.com/mcp"
    }
  }
}

Cursor 0.46+ supports remote MCP via url directly. Reload the window (Cmd-Shift-P β†’ Developer: Reload Window) and the manamurah row appears under Settings β†’ MCP with all 15 tools listed.

Cline (VS Code extension)

Open Cline's sidebar β†’ βš™οΈ β†’ MCP Servers β†’ Add Server β†’ select Remote β†’ paste https://mcp.manamurah.com/mcp β†’ name it manamurah. Cline writes the config to its VS Code global storage itself; no JSON editing needed.

For headless setup, the same JSON shape Claude Desktop uses also works in Cline's cline_mcp_settings.json.

ChatGPT (Custom Connectors)

For ChatGPT Pro / Team / Enterprise: chatgpt.com/connectors β†’ Add custom connector β†’ MCP server URL https://mcp.manamurah.com/mcp β†’ no auth required (public read-only). After approval the connector shows up in the message-input βŠ• menu.

For OpenAI Apps SDK / programmatic use (the codex_apps.manamurah_* tool family in Codex): the server URL field in the app manifest at platform.openai.com/apps must be exactly https://mcp.manamurah.com/mcp β€” not https://manamurah.com (which will fail the streamable transport probe with HTTP 403, since that's the consumer site, not an MCP endpoint).

Other MCP clients

Any client that supports streamable-HTTP MCP transport points directly at https://mcp.manamurah.com/mcp. Stdio-only clients shim via mcp-remote using the same recipe as Claude Desktop above.

Quick smoke test from any shell:

curl -sS -X POST https://mcp.manamurah.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[].name'

You should see fourteen tool names β€” eleven KPDN PriceCatcher tools (weekly cadence) plus three FAMA Panduan Harga Harian tools (daily cadence, three price levels). The richer self-describing manifest (full input schemas + versioning policy) is also a single GET away.

Related MCP server: Azure Pricing MCP Server

Tools

All 15 tools are read-only, public, and capped on response size to keep LLM contexts compact. Every tool carries a detailed description

  • JSON-Schema input so the LLM picks the right one without guessing.

KPDN PriceCatcher (weekly averages)

Retail prices only. ~3,800 premises Γ— ~756 items, collected daily and published as weekly averages from the data.gov.my PriceCatcher dataset.

Tool

Purpose

search_items

Find items by name in Malay / English / Chinese / Tamil

find_cheapest

Up to 10 cheapest premises for one item this week

price_history

Weekly price trend at national/state/district/chain/urban

nearby_premises

Premises within a geographic radius of a coordinate

compare_prices

One item's price across national + state + district + more

list_chains

Directory of retail chains + premise counts + coverage

price_change

Delta between current week and 1 / 3 / 6 / 12 months ago

top_movers

Biggest weekly risers + fallers

category_trends

Per-category movement over a window

basket_watch

Total cost for a 1–20 item basket over time

region_gap

Semenanjung vs Borneo top-N price gap, both directions

FAMA daily prices (Panduan Harga Harian)

Three price levels β€” RUNCIT (retail), BORONG (wholesale), LADANG (farm-gate) β€” tracked daily and independently. ~46 items (fresh produce, eggs, poultry). FAMA's catalogue is independent of PriceCatcher: item_id here is FAMA's own 1..46, not the KPDN item_code.

Tool

Purpose

fama_price_history

Daily series for one item at chosen level + geographic grain

fama_margin

LADANG β†’ BORONG β†’ RUNCIT value-chain spread per day

fama_top_movers

Daily movers per level, anchored on latest index date

fama_margin and fama_top_movers reject grain='daerah' because LADANG/BORONG coverage at daerah grain is too sparse for an honest cut. fama_price_history accepts daerah for retail-only callers.

All tools require zero setup beyond the MCP config above. No API keys. No rate limiting on the client side (upstream has a 12h KV edge cache so repeat queries are essentially free).

Example conversation

You: Berapa harga tembikai merah tanpa biji di Selangor minggu ini?

Claude (calls search_items(query="tembikai") β†’ gets item_code 21 β†’ calls find_cheapest(item_code=21, state="Selangor")):

Tembikai merah tanpa biji di Selangor untuk minggu 2026-04-20: hanya ada 1 kedai yang melaporkan data PriceCatcher β€” Jaya Grocer D'Pulze Cyberjaya di daerah Sepang pada RM 5.20/kg. Data lain di KL menunjukkan NSK Seputeh/Cheras/Kepong menjual tembikai serupa pada RM 1.69/kg β€” mungkin berbaloi keluar PJ/KL jika anda di Selangor Selatan.

The structured response the LLM worked from:

{
  "item_code": 21,
  "item_name": "TEMBIKAI MERAH TANPA BIJI",
  "weekdate": "2026-04-20",
  "results": [
    {
      "weekdate": "2026-04-20",
      "price": 5.20,
      "premise_name": "JAYA GROCER D`PULZE CYBERJAYA",
      "chain": "JAYA GROCER",
      "chain_type": "SUPERMARKET",
      "state": "Selangor",
      "district": "Sepang"
    }
  ],
  "scope": { "state": "Selangor", "district": null, "chain": null, "chain_type": null },
  "status": "ok",
  "reason": null,
  "warnings": []
}

Architecture

 Claude Desktop ─ stdio ─ mcp-remote ─ HTTPS ─ mcp.manamurah.com
                                                    β”‚
                                               (Cloudflare Worker, this repo)
                                                    β”‚
                                                  fetch
                                                    β–Ό
                                        manamurah.com/api/v2/mcp/*
                                                    β”‚
                                               (SvelteKit site +
                                                Cloudflare KV edge cache,
                                                12h TTL)
                                                    β”‚
                                                    β–Ό
                                            public price data

This Worker is a thin protocol shim β€” it speaks MCP JSON-RPC on one side and standard fetch() on the other. No business logic, no credentials, no database binding. Every tool call goes to exactly one upstream /api/v2/mcp/<tool> endpoint and passes the JSON response through.

Keeping the shim thin means:

  • The ~400 lines here are almost all tool-description JSON.

  • Query/caching/index logic lives upstream where it's co-located with the data layer.

  • Updating a tool's behaviour rarely requires a Worker redeploy.

Self-host / fork

git clone https://github.com/manamurah/mcp-server
cd mcp-server
pnpm install

# Local dev β€” hot-reloads on src/ changes, binds to 127.0.0.1:8787
pnpm dev

# Exercise it:
curl -sS -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[].name'

# Deploy to your own Cloudflare account:
pnpm deploy

To point at a staging copy of the upstream (useful when manamurah_20240322 ships new /api/v2/mcp/* endpoints), override the base URL in wrangler.toml:

[vars]
MANAMURAH_API_BASE = "https://staging.manamurah.com"

Protocol notes

  • Transport: HTTP POST at /mcp, JSON-RPC 2.0. CORS-open so browser-based MCP clients work without a proxy.

  • Methods supported: initialize, tools/list, tools/call, prompts/list, prompts/get, resources/list, resources/read, resources/templates/list, completion/complete, ping.

  • Tool response shape: MCP content: [{ type: "text", text: ... }] blocks with the raw JSON payload also attached as structuredContent for clients that prefer it.

  • Error handling: business-level issues (invalid args, no data for this week) come back as { "status": "no_data", "reason": ... } at HTTP 200 so the LLM can narrate them. Only transport/infra failures raise JSON-RPC errors.

  • Upstream errors: 5xx on /api/v2/mcp/* bubbles up as JSON-RPC code: -32603 with the upstream status in data. 4xx passes through unchanged (client validation error already shaped as a JSON envelope on the upstream side).

  • manamurah-mcp-2026 β€” Python stdio MCP server covering the same 15 tools. Use this instead if you want a local-only MCP binary (no Cloudflare, no Worker hop).

  • manamurah_20240322 β€” the SvelteKit site at manamurah.com. Hosts both the public website and the /api/v2/mcp/* proxy endpoints this Worker calls.

  • manamurah-data-2026 β€” the Python ETL that populates the indices behind everything else. Nightly pipeline, data.gov.my PriceCatcher source of truth.

License

MIT. See LICENSE.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol server that enables programmatic querying of Azure resource pricing information from the Azure Retail Prices API through a structured four-step workflow.
    8
    -
  • F
    license
    B
    quality
    D
    maintenance
    A Model Context Protocol server that provides real-time cryptocurrency price fetching capabilities using the CoinGecko API. It enables LLMs to retrieve and process the latest price for any coin by its name or symbol.
    2
    -
  • A
    license
    A
    quality
    C
    maintenance
    A Model Context Protocol server for real-time Swiss grocery shopping that searches and compares products across 8 major Swiss retailers (Migros, Coop, Aldi, Denner, Lidl, Farmy, Volgshop, Otto’s), normalizes per-unit prices, surfaces promotions, computes optimal multi-store shopping plans, and works with any MCP-compatible client without API keys or accounts.
    7
    82 npm
    30
    AGPL 3.0