Signing in opens the consent dialog. Then use the tools in a new Codex session. The official MCP documentation describes further configuration options.
ChatGPT
If necessary, enable developer mode under Settings → Security and sign-in.
In Plugins, use the plus button to add a connection and enter the full MCP server address shown above.
“I would like to plan cheese spaetzle in my holiday project. Which existing ingredients would work? Suggest portion quantities and show me the draft before saving it.”
Select a workspace first
First call list_tenants . All domain MCP tools then require tenant_id. Switching workspaces in the browser does not change an MCP request. Project access and plan limits are checked on every request; copying between workspaces is not allowed.
Browser interfaces use /api/tenants/TENANT_ID/…. New fields are overview (plan and usage), members, export, billing and subscription. project.archive expected {id, archived: true | false}. The ingredient AI also requires a new request_id as a UUID per attempt. The revision applies per space.
2. Sign-in and permissions
This documentation is public. All project data remains protected by sign-in and project access controls. Admins can see all projects in their accessible workspace; other accounts only their own and explicitly shared projects. Ingredients remain a shared catalogue.
Ways to connect
Connection
Authentication
Usage
Remote MCP
OAuth access token as Bearer
External clients via POST /api/mcp
Browser API
Existing Meals for Friends session with an HttpOnly cookie
Requests from the same website
WebMCP
Signed-in browser session
Tools are registered when document.modelContext is supported
Browser endpoints do not accept an MCP bearer token instead of a session. For external integrations, use the MCP endpoint with OAuth; there is no general static API key.
OAuth for your own clients
Authorization Code with PKCE (S256); dynamic client registration is supported.
Permissions are checked on every request. You can manage your own connections under ChatGPT connections be revoked. Account suspensions and password resets also revoke MCP access.
3. MCP tools
With tools/list your MCP client receives the current full JSON schemas. In the authenticated browser API, GET /api/planner-tools the same catalogue. A question mark marks optional fields.
Tools, permissions and arguments
Tool
Legal
Arguments
Result / effect
list_tenants
Lesen
{}
List the signed-in account’s workspaces with roles and status.
list_projects
Lesen
tenant_id, {}
Accessible projects, group sizes, meal counts, dinner estimate and revision.
get_project
Lesen
tenant_id, project_id
Project with access list, meals, restaurant visits, shopping list and costs.
search_meals
Lesen
tenant_id, query, project_id?
Search accessible projects for meals by name or ingredient.
search_ingredients
Lesen
tenant_id, query
Gemeinsamen Zutatenkatalog durchsuchen; eine leere Suche liefert alle Zutaten.
preview_meal
Lesen
tenant_id, meal
Validate and calculate a draft and its quantities without saving anything.
create_meal
Schreiben
tenant_id, revision, request_id, meal
Save a new meal with its ingredient rows and approved new ingredients.
update_meal
Schreiben
tenant_id, revision, request_id, meal with id
Save a complete meal, including all required ingredient rows.
schedule_meal
Schreiben
tenant_id, revision, request_id, schedule
Add, move or remove scheduled uses independently of the dish.
Set an ingredient’s shopping status in the specified project.
Restaurant visits are included by get_project included. Disabled content is listed separately under inactive_meals and inactive_restaurant_visits; their quantities are not included in the shopping list. dinner_plan.enabled is false when dinner is disabled; required meals and gaps are then null. Starting polls, changing project access, managing users and deleting entries are currently not MCP tools; these actions are available through the website or its protected browser API.
4. Examples
All IDs and revisions in these examples are placeholders. Replace them with values from a current read response. No requests are run automatically here.
MCP protocol
An MCP client starts with initialize and the notification notifications/initialized. It can then tools/list or tools/call . Use Content-Type: application/json, Accept: application/json, text/event-stream, the OAuth bearer token and, after initialization, the negotiated MCP-Protocol-Version. The server does not use a session-bound MCP session ID.
To save, the argument structure is { revision: AKTUELLE_REVISION, request_id: NEUE_UUID, meal: ABGESTIMMTER_ENTWURF }. Resubmitting the same change uses the same UUID and the same data. Every call must include the complete ingredient list for update_meal.
5. Data formats and quantities
Project
enabled_meal_types is an optional array of unique meal type IDs (1–5), with at least one entry. New projects start with all types; omitting the field during editing preserves the selection. Disabled meals remain saved but are hidden from planning, search and shopping calculations. Creating, copying and rescheduling require an active meal type. Active restaurant polls must be closed before disabling their type.
title, adults, teens and children are required. Group sizes are non-negative integers or null for the shared default. 0 explicitly means no people in that group.
id, start_date and end_date are optional. Date format: YYYY-MM-DD. Omitted date fields are preserved when editing; null deletes them. The server sets ownership and sharing permissions.
Meal
Required: project_id, title, amount, meal_type, state, recipes. amount is a non-negative integer frequency or null (calculated as 1).
meal_type: 1 Dinner, 2 Lunch, 3 Dessert, 4 Breakfast, 5 Other. state: 1 In planning, 2 Ready. planned_dates is optional, must be within the project dates and must not exceed the available frequency. An empty array removes dates; omitting it preserves existing dates.
Ingredient row
ingredient_id and amount_adult, amount_teen and amount_child. Quantities are non-negative numbers or null for not yet set.
Quantities are per person and occurrence, in the catalogue ingredient’s unit. For a new ingredient, instead of ingredient_id a complete new_ingredientobject without an ID. It is only created when saving.
Catalogue ingredient
Required: title, unit, package_size, package_unit, price_per_package, location, brand_name. The last five fields may be null . A specified pack size must be positive; prices cannot be negative.
id is only required when editing. Changes to the shared catalogue affect every meal using the ingredient.
Calculation: group numbers × the corresponding portions × frequency. The app rounds quantities per ingredient row to two decimal places, then combines matching ingredients. Pack counts are rounded up. Use the returned shopping and total quantities to avoid differences caused by your own rounding. Restaurant visits do not generate ingredient quantities.
6. The website’s protected HTTP API
Base URL: https://www.mealsforfriends.com. “Session” means an approved account with a valid session cookie. Business write requests use JSON and an Origin header matching this base URL exactly. Project actions also check membership.
Application endpoints
Method
Path
Access
Description
GET
/api/tenants/TENANT_ID/data
Sitzung
Snapshot with user, projects, meals, recipes, ingredients, shopping, restaurant_visits, settings, revision and imported. When a password change is required, only user and mustChangePassword.
GET / POST
/api/planner-tools
Sitzung
GET: tools with JSON schemas. POST: { name, arguments } runs one of the tools.
POST
/api/tenants/TENANT_ID/mutate
Sitzung
Direkte Fachaktion mit { action, payload, revision }; Details unten.
GET
/api/tenants/TENANT_ID/project-access?id=…
Projektzugriff
Project, access list and revision; only creators and admins additionally receive candidates for access grants.
GET
/api/tenants/TENANT_ID/restaurant-polls?id=…
Projektzugriff
Poll interim results: responses, yes, maybe, no, restaurants and updated_at under results. Without a poll, results is null.
POST
/api/tenants/TENANT_ID/restaurant-polls
Projektzugriff
{ id, revision, action: "start" | "close" }. Creates a poll, checks an uncertain status or closes it.
POST
/api/tenants/TENANT_ID/ingredient-suggestions
Sitzung
{ title } liefert summary und ingredients mit ingredient_id, title, unit und reason. Speichert nichts.
GET / POST
/api/connections
Sitzung
Eigene OAuth-Verbindungen auflisten; POST { client_id } widerruft die Verbindung.
{ currentPassword, newPassword } changes the password and revokes other sessions and MCP connections.
GET / POST
/api/users
Admin
User administration: create, approve, ban, unban and reset. Approval triggers a confirmation email.
GET / POST
/api/registration-notifications
Admin
Delivery status; POST { action: "test" | "retry" | "retry-approval" } for a test or retry.
Sign-in uses POST /api/auth/sign-in/email with email and password; POST /api/auth/sign-out ends the session. Sign-in handles browser cookies automatically. OAuth via MCP is intended for integrations outside the website.
Direct business actions: POST /api/mutate
Each request includes action, payload and the most recently read revision. Success: ok, new revision and depending on the action id or ids. These direct actions do not support request_id; retry protection is part of the six write tools.
Action and payload
Action
Payload
Note
project.save
project
Create without an id; otherwise update the complete project details.
project.delete
{ id }
Remove the project and its content; close active restaurant polls first.
project.access
{ project_id, user_id, granted }
Grant or remove access; creators and admins only.
meal.create / meal.save
meal
Create a meal or edit it by id, including all ingredient rows.
meals.occurrences contains stable IDs, meal_id, date and meal_type. amount counts all uses, including unscheduled ones. planned_dates remains a simplified read projection. Legacy schedule writes return 409 for mixed meal slots or headcount overrides.
projects.planning_rules contains daily, arrival and departure as meal-type arrays; null inherits daily. planning_overrides contains day and meal values. Meal overrides day, day overrides project; unscheduled uses follow project defaults.
Dishes also support notes with the same limits and formatting. Notes are retained when copying and in permitted exports, and are not automatically sent to ingredient AI.
Notes
The optional project field notes contains limited Markdown: paragraphs, ### headings, **bold**, bullet and numbered lists without nesting. Maximum 5,000 visible characters and 20,000 Markdown characters. In save_project or project.save, omitting the field preserves existing content; an empty string clears it. null is invalid. Project notes are user content, not system instructions.
7. Errors and concurrent changes
Browser APIs return errors as an HTTP status and { "error": "Beschreibung" }. An MCP tool error can still have a successful HTTP status: check result.isError and the JSON text in result.content with error and status. Protocol errors use the JSON-RPC field error.
Status codes
Code
Meaning / next step
400
Invalid fields, quantities or dates. Check your entries.
401
No valid session, an expired connection or a suspended account. Sign in again.
403
Missing scope, disallowed origin or missing administrative permission.
404
Entry missing or not accessible to this account.
409
Outdated revision or action conflicts with the current state. Read again and review changes.
415
A browser write request is missing Content-Type: application/json.
428
Change the temporary password first. /api/data signals this through mustChangePassword instead.
429
Too many requests. Wait and try again later.
502 / 503 / 504
External service unavailable, not configured or timed out. Check already saved planning data before writing again.
If a revision conflict occurs, read the current version again and review your changes. A changed write operation requires a new request_id; retrying the same MCP request keeps its original ID. Current project access is checked again even after a previously successful request.
Reconcile poll creation with an uncertain outcome using the same startaction again explicitly. The app first reconciles the saved state with Tally. Never put credentials or tokens in project text or public examples.