Koskamo

Forkmate MCP

An MCP server for Forkmate, a free AI calorie and macro tracker. It allows AI assistants to log meals, read daily totals, update preferences, search food databases, and manage a private food diary via OAuth or personal keys.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Forkmate MCP logo, by High Country CodesVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by High Country Codes
You need:a free Forkmate account is requiredan app on your own computer, like Claude Code or Cursor, uses a personal key made in Forkmate's settings
MCP endpoint (Streamable HTTP)
https://mcp.forkmate.ai/
Vendor documentation

What you can do with it

  • Log meals by describing food in plain text
  • Read daily calorie and macro totals
  • Update user dietary preferences and allergies
  • Search USDA and Open Food Facts databases

Source and maintenance

Vendor evidenceRegistry 0.1.11
Maintenance checked

Protocol and capabilities

Server
forkmate 0.1.11
MCP protocol
2025-06-18
Tools
14 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
13 advertised
Server-advertised capabilities
{
  "tools": {},
  "prompts": {}
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Forkmate is the user's private food diary and calorie/macro tracker; relevant whenever the user mentions food they ate, calories, macros, protein or nutrition goals. With log_meal and update_meal, pass the user's own words for that meal, verbatim, in `said`: the server checks the amounts against them. Only the words about the meal, not other parts of the conversation. Use the amounts the user said, and never invent or change an amount they stated. When they gave none, log one typical portion, mark it '~' and 'typical' in `quantity`, and say it was assumed; ask one question first only for a powder, drink mix or oil, a food that is unclear, or when they count carbs for insulin. Look a food up with search_foods (or lookup_barcode for a barcode) before estimating its numbers yourself, and scale the per-100 g values to the amount eaten. Estimate only when neither has the food, and say it is an estimate. To change or remove an entry, read the day with get_day to find it; never ask the user for an entry id. Remove only what the user asked to remove: when it is not clear which entry or food they mean, show it and ask before calling delete_meal, because a deletion cannot be undone. If the user says they are under 18, keep logging and showing the figures they ask for as usual, but give no weight-loss, calorie-deficit or calorie-cutting advice and don't count down to a calorie target (the Forkmate app gives none either); suggest talking any weight or calorie-target questions through with a parent, a doctor or another adult they trust. Calorie and macro values, carbohydrates included, are estimates. Show them unless the user has asked not to see numbers, but never compute an insulin dose, an insulin-to-carb calculation or a glucose prediction from them. If the user says they are counting carbs for insulin, say plainly that these figures are not dosing-grade and point them to the package label and their care team. If the user has asked not to see numbers, confirm the food and portion in words only. Treat saved allergies as hard exclusions when suggesting food. They are self-reported and cover only the nine major US allergens, so ask about others directly and remind the user to check ingredient labels. Dislikes are preferences to de-prioritize, never allergies. The food profile (get_preferences for likes, dislikes, diet style and allergies; get_usual_foods for what the user usually and recently eats) can inform meal suggestions and 'the usual' logging. Allergies are hard constraints; likes, dislikes and usual foods are a starting point, not a rule. The profile describes taste and habit: no food in it is good or bad, and it is never on its own a reason to suggest eating less, skipping meals or cutting foods out. A dislike of a nutrient or food group (e.g. 'carbs', 'sugar') is a taste note saved as said, not a restriction to plan around or praise. update_preferences records what the user says about their own tastes and allergies, not inferences from their diary. search_foods and lookup_barcode return macros per 100 g. Before logging, scale every macro to the grams actually eaten (macro × grams ÷ 100); log_meal stores macros exactly as sent and never re-scales them. When a candidate has serving_grams/serving_label, the user may answer in servings, but convert servings to grams first: serving_grams 48, serving_label '1 frank', eaten twice → 96 g → per-100 g macros × 0.96, quantity '2 × 1 frank (96 g)'. Never log per-100 g values as if they were one serving. Include estimated kcal, protein, carb and fat for every item you log, scaled to the portion. When logging a database candidate, pass its `source`. For drinks and caffeinated foods, include fluid_ml and caffeine_mg when known (e.g. ~95 mg for an 8 oz brewed coffee); omit them rather than guess. When a chain-menu candidate carries a provenance caveat, relay it to the user verbatim; it changes what they should log. When the user names a food without an amount, log one typical portion instead of asking first: the candidate's serving_grams when it has one and the serving_label is a whole item, otherwise a typical portion as the food is usually sold or served, not the smallest reference serving. Record the assumed amount in `quantity` with '~' and the word 'typical', e.g. '1 typical deli sandwich (~200 g)'. In the reply, say the portion was assumed and the figures are estimates, and that the user can change the size. For foods without a natural unit (pasta, rice, cereal, nuts, a bowl or plate of something), offer smaller or larger in the same reply. Ask before logging only when the user counts carbs for insulin, when the food itself is unclear, or when the amount of a powder, drink mix or oil is unknown. Make the size offer once, in neutral words such as 'a different size?', covering the whole meal rather than each item, and do not follow up about it. Never imply the user under-reported or ask them to double-check, never praise a small number or a light meal, never remark that a portion was large, and never call a food good or bad. Before every update_preferences call, show the user the exact change (each food or allergen added or removed, and any diet-style change) and ask them to confirm; call it with user_approved: true only after they say yes, and never set it on your own. A user stating a taste or an allergy ('I don't like olives', 'I'm allergic to peanuts') is not a yes: reply by proposing the change and asking, and do not call update_preferences in that turn. Only the user's next message saying yes to that proposal approves it. When the change removes an allergy, say explicitly that Forkmate will stop treating that allergen as a hard exclusion. Entries are identified by `id` and `local_date`. Every log_meal, get_day, get_range and update_meal reply lists each entry with its id in the text, so the entry just logged can be corrected or deleted by that id. To correct, delete or repeat a logged meal, read the day with get_day (today by default): it lists each food's item_index, quantity and macros. Never ask the user for an entry id. To repeat a meal with changes, log the remaining foods with the macros get_day shows. If a reply says the user's consent is needed, show the user the consent summary from that reply and ask whether they agree. Call give_consent only after the user explicitly agrees in this conversation, with user_statement set to their own words; never call it on the user's behalf, and never treat a request to log food as agreement. A meal refused for consent is held and logged by give_consent, so do not send it again. Call send_feedback only when the user asks to give Forkmate feedback, report a bug, report a wrong food or figure, or request a feature; never on your own initiative and never for your own mistakes. Put the user's own words in message (quote them; do not paraphrase or summarize) and set category: bug, feature_request, food_data (a wrong food match or nutrition figure) or other. It changes nothing in the diary: when the user also wants a logged food fixed, fix it with update_meal or delete_meal as well. Leave out health details the user did not ask to include. No reply comes back to the user; just confirm it was sent. Compare the diary only with calorie or macro targets the user states; don't suggest targets, or compare with general recommendations, unless the user asks.

Tools

14 advertised

whoami
Advertised by the server during the last successful anonymous check.
Advertised read-only

Diagnostic: confirms that this connection is signed in to a Forkmate account. Returns no account id, email or other identifier.

whoami input schema
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
whoami output schema
{
  "type": "object",
  "required": [
    "connected"
  ],
  "properties": {
    "connected": {
      "type": "boolean"
    }
  }
}
whoami annotations
{
  "title": "Who am I",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
get_day
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read the user's food diary for one day: its entries, each listed with its `id` and each food with its item_index, quantity and macros, and calorie/macro totals. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

get_day input schema
{
  "type": "object",
  "properties": {
    "local_date": {
      "type": "string",
      "description": "YYYY-MM-DD; defaults to today."
    }
  }
}
get_day output schema
{
  "type": "object",
  "required": [
    "local_date",
    "entries",
    "totals"
  ],
  "properties": {
    "totals": {
      "type": "object",
      "required": [
        "local_date",
        "entry_count",
        "totals"
      ],
      "properties": {
        "totals": {
          "type": "object",
          "required": [
            "kcal",
            "protein_g",
            "carb_g",
            "fat_g"
          ],
          "properties": {
            "kcal": {
              "type": "number"
            },
            "fat_g": {
              "type": "number"
            },
            "carb_g": {
              "type": "number"
            },
            "protein_g": {
              "type": "number"
            }
          },
          "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
        },
        "fluid_ml": {
          "type": "number"
        },
        "local_date": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        },
        "caffeine_mg": {
          "type": "number"
        },
        "entry_count": {
          "type": "integer"
        }
      }
    },
    "entries": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "at",
          "local_date",
          "items"
        ],
        "properties": {
          "at": {
            "type": "string",
            "description": "ISO-8601 UTC instant the food was eaten."
          },
          "id": {
            "type": "string",
            "description": "Identifies the entry for a later edit or deletion."
          },
          "meal": {
            "type": "string",
            "description": "breakfast, lunch, dinner or snack, when set."
          },
          "note": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "macros": {
                  "type": "object",
                  "required": [],
                  "properties": {
                    "kcal": {
                      "type": "number"
                    },
                    "fat_g": {
                      "type": "number"
                    },
                    "carb_g": {
                      "type": "number"
                    },
                    "protein_g": {
                      "type": "number"
                    }
                  },
                  "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
                },
                "fluid_ml": {
                  "type": "number"
                },
                "quantity": {
                  "type": "string"
                },
                "caffeine_mg": {
                  "type": "number"
                },
                "unknown_macros": {
                  "type": "array",
                  "items": {
                    "enum": [
                      "protein_g",
                      "carb_g",
                      "fat_g"
                    ],
                    "type": "string"
                  },
                  "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
                }
              }
            }
          },
          "local_date": {
            "type": "string",
            "description": "A local date, YYYY-MM-DD."
          }
        },
        "description": "One diary entry: a meal with its foods."
      }
    },
    "local_date": {
      "type": "string",
      "description": "A local date, YYYY-MM-DD."
    }
  }
}
get_day annotations
{
  "title": "Get day's diary",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
get_range
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read the user's food diary across a date range, with per-day calorie/macro totals and each entry listed with its `id`. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

get_range input schema
{
  "type": "object",
  "required": [
    "start",
    "end"
  ],
  "properties": {
    "end": {
      "type": "string",
      "description": "YYYY-MM-DD (inclusive)."
    },
    "start": {
      "type": "string",
      "description": "YYYY-MM-DD (inclusive)."
    }
  }
}
get_range output schema
{
  "type": "object",
  "required": [
    "start",
    "end",
    "days",
    "entries"
  ],
  "properties": {
    "end": {
      "type": "string",
      "description": "A local date, YYYY-MM-DD."
    },
    "days": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "local_date",
          "entry_count",
          "totals"
        ],
        "properties": {
          "totals": {
            "type": "object",
            "required": [
              "kcal",
              "protein_g",
              "carb_g",
              "fat_g"
            ],
            "properties": {
              "kcal": {
                "type": "number"
              },
              "fat_g": {
                "type": "number"
              },
              "carb_g": {
                "type": "number"
              },
              "protein_g": {
                "type": "number"
              }
            },
            "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
          },
          "fluid_ml": {
            "type": "number"
          },
          "local_date": {
            "type": "string",
            "description": "A local date, YYYY-MM-DD."
          },
          "caffeine_mg": {
            "type": "number"
          },
          "entry_count": {
            "type": "integer"
          }
        }
      }
    },
    "start": {
      "type": "string",
      "description": "A local date, YYYY-MM-DD."
    },
    "entries": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "at",
          "local_date",
          "items"
        ],
        "properties": {
          "at": {
            "type": "string",
            "description": "ISO-8601 UTC instant the food was eaten."
          },
          "id": {
            "type": "string",
            "description": "Identifies the entry for a later edit or deletion."
          },
          "meal": {
            "type": "string",
            "description": "breakfast, lunch, dinner or snack, when set."
          },
          "note": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "macros": {
                  "type": "object",
                  "required": [],
                  "properties": {
                    "kcal": {
                      "type": "number"
                    },
                    "fat_g": {
                      "type": "number"
                    },
                    "carb_g": {
                      "type": "number"
                    },
                    "protein_g": {
                      "type": "number"
                    }
                  },
                  "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
                },
                "fluid_ml": {
                  "type": "number"
                },
                "quantity": {
                  "type": "string"
                },
                "caffeine_mg": {
                  "type": "number"
                },
                "unknown_macros": {
                  "type": "array",
                  "items": {
                    "enum": [
                      "protein_g",
                      "carb_g",
                      "fat_g"
                    ],
                    "type": "string"
                  },
                  "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
                }
              }
            }
          },
          "local_date": {
            "type": "string",
            "description": "A local date, YYYY-MM-DD."
          }
        },
        "description": "One diary entry: a meal with its foods."
      }
    }
  }
}
get_range annotations
{
  "title": "Get diary range",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
get_preferences
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read the user's food profile: diet style, allergies (a structured list of the major US allergens), foods they like, foods they dislike, and a typical-portion note. Allergies are self-reported and not a safety guarantee; the response includes an allergy_disclaimer. Likes and dislikes are taste preferences, not allergies or restrictions.

get_preferences input schema
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
get_preferences output schema
{
  "type": "object",
  "required": [
    "diet_style",
    "allergies",
    "likes",
    "dislikes",
    "portion_note",
    "allergy_disclaimer"
  ],
  "properties": {
    "likes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "dislikes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "allergies": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "diet_style": {
      "type": [
        "string",
        "null"
      ]
    },
    "portion_note": {
      "type": [
        "string",
        "null"
      ]
    },
    "allergy_disclaimer": {
      "type": "string"
    }
  }
}
get_preferences annotations
{
  "title": "Get food profile",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
update_preferences
Advertised by the server during the last successful anonymous check.
Advertised destructive

Edit the user's food profile: add or remove foods they like or dislike, add or remove allergies from the major US allergen list, or set their diet style. Only the fields sent change. A removal matches a saved name in any casing; a name that matches nothing is reported in `not_found` and nothing else is affected. Adding a food to likes takes it off dislikes, and the reverse. Lists hold up to 50 foods of up to 80 characters each. The reply is the whole updated profile. It saves what the user states about their own tastes and allergies, not inferences from the diary. Every call carries `user_approved: true`, meaning the user saw this exact change and said yes to it; a call without it changes nothing and returns the change for the user to approve. A user stating a preference (e.g. 'I dislike olives') has not approved saving it: approval is a later message agreeing to the change as proposed. The server cannot verify that a person gave the approval. Removals work without health-data consent and then return only what was removed. The user can see and edit the same profile in Forkmate's Settings.

update_preferences input schema
{
  "type": "object",
  "required": [
    "user_approved"
  ],
  "properties": {
    "add_likes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Foods the user enjoys, e.g. 'salmon'."
    },
    "diet_style": {
      "enum": [
        "omnivore",
        "vegetarian",
        "vegan",
        "pescatarian",
        "keto",
        "none"
      ],
      "type": "string",
      "description": "The user's diet style; 'none' clears it."
    },
    "add_dislikes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Foods the user dislikes, e.g. 'mushrooms'. A taste preference, not an allergy or a restriction."
    },
    "remove_likes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Foods to take off the likes list."
    },
    "add_allergies": {
      "type": "array",
      "items": {
        "enum": [
          "milk",
          "eggs",
          "fish",
          "shellfish",
          "tree_nuts",
          "peanuts",
          "wheat",
          "soy",
          "sesame"
        ],
        "type": "string"
      },
      "description": "Allergens to add, from the major US allergen list."
    },
    "user_approved": {
      "type": "boolean",
      "description": "True only when the previous assistant message proposed this exact change and the user's latest message agreed to it. The user stating the preference itself is not approval."
    },
    "remove_dislikes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Foods to take off the dislikes list."
    },
    "remove_allergies": {
      "type": "array",
      "items": {
        "enum": [
          "milk",
          "eggs",
          "fish",
          "shellfish",
          "tree_nuts",
          "peanuts",
          "wheat",
          "soy",
          "sesame"
        ],
        "type": "string"
      },
      "description": "Allergens to remove."
    }
  },
  "additionalProperties": false
}
update_preferences output schema
{
  "type": "object",
  "required": [
    "removed",
    "not_found"
  ],
  "properties": {
    "likes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "removed": {
      "type": "object",
      "required": [
        "likes",
        "dislikes",
        "allergies"
      ],
      "properties": {
        "likes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "dislikes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "allergies": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "dislikes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "allergies": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "not_found": {
      "type": "object",
      "required": [
        "likes",
        "dislikes",
        "allergies"
      ],
      "properties": {
        "likes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "dislikes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "allergies": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "diet_style": {
      "type": [
        "string",
        "null"
      ]
    },
    "portion_note": {
      "type": [
        "string",
        "null"
      ]
    },
    "allergy_disclaimer": {
      "type": "string"
    }
  }
}
update_preferences annotations
{
  "title": "Update food profile",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": true
}
get_usual_foods
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read what the user usually and recently eats. `usual` lists their most-logged foods, most frequent first, each with how many times it was logged, the date last eaten, the meal it is usually logged under, and the portion and macros from the last time. `recent` lists each distinct food from the last seven days with the date last eaten, its meal and how many times. An optional `meal` narrows both lists to one meal. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

get_usual_foods input schema
{
  "type": "object",
  "properties": {
    "meal": {
      "enum": [
        "breakfast",
        "lunch",
        "dinner",
        "snack",
        "other"
      ],
      "type": "string",
      "description": "Only foods logged under this meal."
    }
  },
  "additionalProperties": false
}
get_usual_foods output schema
{
  "type": "object",
  "required": [
    "meal",
    "usual",
    "recent",
    "recent_window"
  ],
  "properties": {
    "meal": {
      "type": [
        "string",
        "null"
      ]
    },
    "usual": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "times_logged",
          "last_eaten",
          "usual_meal",
          "typical_serving"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "last_eaten": {
            "type": "string",
            "description": "A local date, YYYY-MM-DD."
          },
          "usual_meal": {
            "type": [
              "string",
              "null"
            ]
          },
          "times_logged": {
            "type": "integer"
          },
          "typical_serving": {
            "type": "object",
            "required": [
              "quantity",
              "macros"
            ],
            "properties": {
              "macros": {
                "type": "object",
                "required": [
                  "kcal",
                  "protein_g",
                  "carb_g",
                  "fat_g"
                ],
                "properties": {
                  "kcal": {
                    "type": "number"
                  },
                  "fat_g": {
                    "type": "number"
                  },
                  "carb_g": {
                    "type": "number"
                  },
                  "protein_g": {
                    "type": "number"
                  }
                },
                "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
              },
              "quantity": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      }
    },
    "recent": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "last_eaten",
          "meal",
          "times"
        ],
        "properties": {
          "meal": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "times": {
            "type": "integer"
          },
          "last_eaten": {
            "type": "string",
            "description": "A local date, YYYY-MM-DD."
          }
        }
      }
    },
    "recent_window": {
      "type": "object",
      "required": [
        "start",
        "end"
      ],
      "properties": {
        "end": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        },
        "start": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        }
      }
    }
  }
}
get_usual_foods annotations
{
  "title": "Get usual foods",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
log_meal
Advertised by the server during the last successful anonymous check.

Add a meal to the user's food diary: one or more food items, each with an optional quantity and macros, plus an optional meal label, date, note and provenance `source`. The reply names the new entry's `id` and `local_date`, which identify it for a later edit or deletion. A restaurant meal's numbers depend most on the restaurant, the specific menu item, its size and its add-ons (cheese, fries, sauce, dressing); a bare dish name is logged as a typical serving. When the user names one of their saved recipes ("my chicken and rice", "half my chili"), send their words as one item's name, with any amount in quantity; Forkmate logs the recipe's own foods and numbers in its place. Portion amounts are checked against the user's own words for the meal when they arrive in `said`, and the reply lists each food with the amount it was logged at. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

log_meal input schema
{
  "type": "object",
  "required": [
    "items"
  ],
  "properties": {
    "at": {
      "type": "string",
      "description": "ISO-8601 instant the meal was eaten; defaults to now."
    },
    "meal": {
      "enum": [
        "breakfast",
        "lunch",
        "dinner",
        "snack",
        "other"
      ],
      "type": "string",
      "description": "Which meal of the day this was."
    },
    "note": {
      "type": "string",
      "description": "Optional free-text note stored with the meal, e.g. 'post-run'."
    },
    "said": {
      "type": "string",
      "maxLength": 300,
      "description": "The amounts are checked against this: the user's own words for this meal, verbatim (e.g. 'a pint of IPA and wings at the bar'). Only the meal description — not other parts of the conversation. Optional; without it, the amounts are logged as sent."
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "What the food is, e.g. 'scrambled eggs' or 'Greek yogurt, plain'."
          },
          "macros": {
            "type": "object",
            "properties": {
              "kcal": {
                "type": "number",
                "description": "Energy for the whole portion eaten, in kilocalories (not per 100 g)."
              },
              "fat_g": {
                "type": "number",
                "description": "Total fat for the whole portion eaten, in grams."
              },
              "carb_g": {
                "type": "number",
                "description": "Total carbohydrate for the whole portion eaten, in grams."
              },
              "protein_g": {
                "type": "number",
                "description": "Protein for the whole portion eaten, in grams."
              }
            },
            "description": "Estimated nutrition for the portion eaten. Omitted fields are looked up from the food databases. Without this object, kcal (or calories), protein_g, carb_g (or carbs_g) and fat_g set on the item itself are read as these macros."
          },
          "barcode": {
            "type": "string",
            "description": "The package's UPC/EAN barcode, when the food came from a barcode lookup."
          },
          "fluid_ml": {
            "type": "number",
            "description": "Optional fluid/hydration volume of this item, in millilitres (e.g. 240 for an 8 oz cup)."
          },
          "quantity": {
            "type": "string",
            "description": "Portion as a display label, e.g. '3', '1 cup' or '2 × 1 frank (96 g)'. Display only: the server stores macros exactly as sent and does not re-scale them."
          },
          "caffeine_mg": {
            "type": "number",
            "description": "Optional caffeine content of this item, in milligrams (e.g. ~95 for an 8 oz brewed coffee). If you omit it, Forkmate fills it from the label or its reference table when it knows the drink."
          }
        }
      },
      "minItems": 1,
      "description": "The foods in this meal, one entry per food."
    },
    "source": {
      "enum": [
        "USDA",
        "Open Food Facts",
        "Forkmate",
        "product label",
        "estimate"
      ],
      "type": "string",
      "description": "Optional provenance for these items: the `source` label of the food-database candidate they came from ('USDA', 'Open Food Facts', 'Forkmate' or 'product label'), or 'estimate'. Defaults to 'estimate'; unrecognized values are recorded as an estimate."
    },
    "local_date": {
      "type": "string",
      "description": "YYYY-MM-DD diary date; defaults to the user's local date (from their timezone)."
    }
  }
}
log_meal output schema
{
  "type": "object",
  "required": [
    "entry",
    "day_totals"
  ],
  "properties": {
    "entry": {
      "type": "object",
      "required": [
        "id",
        "at",
        "local_date",
        "items"
      ],
      "properties": {
        "at": {
          "type": "string",
          "description": "ISO-8601 UTC instant the food was eaten."
        },
        "id": {
          "type": "string",
          "description": "Identifies the entry for a later edit or deletion."
        },
        "meal": {
          "type": "string",
          "description": "breakfast, lunch, dinner or snack, when set."
        },
        "note": {
          "type": "string"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "macros": {
                "type": "object",
                "required": [],
                "properties": {
                  "kcal": {
                    "type": "number"
                  },
                  "fat_g": {
                    "type": "number"
                  },
                  "carb_g": {
                    "type": "number"
                  },
                  "protein_g": {
                    "type": "number"
                  }
                },
                "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
              },
              "fluid_ml": {
                "type": "number"
              },
              "quantity": {
                "type": "string"
              },
              "caffeine_mg": {
                "type": "number"
              },
              "unknown_macros": {
                "type": "array",
                "items": {
                  "enum": [
                    "protein_g",
                    "carb_g",
                    "fat_g"
                  ],
                  "type": "string"
                },
                "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
              }
            }
          }
        },
        "local_date": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        }
      },
      "description": "One diary entry: a meal with its foods."
    },
    "day_totals": {
      "type": "object",
      "required": [
        "local_date",
        "entry_count",
        "totals"
      ],
      "properties": {
        "totals": {
          "type": "object",
          "required": [
            "kcal",
            "protein_g",
            "carb_g",
            "fat_g"
          ],
          "properties": {
            "kcal": {
              "type": "number"
            },
            "fat_g": {
              "type": "number"
            },
            "carb_g": {
              "type": "number"
            },
            "protein_g": {
              "type": "number"
            }
          },
          "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
        },
        "fluid_ml": {
          "type": "number"
        },
        "local_date": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        },
        "caffeine_mg": {
          "type": "number"
        },
        "entry_count": {
          "type": "integer"
        }
      }
    }
  }
}
log_meal annotations
{
  "title": "Log a meal",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
update_meal
Advertised by the server during the last successful anonymous check.
Advertised destructive

Correct a food already in the user's diary — its name, quantity, macros, caffeine or fluid — or change an entry's meal label or note. The entry is identified by `id` and `local_date`, and a food by its `item_index`. Only the fields sent change; macros are merged onto the existing values and overwritten in place, with no history kept. A new `quantity` sent without `macros` rescales the food's macros, caffeine and fluid by the new amount ÷ the old one when both are the same kind of amount (a weight, a volume or a count), so '150 g' to '300 g' doubles them; otherwise the macros stay as they were and the reply says so. An entry cannot be moved to another day. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

update_meal input schema
{
  "type": "object",
  "required": [
    "id",
    "local_date"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "The entry id, shown with each entry in the reply text when a meal is logged or a day or range is read."
    },
    "meal": {
      "enum": [
        "breakfast",
        "lunch",
        "dinner",
        "snack",
        "other"
      ],
      "type": "string",
      "description": "Move the entry to a different meal label."
    },
    "name": {
      "type": "string",
      "description": "Corrected name of the food."
    },
    "note": {
      "type": "string",
      "description": "Replacement note for the entry."
    },
    "said": {
      "type": "string",
      "maxLength": 300,
      "description": "The amounts are checked against this: the user's own words for this meal, verbatim (e.g. 'a pint of IPA and wings at the bar'). Only the meal description — not other parts of the conversation. Optional; without it, the amounts are logged as sent."
    },
    "macros": {
      "type": "object",
      "properties": {
        "kcal": {
          "type": "number",
          "description": "Corrected energy for the whole portion, in kilocalories."
        },
        "fat_g": {
          "type": "number",
          "description": "Corrected total fat for the whole portion, in grams."
        },
        "carb_g": {
          "type": "number",
          "description": "Corrected total carbohydrate for the whole portion, in grams."
        },
        "protein_g": {
          "type": "number",
          "description": "Corrected protein for the whole portion, in grams."
        }
      },
      "description": "Corrected macros. Only the components included are changed."
    },
    "fluid_ml": {
      "type": "number",
      "description": "Corrected fluid/hydration volume, in millilitres."
    },
    "quantity": {
      "type": "string",
      "description": "Portion as stated, e.g. '2' or '1 cup'."
    },
    "item_index": {
      "type": "number",
      "description": "Which food in the entry's items[] to edit (0-based). Required when changing a food's name/quantity/macros/caffeine/fluid; omit for an entry-level change (meal/note)."
    },
    "local_date": {
      "type": "string",
      "description": "YYYY-MM-DD diary date of the entry."
    },
    "caffeine_mg": {
      "type": "number",
      "description": "Corrected caffeine content, in milligrams."
    }
  }
}
update_meal output schema
{
  "type": "object",
  "required": [
    "entry",
    "day_totals"
  ],
  "properties": {
    "entry": {
      "type": "object",
      "required": [
        "id",
        "at",
        "local_date",
        "items"
      ],
      "properties": {
        "at": {
          "type": "string",
          "description": "ISO-8601 UTC instant the food was eaten."
        },
        "id": {
          "type": "string",
          "description": "Identifies the entry for a later edit or deletion."
        },
        "meal": {
          "type": "string",
          "description": "breakfast, lunch, dinner or snack, when set."
        },
        "note": {
          "type": "string"
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "macros": {
                "type": "object",
                "required": [],
                "properties": {
                  "kcal": {
                    "type": "number"
                  },
                  "fat_g": {
                    "type": "number"
                  },
                  "carb_g": {
                    "type": "number"
                  },
                  "protein_g": {
                    "type": "number"
                  }
                },
                "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
              },
              "fluid_ml": {
                "type": "number"
              },
              "quantity": {
                "type": "string"
              },
              "caffeine_mg": {
                "type": "number"
              },
              "unknown_macros": {
                "type": "array",
                "items": {
                  "enum": [
                    "protein_g",
                    "carb_g",
                    "fat_g"
                  ],
                  "type": "string"
                },
                "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
              }
            }
          }
        },
        "local_date": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        }
      },
      "description": "One diary entry: a meal with its foods."
    },
    "day_totals": {
      "type": "object",
      "required": [
        "local_date",
        "entry_count",
        "totals"
      ],
      "properties": {
        "totals": {
          "type": "object",
          "required": [
            "kcal",
            "protein_g",
            "carb_g",
            "fat_g"
          ],
          "properties": {
            "kcal": {
              "type": "number"
            },
            "fat_g": {
              "type": "number"
            },
            "carb_g": {
              "type": "number"
            },
            "protein_g": {
              "type": "number"
            }
          },
          "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
        },
        "fluid_ml": {
          "type": "number"
        },
        "local_date": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        },
        "caffeine_mg": {
          "type": "number"
        },
        "entry_count": {
          "type": "integer"
        }
      }
    }
  }
}
update_meal annotations
{
  "title": "Edit a logged food",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": true
}
delete_meal
Advertised by the server during the last successful anonymous check.
Advertised destructive

