Skip to main content
Glama
esreddy2

umich-dining-mcp

by esreddy2

Filter dishes

filter_dishes
Read-onlyIdempotent

Filter University of Michigan dining hall menus by allergens, traits, nutrient ranges, carbon footprint, calories, sodium, or dish-name query to find dishes matching dietary and nutritional needs.

Instructions

Filter dining hall menus by allergen, trait, nutrient density, carbon, calories, sodium and name. All params optional; no params lists every dish for the day. Allergens: alcohol, beef, coconut, eggs, fish, item-is-deep-fried, milk, oats, peanuts, pork, sesame-seed, shellfish, soy, tree-nuts, wheat_barley_rye. Traits: glutenfree, halal, kosher, spicy, vegan, vegetarian. min_mhealthy: keep tiers >= (1-5). max_carbon: keep tiers <= (1 low, 2 medium, 3 high). Untagged dropped by both. nutrients: range per nutrient, e.g. {"protein":{"min":20,"unit":"g"}}. query: case-insensitive substring. Rows are arrays: [hall, meal, station, name, traits, allergens, mhealthyTier] plus carbonFootprint when max_carbon or sort_by carbon, then calories, servingSize, servingSizeGrams, dates in a range, then nutrients named by include_nutrients. traits are codes 1-6; allergens are codes; read the key. Station codes in each row resolve via key.stations. Every row already includes calories, servingSize, and servingSizeGrams. Use include_nutrients to get full nutrition data in the same call - no need to call get_item_nutrition per dish. stale means the data is from cache and may be slightly old, but is still the best available; asOf is the age. Re-call only if you need guaranteed-fresh data. Allergens advisory.

Input Schema

NameRequiredDescriptionDefault
toNoThe last day of a range to filter. Defaults to the last published day.
dateNoA single day to filter. Cannot be combined with from/to.
fromNoThe first day of a range to filter.
hallNoHalls: one, a list, or none for all.
mealNoKeeps only that meal.
limitNoRows to return (default 50, max 500).
queryNoA case-insensitive substring of the dish name.
offsetNoPages of the range to skip.
sort_byNoSort field: a nutrient key, carbonFootprint, a micronutrient name, servingSize, mhealthyTier, or a ratio "numerator:denominator" (e.g. "protein:calories", "vitaminA:iron"). Legacy: proteinToCalorie, fiberToCalorie.
stationNoKeeps only that station.
nutrientsNoRange per nutrient, e.g. {"protein":{"min":20,"unit":"g"}}. A constraint drops dishes with no value.
max_carbonNoThe highest acceptable carbon footprint: 1 (low), 2 (medium) or 3 (high). The dishes the site did not tag are dropped.
sort_orderNoThe direction of the sort. It defaults to desc, so the biggest value comes first.
min_mhealthyNoThe lowest acceptable nutrient-density tier. The dishes the site did not tag are dropped.
require_traitsNoKeeps only the dishes that carry every one of these traits.
exclude_allergensNoKeeps only the dishes that carry none of these allergens.
include_nutrientsNoNutrients to return, by key/name, or ["all"].

Output Schema

