Skip to main content
Glama
vienneje
by vienneje

foodpanda-mcp (Hong Kong fork)

An MCP server that lets an AI assistant search restaurants, browse menus, build a cart and place foodpanda orders on your behalf.

This is a fork of johnwhoyou/foodpanda-mcp, which targets foodpanda.ph only. Upstream hardcodes the Philippine API host, locale and currency, so it cannot talk to any other country. This fork makes the region a configuration value and ships a Hong Kong preset (plus a working PH preset), and replaces the bare fetch() transport with one that runs inside a real browser context — necessary because fd-api sits behind a PerimeterX bot wall.

Nothing personal is baked in: delivery coordinates, session token and region all come from environment variables.

What changed vs upstream

Area

Upstream

This fork

API host

hardcoded https://ph.fd-api.com

src/config.ts preset per country, env-overridable

Storefront / login / payment redirect

hardcoded foodpanda.ph

preset (foodpanda.hk for HK), env-overridable

Locale and language id

en_PH, language_id=1

configurable (en_HK, configurable id)

Currency

PHP baked into baskets, purchase intents and checkout

from config (HKD for HK)

GraphQL persisted-query hashes

PH constants

env-overridable + scripts/discover-hashes.mjs to harvest a region's own hashes

HTTP transport

bare fetch()

browser-context transport, so requests carry the _px3 clearance cookie

PerimeterX failures

surfaced as a misleading "session expired"

detected and reported for what they are

Login

its own throwaway browser profile

shares the transport's persistent context, so login cookies and PX clearance are reused

Related MCP server: doordash-mcp

Requirements

  • Node.js 20 or newer

  • npx playwright install chromium (the transport and the login flow both need a browser)

  • Xvfb on a headless machine — the browser must run headed to clear PerimeterX, and the transport starts its own Xvfb when DISPLAY is unset (apt-get install xvfb)

  • A foodpanda account in the region you configure, with the delivery address you intend to use already saved in that account (checkout picks the saved address nearest your configured coordinates)

Install

1. Get the code and build it

git clone https://github.com/vienneje/foodpanda-mcp-hk.git
cd foodpanda-mcp-hk
npm install --ignore-scripts     # --ignore-scripts skips the bundled Chrome download
npx tsc -p tsconfig.json         # produces build/
npx playwright install chromium  # the full Chromium build, used in new-headless mode

The transport launches Chromium with channel: "chromium" (the full build, new headless mode), so Playwright's separate chromium-headless-shell download is not needed. If you prefer the headless shell, set FOODPANDA_BROWSER_CHANNEL= (empty) and run npx playwright install chromium-headless-shell instead.

2. Hermes Agent

Add a server entry to ~/.hermes/config.yaml (or $HERMES_HOME/config.yaml):

mcp_servers:
  foodpanda:
    command: "node"
    args: ["/path/to/foodpanda-mcp-hk/build/index.js"]
    env:
      FOODPANDA_COUNTRY: "hk"
      FOODPANDA_LATITUDE: "22.2793"      # your delivery coordinates
      FOODPANDA_LONGITUDE: "114.1628"
      # FOODPANDA_GQL_SEARCH_HASH: "..."      # see "Harvest the region's hashes"
      # FOODPANDA_GQL_VENDOR_LIST_HASH: "..."
    timeout: 180
    connect_timeout: 60

MCP subprocesses do not inherit your shell environment, so every setting must be listed under env:. Restart Hermes (MCP servers are connected at startup, there is no hot reload); the tools then appear as mcp_foodpanda_*.

3. Claude Desktop or any other stdio MCP client

{
  "mcpServers": {
    "foodpanda": {
      "command": "node",
      "args": ["/path/to/foodpanda-mcp-hk/build/index.js"],
      "env": {
        "FOODPANDA_COUNTRY": "hk",
        "FOODPANDA_LATITUDE": "22.2793",
        "FOODPANDA_LONGITUDE": "114.1628"
      }
    }
  }
}

4. Run it directly (no client)