Delete one food from a diary entry (by `item_index`), or the whole entry (without it). The entry is identified by `id` and `local_date`. Deletion is permanent, with no undo; deleting the last food removes the entry, and an `id` that matches no entry on that date returns a not-found error and deletes nothing. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

delete_meal input schema
{
  "type": "object",
  "required": [
    "id",
    "local_date"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "The entry id, shown with each entry in the reply text when a meal is logged or a day or range is read."
    },
    "item_index": {
      "type": "number",
      "description": "Which food to remove (0-based). Omit to delete the whole entry."
    },
    "local_date": {
      "type": "string",
      "description": "YYYY-MM-DD diary date of the entry."
    }
  }
}
delete_meal output schema
{
  "type": "object",
  "required": [
    "removed",
    "entry",
    "day_totals"
  ],
  "properties": {
    "entry": {
      "anyOf": [
        {
          "type": "object",
          "required": [
            "id",
            "at",
            "local_date",
            "items"
          ],
          "properties": {
            "at": {
              "type": "string",
              "description": "ISO-8601 UTC instant the food was eaten."
            },
            "id": {
              "type": "string",
              "description": "Identifies the entry for a later edit or deletion."
            },
            "meal": {
              "type": "string",
              "description": "breakfast, lunch, dinner or snack, when set."
            },
            "note": {
              "type": "string"
            },
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "macros": {
                    "type": "object",
                    "required": [],
                    "properties": {
                      "kcal": {
                        "type": "number"
                      },
                      "fat_g": {
                        "type": "number"
                      },
                      "carb_g": {
                        "type": "number"
                      },
                      "protein_g": {
                        "type": "number"
                      }
                    },
                    "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
                  },
                  "fluid_ml": {
                    "type": "number"
                  },
                  "quantity": {
                    "type": "string"
                  },
                  "caffeine_mg": {
                    "type": "number"
                  },
                  "unknown_macros": {
                    "type": "array",
                    "items": {
                      "enum": [
                        "protein_g",
                        "carb_g",
                        "fat_g"
                      ],
                      "type": "string"
                    },
                    "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
                  }
                }
              }
            },
            "local_date": {
              "type": "string",
              "description": "A local date, YYYY-MM-DD."
            }
          },
          "description": "One diary entry: a meal with its foods."
        },
        {
          "type": "null"
        }
      ],
      "description": "What remains of the entry, or null."
    },
    "removed": {
      "type": "boolean"
    },
    "day_totals": {
      "type": "object",
      "required": [
        "local_date",
        "entry_count",
        "totals"
      ],
      "properties": {
        "totals": {
          "type": "object",
          "required": [
            "kcal",
            "protein_g",
            "carb_g",
            "fat_g"
          ],
          "properties": {
            "kcal": {
              "type": "number"
            },
            "fat_g": {
              "type": "number"
            },
            "carb_g": {
              "type": "number"
            },
            "protein_g": {
              "type": "number"
            }
          },
          "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
        },
        "fluid_ml": {
          "type": "number"
        },
        "local_date": {
          "type": "string",
          "description": "A local date, YYYY-MM-DD."
        },
        "caffeine_mg": {
          "type": "number"
        },
        "entry_count": {
          "type": "integer"
        }
      }
    }
  }
}
delete_meal annotations
{
  "title": "Delete a logged food",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": true
}
give_consent
Advertised by the server during the last successful anonymous check.