NameRequiredDescriptionDefault
keyYes
asOfNo
dateNo
noteNo
flagsNo
staleYes
unitsNo
filterNo
noMenuNo
matchesYes
coverageNo
failuresYes
dateRangeNo
nutrientsNo
truncatedYes
totalMatchesYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed46 schema fields changedv0.1.1
    • addedInput schema / additionalProperties
      Added value: +false
    • changedInput schema / properties / date / description
      Previous value: -"Calendar date in YYYY-MM-DD. The site publishes menus for today-3 days to today+14 days."New value: +"A single day to filter. Cannot be combined with from/to."
    • addedInput schema / properties / exclude_allergens / description
      Added value: +"Keeps only the dishes that carry none of these allergens."
    • addedInput schema / properties / from
      Added value: +{
      +  "description": "The first day of a range to filter.",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / hall / anyOf
      Added value: +[
      +  {
      +    "enum": [
      +      "bursley",
      +      "east-quad",
      +      "markley",
      +      "mosher-jordan",
      +      "north-quad",
      +      "south-quad",
      +      "twigs-at-oxford",
      +      "wolverine-village",
      +      "lawyers-club",
      +      "martha-cook"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "items": {
      +      "enum": [
      +        "bursley",
      +        "east-quad",
      +        "markley",
      +        "mosher-jordan",
      +        "north-quad",
      +        "south-quad",
      +        "twigs-at-oxford",
      +        "wolverine-village",
      +        "lawyers-club",
      +        "martha-cook"
      +      ],
      +      "type": "string"
      +    },
      +    "maxItems": 10,
      +    "type": "array"
      +  }
      +]
    • addedInput schema / properties / hall / description
      Added value: +"Halls: one, a list, or none for all."
    • removedInput schema / properties / hall / enum
      Removed value: -[
      -  "bursley",
      -  "east-quad",
      -  "markley",
      -  "mosher-jordan",
      -  "north-quad",
      -  "south-quad",
      -  "twigs-at-oxford",
      -  "wolverine-village",
      -  "lawyers-club",
      -  "martha-cook"
      -]
    • removedInput schema / properties / hall / type
      Removed value: -"string"
    • addedInput schema / properties / include_nutrients
      Added value: +{
      +  "description": "Nutrients to return, by key/name, or [\"all\"].",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / limit / description
      Added value: +"Rows to return (default 50, max 500)."
    • removedInput schema / properties / max_calories
      Removed value: -{
      -  "minimum": 0,
      -  "type": "number"
      -}
    • addedInput schema / properties / max_carbon / description
      Added value: +"The highest acceptable carbon footprint: 1 (low), 2 (medium) or 3 (high). The dishes the site did not tag are dropped."
    • removedInput schema / properties / max_carbon / enum
      Removed value: -[
      -  "low",
      -  "medium",
      -  "high"
      -]
    • addedInput schema / properties / max_carbon / maximum
      Added value: +3
    • addedInput schema / properties / max_carbon / minimum
      Added value: +1
    • changedInput schema / properties / max_carbon / type
      Previous value: -"string"New value: +"integer"
    • removedInput schema / properties / max_sodium_mg
      Removed value: -{
      -  "minimum": 0,
      -  "type": "number"
      -}
    • addedInput schema / properties / meal
      Added value: +{
      +  "description": "Keeps only that meal.",
      +  "enum": [
      +    "Breakfast",
      +    "Brunch",
      +    "Lunch",
      +    "Dinner"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / min_mhealthy / description
      Added value: +"The lowest acceptable nutrient-density tier. The dishes the site did not tag are dropped."
    • addedInput schema / properties / nutrients
      Added value: +{
      +  "additionalProperties": {
      +    "properties": {
      +      "max": {
      +        "description": "The highest acceptable value, in the unit below.",
      +        "type": "number"
      +      },
      +      "min": {
      +        "description": "The lowest acceptable value, in the unit below.",
      +        "type": "number"
      +      },
      +      "unit": {
      +        "description": "The unit of the bounds. It defaults to the nutrient's own; a micronutrient defaults to the published percent.",
      +        "type": "string"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "description": "Range per nutrient, e.g. {\"protein\":{\"min\":20,\"unit\":\"g\"}}. A constraint drops dishes with no value.",
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / offset
      Added value: +{
      +  "description": "Pages of the range to skip.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / query
      Added value: +{
      +  "description": "A case-insensitive substring of the dish name.",
      +  "type": "string"
      +}
    • addedInput schema / properties / require_traits / description
      Added value: +"Keeps only the dishes that carry every one of these traits."
    • addedInput schema / properties / sort_by
      Added value: +{
      +  "description": "Sort field: a nutrient key, carbonFootprint, a micronutrient name, servingSize, mhealthyTier, or a ratio \"numerator:denominator\" (e.g. \"protein:calories\", \"vitaminA:iron\"). Legacy: proteinToCalorie, fiberToCalorie.",
      +  "type": "string"
      +}
    • addedInput schema / properties / sort_order
      Added value: +{
      +  "description": "The direction of the sort. It defaults to desc, so the biggest value comes first.",
      +  "enum": [
      +    "asc",
      +    "desc"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / station
      Added value: +{
      +  "description": "Keeps only that station.",
      +  "type": "string"
      +}
    • addedInput schema / properties / to
      Added value: +{
      +  "description": "The last day of a range to filter. Defaults to the last published day.",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +  "type": "string"
      +}
    • addedOutput schema / properties / asOf
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / coverage
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "cached": {
      +      "type": "number"
      +    },
      +    "failed": {
      +      "type": "number"
      +    },
      +    "fetchedNow": {
      +      "type": "number"
      +    },
      +    "nextOffset": {
      +      "type": [
      +        "number",
      +        "null"
      +      ]
      +    },
      +    "offset": {
      +      "type": "number"
      +    },
      +    "pages": {
      +      "type": "number"
      +    },
      +    "pending": {
      +      "type": "number"
      +    },
      +    "requested": {
      +      "type": "number"
      +    },
      +    "stale": {
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "requested",
      +    "cached",
      +    "fetchedNow",
      +    "pending",
      +    "failed",
      +    "stale",
      +    "offset",
      +    "pages",
      +    "nextOffset"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / dateRange
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "from": {
      +      "type": "string"
      +    },
      +    "to": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "from",
      +    "to"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / filter
      Added value: +{
      +  "additionalProperties": {},
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / flags
      Added value: +{
      +  "additionalProperties": {},
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / key
      Added value: +{
      +  "additionalProperties": {
      +    "additionalProperties": {
      +      "type": "string"
      +    },
      +    "propertyNames": {
      +      "type": "string"
      +    },
      +    "type": "object"
      +  },
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • removedOutput schema / properties / matches / items / additionalProperties
      Removed value: -false
    • addedOutput schema / properties / matches / items / items
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "number"
      +    },
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "boolean"
      +    },
      +    {
      +      "type": "null"
      +    },
      +    {
      +      "items": {
      +        "type": "number"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "additionalProperties": {
      +        "type": "number"
      +      },
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    }
      +  ]
      +}
    • removedOutput schema / properties / matches / items / properties
      Removed value: -{
      -  "allergens": {
      -    "items": {
      -      "type": "string"
      -    },
      -    "type": "array"
      -  },
      -  "calories": {
      -    "type": [
      -      "number",
      -      "null"
      -    ]
      -  },
      -  "carbonFootprint": {
      -    "anyOf": [
      -      {
      -        "enum": [
      -          "low",
      -          "medium",
      -          "high"
      -        ],
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ]
      -  },
      -  "date": {
      -    "type": "string"
      -  },
      -  "hall": {
      -    "enum": [
      -      "bursley",
      -      "east-quad",
      -      "markley",
      -      "mosher-jordan",
      -      "north-quad",
      -      "south-quad",
      -      "twigs-at-oxford",
      -      "wolverine-village",
      -      "lawyers-club",
      -      "martha-cook"
      -    ],
      -    "type": "string"
      -  },
      -  "hallName": {
      -    "type": "string"
      -  },
      -  "meal": {
      -    "enum": [
      -      "Breakfast",
      -      "Lunch",
      -      "Dinner"
      -    ],
      -    "type": "string"
      -  },
      -  "mhealthyTier": {
      -    "type": [
      -      "number",
      -      "null"
      -    ]
      -  },
      -  "name": {
      -    "type": "string"
      -  },
      -  "sodiumMg": {
      -    "type": [
      -      "number",
      -      "null"
      -    ]
      -  },
      -  "station": {
      -    "type": "string"
      -  },
      -  "traitLabels": {
      -    "additionalProperties": {
      -      "type": "string"
      -    },
      -    "propertyNames": {
      -      "type": "string"
      -    },
      -    "type": "object"
      -  },
      -  "traits": {
      -    "items": {
      -      "type": "string"
      -    },
      -    "type": "array"
      -  }
      -}
    • removedOutput schema / properties / matches / items / required
      Removed value: -[
      -  "hall",
      -  "hallName",
      -  "date",
      -  "meal",
      -  "station",
      -  "name",
      -  "traits",
      -  "traitLabels",
      -  "allergens",
      -  "mhealthyTier",
      -  "carbonFootprint",
      -  "calories",
      -  "sodiumMg"
      -]
    • changedOutput schema / properties / matches / items / type
      Previous value: -"object"New value: +"array"
    • addedOutput schema / properties / noMenu
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "date": {
      +        "type": "string"
      +      },
      +      "hall": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "hall",
      +      "date"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / note
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / nutrients
      Added value: +{
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / stale
      Added value: +{
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / units
      Added value: +{
      +  "additionalProperties": {
      +    "type": "string"
      +  },
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • removedOutput schema / properties / warning
      Removed value: -{
      -  "type": "string"
      -}
    • changedOutput schema / required
      Previous value: -[
      -  "date",
      -  "totalMatches",
      -  "matches",
      -  "failures",
      -  "warning"
      -]New value: +[
      +  "key",
      +  "totalMatches",
      +  "truncated",
      +  "stale",
      +  "matches",
      +  "failures"
      +]
  2. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial context on top: the exact row layout, when carbonFootprint and nutrient columns appear, that trait/allergen values are numeric codes resolvable via the returned key, and that 'stale' data is cached. The 'Allergens advisory' caveat is a meaningful safety disclosure no annotation carries.

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

Conciseness4/5

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

The filtering capability is front-loaded and nearly every sentence carries operational detail. The long row-ordering sentence is dense and partially overlaps the output schema, keeping it short of a 5.

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

Completeness5/5

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

For a 17-parameter tool with nested objects and no required fields, the description covers defaults, constraint side effects, output row structure, cache freshness, and the alternative nutrition call. Combined with the output schema and annotations, an agent has everything needed to invoke it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond it: a concrete nutrients syntax example, tier mappings for min_mhealthy and max_carbon, the rule that a constraint drops dishes with no value, and that query is a case-insensitive substring. The enumerated allergen/trait vocabularies duplicate the schema enums, which caps it below 5.

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

Purpose5/5

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

Opens with a specific verb and resource ('Filter dining hall menus') plus the exact dimension set it filters on. It also distinguishes itself from the closest sibling by stating 'Use include_nutrients to get full nutrition data in the same call - no need to call get_item_nutrition per dish.'

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

Usage Guidelines4/5

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

Gives a clear default behavior ('no params lists every dish for the day'), explains the untagged-drop side effect, and tells the agent when to re-call versus accept cached data ('Re-call only if you need guaranteed-fresh data'). It does not explicitly contrast itself with get_menu, so routing between those two is left implicit.

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