FOODPANDA_COUNTRY=hk \
FOODPANDA_LATITUDE=22.2793 \
FOODPANDA_LONGITUDE=114.1628 \
node build/index.js

Startup writes one line to stderr telling you which region it resolved:

foodpanda-mcp: region=foodpanda Hong Kong api=https://hk.fd-api.com web=https://www.foodpanda.hk locale=en_HK currency=HKD transport=browser

Configuration

Variable

Default

Meaning

FOODPANDA_COUNTRY

hk

preset selector: hk, ph

FOODPANDA_API_BASE

preset (https://hk.fd-api.com)

API host, for another country

FOODPANDA_WEB_HOST

preset (https://www.foodpanda.hk)

storefront, login, payment redirects

FOODPANDA_LOCALE

preset (en_HK)

API locale

FOODPANDA_LANGUAGE_ID

preset (1)

API language id

FOODPANDA_CURRENCY

preset (HKD)

basket currency

FOODPANDA_LATITUDE / FOODPANDA_LONGITUDE

required

delivery address coordinates

FOODPANDA_GQL_SEARCH_HASH

unset

Apollo hash used by search_restaurants

FOODPANDA_GQL_VENDOR_LIST_HASH

unset

Apollo hash used by list_outlets

FOODPANDA_BROWSER_TRANSPORT

1

route API calls through the browser context

FOODPANDA_HEADLESS

1

run the transport/login browser headless

FOODPANDA_BROWSER_CHANNEL

chromium

Chromium build to drive; empty = Playwright default (headless shell)

FOODPANDA_BROWSER_EXECUTABLE

unset

absolute path to a browser binary to drive instead (system Chrome/Chromium, or an existing Playwright build)

FOODPANDA_PROXY

unset

proxy the browser egresses through: socks5://host:port, http://host:port, or http://user:pass@host:port

FOODPANDA_XVFB

1

start a private Xvfb when a headed browser is needed and DISPLAY is unset

FOODPANDA_STATE_DIR

~/.foodpanda-mcp

token + browser profile location

FOODPANDA_SESSION_TOKEN

unset

JWT, if you prefer to supply one instead of logging in

Adding a country: add a preset to PRESETS in src/config.ts, or set FOODPANDA_API_BASE, FOODPANDA_WEB_HOST, FOODPANDA_LOCALE and FOODPANDA_CURRENCY directly.

Inspect what the server resolved, without starting a client:

FOODPANDA_COUNTRY=hk FOODPANDA_LATITUDE=22.2793 FOODPANDA_LONGITUDE=114.1628 \
  node -e "import('./build/config.js').then(m => console.log(m.getRegionConfig()))"

Logging in

You do not copy tokens out of DevTools. Ask the assistant to call refresh_token: the server opens the regional storefront in its persistent browser profile, you log in (including any CAPTCHA you meet), and the Bearer token the page sends to fd-api is captured and stored in $FOODPANDA_STATE_DIR/token.json (mode 0600). The profile in $FOODPANDA_STATE_DIR/browser-data keeps your login and the PerimeterX clearance between runs.

On a headless server set FOODPANDA_HEADLESS=1 and expect to complete the login interactively on a machine that has a screen, then copy token.json plus the browser-data profile across.

Logging in on a server (no screen) — what actually works

scripts/login-browser.sh starts a visible Chromium on a virtual display that owns the MCP's browser profile, so a login performed there is the login the server later orders with. It also exposes CDP and points $HERMES_HOME/chrome-debug at that profile, which is the directory Hermes' own browser tooling probes — so browser_exec attaches to this window instead of launching its own headless browser (a headless one is refused by PerimeterX, which is the whole point).

FOODPANDA_BROWSER_EXECUTABLE=/path/to/chrome \
FOODPANDA_LOGIN_PROFILE="$HERMES_HOME/chrome-debug" \
  scripts/login-browser.sh          # Ctrl-C is fine; stop with: scripts/login-browser.sh --stop

Then, from the agent: navigate to https://www.foodpanda.hk/login, type the account e-mail, and let browser_vault_save_login / browser_vault_fill supply the password (it is typed by the vault, never by the agent, and never appears in the conversation). After the session is established, the MCP's own refresh_token tool picks the bearer token out of the profile.

Known blocker: foodpanda's two-factor screen. Its OTP is four separate single-digit inputs, and the vault fills one field per entry — so an e-mail OTP cannot be delivered into that form. Nor does the verification e-mail carry a link to click. Practical answers: disable 2FA on the account while you set the session up (then re-enable it), or do the login on a machine where you can see the screen. Password-only login (no 2FA) works end to end with the steps above.

Harvest the region's hashes

search_restaurants and list_outlets call Apollo persisted queries: instead of sending a GraphQL document they send a sha256 hash that is compiled into each regional web build. The PH hashes in upstream do not exist on the HK build, so run:

FOODPANDA_COUNTRY=hk FOODPANDA_HEADLESS=0 node scripts/discover-hashes.mjs

It opens the storefront in the same persistent profile, watches POST /graphql, drives a search on the page, and prints:

FOODPANDA_GQL_SEARCH_HASH=...
FOODPANDA_GQL_VENDOR_LIST_HASH=...

Put those into your client's env: block. The other tools (get_menu, get_restaurant_details, cart and checkout) use plain REST endpoints and need no hashes.

Available tools

Tool

Description

search_restaurants

search vendors by name/cuisine near the configured address

list_outlets

all branches of a restaurant chain

get_restaurant_details

hours, delivery fee, minimum order, address

get_menu

full menu by category

get_item_details

toppings and customisation options for one item

add_to_cart / get_cart / remove_from_cart

in-memory cart, prices re-validated against the API

preview_order

order summary: items, totals, address, payment methods

place_order

submits the order (after your confirmation)

refresh_token

browser login, captures and persists the session token

Getting past PerimeterX — the part that matters

*.fd-api.com sits behind PerimeterX. What actually decides whether you get through is not the country you are in: it is whether the browser looks automated.

  • A plain fetch(), curl, or a headless browser (including Playwright's chromium-headless-shell) is challenged: 403 with a px-captcha payload, or a page titled "Access to this page has been denied".

  • The same server, same IP, driving a headed Chromium on a virtual display, gets through.

So the transport runs headed Chromium and starts its own Xvfb when DISPLAY is unset (FOODPANDA_XVFB, on by default) — a server needs no screen. Two consequences worth knowing:

  • A challenge verdict is sticky: an unsolved visit leaves PX cookies that mark the profile as suspicious and every later launch from it is challenged again. warmUp() therefore wipes the browser profile and retries with a clean identity (3 attempts), which is what makes the first call succeed where a naive retry loop would keep failing.

  • Navigation itself can be re-challenged, so the transport warms up once and then talks to the API from that same context instead of reloading the storefront.

Browsing needs no account. Search, menus and vendor details are public, and the server works without a session token (verified: a live HK search returned real restaurants). Only the cart and checkout need you to log in — see Logging in.

One more asymmetry, measured the hard way: the GraphQL endpoint (/graphql, a POST) answers requests made from the browser context, but the REST endpoints (/api/v5/vendors/..., a GET) are only accepted when the request is issued from the storefront page itself — and they must not carry Content-Type, which would turn a GET into a CORS preflight the API rejects (Failed to fetch inside the page). The transport therefore picks the origin by method: GET from the page, POST from the context. FOODPANDA_FETCH_MODE=page|context forces either one.

Rate limiting is real too: a burst of calls (seven searches back to back) gets the API challenged even from a warm session. Requests are spaced by FOODPANDA_MIN_INTERVAL_MS (default 2s), and a challenge triggers a back-off (45s, then 90s), a profile reset and a retry.

A token will not rescue a blocked browser, and a headed browser will not rescue a hardened datacenter IP forever: if you keep getting challenged, set FOODPANDA_PROXY to egress elsewhere (socks5://, http://, or http://user:pass@host:port — applied to the browser, hence to every API call).

Order safety

Checkout is deliberately two-step and human-in-the-loop: preview_order returns the full summary (items, totals, delivery address, payment methods), and place_order is meant to be called only after you have seen and approved that summary. Keep that instruction in whatever system prompt your agent uses — the server cannot enforce it by itself.

Known limitations

  1. PerimeterX. See Getting past PerimeterX: the browser must look human (headed, on Xvfb), a challenge poisons the profile until it is reset, and repeated challenges from one IP mean you need FOODPANDA_PROXY or another host.

  2. Apollo hashes must be harvested per region (see above) before search works.

  3. Payment. Checkout is implemented for cash on delivery. Card payments go through foodpanda's Adyen flow in a browser and are not supported here.

  4. Single saved address. Checkout uses the saved address nearest your configured coordinates, so that address has to exist in the account first.

  5. Unofficial. This talks to foodpanda's internal web API, which can change without notice and may be against their terms of service. Use it on your own account, at your own risk.

Development

src/config.ts                region presets and env resolution
src/browser-transport.ts     persistent Playwright context used as the HTTP transport
src/foodpanda-client.ts      API client (search, menus, cart, purchase intent, checkout)
src/token-manager.ts         token persistence and browser login capture
src/server.ts                MCP tool definitions
src/index.ts                 stdio entry point
scripts/discover-hashes.mjs  Apollo persisted-query hash harvester
npm install --ignore-scripts
npx tsc -p tsconfig.json
# then point any MCP client at build/index.js, or run it standalone with the env vars above

build/ is gitignored; build it after cloning.

Credits and licence

MIT. Upstream project and original implementation: johnwhoyou/foodpanda-mcp (© John Carlo Joyo). This fork only adds regional configuration, the browser-context transport and the hash harvester.

Available Tools

11 tools
add_to_cartAdd to CartA

Add one or more items to the cart. If items are from a different restaurant than the current cart, the cart is cleared first. Sends the full cart to foodpanda for price validation and returns updated totals.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYesItems to add to cart
restaurant_idYesThe vendor code (e.g. 'p7nl')

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses important side effects: the cart is cleared when items come from a different restaurant, the full cart is sent to foodpanda for price validation, and updated totals are returned. It does not mention failure modes, authentication, or quantity merging, but the core behavior is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences with no filler. The action is front-loaded, followed by the key behavioral caveat and the outcome, making every word purposeful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema and no annotations, yet the description covers the primary return ('updated totals') and the critical cross-restaurant behavior. It is sufficiently complete for an add-to-cart operation, though it could mention potential validation failures or item unavailability.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful parameter-related context by linking restaurant_id to the cart-clearing behavior and indicating that the items parameter supports multiple entries. This goes slightly beyond the schema's field-level descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Add') on a specific resource ('cart'), supports 'one or more items', and highlights a distinguishing behavior (clearing the cart when the restaurant changes). It is easily differentiated from siblings like get_cart, remove_from_cart, and place_order.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: whenever items need to be added to the cart. It also explains the specific scenario of switching restaurants and the resulting cart-clearing behavior. It does not explicitly list when-not-to-use or alternatives, but the context is unambiguous given the sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_cartGet CartA

View the current in-memory cart contents including items, quantities, prices, delivery fee, service fee, and totals. Returns 'Cart is empty.' if no items have been added.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the empty-cart return behavior ('Cart is empty.') and lists the exact contents. It does not mention side effects, but as a read operation none are expected. This is sufficient for a simple getter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no waste. The purpose and content are front-loaded, and the empty-case behavior is added as a separate, clear note. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless, no-output-schema tool, this description fully covers what an agent needs to know: what it returns and the special empty case. The sibling set is sufficiently distinct that no additional routing guidance is necessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the schema provides no semantics. The description compensates by explaining what the tool returns, which is the only relevant information. Given 0 parameters, this is appropriately handled.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'View' and the resource 'current in-memory cart contents', enumerating the included fields (items, quantities, prices, delivery fee, service fee, totals). This distinguishes it from sibling tools like add_to_cart or place_order, which imply mutation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly implies this is the read-only cart inspection tool, contrasting with siblings that modify or finalize orders. While it doesn't explicitly state 'use this instead of preview_order', the context is strong enough that an agent would know when to call it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_item_detailsGet Item DetailsA

Get full details for a menu item including all topping groups and customization options. Use this when you need to know what toppings/variations are available before adding to cart.

ParametersJSON Schema
NameRequiredDescriptionDefault
item_codeYesThe product code from the menu (e.g. 'ct-36-pd-1673')
restaurant_idYesThe vendor code (e.g. 'p7nl')

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the behavioral burden. It states it 'gets' details, implying a read-only operation, but never explicitly confirms no side effects or mutation. It also doesn't mention potential rate limits, error conditions, or data volume. The description stays at the purpose level and does not add behavioral context beyond that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences. The first states purpose and scope; the second provides usage context. No redundant phrases or unnecessary details. Information is front-loaded, making it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with two fully documented parameters and no output schema, the description covers the essential usage scenario. It tells the agent when to call it and what to expect (toppings and customization options). It lacks mention of return format, but that's not required without an output schema. The guidance is sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with both parameters described (item_code as product code, restaurant_id as vendor code). The description does not add any parameter-specific meaning beyond the schema, which is the baseline for high coverage. No extra syntax or format details are given, so a 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb 'Get' and resource 'full details for a menu item', and explicitly lists what's included (topping groups, customization options). This distinguishes it from siblings like get_menu (which likely lists items) and get_restaurant_details (restaurant-level info).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear when-to-use scenario: 'before adding to cart' when you need to know available toppings/variations. It implies it's not needed otherwise, though it doesn't explicitly name alternatives like get_menu for basic menu browsing. The guidance is sufficient for an agent to decide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_menuGet MenuA

Get the menu for a restaurant, organized by category. Returns a compact list with each item's code, name, price, and sold-out status. Use the item code when adding to cart. Use get_item_details if you need topping/customization options for a specific item.

ParametersJSON Schema
NameRequiredDescriptionDefault
restaurant_idYesThe vendor code (e.g. 'p7nl')

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states that the tool returns a compact list, organized by category, and includes sold-out status. This conveys the read-only nature implicitly via 'Get' and describes the output structure. However, it does not explicitly mention that no modifications occur or any authentication/rate-limit requirements, but for a simple get operation this is sufficient. It adds useful behavioral context about the return format and status flags.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with zero filler. The primary action and output are front-loaded, and the alternative tool is mentioned concisely. Every sentence contributes to the agent's understanding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple get-menu tool with one parameter and no output schema, the description is complete. It tells the agent what to expect in the response (code, name, price, sold-out status), how to use the result (item code for cart), and when to use an alternative. There is no missing information an agent would need to correctly invoke this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter, restaurant_id, which is described as 'The vendor code (e.g. 'p7nl')'. The description does not add additional meaning to the parameter beyond what the schema already provides. Baseline of 3 is appropriate when the schema fully documents the parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Get'), the resource ('the menu for a restaurant'), and the organization ('by category'). It also specifies the return contents (item code, name, price, sold-out status) and differentiates from get_item_details by indicating that tool is for toppings/customizations. This makes the tool's purpose unambiguous and distinct from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent when to use this tool ('Get the menu') and when to use an alternative ('Use get_item_details if you need topping/customization options'). It also provides a follow-up action ('Use the item code when adding to cart'), guiding the agent toward the correct workflow. This is explicit usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_restaurant_detailsGet Restaurant DetailsA

Get detailed information about a specific restaurant including address, opening hours, minimum order, and delivery info.

ParametersJSON Schema
NameRequiredDescriptionDefault
restaurant_idYesThe vendor code from search results (e.g. 'p7nl')

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full disclosure burden. It usefully lists the kinds of data returned (address, hours, minimum order, delivery info), which compensates for the missing output schema. However, it does not explicitly state that the operation is read-only or describe error behavior, so behavioral transparency is only partially fulfilled.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one concise sentence with no wasted words. It front-loads the main action and packs the key details into a compact list, making it easy for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter read operation with no output schema, the description adequately conveys what information will be returned. It could mention how to obtain the restaurant_id or what happens on lookup failure, but those are minor gaps given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully documents the single required parameter, including that restaurant_id is 'the vendor code from search results (e.g. 'p7nl')'. The tool description adds no additional parameter semantics beyond what the schema already provides, so a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Get') and resource ('restaurant details') and enumerates specific fields (address, opening hours, minimum order, delivery info), which distinguishes it from sibling tools like get_menu or search_restaurants. It does not explicitly name alternatives, but the resource scope is precise enough to make the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'specific restaurant' implies the tool is used when you already have a restaurant identifier, but no explicit when-to-use or when-not-to-use guidance is given. It does not mention hunting for alternatives or mention that restaurant_id should come from search_restaurants, leaving usage largely inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_outletsList Chain OutletsA

List all outlet branches for a restaurant chain. Use the chain_code from search_restaurants results (only available when total_outlets > 1). Returns all outlets with their individual vendor codes, names, delivery fees, and distances so the user can pick a specific branch.

ParametersJSON Schema
NameRequiredDescriptionDefault
chain_codeYesThe chain code from search results (e.g. 'cg0ep' for Jollibee)

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden, and it delivers: it discloses the provenance precondition for the input, states that all outlets are returned, and enumerates the returned fields (vendor codes, names, delivery fees, distances). It implies a read-only operation via 'List' and 'Returns,' providing solid behavioral context without a safety annotation to lean on.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero redundancy: the first states the operation, the second packs in input provenance, availability condition, return fields, and user purpose. Every clause earns its place and the core verb comes first.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with no output schema, the description is nearly complete: it covers input source, availability condition, return contents, and end-user purpose. Minor gaps remain—no error behavior for an invalid chain_code and no explicit routing when total_outlets == 1—but nothing blocks a correct first call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (chain_code has type and a Jollibee example), so the baseline is 3. The description adds meaning beyond the schema by explaining where the value comes from ('Use the chain_code from search_restaurants results') and under what condition it exists, which a schema alone cannot convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List all outlet branches for a restaurant chain.' It clearly differentiates from siblings like get_restaurant_details and search_restaurants by focusing on branch-level listing and ends with the user-facing goal ('so the user can pick a specific branch').

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context on when to invoke this tool: it explicitly names search_restaurants as the source of chain_code and states the availability condition ('only available when total_outlets > 1'), which implies the exclusion case. However, it does not name an explicit alternative to use when total_outlets == 1.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

place_orderPlace OrderA

Place the current cart as an order. You MUST call preview_order first and get explicit user confirmation before calling this. Only 'payment_on_delivery' (Cash on Delivery) is supported. Credit card and GCash require browser-based payment flows that cannot be completed via MCP.

ParametersJSON Schema
NameRequiredDescriptionDefault
payment_methodYesPayment method name — use 'payment_on_delivery' (Cash on Delivery). Credit card is not supported via MCP.
delivery_instructionsNoSpecial delivery instructions (e.g. 'Leave at door', 'Ring doorbell')

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses the required human-confirmation workflowaine and the payment-method limitation, which are meaningful behavioral constraints. However, it does not mention post-call side effects such as whether the cart is cleared, whether an order confirmation is returned, or whether the order can be canceled.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences carry the action, a mandatory prerequisite, and the key payment constraint without any filler. Critical workflow information is front-loaded immediately after the main verb phrase.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schemahare, the description covers prerequisites, user-confirmation requirements, and payment restrictions. The main gap is the absence of any statement about what happens after the order is placed, such as cart clearing or a returned order identifier, but the essential invocation context is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes both parameters with 100% coverage, including the exact payment_method value and the delivery_instructions purpose. The description reinforces the payment_method constraint but adds little semantic detail beyond what the schema provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Place the current cart as an order.' This clearly distinguishes the tool from its sibling preview_order, which only previews rather than finalizes, and from cart-management tools like add_to_cart and remove_from_cart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states the mandatory precondition: call preview_order first and obtain explicit user confirmation before invoking place_order. It also names the only supported payment method and explains why credit card and GCash are not viable alternatives through MCP, giving the agent clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

preview_orderPreview OrderA

Preview the current cart as an order. Returns a summary of items, totals, delivery address, and available payment methods. IMPORTANT: After calling this, you MUST show the full summary to the user and ask them to explicitly confirm before calling place_order. Never place an order without user confirmation.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses the return contents (items, totals, delivery address, payment methods) and the critical requirement to obtain user confirmation before place_order. It does not state whether the preview mutates state, but 'preview' implies read-only; the workflow constraint is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no wasted words. The primary purpose is stated first, followed by the critical usage directive. The structure is optimal for an agent to quickly parse and act.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with no output schema, the description fully covers what an agent needs: the action, the expected return summary, and the required subsequent workflow. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero parameters, so the baseline is 4. The description adds no parameter details, which is appropriate since there are none to document. It doesn't need to compensate for any coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Preview') and resource ('the current cart as an order'), and specifies what the result includes. It differentiates from the sibling place_order by explicitly positioning this as a pre-confirmation step.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit usage guidance: after preview, the agent MUST show the summary and ask for confirmation before calling place_order. It also implies when not to use it (never place an order without confirmation). This is a clear conditional workflow instruction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

refresh_tokenRefresh Session TokenA

Opens a browser window to https://www.foodpanda.hk so the user can log in to their foodpanda Hong Kong account. Intercepts the session token from network requests and updates the server. Call this when: (1) other tools return a 'session token expired' or 'No session token configured' error, or (2) the user wants to switch accounts. The browser window is visible — the user logs in manually (handling any CAPTCHAs or MFA). Once logged in, the token is captured automatically and saved for future sessions. Requires a desktop session; on a headless server set FOODPANDA_HEADLESS=1 and expect to complete the login elsewhere.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNoHow long to wait for login in seconds (default 120). Increase if the user needs more time.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description fully discloses interactive login, manual user action, CAPTCHA/MFA handling, automatic token capture, desktop requirement, and headless alternative. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with numbered triggers and a clear sequence, but slightly verbose. Every sentence adds value though; front-loads the trigger conditions before procedural details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an interactive auth tool with no output schema, it covers prerequisites, side effects, error conditions, and environment constraints. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already documents timeout with default and purpose. Description adds practical guidance ('Increase if the user needs more time'), going slightly beyond the schema's description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it opens a browser window, intercepts the session token, and updates the server. Distinct from sibling tools (all foodpanda operations) by focusing on authentication.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly lists two conditions for invocation: session token expired/not configured errors, or user wants to switch accounts. Also provides headless server guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_from_cartRemove from CartA

Remove an item from the cart by its cart item ID (e.g. 'cart-1'). Re-calculates totals with remaining items.

ParametersJSON Schema
NameRequiredDescriptionDefault
cart_item_idYesThe cart item ID to remove (e.g. 'cart-1', from get_cart results)

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions the side effect of recalculating totals, which is a useful behavioral trait, but it does not disclose whether removal is destructive to the cart item permanently, whether there are any constraints (e.g., cannot remove after order placed), or whether the operation requires specific cart state. This is a mutation tool with zero annotation coverage, so more detail is needed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no waste; the core action and the side effect are front-loaded. A perfect score would require additional detail, but for the scope it is efficient and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given it is a simple one-parameter tool with no output schema, the description covers the essential usage. The only gap is the lack of behavioral context (e.g., error conditions or irreversible nature), but it is not severely incomplete for a straightforward removal operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description reinforces the parameter's purpose by providing an example ('cart-1'). This adds value beyond the schema by giving a concrete, recognizable format, though it is a single parameter and the schema already explains it well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Remove an item from the cart') and clarifies the identifier used ('cart item ID'). It is clearly distinguished from siblings like add_to_cart and get_cart, so an agent can select it without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear context for when to use: when you need to remove a specific cart item. Does not explicitly exclude alternatives or state when not to use, but in this toolset the purpose is self-evident and sibling names clarify scope.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_restaurantsSearch RestaurantsA