Records the user's consent to Forkmate storing and processing their health-related data, as summarised in the consent text that a refused log reply shows. Valid only as the user's own explicit agreement given in this conversation; an assistant agreeing on the user's behalf is not consent. Stores the consent version, the time, the connected app and the user's words, then logs any meal that was waiting for consent. Withdrawal is in Forkmate Settings.

give_consent input schema
{
  "type": "object",
  "required": [
    "user_statement",
    "version"
  ],
  "properties": {
    "version": {
      "enum": [
        "health_ack_v5"
      ],
      "type": "string",
      "description": "The consent version shown to the user."
    },
    "user_statement": {
      "type": "string",
      "maxLength": 280,
      "description": "The user's own words agreeing, as they replied, e.g. 'yes, I agree'."
    }
  },
  "additionalProperties": false
}
give_consent output schema
{
  "type": "object",
  "required": [
    "consented",
    "version",
    "logged"
  ],
  "properties": {
    "logged": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "at",
          "local_date",
          "items"
        ],
        "properties": {
          "at": {
            "type": "string",
            "description": "ISO-8601 UTC instant the food was eaten."
          },
          "id": {
            "type": "string",
            "description": "Identifies the entry for a later edit or deletion."
          },
          "meal": {
            "type": "string",
            "description": "breakfast, lunch, dinner or snack, when set."
          },
          "note": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "macros": {
                  "type": "object",
                  "required": [],
                  "properties": {
                    "kcal": {
                      "type": "number"
                    },
                    "fat_g": {
                      "type": "number"
                    },
                    "carb_g": {
                      "type": "number"
                    },
                    "protein_g": {
                      "type": "number"
                    }
                  },
                  "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
                },
                "fluid_ml": {
                  "type": "number"
                },
                "quantity": {
                  "type": "string"
                },
                "caffeine_mg": {
                  "type": "number"
                },
                "unknown_macros": {
                  "type": "array",
                  "items": {
                    "enum": [
                      "protein_g",
                      "carb_g",
                      "fat_g"
                    ],
                    "type": "string"
                  },
                  "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
                }
              }
            }
          },
          "local_date": {
            "type": "string",
            "description": "A local date, YYYY-MM-DD."
          }
        },
        "description": "One diary entry: a meal with its foods."
      },
      "description": "Meals held until consent, now logged."
    },
    "version": {
      "type": "string"
    },
    "consented": {
      "type": "boolean"
    }
  }
}
give_consent annotations
{
  "title": "Give consent",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
search_foods
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search USDA FoodData Central, Open Food Facts and Forkmate's curated restaurant menus for a named food. Returns up to 5 candidates, each with macros per 100 g, a `source` label ('USDA', 'Open Food Facts', 'Forkmate' or 'product label', a packaged product's published label read from a cited page and not yet checked by Forkmate), and, when known, `serving_grams`/`serving_label` for one household serving. Curated chain-menu candidates include a `provenance` object that may carry a portion caveat. A query names a food (at least 2 letters, no wildcards); there is no paging. For a bare generic dish ("a burger", "coffee"), the reply also lists `details_that_change_it`: the details that change that dish's numbers most, such as where it is from, which item, its size and add-ons. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

