For agents & developers
Connect to the
laparku MCP server.
laparku-menus exposes an MCP (Model Context Protocol) server over Streamable HTTP, so any MCP client โ Claude Code, Claude Desktop, an agent you write โ can search Brunei's crowdsourced food dataset and file menu submissions.
The endpoint
One URL, POST-only, JSON-RPC over Streamable HTTP:
https://laparku-menus.bbdl.workers.dev/mcp
Requests must send Accept: application/json, text/event-stream and
Content-Type: application/json. The server is stateless โ no session
cookies, no resumable streams. Each request creates and tears down a session
inside one response.
curl -s -X POST https://laparku-menus.bbdl.workers.dev/mcp \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
Client configs
1Claude Code
From a terminal, register it as an HTTP server:
claude mcp add --transport http laparku-menus \
https://laparku-menus.bbdl.workers.dev/mcp
2Claude Desktop / other MCP clients
For clients that only launch stdio servers locally, point them at a
stdio-to-HTTP bridge such as mcp-remote and give it the endpoint URL:
{
"mcpServers": {
"laparku-menus": {
"command": "npx",
"args": ["mcp-remote", "https://laparku-menus.bbdl.workers.dev/mcp"]
}
}
}
3From your own code
Use any MCP client SDK in Streamable-HTTP mode. With the official TypeScript SDK:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(new StreamableHTTPClientTransport(
new URL("https://laparku-menus.bbdl.workers.dev/mcp"),
));
const { tools } = await client.listTools();
const result = await client.callTool({
name: "search_items",
arguments: { query: "nasi katok", filters: { area: "Brunei-Muara" } },
});
Available tools
Read tools are public โ no authentication needed. Write tools take your API
key as a tool argument called api_key.
| Tool | Auth | What it does |
|---|---|---|
search_items |
public |
Full-text search over published items and venues.
Args: query (string, required), filters โ
venue_type, item_type (dish|product),
area, halal, tag,
max_price (BND).
|
list_venues |
public |
List published venues.
Args: filters โ type, area,
halal, q.
|
get_venue_items |
public |
The current published menu of one venue.
Args: venue_id (required).
|
submit_menu |
api_key |
File a submission for human review โ nothing publishes without
approval. Args: api_key, payload with
source_type (menu_pdf, menu_photo, product_photo,
barcode, url, manual_entry), provenance (where the data
came from โ required), optional contact,
files (base64 jpeg/png/webp/pdf) or
items (manual_entry only).
|
get_submission_status |
api_key |
Check one of your own submissions โ a key only sees what it filed.
Args: id (from submit_menu), api_key.
|
Valid enum values โ area: Brunei-Muara, Tutong, Belait,
Temburong. venue_type: restaurant, stall, supermarket,
grocer, convenience. halal: halal-certified, muslim-owned,
non-halal, unknown, n-a.
Getting an API key
Keys belong to a submitter account, which is how submissions and reputation are attributed:
- Open the menu app and sign in โ magic link, no password.
-
Create a key via the auth API while signed in:
curl -s -X POST https://laparku-menus.bbdl.workers.dev/api/auth/api-key/create \ -H 'Content-Type: application/json' \ -H 'Cookie: <your session cookie>' \ -d '{"name":"my-agent"}' -
Pass the returned key as the
api_keyargument tosubmit_menuandget_submission_status. Keep it secret โ it identifies you.
Build something on it
The dataset is open and growing โ a diet coach that plans hawker meals, a grocery price tracker, a meal-planner that knows what's nearby. If your app needs a tool that doesn't exist yet, open an issue.