MCPサーバー

vitamind

io.github.JaviMaligno/vitamind
ヘルスケア 地図・位置情報 公開・接続可能 MCP 2025-11-25

このMCPでできること

Uses location, UV, weather, solar, and personal skin-profile data to estimate vitamin D synthesis windows, sun exposure duration, and sunburn risk.

compare_vitamin_d_year
Compare the vitamin D year of 2 to 5 places side by side in ONE call — 'Madrid vs Berlin vs Oslo, where do I actually get winter sun?'. Returns each place's months with sun, exact season span and viable days per year, plus rankedByViableDays. Use this instead of calling get_vitamin_d_year once per city: only this tool can draw the years on a shared axis.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['places'], 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'places': {'type': 'array', 'items': {'type': 'object', 'required': ['name', 'lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'name': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'How to label this place in the comparison'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'elevationM': {'type': 'number', 'maximum': 6000, 'minimum': -100, 'description': 'Ground elevation in metres (UV rises ~8%/km); default sea level'}}, 'additionalProperties': False}, 'maxItems': 5, 'minItems': 2, 'description': 'The places to compare, 2 to 5'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
configure_sun_profile
Show the user an interactive form for the four values every other tool assumes — Fitzpatrick skin type, fraction of skin exposed, age and target IU — with the minutes they need updating live. Use this when those values are unknown, when the user wants to change them, or instead of asking for them one at a time in conversation. Whatever the user picks comes back into the conversation; pass those values explicitly to the other tools afterwards.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': "Latitude of the place being discussed, so the live estimate uses today's real UV there"}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, paired with lat'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'placeName': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'How to label that place in the widget'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
estimate_sun_session
Estimate a sun session's outcome: 'I was (or will be) out N minutes — how much vitamin D did I make?' plus 'how long before I'd burn?' for the profile. Takes a start time (defaults to the day's best hour) and session minutes; returns estimated IU (with the physiological cap), average UV and clear-sky minutes-to-sunburn. Use for any 'how much did I get / can I get in X minutes' or 'how long without burning' question.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['lat', 'lon', 'minutes'], 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'date': {'type': 'string', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'Date as YYYY-MM-DD; defaults to today'}, 'minutes': {'type': 'number', 'maximum': 600, 'minimum': 1, 'description': 'Session length in minutes'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'startTime': {'type': 'string', 'pattern': '^\\d{1,2}:\\d{2}$', 'description': "Local HH:MM the session starts; defaults to the day's best hour"}, 'elevationM': {'type': 'number', 'maximum': 6000, 'minimum': -100, 'description': 'Ground elevation in metres (UV rises ~8%/km); default sea level'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
get_current_status
Whether RIGHT NOW is a good moment for vitamin D synthesis at a location, using live Open-Meteo UV/cloud data when reachable (clear-sky model otherwise): current UV index, minutes needed now, and when today's window opens or closes.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['lat', 'lon'], 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'elevationM': {'type': 'number', 'maximum': 6000, 'minimum': -100, 'description': 'Ground elevation in metres (UV rises ~8%/km); default sea level'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
get_my_cities
The signed-in user's current city and favorite cities with coordinates and timezones, ready to feed into the public tools. Requires OAuth (scope profile:read).
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
get_my_history
The signed-in user's sun history from the app's calendar: which recent days had viable sun, which they confirmed going outside, and their current streak. Covers the calendar days from `from` to `to`; records exist only for days the app was open, so a date missing from `records` means nothing was measured, not that the sun was insufficient. Requires OAuth (scope history:read). Renders as a calendar the user can tap to confirm a day.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'days': {'type': 'integer', 'maximum': 365, 'minimum': 1, 'description': 'How many recent days to return; default 30'}}, 'additionalProperties': False}
get_my_profile
The signed-in user's saved Vitamin D profile: skin type, exposed-skin default, age, target IU and their current city. Requires connecting with OAuth (scope profile:read). Call this FIRST for any personal question, then pass its values to the public tools instead of asking the user.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
get_sun_forecast
The NEXT FEW DAYS of vitamin D sun at a location, using the live Open-Meteo forecast: per day the peak UV, average cloud cover, the synthesis window and the minutes needed, plus bestDay. Use this for any question spanning several days — 'which day this week should I go out', 'will it be better tomorrow', 'when's my next chance' — instead of calling get_vitamin_d_window once per date.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['lat', 'lon'], 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'days': {'type': 'integer', 'maximum': 7, 'minimum': 2, 'description': 'How many days ahead, 2 to 7; default 5'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'elevationM': {'type': 'number', 'maximum': 6000, 'minimum': -100, 'description': 'Ground elevation in metres (UV rises ~8%/km); default sea level'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
get_sun_times
Sunrise, sunset, solar noon, civil dawn/dusk, morning AND evening golden hour, and day length (with day-over-day trend) for a location and date. Handles midnight sun and polar night. Pure sun times — for vitamin D questions use the vitamin_d tools instead.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'date': {'type': 'string', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'Date as YYYY-MM-DD; defaults to today'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}}, 'additionalProperties': False}
get_vitamin_d_window
The solar vitamin D synthesis window for ONE specific day at a location, for a personal profile: when UV is strong enough (index ≥ 3), the best hour, the clear-sky minutes needed to reach the target IU, and (with atTime) the minutes at the specific hour the user plans to go out. Returns synthesisPossible=false when the sun never gets high enough that day. Only for single-day questions — for months, seasons or 'when during the year', call get_vitamin_d_year instead of calling this once per date.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['lat', 'lon'], 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'date': {'type': 'string', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'Date as YYYY-MM-DD; defaults to today'}, 'atTime': {'type': 'string', 'pattern': '^\\d{1,2}:\\d{2}$', 'description': 'Local HH:MM the user plans to go out â\x80\x94 adds minutesNeeded and UV at that exact time'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'elevationM': {'type': 'number', 'maximum': 6000, 'minimum': -100, 'description': 'Ground elevation in metres (UV rises ~8%/km); default sea level'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
get_vitamin_d_year
The WHOLE YEAR of solar vitamin D for a location in a single call. monthsWithSun lists every month with at least one viable day (season edges count as partial months, see byMonth[].viableDays); solidMonths lists months where most days work; exactViableSpan gives the exact season boundaries; summary carries per-year aggregates for comparing places. Use this for any question about months, seasons, winter/summer or 'when during the year can I…' — never probe individual dates with get_vitamin_d_window for that.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['lat', 'lon'], 'properties': {'age': {'type': 'number', 'maximum': 120, 'minimum': 0, 'description': 'Age in years (synthesis declines with age); omit for adult baseline'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude in decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude in decimal degrees'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'timezone': {'type': 'string', 'maxLength': 64, 'description': "IANA timezone like 'Europe/Madrid'. Strongly recommended â\x80\x94 without it all times are UTC"}, 'placeName': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': "The place's name as the user said it â\x80\x94 used to caption the chart"}, 'elevationM': {'type': 'number', 'maximum': 6000, 'minimum': -100, 'description': 'Ground elevation in metres (UV rises ~8%/km); default sea level'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
log_sun_session
Sets a day's answer in the signed-in user's history calendar. Three values: confirmed=true (went out, the default), confirmed=false (had usable sun but stayed in), confirmed=null (clear the answer). Defaults to today. Requires OAuth (scope history:write).
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'date': {'type': 'string', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'Day to set, YYYY-MM-DD; defaults to today'}, 'minutes': {'type': 'number', 'maximum': 600, 'minimum': 1, 'description': 'Minutes the user reports having spent in the sun (acknowledged, not stored)'}, 'confirmed': {'type': ['boolean', 'null'], 'description': 'true (default) the user went out; false they had sun but stayed in; null clears the answer'}}, 'additionalProperties': False}
search_city
Find a city in the app's database by name (any of the app's six languages works) and get its coordinates, IANA timezone and elevation — feed those into the other tools.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['query'], 'properties': {'query': {'type': 'string', 'maxLength': 80, 'minLength': 1, 'description': "City name, e.g. 'Madrid', 'London', 'Nueva York'"}}, 'additionalProperties': False}
set_history_location
Records where the signed-in user was over a range of past days, so their history stops assuming. Use it when the user corrects a stretch — get_my_history marks inherited days with `locationAssumed`, and the history calendar offers those stretches for correction. Pass a cityId from search_city, or lat/lon. Changes only the location: whether they went outside that day is untouched. Requires OAuth (scope history:write).
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['from', 'to'], 'properties': {'to': {'type': 'string', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'Last day of the stretch, YYYY-MM-DD; same as `from` for one day'}, 'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude, for a place not in the database'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, paired with lat'}, 'from': {'type': 'string', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'First day of the stretch, YYYY-MM-DD'}, 'cityId': {'type': 'string', 'maxLength': 80, 'description': "City id from search_city, e.g. 'builtin:londres'"}}, 'additionalProperties': False}
update_my_profile
Save the signed-in user's synthesis profile — skin type, exposed-skin fraction, age and target IU — to their account, so the app and every later call use them. Requires OAuth (scope profile:write). Only these four values are writable; favourites, cities and history are not.
入力スキーマ
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'age': {'anyOf': [{'type': 'number', 'maximum': 120, 'minimum': 0}, {'type': 'null'}], 'description': 'Age in years, or null for the adult baseline'}, 'skinType': {'type': 'integer', 'maximum': 6, 'minimum': 1, 'description': 'Fitzpatrick skin type 1 (very fair) to 6 (very dark); default 3'}, 'targetIU': {'type': 'number', 'maximum': 10000, 'minimum': 100, 'description': 'Vitamin D target per session in IU; default 1000'}, 'exposedSkinFraction': {'type': 'number', 'maximum': 1, 'minimum': 0.05, 'description': 'Skin exposed: 0.10 face+hands, 0.18 face+arms, 0.25 t-shirt+shorts (default), 0.40 swimsuit'}}, 'additionalProperties': False}
追加
set_history_location
2026年9月17日12:42
追加
log_sun_session
2026年9月17日12:42
追加
get_my_history
2026年9月17日12:42
追加
update_my_profile
2026年9月17日12:42
追加
get_my_cities
2026年9月17日12:42
追加
get_my_profile
2026年9月17日12:42
追加
estimate_sun_session
2026年9月17日12:42
追加
get_current_status
2026年9月17日12:42
追加
compare_vitamin_d_year
2026年9月17日12:42
追加
get_sun_forecast
2026年9月17日12:42
追加
configure_sun_profile
2026年9月17日12:42
追加
get_vitamin_d_year
2026年9月17日12:42
追加
get_vitamin_d_window
2026年9月17日12:42
追加
get_sun_times
2026年9月17日12:42
追加
search_city
2026年9月17日12:42