search_foods input schema
{
  "type": "object",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "description": "Max candidates to return (default and maximum 5)."
    },
    "query": {
      "type": "string",
      "description": "Food to search, e.g. 'greek yogurt' or 'Chipotle chicken'. At least 2 letters; wildcards are not supported."
    }
  },
  "additionalProperties": false
}
search_foods output schema
{
  "type": "object",
  "required": [
    "candidates"
  ],
  "properties": {
    "candidates": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "serving",
          "macros",
          "source"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "macros": {
            "type": "object",
            "required": [
              "kcal",
              "protein_g",
              "carb_g",
              "fat_g"
            ],
            "properties": {
              "kcal": {
                "type": "number"
              },
              "fat_g": {
                "type": "number"
              },
              "carb_g": {
                "type": "number"
              },
              "protein_g": {
                "type": "number"
              }
            },
            "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
          },
          "source": {
            "enum": [
              "USDA",
              "Open Food Facts",
              "Forkmate",
              "your entry",
              "estimate"
            ],
            "type": "string",
            "description": "Where the figures came from, as a label."
          },
          "serving": {
            "type": "string",
            "description": "The basis the macros are for, e.g. '100 g'."
          },
          "provenance": {
            "type": "object",
            "required": [
              "chain",
              "as_of"
            ],
            "properties": {
              "as_of": {
                "type": "string",
                "description": "A local date, YYYY-MM-DD."
              },
              "chain": {
                "type": "string"
              },
              "caveat": {
                "type": "string"
              },
              "source_url": {
                "type": "string"
              },
              "assumed_build": {
                "type": "string"
              }
            },
            "description": "Citation: the chain or a product label's brand, its data date, its published page, the assumed build and a caveat."
          },
          "serving_grams": {
            "type": "number"
          },
          "serving_label": {
            "type": "string"
          },
          "serving_approx": {
            "type": "boolean",
            "description": "serving_grams is estimated from a drink's volume."
          },
          "unknown_macros": {
            "type": "array",
            "items": {
              "enum": [
                "protein_g",
                "carb_g",
                "fat_g"
              ],
              "type": "string"
            },
            "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
          }
        },
        "description": "A food match. Macros are PER 100 g — scale to the portion before logging."
      }
    },
    "details_that_change_it": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "For a bare generic dish: the details that change its numbers most (where it's from, which item, size, add-ons)."
    }
  }
}
search_foods annotations
{
  "title": "Search foods",
  "readOnlyHint": true,
  "openWorldHint": true,
  "destructiveHint": false
}
lookup_barcode
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Look up a packaged food by its UPC/EAN barcode in Open Food Facts. Returns macros per 100 g, a `source` label ('Open Food Facts'), and, when known, `serving_grams`/`serving_label` for one household serving. All calorie and macro values, including carbohydrates, are estimates from USDA FoodData Central, Open Food Facts, the user's own entry or an AI assistant's estimate — approximate, not lab-measured or specific to a package or batch, and not suitable for insulin dosing (including carb counting for a meal bolus), blood-glucose prediction or any other medical decision.

