iJava Developers
MCP Server
Let any AI assistant read the iJava menu, place a pickup order, and check on it.
https://ijavacafe.com/api/mcpThe iJava MCP server lets an AI assistant order real food from iJava Cafe in San Jose. It can read the cafes and the live menu, build a pickup order, hand the customer a secure payment link, and check the order afterwards.
It speaks the Model Context Protocol, so Claude, Cursor and any other MCP client can use it with no SDK and no glue code.
| Endpoint | https://ijavacafe.com/api/mcp |
| Transport | Streamable HTTP, stateless. One JSON-RPC 2.0 message per POST, answered with JSON. |
| Protocol versions | 2025-06-18, 2025-03-26, 2024-11-05 |
| Authentication | None. See Authentication and limits. |
| Fulfilment | Pickup only, at Delmas (Downtown San Jose) and Willow Glen. |
| Payment | The customer pays on a Stripe page. The server never charges a card by itself. |
What is available
| Piece | Status |
|---|---|
MCP tools: list_locations, search_menu, create_order, get_order_status | Live |
Customer accounts, favourites, schedule_order, cancel_order | Coming |
| Saved cards and spending rules ("Max $25", automatic orders) | Coming |
| REST API, API keys, webhooks, sandbox | Coming |
Add the server to your client, then ask it something like "What cold drinks does iJava Willow Glen have?"
claude mcp add --transport http ijava https://ijavacafe.com/api/mcpNo key and no sign-up. Every tool works the moment the client connects.
- Pick a cafe. Call
list_locations. Use a cafe whereonline_pickup_openistrue. - Find the items. Call
search_menuto get eachitem_id, its sizes, and its required options. - Confirm with the customer. Read back the items and the price before you order.
- Create the order. Call
create_order. You get anorder_numberand apayment_url. - Hand over the link. The customer pays on Stripe's page. The order goes to the kitchen the moment they pay.
- Check on it. Call
get_order_statuswith the order number and the customer's email.
When a cafe is not taking online pickup orders, create_order refuses with a link where the customer can order instead. Pass that link on.
The server needs no key. The tools only read the public menu, or create an order the customer still has to pay for. Customer details are never returned, except to someone who already has both the order number and the email.
Rate limits
| Limit | Per |
|---|---|
| 120 requests a minute | caller |
5 create_order calls a minute | caller |
20 get_order_status calls a minute | caller |
30 create_order calls a minute | all callers together |
Past a limit the server answers HTTP 429 with JSON-RPC error -32000. Wait a minute and try again. Request bodies over 64 KB get HTTP 413.
List iJava cafes
iJava cafe locations with address, phone, weekly hours, and whether online pickup orders are open right now.
Arguments
None. Send an empty object, {}.
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_locations",
"arguments": {}
}
}[
{
"location": "delmas",
"name": "iJava Cafe — Delmas",
"address": "387 Delmas Ave, San Jose, CA 95126",
"phone": "(408) 753-9732",
"hours": {
"sun": "06:30-14:00",
"mon": "06:30-14:00",
"…": "…"
},
"online_pickup_open": false,
"order_elsewhere": "https://order.toasttab.com/online/ijava-cafe-delmas-387-delmas-avenue"
},
{
"location": "almaden",
"name": "iJava Cafe — Willow Glen",
"address": "2306 Almaden Rd #150, San Jose, CA 95125",
"phone": "(408) 979-0251",
"hours": {
"sun": "08:00-14:00",
"mon": "08:00-14:00",
"…": "…"
},
"online_pickup_open": true,
"next_pickup": "ASAP"
}
]Hours are Pacific time, 24-hour clock. When online_pickup_open is true the result has next_pickup (ASAP, or the next opening such as Saturday at 8:00 AM). When it is false the result has order_elsewhere, a link the customer can order from instead.
Create a pickup order
Prices a pickup order and returns a secure Stripe payment link. Nothing is charged until the customer opens the link and pays; give the link to the customer. The kitchen gets the order once payment goes through. Confirm the items and total with the customer before calling this.
Arguments
locationdelmas = Downtown San Jose, almaden = Willow Glen
customerThe person picking up
customer.nameName on the pickup ticket (max 120 chars)
customer.emailGets the receipt; needed for get_order_status (email, max 320 chars)
customer.phoneThe cafe calls this number if there is a problem (max 40 chars)
linesOne entry per menu item. At most 40 items in all (1–40 items)
lines[].item_idFrom search_menu
lines[].quantityHow many of this item (1–20)
lines[].sizeRequired when the item has sizes; one of its sizes
lines[].modifiersOption names exactly as search_menu lists them, without the price suffix
lines[].modifiers[].name—
lines[].modifiers[].options—
lines[].special_instructionsNote for this item (max 280 chars)
special_instructionsNote for the whole order (max 500 chars)
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_order",
"arguments": {
"location": "almaden",
"customer": {
"name": "Jordan Lee",
"email": "jordan@example.com",
"phone": "408-555-0100"
},
"lines": [
{
"item_id": "cold-brew",
"quantity": 2,
"modifiers": [
{
"name": "Milk",
"options": [
"Oat milk"
]
}
]
}
],
"special_instructions": "Light ice"
}
}
}{
"order_number": "IJ-261002-4214BB",
"payment_url": "https://checkout.stripe.com/c/pay/cs_live_…",
"payment_link_expires_in_minutes": 30,
"status": "pending_payment",
"next_step": "Send payment_url to the customer. The order goes to the kitchen when they pay."
}Prices, tax and the pickup time are set by the server. The payment page shows the final total with tax. The link stays valid for 30 minutes.
No “Try it” for this tool: a test call would create a real order and a real payment link. Use the example above from your own client.
Check an order
Status, pickup time, items and total for an order. Needs the order number and the email it was placed with.
Arguments
order_numbere.g. IJ-261002-A1B2C3, returned by create_order (max 40 chars)
emailThe email the order was placed with (email)
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_order_status",
"arguments": {
"order_number": "IJ-261002-4214BB",
"email": "jordan@example.com"
}
}
}{
"order_number": "IJ-261002-4214BB",
"status": "paid",
"location": "almaden",
"cafe": "iJava Cafe — Willow Glen",
"address": "2306 Almaden Rd #150, San Jose, CA 95125",
"pickup": "ASAP",
"items": [
{
"name": "Cold Brew",
"quantity": 2,
"price": "$15.50"
}
],
"subtotal": "$15.50",
"total_paid": "$16.95"
}| status | Meaning |
|---|---|
pending_payment | Link created, the customer has not paid yet. |
paid | Paid. The order is with the cafe. refunded appears if staff refunded any of it. |
payment_failed | Checkout could not start or did not complete. |
canceled | Staff canceled the order. |
A wrong email and an unknown order number get the same answer, No order matches that number and email.
There are two kinds. A tool error means the tool ran and said no: bad arguments, a sold-out item, a closed cafe. It comes back as a normal result with isError: true and a sentence your model can read and act on.
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Complete Milk for Cold Brew."
}
],
"isError": true
}
}A protocol error means the request itself was wrong. It comes back as a JSON-RPC error.
| Code | HTTP | Meaning |
|---|---|---|
-32700 | 400 | The body is not valid JSON. |
-32600 | 400 / 413 | Not a single JSON-RPC 2.0 message, or the body is over 64 KB. |
-32601 | 200 | Unknown method. The server supports initialize, ping, tools/list and tools/call. |
-32602 | 200 | Unknown tool name. |
-32000 | 429 | Rate limited. |
You only need this to call the server without an MCP client. Every request is a POST to the endpoint with one JSON-RPC message. There are no sessions: you can skip initialize and call tools/call directly.
curl -s https://ijavacafe.com/api/mcp \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'curl -s https://ijavacafe.com/api/mcp \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_locations","arguments":{}}}'The result of tools/call is { content: [{ type: "text", text }] }, where text is JSON. tools/list returns each tool's full JSON Schema as inputSchema. Notifications get HTTP 202 with no body. GET and DELETE get 405, because there is no event stream and no session to end. CORS is open, so a browser page can call the server directly.
| Date | Version | Change |
|---|---|---|
| 2026-10-02 | 1.0.0 | First release: list_locations, search_menu, create_order, get_order_status. |