Search for restaurants on foodpanda Hong Kong near the configured delivery address (prices in HKD). Returns a list of matching restaurants with id (vendor code), name, cuisine, rating, delivery fee, estimated delivery time, and minimum order amount. Chain restaurants (e.g. McDonald's, KFC) include chain_code, chain_name, and total_outlets fields. When total_outlets > 1, use list_outlets with the chain_code to see all branches.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax number of results (default 10)
queryYesSearch query (e.g. 'Jollibee', 'pizza', 'Thai food')
cuisineNoFilter by cuisine type

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden. It discloses the return structure (id, name, cuisine, rating, delivery fee, etc.), the chain-related fields, and the branching condition for using another tool. It does not explicitly state read-only behavior, but the nature of a search tool implies it; this is a minor omission.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the main purpose and location/currency, then the return fields and the chain branching. Every sentence earns its place with no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Without an output schema, the description explains the return fields and chain logic sufficiently. It does not mention pagination or sorting, but the limit parameter covers result count. For a search tool, this is reasonably complete, though a note on result ordering would push it to 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters are fully documented in the schema. The description adds context about the query examples and the return behavior, but does not materially enhance parameter understanding beyond the schema. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (search) and resource (restaurants on foodpanda Hong Kong), adds location and currency context, and enumerates the return fields. It clearly distinguishes itself from siblings like get_restaurant_details and list_outlets by focusing on the search function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides an alternative when total_outlets > 1, directing the agent to use list_outlets with chain_code. This gives clear conditional guidance on tool selection, exceeding the bare minimum.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 11 tool updatesv1.2.1
    • First observedadd_to_cart
    • First observedget_cart
    • First observedget_item_details
    • First observedget_menu
    • First observedget_restaurant_details
    • First observedlist_outlets
    • First observedplace_order
    • First observedpreview_order
    • First observedrefresh_token
    • First observedremove_from_cart
    • First observedsearch_restaurants

TDQS

A4.2/5.0

Scored across 11 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: restaurant discovery, menu browsing, cart management, order preview/placement, and authentication. Even get_menu and get_item_details are well separated by menu-level item data versus full customization details.

Naming Consistency5/5

All tool names follow clear verb_noun snake_case conventions: search_/list_/get_ for lookups, add_to_cart/get_cart/remove_from_cart for cart operations, and preview_order/place_order for checkout. The naming pattern is predictable and consistent across the full set.

Tool Count5/5

11 tools is well-scoped for the food delivery ordering domain. Each tool maps to a necessary step in the workflow from restaurant discovery to placing an order, with no redundant or unnecessary additions.

Completeness4/5

The set covers the core lifecycle: search restaurants, browse menus, manage cart, preview, and place order. Minor gaps like not having an explicit quantity update or clear-cart operation, and lacking order history, keep it slightly below complete, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to discover and order food from multiple delivery services (DoorDash, UberEats, Grubhub) using A2A protocol and process payments via Stripe with AP2 protocol mandates for cryptographically signed user authorization.
    1
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    Enables AI agents to search restaurants, browse menus, manage carts, and place orders on DoorDash programmatically. It utilizes a headless browser to interact with DoorDash's GraphQL API and bypass anti-bot protections for the full delivery lifecycle.
    22
    341 npm
    3
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables any AI agent to discover, query, and order from a restaurant's storefront via MCP tools. It handles menu lookup, modifier validation, and enforces a mandatory confirmation gate before payment, replacing the human-operated phone line.
    -
  • F
    license
    A
    quality
    D
    maintenance
    Allows AI assistants to browse menus, manage carts, and place orders on Uber Eats through natural language commands.
    34
    2
    -