lookup_barcode input schema
{
  "type": "object",
  "required": [
    "upc"
  ],
  "properties": {
    "upc": {
      "type": "string",
      "description": "UPC/EAN barcode, digits only (8–14 digits)."
    }
  },
  "additionalProperties": false
}
lookup_barcode output schema
{
  "type": "object",
  "required": [
    "candidates"
  ],
  "properties": {
    "candidates": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "serving",
          "macros",
          "source"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "macros": {
            "type": "object",
            "required": [
              "kcal",
              "protein_g",
              "carb_g",
              "fat_g"
            ],
            "properties": {
              "kcal": {
                "type": "number"
              },
              "fat_g": {
                "type": "number"
              },
              "carb_g": {
                "type": "number"
              },
              "protein_g": {
                "type": "number"
              }
            },
            "description": "Calories and macros. Estimates, not lab-measured; not for insulin dosing."
          },
          "source": {
            "enum": [
              "USDA",
              "Open Food Facts",
              "Forkmate",
              "your entry",
              "estimate"
            ],
            "type": "string",
            "description": "Where the figures came from, as a label."
          },
          "serving": {
            "type": "string",
            "description": "The basis the macros are for, e.g. '100 g'."
          },
          "provenance": {
            "type": "object",
            "required": [
              "chain",
              "as_of"
            ],
            "properties": {
              "as_of": {
                "type": "string",
                "description": "A local date, YYYY-MM-DD."
              },
              "chain": {
                "type": "string"
              },
              "caveat": {
                "type": "string"
              },
              "source_url": {
                "type": "string"
              },
              "assumed_build": {
                "type": "string"
              }
            },
            "description": "Citation: the chain or a product label's brand, its data date, its published page, the assumed build and a caveat."
          },
          "serving_grams": {
            "type": "number"
          },
          "serving_label": {
            "type": "string"
          },
          "serving_approx": {
            "type": "boolean",
            "description": "serving_grams is estimated from a drink's volume."
          },
          "unknown_macros": {
            "type": "array",
            "items": {
              "enum": [
                "protein_g",
                "carb_g",
                "fat_g"
              ],
              "type": "string"
            },
            "description": "Macros missing from the source data: shown as 0 but unknown, not a real zero."
          }
        },
        "description": "A food match. Macros are PER 100 g — scale to the portion before logging."
      }
    }
  }
}
lookup_barcode annotations
{
  "title": "Look up barcode",
  "readOnlyHint": true,
  "openWorldHint": true,
  "destructiveHint": false
}
send_feedback
Advertised by the server during the last successful anonymous check.

