Show raw JSON evidence
{
"checks": {
"action_safety_probe": {
"details": {
"auth_present": true,
"confirmation_signals": [
"delete_meal"
],
"safeguard_count": 0,
"summary": {
"bulk_access_tools": 1,
"capability_distribution": {
"admin": 12,
"delete": 3,
"exec": 1,
"export": 1,
"read": 11,
"write": 11
},
"destructive_tools": 3,
"egress_tools": 0,
"exec_tools": 1,
"high_risk_tools": 4,
"risk_distribution": {
"critical": 1,
"high": 3,
"low": 0,
"medium": 8
},
"secret_tools": 0,
"tool_count": 12
}
},
"latency_ms": null,
"status": "warning"
},
"advanced_capabilities_probe": {
"details": {
"capabilities": {
"completions": false,
"elicitation": false,
"prompts": true,
"resource_links": false,
"resources": true,
"roots": false,
"sampling": false,
"structured_outputs": false
},
"enabled": [
"prompts",
"resources"
],
"enabled_count": 2,
"initialize_capability_keys": [
"tools"
]
},
"latency_ms": null,
"status": "warning"
},
"connector_publishability_probe": {
"details": {
"blockers": [
"transport_compliance",
"server_card"
],
"criteria": {
"action_safety": true,
"auth_flow": true,
"connector_replay": true,
"initialize": true,
"protocol_version": true,
"remote_transport": true,
"request_association": true,
"server_card": false,
"session_resume": true,
"step_up_auth": true,
"tool_surface": true,
"tools_list": true,
"transport_compliance": false
},
"high_risk_tools": 4,
"tool_count": 12,
"transport": "streamable-http"
},
"latency_ms": null,
"status": "warning"
},
"connector_replay_probe": {
"details": {
"added_tools": [],
"additive_output_changes": [],
"backward_compatible": true,
"output_breaks": [],
"removed_tools": [],
"required_arg_breaks": [],
"would_break_after_refresh": false
},
"latency_ms": null,
"status": "ok"
},
"determinism_probe": {
"details": {
"attempts": 2,
"baseline_signature": "06d858e5c213ad2341e27a8b0a2f91e11d705c35ba5a908866502c22652bcb66",
"errors": [],
"matches": 2,
"stable_ratio": 1.0,
"successful": 2
},
"latency_ms": 47.55,
"status": "ok"
},
"initialize": {
"details": {
"headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"http_status": 200,
"payload": {
"id": 1,
"jsonrpc": "2.0",
"result": {
"capabilities": {
"tools": {}
},
"protocolVersion": "2025-06-18",
"serverInfo": {
"name": "forkmate",
"version": "0.0.0"
}
}
},
"url": "https://mcp.forkmate.ai/"
},
"latency_ms": 41.9,
"status": "ok"
},
"interactive_flow_probe": {
"details": {
"oauth_supported": true,
"prompt_available": false,
"risk_hits": [],
"safe_hits": []
},
"latency_ms": null,
"status": "ok"
},
"oauth_authorization_server": {
"details": {
"headers": {
"content-type": "application/json; charset=utf-8",
"strict-transport-security": "max-age=31536000; includeSubDomains; preload"
},
"http_status": 200,
"payload": {
"authorization_endpoint": "https://flexible-thought-84.authkit.app/oauth2/authorize",
"client_id_metadata_document_supported": true,
"code_challenge_methods_supported": [
"S256"
],
"device_authorization_endpoint": "https://flexible-thought-84.authkit.app/oauth2/device_authorization",
"grant_types_supported": [
"authorization_code",
"refresh_token",
"urn:ietf:params:oauth:grant-type:device_code"
],
"introspection_endpoint": "https://flexible-thought-84.authkit.app/oauth2/introspection",
"issuer": "https://flexible-thought-84.authkit.app",
"jwks_uri": "https://flexible-thought-84.authkit.app/oauth2/jwks",
"registration_endpoint": "https://flexible-thought-84.authkit.app/oauth2/register",
"response_modes_supported": [
"query"
],
"response_types_supported": [
"code"
],
"scopes_supported": [
"email",
"offline_access",
"openid",
"profile"
],
"token_endpoint": "https://flexible-thought-84.authkit.app/oauth2/token",
"token_endpoint_auth_methods_supported": [
"none",
"client_secret_post",
"client_secret_basic"
]
},
"url": "https://flexible-thought-84.authkit.app/.well-known/oauth-authorization-server"
},
"latency_ms": 549.38,
"status": "ok"
},
"oauth_protected_resource": {
"details": {
"headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"http_status": 200,
"payload": {
"authorization_servers": [
"https://flexible-thought-84.authkit.app"
],
"bearer_methods_supported": [
"header"
],
"resource": "https://mcp.forkmate.ai",
"scopes_supported": [
"openid",
"profile",
"email",
"offline_access"
]
},
"url": "https://mcp.forkmate.ai/.well-known/oauth-protected-resource"
},
"latency_ms": 44.58,
"status": "ok"
},
"official_registry_probe": {
"details": {
"direct_match": true,
"official_peer_count": 1,
"registry_identifier": "ai.forkmate/forkmate",
"registry_source": "official_registry"
},
"latency_ms": null,
"status": "ok"
},
"openid_configuration": {
"details": {
"headers": {
"content-type": "application/json; charset=utf-8",
"strict-transport-security": "max-age=31536000; includeSubDomains; preload"
},
"http_status": 200,
"payload": {
"authorization_endpoint": "https://flexible-thought-84.authkit.app/oauth2/authorize",
"device_authorization_endpoint": "https://flexible-thought-84.authkit.app/oauth2/device_authorization",
"grant_types_supported": [
"authorization_code",
"client_credentials",
"refresh_token",
"urn:ietf:params:oauth:grant-type:device_code"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"introspection_endpoint": "https://flexible-thought-84.authkit.app/oauth2/introspection",
"issuer": "https://flexible-thought-84.authkit.app",
"jwks_uri": "https://flexible-thought-84.authkit.app/oauth2/jwks",
"response_types_supported": [
"code"
],
"scopes_supported": [
"email",
"offline_access",
"openid",
"profile"
],
"subject_types_supported": [
"public"
],
"token_endpoint": "https://flexible-thought-84.authkit.app/oauth2/token",
"token_endpoint_auth_methods_supported": [
"none",
"client_secret_basic",
"client_secret_post"
],
"userinfo_endpoint": "https://flexible-thought-84.authkit.app/oauth2/userinfo"
},
"url": "https://flexible-thought-84.authkit.app/.well-known/openid-configuration"
},
"latency_ms": 149.44,
"status": "ok"
},
"probe_noise_resilience": {
"details": {
"headers": {
"content-type": "text/plain; charset=utf-8",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"http_status": 200,
"url": "https://mcp.forkmate.ai/robots.txt"
},
"latency_ms": 41.62,
"status": "ok"
},
"prompt_get": {
"details": {
"reason": "not_advertised"
},
"latency_ms": null,
"status": "missing"
},
"prompts_list": {
"details": {
"headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"http_status": 200,
"payload": {
"id": 3,
"jsonrpc": "2.0",
"result": {
"prompts": []
}
},
"url": "https://mcp.forkmate.ai/"
},
"latency_ms": 47.13,
"status": "ok"
},
"protocol_version_probe": {
"details": {
"claimed_version": "2025-06-18",
"lag_days": 160,
"latest_known_version": "2025-11-25",
"releases_behind": 1,
"validator_protocol_version": "2025-03-26"
},
"latency_ms": null,
"status": "warning"
},
"provenance_divergence_probe": {
"details": {
"direct_official_match": true,
"drift_fields": [],
"metadata_document_count": 2,
"registry_homepage": null,
"registry_repository": null,
"registry_title": null,
"registry_version": null,
"server_card_homepage": null,
"server_card_repository": null,
"server_card_title": null,
"server_card_version": null
},
"latency_ms": null,
"status": "ok"
},
"request_association_probe": {
"details": {
"reason": "no_request_association_capabilities_advertised"
},
"latency_ms": null,
"status": "missing"
},
"resource_read": {
"details": {
"reason": "not_advertised"
},
"latency_ms": null,
"status": "missing"
},
"resources_list": {
"details": {
"headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"http_status": 200,
"payload": {
"id": 5,
"jsonrpc": "2.0",
"result": {
"resources": []
}
},
"url": "https://mcp.forkmate.ai/"
},
"latency_ms": 48.13,
"status": "ok"
},
"server_card": {
"details": {
"error": "Expecting value: line 1 column 1 (char 0)",
"url": "https://mcp.forkmate.ai/.well-known/mcp/server-card.json"
},
"latency_ms": 435.84,
"status": "error"
},
"session_resume_probe": {
"details": {
"protocol_version": "2025-06-18",
"reason": "no_session_id",
"resume_expected": true,
"transport": "streamable-http"
},
"latency_ms": null,
"status": "warning"
},
"step_up_auth_probe": {
"details": {
"auth_required_checks": [],
"broad_scopes": [],
"challenge_headers": [],
"minimal_scope_documented": false,
"oauth_present": true,
"scope_specificity_ratio": 0.2,
"step_up_signals": [],
"supported_scopes": [
"email",
"offline_access",
"openid",
"profile"
]
},
"latency_ms": null,
"status": "warning"
},
"tool_snapshot_probe": {
"details": {
"added": [],
"changed_outputs": [],
"current_tool_count": 12,
"previous_tool_count": 12,
"removed": [],
"similarity": 1.0
},
"latency_ms": null,
"status": "ok"
},
"tools_list": {
"details": {
"headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"http_status": 200,
"payload": {
"id": 2,
"jsonrpc": "2.0",
"result": {
"tools": [
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Who am I"
},
"description": "Diagnostic: returns the authenticated user id and scopes.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "whoami"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get day's diary"
},
"description": "Read the user's food diary for a day (entries + calorie/macro totals). SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"local_date": {
"description": "YYYY-MM-DD; defaults to today.",
"type": "string"
}
},
"type": "object"
},
"name": "get_day"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get diary range"
},
"description": "Read the user's diary across a date range, with per-day calorie/macro totals. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"end": {
"description": "YYYY-MM-DD (inclusive).",
"type": "string"
},
"start": {
"description": "YYYY-MM-DD (inclusive).",
"type": "string"
}
},
"required": [
"start",
"end"
],
"type": "object"
},
"name": "get_range"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get dietary preferences"
},
"description": "Read the user's saved dietary preferences so you can tailor logging and suggestions WITHOUT re-asking every chat: their diet style, a structured list of allergies to avoid (the big-9 major allergens), foods they dislike, and a typical-portion note. IMPORTANT: the allergen list is self-reported and is NOT a safety guarantee \u2014 always tell the user to check ingredient labels themselves; cross-contamination and gaps in food data are not captured (see the returned allergy_disclaimer). The `allergies` field covers the major US allergens ONLY; a user may have an allergen outside it (e.g. mustard, celery, corn, mollusks, barley/rye) \u2014 ask about those directly. NEVER treat the `dislikes` list as an allergy: it is a taste preference to de-prioritize, never a safety exclusion.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "get_preferences"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Log a meal"
},
"description": "Log what the user ate to their food diary. Parse the user's free text into items and, when you can, include estimated macros per item for accuracy. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"at": {
"description": "ISO-8601 instant the meal was eaten; defaults to now.",
"type": "string"
},
"items": {
"items": {
"properties": {
"barcode": {
"type": "string"
},
"caffeine_mg": {
"description": "Optional caffeine content of this item, in milligrams (e.g. ~95 for a mug of brewed coffee). Include it for caffeinated drinks/foods when known; omit if unknown.",
"type": "number"
},
"fluid_ml": {
"description": "Optional fluid/hydration volume of this item, in millilitres (e.g. 240 for an 8 oz cup). Include it for drinks when known; omit if unknown.",
"type": "number"
},
"macros": {
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"name": {
"type": "string"
},
"quantity": {
"description": "Portion as the user stated it, e.g. '3' or '1 cup'. When logging a search_foods/lookup_barcode candidate you scaled by its serving, write it as 'N \u00d7 <serving_label> (<total_g> g)' to match the web app's diary \u2014 e.g. a candidate with serving_grams 48 and serving_label '1 frank', eaten \u00d72, becomes macros = the per-100 g figures \u00d7 0.96 (96 g total), quantity '2 \u00d7 1 frank (96 g)', and `source` set to that candidate's source. This field is a DISPLAY LABEL ONLY \u2014 you must still send the already-scaled macros; the server never re-scales them.",
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"minItems": 1,
"type": "array"
},
"local_date": {
"description": "YYYY-MM-DD diary date; defaults to the user's local date (from their timezone). Pass this to log a meal on a different day.",
"type": "string"
},
"meal": {
"enum": [
"breakfast",
"lunch",
"dinner",
"snack",
"other"
],
"type": "string"
},
"note": {
"type": "string"
},
"source": {
"description": "Optional provenance for these items. After search_foods/lookup_barcode, pass the candidate's source class (e.g. 'usda' or 'off') so the diary shows it's grounded. Defaults to 'client' (your own estimate). Unrecognized values are recorded as 'client'.",
"enum": [
"client",
"usda",
"off",
"usda-index",
"mfp-import",
"manual",
"chain-menu"
],
"type": "string"
}
},
"required": [
"items"
],
"type": "object"
},
"name": "log_meal"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Edit a logged food"
},
"description": "Correct a food already logged to the user's diary \u2014 fix a wrong calorie/macro value, quantity, or name, or move an entry to a different meal. Identify the entry by its `id` and `local_date` (both from get_day) and the food by its `item_index` within that entry's items[]. Only the fields you send change; the macros you send are MERGED onto the existing ones (so sending just `kcal` leaves protein/carb/fat as they were). This overwrites the value IN PLACE \u2014 there is no history of the previous value. Editing never moves an entry to another day (to do that, delete and re-log). SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"caffeine_mg": {
"description": "Corrected caffeine content, in milligrams.",
"type": "number"
},
"fluid_ml": {
"description": "Corrected fluid/hydration volume, in millilitres.",
"type": "number"
},
"id": {
"description": "The entry id to edit (from get_day).",
"type": "string"
},
"item_index": {
"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).",
"type": "number"
},
"local_date": {
"description": "YYYY-MM-DD diary date of the entry (from get_day).",
"type": "string"
},
"macros": {
"description": "Corrected macros \u2014 only the components you send are changed.",
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"meal": {
"description": "Move the entry to a different meal label.",
"enum": [
"breakfast",
"lunch",
"dinner",
"snack",
"other"
],
"type": "string"
},
"name": {
"type": "string"
},
"note": {
"type": "string"
},
"quantity": {
"description": "Portion as stated, e.g. '2' or '1 cup'.",
"type": "string"
}
},
"required": [
"id",
"local_date"
],
"type": "object"
},
"name": "update_meal"
},
{
"annotations": {
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Delete a logged food"
},
"description": "Delete a food from the user's diary \u2014 remove one food from an entry (by `item_index`), or the whole entry (omit `item_index`). Identify the entry by its `id` and `local_date` (both from get_day). This is a TRUE removal: the data is gone, with NO server-side tombstone and no undo. Deleting the last food in an entry removes the entry. Safe to retry \u2014 deleting something already gone is a no-op success. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"id": {
"description": "The entry id to delete from (from get_day).",
"type": "string"
},
"item_index": {
"description": "Which food to remove (0-based). Omit to delete the whole entry.",
"type": "number"
},
"local_date": {
"description": "YYYY-MM-DD diary date of the entry (from get_day).",
"type": "string"
}
},
"required": [
"id",
"local_date"
],
"type": "object"
},
"name": "delete_meal"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get pantry"
},
"description": "Read the user's PANTRY \u2014 the foods they keep ON HAND (their staples), so you can suggest meals from what they actually have and pre-fill macros when they log one. Returns each item's name and, when the user saved them, macros (for the item's serving), a serving label, a `source`, and a short note. The pantry is the user's CURATED list of what they stock \u2014 separate from what they've logged (their diary) and from their frequents (what they log often). IMPORTANT: a `source` (e.g. 'usda') is the user's own CLAIM about where the macros came from, NOT a server-verified guarantee \u2014 treat it as a hint, never as certified.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "get_pantry"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Add or update a pantry item"
},
"description": "Add a food to the user's pantry, or UPDATE it if it's already there (matched by name, any casing) \u2014 e.g. 'add rolled oats to my pantry'. Only `name` is required; include `macros` (for one serving), a `serving` label, a `source`, and a short `note` when you know them, so a later log can reuse them. Re-adding the same food REPLACES its details (an upsert \u2014 it never creates a duplicate). Only pass a `source` you actually got from search_foods/lookup_barcode; an unrecognized value is recorded as the user's own estimate ('client'). This does NOT log a meal \u2014 it only curates the user's staples.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"macros": {
"description": "Macros for ONE serving of this food, when known.",
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"name": {
"description": "The food to keep on hand, e.g. 'rolled oats'.",
"type": "string"
},
"note": {
"description": "Optional short note, e.g. 'the Costco tub'.",
"type": "string"
},
"serving": {
"description": "Serving label the macros are for, e.g. '1 cup' or 'per 100 g'.",
"type": "string"
},
"source": {
"description": "Where the macros came from, if grounded via search_foods/lookup_barcode (e.g. 'usda'). Defaults to your own estimate ('client'); unrecognized values are recorded as 'client'.",
"enum": [
"client",
"usda",
"off",
"usda-index",
"mfp-import",
"manual",
"chain-menu"
],
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "add_pantry_item"
},
{
"annotations": {
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Remove a pantry item"
},
"description": "Remove a food from the user's pantry by name \u2014 e.g. 'take eggs off my pantry list'. This removes it from their on-hand STAPLES only; it does NOT delete anything from their food diary. Safe to retry \u2014 removing something that isn't in the pantry is a no-op success.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"name": {
"description": "The food to remove from the pantry (any casing).",
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "remove_pantry_item"
},
{
"annotations": {
"openWorldHint": true,
"readOnlyHint": true,
"title": "Search foods"
},
"description": "Search USDA FoodData Central and Open Food Facts for foods matching a query, returning candidates with macros and a `source` you can show the user. IMPORTANT: the macros are PER 100 g (see each candidate's `serving`) \u2014 scale them to the portion the user actually ate before logging with log_meal. A candidate MAY also carry `serving_grams`/`serving_label` for ONE household serving (e.g. 48 g / \"1 frank\") \u2014 when present, offer the user 'N servings' instead of asking for grams, but still scale the per-100 g macros to the resolved grams before logging. When you log a chosen candidate, pass its `source` to log_meal so the diary records real provenance (USDA/Open Food Facts) instead of an estimate. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"limit": {
"description": "Max candidates to return (default 5, clamped to 1\u201310).",
"type": "number"
},
"query": {
"description": "Food to search, e.g. 'greek yogurt' or 'Chipotle chicken'.",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "search_foods"
},
{
"annotations": {
"openWorldHint": true,
"readOnlyHint": true,
"title": "Look up barcode"
},
"description": "Look up a packaged food by its UPC/EAN barcode via Open Food Facts. IMPORTANT: the macros are PER 100 g (see `serving`) \u2014 scale to the portion eaten before logging with log_meal. It MAY also carry `serving_grams`/`serving_label` for one household serving \u2014 offer 'N servings' when present, still scaling the per-100 g macros before logging. Pass the returned `source` to log_meal to preserve provenance. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"upc": {
"description": "UPC/EAN barcode, digits only (8\u201314 digits).",
"type": "string"
}
},
"required": [
"upc"
],
"type": "object"
},
"name": "lookup_barcode"
}
]
}
},
"url": "https://mcp.forkmate.ai/"
},
"latency_ms": 43.76,
"status": "ok"
},
"transport_compliance_probe": {
"details": {
"bad_protocol_error": null,
"bad_protocol_headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"bad_protocol_payload": {
"id": 410,
"jsonrpc": "2.0",
"result": {
"tools": [
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Who am I"
},
"description": "Diagnostic: returns the authenticated user id and scopes.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "whoami"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get day's diary"
},
"description": "Read the user's food diary for a day (entries + calorie/macro totals). SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"local_date": {
"description": "YYYY-MM-DD; defaults to today.",
"type": "string"
}
},
"type": "object"
},
"name": "get_day"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get diary range"
},
"description": "Read the user's diary across a date range, with per-day calorie/macro totals. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"end": {
"description": "YYYY-MM-DD (inclusive).",
"type": "string"
},
"start": {
"description": "YYYY-MM-DD (inclusive).",
"type": "string"
}
},
"required": [
"start",
"end"
],
"type": "object"
},
"name": "get_range"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get dietary preferences"
},
"description": "Read the user's saved dietary preferences so you can tailor logging and suggestions WITHOUT re-asking every chat: their diet style, a structured list of allergies to avoid (the big-9 major allergens), foods they dislike, and a typical-portion note. IMPORTANT: the allergen list is self-reported and is NOT a safety guarantee \u2014 always tell the user to check ingredient labels themselves; cross-contamination and gaps in food data are not captured (see the returned allergy_disclaimer). The `allergies` field covers the major US allergens ONLY; a user may have an allergen outside it (e.g. mustard, celery, corn, mollusks, barley/rye) \u2014 ask about those directly. NEVER treat the `dislikes` list as an allergy: it is a taste preference to de-prioritize, never a safety exclusion.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "get_preferences"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Log a meal"
},
"description": "Log what the user ate to their food diary. Parse the user's free text into items and, when you can, include estimated macros per item for accuracy. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"at": {
"description": "ISO-8601 instant the meal was eaten; defaults to now.",
"type": "string"
},
"items": {
"items": {
"properties": {
"barcode": {
"type": "string"
},
"caffeine_mg": {
"description": "Optional caffeine content of this item, in milligrams (e.g. ~95 for a mug of brewed coffee). Include it for caffeinated drinks/foods when known; omit if unknown.",
"type": "number"
},
"fluid_ml": {
"description": "Optional fluid/hydration volume of this item, in millilitres (e.g. 240 for an 8 oz cup). Include it for drinks when known; omit if unknown.",
"type": "number"
},
"macros": {
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"name": {
"type": "string"
},
"quantity": {
"description": "Portion as the user stated it, e.g. '3' or '1 cup'. When logging a search_foods/lookup_barcode candidate you scaled by its serving, write it as 'N \u00d7 <serving_label> (<total_g> g)' to match the web app's diary \u2014 e.g. a candidate with serving_grams 48 and serving_label '1 frank', eaten \u00d72, becomes macros = the per-100 g figures \u00d7 0.96 (96 g total), quantity '2 \u00d7 1 frank (96 g)', and `source` set to that candidate's source. This field is a DISPLAY LABEL ONLY \u2014 you must still send the already-scaled macros; the server never re-scales them.",
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"minItems": 1,
"type": "array"
},
"local_date": {
"description": "YYYY-MM-DD diary date; defaults to the user's local date (from their timezone). Pass this to log a meal on a different day.",
"type": "string"
},
"meal": {
"enum": [
"breakfast",
"lunch",
"dinner",
"snack",
"other"
],
"type": "string"
},
"note": {
"type": "string"
},
"source": {
"description": "Optional provenance for these items. After search_foods/lookup_barcode, pass the candidate's source class (e.g. 'usda' or 'off') so the diary shows it's grounded. Defaults to 'client' (your own estimate). Unrecognized values are recorded as 'client'.",
"enum": [
"client",
"usda",
"off",
"usda-index",
"mfp-import",
"manual",
"chain-menu"
],
"type": "string"
}
},
"required": [
"items"
],
"type": "object"
},
"name": "log_meal"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Edit a logged food"
},
"description": "Correct a food already logged to the user's diary \u2014 fix a wrong calorie/macro value, quantity, or name, or move an entry to a different meal. Identify the entry by its `id` and `local_date` (both from get_day) and the food by its `item_index` within that entry's items[]. Only the fields you send change; the macros you send are MERGED onto the existing ones (so sending just `kcal` leaves protein/carb/fat as they were). This overwrites the value IN PLACE \u2014 there is no history of the previous value. Editing never moves an entry to another day (to do that, delete and re-log). SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"caffeine_mg": {
"description": "Corrected caffeine content, in milligrams.",
"type": "number"
},
"fluid_ml": {
"description": "Corrected fluid/hydration volume, in millilitres.",
"type": "number"
},
"id": {
"description": "The entry id to edit (from get_day).",
"type": "string"
},
"item_index": {
"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).",
"type": "number"
},
"local_date": {
"description": "YYYY-MM-DD diary date of the entry (from get_day).",
"type": "string"
},
"macros": {
"description": "Corrected macros \u2014 only the components you send are changed.",
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"meal": {
"description": "Move the entry to a different meal label.",
"enum": [
"breakfast",
"lunch",
"dinner",
"snack",
"other"
],
"type": "string"
},
"name": {
"type": "string"
},
"note": {
"type": "string"
},
"quantity": {
"description": "Portion as stated, e.g. '2' or '1 cup'.",
"type": "string"
}
},
"required": [
"id",
"local_date"
],
"type": "object"
},
"name": "update_meal"
},
{
"annotations": {
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Delete a logged food"
},
"description": "Delete a food from the user's diary \u2014 remove one food from an entry (by `item_index`), or the whole entry (omit `item_index`). Identify the entry by its `id` and `local_date` (both from get_day). This is a TRUE removal: the data is gone, with NO server-side tombstone and no undo. Deleting the last food in an entry removes the entry. Safe to retry \u2014 deleting something already gone is a no-op success. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"id": {
"description": "The entry id to delete from (from get_day).",
"type": "string"
},
"item_index": {
"description": "Which food to remove (0-based). Omit to delete the whole entry.",
"type": "number"
},
"local_date": {
"description": "YYYY-MM-DD diary date of the entry (from get_day).",
"type": "string"
}
},
"required": [
"id",
"local_date"
],
"type": "object"
},
"name": "delete_meal"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get pantry"
},
"description": "Read the user's PANTRY \u2014 the foods they keep ON HAND (their staples), so you can suggest meals from what they actually have and pre-fill macros when they log one. Returns each item's name and, when the user saved them, macros (for the item's serving), a serving label, a `source`, and a short note. The pantry is the user's CURATED list of what they stock \u2014 separate from what they've logged (their diary) and from their frequents (what they log often). IMPORTANT: a `source` (e.g. 'usda') is the user's own CLAIM about where the macros came from, NOT a server-verified guarantee \u2014 treat it as a hint, never as certified.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "get_pantry"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Add or update a pantry item"
},
"description": "Add a food to the user's pantry, or UPDATE it if it's already there (matched by name, any casing) \u2014 e.g. 'add rolled oats to my pantry'. Only `name` is required; include `macros` (for one serving), a `serving` label, a `source`, and a short `note` when you know them, so a later log can reuse them. Re-adding the same food REPLACES its details (an upsert \u2014 it never creates a duplicate). Only pass a `source` you actually got from search_foods/lookup_barcode; an unrecognized value is recorded as the user's own estimate ('client'). This does NOT log a meal \u2014 it only curates the user's staples.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"macros": {
"description": "Macros for ONE serving of this food, when known.",
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"name": {
"description": "The food to keep on hand, e.g. 'rolled oats'.",
"type": "string"
},
"note": {
"description": "Optional short note, e.g. 'the Costco tub'.",
"type": "string"
},
"serving": {
"description": "Serving label the macros are for, e.g. '1 cup' or 'per 100 g'.",
"type": "string"
},
"source": {
"description": "Where the macros came from, if grounded via search_foods/lookup_barcode (e.g. 'usda'). Defaults to your own estimate ('client'); unrecognized values are recorded as 'client'.",
"enum": [
"client",
"usda",
"off",
"usda-index",
"mfp-import",
"manual",
"chain-menu"
],
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "add_pantry_item"
},
{
"annotations": {
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Remove a pantry item"
},
"description": "Remove a food from the user's pantry by name \u2014 e.g. 'take eggs off my pantry list'. This removes it from their on-hand STAPLES only; it does NOT delete anything from their food diary. Safe to retry \u2014 removing something that isn't in the pantry is a no-op success.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"name": {
"description": "The food to remove from the pantry (any casing).",
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "remove_pantry_item"
},
{
"annotations": {
"openWorldHint": true,
"readOnlyHint": true,
"title": "Search foods"
},
"description": "Search USDA FoodData Central and Open Food Facts for foods matching a query, returning candidates with macros and a `source` you can show the user. IMPORTANT: the macros are PER 100 g (see each candidate's `serving`) \u2014 scale them to the portion the user actually ate before logging with log_meal. A candidate MAY also carry `serving_grams`/`serving_label` for ONE household serving (e.g. 48 g / \"1 frank\") \u2014 when present, offer the user 'N servings' instead of asking for grams, but still scale the per-100 g macros to the resolved grams before logging. When you log a chosen candidate, pass its `source` to log_meal so the diary records real provenance (USDA/Open Food Facts) instead of an estimate. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"limit": {
"description": "Max candidates to return (default 5, clamped to 1\u201310).",
"type": "number"
},
"query": {
"description": "Food to search, e.g. 'greek yogurt' or 'Chipotle chicken'.",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "search_foods"
},
{
"annotations": {
"openWorldHint": true,
"readOnlyHint": true,
"title": "Look up barcode"
},
"description": "Look up a packaged food by its UPC/EAN barcode via Open Food Facts. IMPORTANT: the macros are PER 100 g (see `serving`) \u2014 scale to the portion eaten before logging with log_meal. It MAY also carry `serving_grams`/`serving_label` for one household serving \u2014 offer 'N servings' when present, still scaling the per-100 g macros before logging. Pass the returned `source` to log_meal to preserve provenance. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"upc": {
"description": "UPC/EAN barcode, digits only (8\u201314 digits).",
"type": "string"
}
},
"required": [
"upc"
],
"type": "object"
},
"name": "lookup_barcode"
}
]
}
},
"bad_protocol_status_code": 200,
"delete_error": null,
"delete_status_code": null,
"expired_session_error": null,
"expired_session_status_code": null,
"issues": [
"missing_session_id",
"missing_protocol_header",
"bad_protocol_not_rejected"
],
"last_event_id_visible": false,
"protocol_header_present": false,
"requested_protocol_version": "2025-06-18",
"session_id_present": false,
"transport": "streamable-http"
},
"latency_ms": 44.9,
"status": "error"
},
"utility_coverage_probe": {
"details": {
"completions": {
"advertised": false,
"live_probe": "not_executed",
"sample_target": null
},
"initialize_capability_keys": [
"tools"
],
"pagination": {
"metadata_signal": false,
"next_cursor_methods": [],
"supported": false
},
"tasks": {
"advertised": false,
"http_status": 401,
"probe_status": "auth_required"
}
},
"latency_ms": 43.67,
"status": "ok"
}
},
"failures": {
"server_card": {
"error": "Expecting value: line 1 column 1 (char 0)",
"url": "https://mcp.forkmate.ai/.well-known/mcp/server-card.json"
},
"transport_compliance_probe": {
"bad_protocol_error": null,
"bad_protocol_headers": {
"content-type": "application/json",
"strict-transport-security": "max-age=63072000; includeSubDomains"
},
"bad_protocol_payload": {
"id": 410,
"jsonrpc": "2.0",
"result": {
"tools": [
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Who am I"
},
"description": "Diagnostic: returns the authenticated user id and scopes.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "whoami"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get day's diary"
},
"description": "Read the user's food diary for a day (entries + calorie/macro totals). SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"local_date": {
"description": "YYYY-MM-DD; defaults to today.",
"type": "string"
}
},
"type": "object"
},
"name": "get_day"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get diary range"
},
"description": "Read the user's diary across a date range, with per-day calorie/macro totals. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"end": {
"description": "YYYY-MM-DD (inclusive).",
"type": "string"
},
"start": {
"description": "YYYY-MM-DD (inclusive).",
"type": "string"
}
},
"required": [
"start",
"end"
],
"type": "object"
},
"name": "get_range"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get dietary preferences"
},
"description": "Read the user's saved dietary preferences so you can tailor logging and suggestions WITHOUT re-asking every chat: their diet style, a structured list of allergies to avoid (the big-9 major allergens), foods they dislike, and a typical-portion note. IMPORTANT: the allergen list is self-reported and is NOT a safety guarantee \u2014 always tell the user to check ingredient labels themselves; cross-contamination and gaps in food data are not captured (see the returned allergy_disclaimer). The `allergies` field covers the major US allergens ONLY; a user may have an allergen outside it (e.g. mustard, celery, corn, mollusks, barley/rye) \u2014 ask about those directly. NEVER treat the `dislikes` list as an allergy: it is a taste preference to de-prioritize, never a safety exclusion.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "get_preferences"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Log a meal"
},
"description": "Log what the user ate to their food diary. Parse the user's free text into items and, when you can, include estimated macros per item for accuracy. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"at": {
"description": "ISO-8601 instant the meal was eaten; defaults to now.",
"type": "string"
},
"items": {
"items": {
"properties": {
"barcode": {
"type": "string"
},
"caffeine_mg": {
"description": "Optional caffeine content of this item, in milligrams (e.g. ~95 for a mug of brewed coffee). Include it for caffeinated drinks/foods when known; omit if unknown.",
"type": "number"
},
"fluid_ml": {
"description": "Optional fluid/hydration volume of this item, in millilitres (e.g. 240 for an 8 oz cup). Include it for drinks when known; omit if unknown.",
"type": "number"
},
"macros": {
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"name": {
"type": "string"
},
"quantity": {
"description": "Portion as the user stated it, e.g. '3' or '1 cup'. When logging a search_foods/lookup_barcode candidate you scaled by its serving, write it as 'N \u00d7 <serving_label> (<total_g> g)' to match the web app's diary \u2014 e.g. a candidate with serving_grams 48 and serving_label '1 frank', eaten \u00d72, becomes macros = the per-100 g figures \u00d7 0.96 (96 g total), quantity '2 \u00d7 1 frank (96 g)', and `source` set to that candidate's source. This field is a DISPLAY LABEL ONLY \u2014 you must still send the already-scaled macros; the server never re-scales them.",
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"minItems": 1,
"type": "array"
},
"local_date": {
"description": "YYYY-MM-DD diary date; defaults to the user's local date (from their timezone). Pass this to log a meal on a different day.",
"type": "string"
},
"meal": {
"enum": [
"breakfast",
"lunch",
"dinner",
"snack",
"other"
],
"type": "string"
},
"note": {
"type": "string"
},
"source": {
"description": "Optional provenance for these items. After search_foods/lookup_barcode, pass the candidate's source class (e.g. 'usda' or 'off') so the diary shows it's grounded. Defaults to 'client' (your own estimate). Unrecognized values are recorded as 'client'.",
"enum": [
"client",
"usda",
"off",
"usda-index",
"mfp-import",
"manual",
"chain-menu"
],
"type": "string"
}
},
"required": [
"items"
],
"type": "object"
},
"name": "log_meal"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Edit a logged food"
},
"description": "Correct a food already logged to the user's diary \u2014 fix a wrong calorie/macro value, quantity, or name, or move an entry to a different meal. Identify the entry by its `id` and `local_date` (both from get_day) and the food by its `item_index` within that entry's items[]. Only the fields you send change; the macros you send are MERGED onto the existing ones (so sending just `kcal` leaves protein/carb/fat as they were). This overwrites the value IN PLACE \u2014 there is no history of the previous value. Editing never moves an entry to another day (to do that, delete and re-log). SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"caffeine_mg": {
"description": "Corrected caffeine content, in milligrams.",
"type": "number"
},
"fluid_ml": {
"description": "Corrected fluid/hydration volume, in millilitres.",
"type": "number"
},
"id": {
"description": "The entry id to edit (from get_day).",
"type": "string"
},
"item_index": {
"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).",
"type": "number"
},
"local_date": {
"description": "YYYY-MM-DD diary date of the entry (from get_day).",
"type": "string"
},
"macros": {
"description": "Corrected macros \u2014 only the components you send are changed.",
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"meal": {
"description": "Move the entry to a different meal label.",
"enum": [
"breakfast",
"lunch",
"dinner",
"snack",
"other"
],
"type": "string"
},
"name": {
"type": "string"
},
"note": {
"type": "string"
},
"quantity": {
"description": "Portion as stated, e.g. '2' or '1 cup'.",
"type": "string"
}
},
"required": [
"id",
"local_date"
],
"type": "object"
},
"name": "update_meal"
},
{
"annotations": {
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Delete a logged food"
},
"description": "Delete a food from the user's diary \u2014 remove one food from an entry (by `item_index`), or the whole entry (omit `item_index`). Identify the entry by its `id` and `local_date` (both from get_day). This is a TRUE removal: the data is gone, with NO server-side tombstone and no undo. Deleting the last food in an entry removes the entry. Safe to retry \u2014 deleting something already gone is a no-op success. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"properties": {
"id": {
"description": "The entry id to delete from (from get_day).",
"type": "string"
},
"item_index": {
"description": "Which food to remove (0-based). Omit to delete the whole entry.",
"type": "number"
},
"local_date": {
"description": "YYYY-MM-DD diary date of the entry (from get_day).",
"type": "string"
}
},
"required": [
"id",
"local_date"
],
"type": "object"
},
"name": "delete_meal"
},
{
"annotations": {
"openWorldHint": false,
"readOnlyHint": true,
"title": "Get pantry"
},
"description": "Read the user's PANTRY \u2014 the foods they keep ON HAND (their staples), so you can suggest meals from what they actually have and pre-fill macros when they log one. Returns each item's name and, when the user saved them, macros (for the item's serving), a serving label, a `source`, and a short note. The pantry is the user's CURATED list of what they stock \u2014 separate from what they've logged (their diary) and from their frequents (what they log often). IMPORTANT: a `source` (e.g. 'usda') is the user's own CLAIM about where the macros came from, NOT a server-verified guarantee \u2014 treat it as a hint, never as certified.",
"inputSchema": {
"additionalProperties": false,
"properties": {},
"type": "object"
},
"name": "get_pantry"
},
{
"annotations": {
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Add or update a pantry item"
},
"description": "Add a food to the user's pantry, or UPDATE it if it's already there (matched by name, any casing) \u2014 e.g. 'add rolled oats to my pantry'. Only `name` is required; include `macros` (for one serving), a `serving` label, a `source`, and a short `note` when you know them, so a later log can reuse them. Re-adding the same food REPLACES its details (an upsert \u2014 it never creates a duplicate). Only pass a `source` you actually got from search_foods/lookup_barcode; an unrecognized value is recorded as the user's own estimate ('client'). This does NOT log a meal \u2014 it only curates the user's staples.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"macros": {
"description": "Macros for ONE serving of this food, when known.",
"properties": {
"carb_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"kcal": {
"type": "number"
},
"protein_g": {
"type": "number"
}
},
"type": "object"
},
"name": {
"description": "The food to keep on hand, e.g. 'rolled oats'.",
"type": "string"
},
"note": {
"description": "Optional short note, e.g. 'the Costco tub'.",
"type": "string"
},
"serving": {
"description": "Serving label the macros are for, e.g. '1 cup' or 'per 100 g'.",
"type": "string"
},
"source": {
"description": "Where the macros came from, if grounded via search_foods/lookup_barcode (e.g. 'usda'). Defaults to your own estimate ('client'); unrecognized values are recorded as 'client'.",
"enum": [
"client",
"usda",
"off",
"usda-index",
"mfp-import",
"manual",
"chain-menu"
],
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "add_pantry_item"
},
{
"annotations": {
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false,
"readOnlyHint": false,
"title": "Remove a pantry item"
},
"description": "Remove a food from the user's pantry by name \u2014 e.g. 'take eggs off my pantry list'. This removes it from their on-hand STAPLES only; it does NOT delete anything from their food diary. Safe to retry \u2014 removing something that isn't in the pantry is a no-op success.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"name": {
"description": "The food to remove from the pantry (any casing).",
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "remove_pantry_item"
},
{
"annotations": {
"openWorldHint": true,
"readOnlyHint": true,
"title": "Search foods"
},
"description": "Search USDA FoodData Central and Open Food Facts for foods matching a query, returning candidates with macros and a `source` you can show the user. IMPORTANT: the macros are PER 100 g (see each candidate's `serving`) \u2014 scale them to the portion the user actually ate before logging with log_meal. A candidate MAY also carry `serving_grams`/`serving_label` for ONE household serving (e.g. 48 g / \"1 frank\") \u2014 when present, offer the user 'N servings' instead of asking for grams, but still scale the per-100 g macros to the resolved grams before logging. When you log a chosen candidate, pass its `source` to log_meal so the diary records real provenance (USDA/Open Food Facts) instead of an estimate. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"limit": {
"description": "Max candidates to return (default 5, clamped to 1\u201310).",
"type": "number"
},
"query": {
"description": "Food to search, e.g. 'greek yogurt' or 'Chipotle chicken'.",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "search_foods"
},
{
"annotations": {
"openWorldHint": true,
"readOnlyHint": true,
"title": "Look up barcode"
},
"description": "Look up a packaged food by its UPC/EAN barcode via Open Food Facts. IMPORTANT: the macros are PER 100 g (see `serving`) \u2014 scale to the portion eaten before logging with log_meal. It MAY also carry `serving_grams`/`serving_label` for one household serving \u2014 offer 'N servings' when present, still scaling the per-100 g macros before logging. Pass the returned `source` to log_meal to preserve provenance. SAFETY: all calorie and macro values here \u2014 including carbohydrates \u2014 are ESTIMATES (from USDA / Open Food Facts or the user's own entry), approximate and not lab-measured or per-batch. They are for general nutrition tracking ONLY. Do NOT use them for insulin dosing, carb-counting for a bolus, blood-glucose prediction, or any other medical decision, and do NOT compute a dose or glucose estimate from them. For anything medical, direct the user to the product's own label and their care team.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"upc": {
"description": "UPC/EAN barcode, digits only (8\u201314 digits).",
"type": "string"
}
},
"required": [
"upc"
],
"type": "object"
},
"name": "lookup_barcode"
}
]
}
},
"bad_protocol_status_code": 200,
"delete_error": null,
"delete_status_code": null,
"expired_session_error": null,
"expired_session_status_code": null,
"issues": [
"missing_session_id",
"missing_protocol_header",
"bad_protocol_not_rejected"
],
"last_event_id_visible": false,
"protocol_header_present": false,
"requested_protocol_version": "2025-06-18",
"session_id_present": false,
"transport": "streamable-http"
}
},
"remote_url": "https://mcp.forkmate.ai/",
"server_card_payload": null,
"server_identifier": "ai.forkmate/forkmate"
}