umich-dining-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| UMICH_DINING_BASE_URL | No | The site to read. Default is https://dining.umich.edu. | |
| UMICH_DINING_MIN_GAP_MS | No | Minimum gap between requests in milliseconds. Default is 500. | |
| UMICH_DINING_TIMEOUT_MS | No | Per-request timeout in milliseconds. Default is 20000. | |
| UMICH_DINING_USER_AGENT | No | The User-Agent to use when requesting dining.umich.edu. Default is python-requests/2.32.3. | |
| UMICH_DINING_MAX_RETRIES | No | Number of retries after the first attempt. Default is 3. | |
| UMICH_DINING_TTL_PAST_MS | No | Cache lifetime of a past menu in milliseconds. Default is 86400000. | |
| UMICH_DINING_TTL_TODAY_MS | No | Cache lifetime of today's menu in milliseconds. Default is 900000. | |
| UMICH_DINING_TTL_FUTURE_MS | No | Cache lifetime of a future menu in milliseconds. Default is 21600000. | |
| UMICH_DINING_MAX_CONCURRENCY | No | Maximum number of requests in flight. Default is 2. | |
| UMICH_DINING_TTL_REGULAR_HOURS_MS | No | Cache lifetime of the weekly schedule in milliseconds. Default is 86400000. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_locationsA | List the dining halls and their service periods for the day, with whether they are open now. openNow is evaluated at the current campus-local time. The entries are the halls and their service periods for the day. stale means a page was served from an expired cache entry; asOf is the age of the data. Cafes, markets, bakeries, grills, prices and meal plans are out of scope. |
| get_menuA | Get the menu of one dining hall: meals, stations and dishes. Dish rows are arrays: [name, traits, allergens, mhealthyTier, calories, servingSize, servingSizeGrams] plus nutrients named by include_nutrients (a get_menu row never carries carbonFootprint). traits are codes 1-6 (glutenfree, halal, kosher, spicy, vegan, vegetarian); allergens are codes; read the key block. mhealthyTier 1-5. Calories kcal. With no meal, the meal being served now is returned (or the next one if closed); the response says which and why. Date defaults to today; site publishes today-3..+14. 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. |
| filter_dishesA | 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. |
| list_nutrition_fieldsA | List the canonical nutrient identifiers, their units, the alternative units a threshold may be written in, and the Daily Value basis of the published micronutrients. A constraint on a nutrient excludes the dishes that publish no value for it, and a value the site writes as "trace" or "< 1%" is missing rather than zero. sortFields includes servingSize, mhealthyTier and ratio syntax "a:b". |
| get_hoursA | Get the service periods published for a dining hall on the requested day, plus the regular weekly schedule. Accepts one hall, a list, or none for all (like filter_dishes). today is the day's published service periods and regular is the weekly schedule. A hall that cannot be read is reported in the failures and the other halls are still returned. The response carries the weekday name of the requested date. 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. |
| find_open_nowA | The dining halls that are serving at the given time of day, and the ids of the ones that are not, with the service periods of the day for the halls that are open. Without arguments the current campus-local time is used, and the response says which time it resolved. open carries the hall details and today's periods; closed carries hall ids only. stale means a page was served from an expired cache entry; asOf is the age of the data. |
| get_item_nutritionA | Get the full nutrition panel of one dish. Name matched case-insensitively; exact match wins, else unique substring. Dish row uses the same coded layout as the sweep tools. Panel values are numbers with one units map; micronutrient amount is the derived amount, with the published percent behind it. asOf data age. Allergens advisory. Use this only when you need the full panel for a single dish. For multiple dishes, use filter_dishes with include_nutrients instead. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| dining-halls | The ten supported University of Michigan dining halls, with their code. |
| taxonomy | The allergen, trait and station vocabularies of the dining site with their codes, the trait implication closure and the caveat that applies to all allergen data. |
TDQS
Scored across 7 tools
Three tools (list_locations, get_hours, find_open_now) all touch opening status and service periods, and get_menu/filter_dishes both surface dish data for the day. The descriptions do draw distinctions (openNow vs. periods vs. time-filtered open list; filtering vs. single-hall menu), but an agent could reasonably pick the wrong one for a 'is it open / what's on' question.
All tools are lowercase snake_case and verb-led (list_, get_, filter_, find_), which is predictable. The minor deviation is find_open_now, which is a verb+adverb phrase rather than the verb_noun shape used elsewhere.
Seven tools for a read-only dining domain (locations, menus, filtering, nutrition, hours, open-now, per-item nutrition) is well-scoped, with each tool earning its place.
Core read workflows are covered: locations, hall menus, cross-hall filtering with nutrients, nutrient field reference, hours, open-now, and item nutrition. Coverage is deliberately scoped to dining halls (cafes, prices, meal plans explicitly out), which is reasonable, though there is no direct station-level view beyond what get_menu/filter_dishes return.