Sends feedback to Forkmate to improve the app: a bug, a feature request, a food or nutrition figure that looked wrong (food_data), or something else. It is for feedback the user has asked to send, in the user's own words rather than a paraphrase. It changes nothing in the diary. The note is kept in the user's own account and deleted with it, and no reply is sent.

send_feedback input schema
{
  "type": "object",
  "required": [
    "message"
  ],
  "properties": {
    "about": {
      "enum": [
        "logging",
        "accuracy",
        "connect",
        "other"
      ],
      "type": "string",
      "description": "What the note is about: logging (saving or editing meals), accuracy (a food or number that looked wrong), connect (connecting this AI app), or other."
    },
    "rating": {
      "enum": [
        "up",
        "down"
      ],
      "type": "string",
      "description": "The user's thumbs up or down on Forkmate, when they gave one."
    },
    "message": {
      "type": "string",
      "maxLength": 4000,
      "description": "The feedback, in the user's own words as they said it (at most 4000 characters)."
    },
    "category": {
      "enum": [
        "bug",
        "feature_request",
        "food_data",
        "other"
      ],
      "type": "string",
      "description": "The kind of feedback: bug (something broken), feature_request (something the user would like), food_data (a wrong food match or nutrition figure), or other."
    }
  },
  "additionalProperties": false
}
send_feedback output schema
{
  "type": "object",
  "required": [
    "sent"
  ],
  "properties": {
    "sent": {
      "type": "boolean"
    }
  }
}
send_feedback annotations
{
  "title": "Send feedback to Forkmate",
  "readOnlyHint": false,
  "openWorldHint": false,
  "destructiveHint": false
}
get_notifications
Advertised by the server during the last successful anonymous check.
Advertised read-only

Reads the user's Forkmate notifications, newest first: notices that something the user reported was fixed, Forkmate release notes (what's new), and account messages. Each one has a kind, a title, a body, an optional link, the day it arrived and whether it is unread, and the reply includes the unread count. Read-only: reading marks nothing as read. Notifications older than 180 days are not kept.

get_notifications input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "maximum": 20,
      "minimum": 1,
      "description": "How many to return, newest first (1 to 20, default 10)."
    },
    "unread_only": {
      "type": "boolean",
      "description": "Only unread notifications. Defaults to false."
    }
  },
  "additionalProperties": false
}
get_notifications output schema
{
  "type": "object",
  "required": [
    "notifications",
    "unread_count"
  ],
  "properties": {
    "unread_count": {
      "type": "integer",
      "minimum": 0
    },
    "notifications": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "kind",
          "title",
          "body",
          "date",
          "unread"
        ],
        "properties": {
          "body": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "description": "The day it arrived, YYYY-MM-DD."
          },
          "kind": {
            "enum": [
              "fix_notice",
              "whats_new",
              "system"
            ],
            "type": "string"
          },
          "link": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "unread": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
get_notifications annotations
{
  "title": "Get notifications",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}

Prompts

13 advertised

log-meal — Log a meal

Advertised by the server during the last successful anonymous check.

Log something you ate to your Forkmate diary, described in your own words.

meal
What you ate, e.g. 'two eggs and toast with butter'. (required)
fix-last-entry — Fix my last entry

Advertised by the server during the last successful anonymous check.

Correct the most recent food in your Forkmate diary: the amount, the food, the meal or the day.

change
What was wrong, e.g. 'it was 2 eggs, not 3' or 'that was yesterday'.
today-so-far — What's left today

Advertised by the server during the last successful anonymous check.

Today's calories, protein, carbs and fat from your Forkmate diary, and what is left of your own targets if you give them.

calories
Your calorie target for today, e.g. '2200'. Optional.
protein_g
Your protein target for today in grams, e.g. '120'. Optional.
log-my-usual — Log my usual

Advertised by the server during the last successful anonymous check.

Log a meal you often eat, from your Forkmate history, after you check the foods and portions.

which
Which meal or food, e.g. 'breakfast' or 'the oatmeal from Tuesday'.
hit-protein — Hit my protein today

Advertised by the server during the last successful anonymous check.

See how much protein you have had today and get food ideas to close the gap.

target_g
Your protein target for today in grams, e.g. '140'.
week-review — Weekly check-in

Advertised by the server during the last successful anonymous check.

The last 7 days of your Forkmate diary: calories and macros per day and on average, and the foods you ate most.

No arguments advertised.

log-photo — Log a meal from a photo

Advertised by the server during the last successful anonymous check.

Attach a photo of your meal and log it to your Forkmate diary as an estimate you check first.

note
Anything the photo does not show, e.g. 'cooked in butter' or 'I ate half'.
import-myfitnesspal — Move my MyFitnessPal history

Advertised by the server during the last successful anonymous check.

Get the steps to export your MyFitnessPal data for free and import it into Forkmate.

No arguments advertised.

give-feedback — Give Forkmate feedback

Advertised by the server during the last successful anonymous check.

Tell Forkmate about a bug, a feature you would like, or a food or nutrition figure that looked wrong. You see the note before it is sent, and it changes nothing in your diary.

note
Optional: what you want to say, in your own words.
fuel-for-a-pr — Fuel for a PR

Advertised by the server during the last successful anonymous check.

A before, during and after fueling plan for a personal-best attempt on a route, from your recent Forkmate diary and, if your activity app is connected here too, your own past efforts on it.

route
The route, segment or activity name, e.g. 'river loop' or 'Saturday hill repeats'.
goal_time
Optional goal time, e.g. '45:00'.
fuel-for-a-race — Fuel for a race

Advertised by the server during the last successful anonymous check.

A fueling plan for a running race, from the days before to race morning, during and after, using general sports-nutrition ranges and your recent Forkmate diary.

distance
5K, 10K, half marathon or marathon.
date
Race date, e.g. '2026-11-08'.
long-ride-fueling — Fuel a long ride

Advertised by the server during the last successful anonymous check.

What to eat before, during and after a long bike ride: carbs per hour, fluids and a recovery meal, sized to the ride's length and intensity.

duration
How long the ride is, e.g. '3 hours'.
intensity
Easy, moderate or hard.
how-am-i-eating — How have I been eating?

Advertised by the server during the last successful anonymous check.

A review of your recent eating in Forkmate, 14 days by default: calories, carbs and protein per day and on average, set beside your training if your activity app is connected here too.

days
How many days to look back, 1 to 93. Default 14.

Resources

Not advertised

No resource definitions available.

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
420 ms
95th percentile latency
420 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 420 ms · metadata changed · 14 tool(s), 13 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http forkmate-mcp https://mcp.forkmate.ai/

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add forkmate-mcp --url https://mcp.forkmate.ai/

Cursor

Merge this server into .cursor/mcp.json in your project, then enable forkmate-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "forkmate-mcp": {
      "url": "https://mcp.forkmate.ai/"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "forkmate-mcp": {
      "type": "streamableHttp",
      "url": "https://mcp.forkmate.ai/",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start forkmate-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "forkmate-mcp": {
      "type": "http",
      "url": "https://mcp.forkmate.ai/"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http forkmate-mcp https://mcp.forkmate.ai/

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "forkmate-mcp": {
      "url": "https://mcp.forkmate.ai/"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "forkmate-mcp": {
      "serverUrl": "https://mcp.forkmate.ai/"
    }
  }
}

Let your agent find its tools

Find servers like Forkmate MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run Forkmate MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing