sdv-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sdv_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vehemont
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
sdv_mcp-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: sdv-mcp
3
+ Version: 0.1.0
4
+ Summary: Read-only MCP server for inspecting Stardew Valley save files: save parser, Stardew Wiki verification, and 17 calculators across 40 tools.
5
+ Author: vehemont
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 vehemont
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/vehemont/sdv-mcp
29
+ Project-URL: Repository, https://github.com/vehemont/sdv-mcp
30
+ Project-URL: Issues, https://github.com/vehemont/sdv-mcp/issues
31
+ Keywords: stardew-valley,mcp,model-context-protocol,savegame
32
+ Requires-Python: >=3.10
33
+ Description-Content-Type: text/markdown
34
+ License-File: LICENSE
35
+ Requires-Dist: mcp>=1.2.0
36
+ Dynamic: license-file
37
+
38
+ # sdv-mcp
39
+
40
+ I recently got into the game with my wife and noticed I was spending more time reading the Stardew Wiki rather than playing, so I made this to answer the questions I had. This is a read-only MCP server that reads a Stardew Valley save and answers questions about it. It includes 40 tools, and also allows Stardew Wiki search through MediaWiki API. I made this with mainly vanilla in mind, so YMMV with mods.
41
+
42
+ > This MCP is read-only and should not cause any issues, but safety first is always the best approach! Use a save copy first, not an original. Stardew Valley makes a one-night-before backup automatically, denoted by the sufix _old in the filename.
43
+
44
+ ## Requirements
45
+ - Python 3.10+
46
+ - `pip install -r requirements.txt` (just the `mcp` SDK; wiki client uses stdlib `urllib`)
47
+
48
+ Keep the four modules in the same folder — the server imports the others from its own dir.
49
+
50
+ ## Install into a client
51
+
52
+ ### Recommended: uvx (auto-download, npx-style)
53
+ Needs [uv](https://docs.astral.sh/uv/). uvx clones/builds/caches the repo and runs
54
+ it — no manual install, no venv:
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "sdv-mcp": {
59
+ "command": "uvx",
60
+ "args": [
61
+ "--from", "git+https://github.com/vehemont/sdv-mcp",
62
+ "sdv-mcp",
63
+ "--save-dir", "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456"
64
+ ]
65
+ }
66
+ }
67
+ }
68
+ ```
69
+ Pin a version with `git+https://github.com/vehemont/sdv-mcp@v0.1.0`. Once it's on
70
+ PyPI this collapses to `"args": ["sdv-mcp", "--save-dir", "..."]`.
71
+
72
+ ### Alternative: run a local checkout
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "sdv-mcp": {
77
+ "command": "python",
78
+ "args": [
79
+ "/path/to/sdv-mcp/sdv_mcp_server.py",
80
+ "--save-dir", "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456"
81
+ ]
82
+ }
83
+ }
84
+ }
85
+ ```
86
+ macOS/Linux use `python3`; `pip install -r requirements.txt` first.
87
+
88
+ Either way: runs on stdio. Point `--save-dir` at your save FOLDER (main file
89
+ auto-located) or `--save` at the file; skip both and it auto-discovers.
90
+
91
+ ## Picking a save
92
+ Precedence for which save a tool reads:
93
+ 1. An explicit `save_path` on the tool call (a save file **or** a save folder).
94
+ 2. The save configured at server startup — `--save-dir DIR` / `--save FILE`, or the
95
+ `SDV_SAVE_DIR` / `SDV_SAVE_PATH` env var. Set this once in the MCP config and you
96
+ never pass `save_path` again. A CLI flag overrides the env var.
97
+ 3. Auto-discovery (Windows `%APPDATA%\StardewValley\Saves`, macOS/Linux `~/.config`
98
+ + Application Support, Steam Proton). One save = used; several = call `list_saves`
99
+ and pass the path.
100
+
101
+ Either a folder (`.../Saves/FarmName_123456`) or the file
102
+ (`.../Saves/FarmName_123456/FarmName_123456`) works everywhere a save is accepted —
103
+ given a folder, the main save file is auto-located (ignores `_old` backups and
104
+ `SaveGameInfo`).
105
+
106
+ Env-var config example (instead of the CLI flag):
107
+ ```json
108
+ "env": { "SDV_SAVE_DIR": "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456" }
109
+ ``
110
+
111
+ ## Disabling tools
112
+ Any tool you consider cheating/unfair can be turned off so the model never sees it.
113
+ Two knobs, both settable as a CLI arg (wins) or an env var:
114
+
115
+ - **Denylist** — `--disable-tools a,b,c` or `SDV_DISABLE_TOOLS=a,b,c`. Serves everything except those.
116
+ - **Allowlist** — `--enable-tools a,b,c` or `SDV_ENABLE_TOOLS=a,b,c`. Serves *only* those (disable is applied after).
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "sdv-mcp": {
122
+ "command": "python",
123
+ "args": [
124
+ "/path/to/sdv-mcp/sdv_mcp_server.py",
125
+ "--save-dir", "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456",
126
+ "--disable-tools", "find_item,missing_museum,perfection"
127
+ ]
128
+ }
129
+ }
130
+ }
131
+ ```
132
+
133
+ ## Tools (40)
134
+
135
+ ### Save state
136
+ | Tool | What |
137
+ |------|------|
138
+ | `list_saves` | Discovered saves (farm + path) |
139
+ | `overview` | Date, players, shared money, lifetime earnings, deepest mine, version |
140
+ | `players` | Per-player levels, XP, XP-to-next, professions, spouse, backpack, house |
141
+ | `community_center` | Rooms done/left, incomplete bundles + exact items needed, Vault status |
142
+ | `museum` | Donations / 95 + next milestone (60 = Rusty Key) |
143
+ | `monster_goals` | Guild eradication goals: kills vs target + reward |
144
+ | `friendships` | Villager hearts/points + spouse, per player |
145
+ | `player_tools` | Each player's tools + upgrade tier |
146
+ | `wallet` | Keys/special items (Rusty Key, Skull Key, Club Card, ...) |
147
+ | `feed` | Animals, silo hay, fiber, days of feed covered (+ fiber-as-grass-starters) |
148
+ | `full_report` | All of the above in one shot |
149
+
150
+ ### Inventory + location
151
+ | Tool | What |
152
+ |------|------|
153
+ | `inventory` | Backpacks + chests. `full=True` = all items; `by_container=True` = per-chest |
154
+ | `processing` | Held crops grouped fruit/veg/special by the save's own item category |
155
+ | `chests` | Every container: type (Chest/Stone/Big/special), map + tile, color, contents |
156
+ | `find_item` | Where is X? Searches backpacks, chests, machine outputs. Map + tile + color |
157
+ | `net_worth` | Gold + sellable value of everything held (from each item's own price) |
158
+
159
+ ### Planning + completion
160
+ | Tool | What |
161
+ |------|------|
162
+ | `can_complete_now` | CC bundles you could finish from what's in your chests right now |
163
+ | `missing_museum` | Undonated minerals + artifacts, with where they drop |
164
+ | `perfection` | Real weighted Perfection %: 11 categories, each with have/total + earned % |
165
+ | `daily_briefing` | Morning digest: luck, birthdays, festivals, machines/crops ready, pets due |
166
+ | `gift_helper` | Birthdays (from save) + your hearts + loved gifts, flags what you already hold |
167
+ | `ready_to_collect` | Machines with product ready + crops ready to harvest |
168
+ | `fish_available` | Fish catchable now (season/weather/time), `only_uncaught` filters |
169
+ | `mods` | Detect mods; list what couldn't map to vanilla (modded ids, unmapped bundle/museum) |
170
+
171
+ ### Calculators (save + verified game formulas)
172
+ | Tool | What |
173
+ |------|------|
174
+ | `skill_xp_forecast` | Actions to hit a target skill level (farming XP formula) |
175
+ | `fishing_xp_forecast` | Catches to a target fishing level (difficulty/perfect/treasure/legendary) |
176
+ | `processing_planner` | Kegs/jars to clear the crop backlog in N days + est. gross gold |
177
+ | `processing_value` | Raw vs wine/juice vs jelly/pickle for a crop (Tiller/Artisan/quality aware) |
178
+ | `crop_planner` | Crops that mature in the window + profit/tile (`quality_weighted` optional) |
179
+ | `crop_quality_odds` | Gold/silver/normal/iridium % from farming level + fertilizer + food buff |
180
+ | `sprinkler_plan` | Sprinklers + materials for N tiles, and whether your bars can build them |
181
+ | `fish_pond_forecast` | Days to fill a pond to capacity + roe notes |
182
+ | `friendship_forecast` | Loved gifts + weeks to a target heart level |
183
+ | `animal_product_quality` | Iridium/gold/silver produce odds per animal (friendship + mood + prof) |
184
+ | `animal_product_value` | Raw (Rancher) vs processed (Artisan) value of milk/egg/wool |
185
+ | `list_buffs` | Food buffs that raise a skill level (Farmer's Lunch +3, Trout Soup +1) |
186
+
187
+ ### Wiki verification (live)
188
+ | Tool | What |
189
+ |------|------|
190
+ | `wiki_search` | Search the Stardew Valley Wiki (titles + snippets) |
191
+ | `wiki_page` | A page (or one section) as clean text — to verify facts / pull context |
192
+ | `wiki_infobox` | A page's infobox as structured fields (price/season/location) |
193
+ | `villager_schedule` | A villager's wiki schedule + your save's date/weather/hearts |
194
+
195
+ ## How the model reads the output
196
+ Inputs have per-parameter descriptions and enums for constrained args (`quality` = normal/silver/gold/iridium, `artisan` = auto/true/false, etc.). The 11 calculator tools also declare an **output schema** (field names + types) so the shape is known up front. MCP output schemas can't carry field descriptions, so every result also has a `note` with units/formulas/caveats — read it. Unit conventions in key names: `*_pct` = percent, `*_gold` = gold, `*_days`/`days_*` = days, `*_xp` = XP.
197
+
198
+ ## Mods
199
+ Item classification (keg fruit/veg) is data-driven from each item's own `<category>` in the save, so vanilla content of any version is covered automatically. Modded items get detected (namespaced ids with a dot) and **excluded from vanilla-reference totals but reported by name/qty** — see `mods` and `processing.modded_items_excluded`. Bundle structure is read from the save, so overhaul/remix CCs parse; modded item *names* the parser can't resolve show as `#id`. Full modded-name resolution (loading `Data/Objects` + the `Mods` folder) is intentionally not built yet.
200
+
201
+ ## Verified, not guessed
202
+ The calculator constants were checked against the wiki, not pulled from memory: crop quality formula + multipliers (iridium 2x / gold 1.5x / silver 1.25x), farming + fishing XP formulas, Tiller +10% / Rancher +20% / Artisan +40%, keg/jar multipliers, sprinkler recipes, fish-pond reproduction, Perfection weights, animal-product prices. Reference tables (crops, prices, fish difficulty) live at the top of `sdv_calc.py` and `sdv_parser.py` — extend them, or cross-check anything with the `wiki_*` tools.
203
+
204
+ ## Releasing
205
+ CI publishes to PyPI on a version tag via **Trusted Publishing** (OIDC - no tokens).
206
+ One-time setup on PyPI: your account -> Publishing -> add a *pending* publisher:
207
+ - PyPI project: `sdv-mcp` Owner: `vehemont` Repo: `sdv-mcp`
208
+ - Workflow: `publish.yml` Environment: `pypi`
209
+
210
+ Then, per release:
211
+ ```bash
212
+ # bump version in pyproject.toml, commit, then:
213
+ git tag v0.1.0 && git push --tags
214
+ ```
215
+ `.github/workflows/publish.yml` builds, smoke-tests the wheel, and publishes.
216
+
217
+ First release without waiting on CI (uses your PyPI token):
218
+ ```bash
219
+ uv build && uv publish # prompts for token, or set UV_PUBLISH_TOKEN
220
+ ```
221
+
222
+ ## Packaging
223
+ `pyproject.toml` makes this a real package: `uv build` produces a wheel, and the `sdv-mcp` console script maps to `sdv_mcp_server:main`. Publish with `uv publish`.
224
+
225
+ ## Files
226
+ - `sdv_parser.py` — the read-only save parser (ElementTree)
227
+ - `sdv_wiki.py` — MediaWiki Action API client (api.php; the wiki's rest.php returns empty, so Action API it is), cached + rate-limited
228
+ - `sdv_calc.py` — the calculators + reference tables
229
+ - `sdv_mcp_server.py` — the 40 tools
230
+
231
+ ## Known limits
232
+ - Vanilla + whatever this wiki documents. Modded content lives on separate wikis.
233
+ - Full Shipment / missing-recipes by *name* aren't built yet — `perfection` gives the counts.
234
+ - Wiki tools need outbound network. The save tools don't.
@@ -0,0 +1,197 @@
1
+ # sdv-mcp
2
+
3
+ I recently got into the game with my wife and noticed I was spending more time reading the Stardew Wiki rather than playing, so I made this to answer the questions I had. This is a read-only MCP server that reads a Stardew Valley save and answers questions about it. It includes 40 tools, and also allows Stardew Wiki search through MediaWiki API. I made this with mainly vanilla in mind, so YMMV with mods.
4
+
5
+ > This MCP is read-only and should not cause any issues, but safety first is always the best approach! Use a save copy first, not an original. Stardew Valley makes a one-night-before backup automatically, denoted by the sufix _old in the filename.
6
+
7
+ ## Requirements
8
+ - Python 3.10+
9
+ - `pip install -r requirements.txt` (just the `mcp` SDK; wiki client uses stdlib `urllib`)
10
+
11
+ Keep the four modules in the same folder — the server imports the others from its own dir.
12
+
13
+ ## Install into a client
14
+
15
+ ### Recommended: uvx (auto-download, npx-style)
16
+ Needs [uv](https://docs.astral.sh/uv/). uvx clones/builds/caches the repo and runs
17
+ it — no manual install, no venv:
18
+ ```json
19
+ {
20
+ "mcpServers": {
21
+ "sdv-mcp": {
22
+ "command": "uvx",
23
+ "args": [
24
+ "--from", "git+https://github.com/vehemont/sdv-mcp",
25
+ "sdv-mcp",
26
+ "--save-dir", "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456"
27
+ ]
28
+ }
29
+ }
30
+ }
31
+ ```
32
+ Pin a version with `git+https://github.com/vehemont/sdv-mcp@v0.1.0`. Once it's on
33
+ PyPI this collapses to `"args": ["sdv-mcp", "--save-dir", "..."]`.
34
+
35
+ ### Alternative: run a local checkout
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "sdv-mcp": {
40
+ "command": "python",
41
+ "args": [
42
+ "/path/to/sdv-mcp/sdv_mcp_server.py",
43
+ "--save-dir", "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456"
44
+ ]
45
+ }
46
+ }
47
+ }
48
+ ```
49
+ macOS/Linux use `python3`; `pip install -r requirements.txt` first.
50
+
51
+ Either way: runs on stdio. Point `--save-dir` at your save FOLDER (main file
52
+ auto-located) or `--save` at the file; skip both and it auto-discovers.
53
+
54
+ ## Picking a save
55
+ Precedence for which save a tool reads:
56
+ 1. An explicit `save_path` on the tool call (a save file **or** a save folder).
57
+ 2. The save configured at server startup — `--save-dir DIR` / `--save FILE`, or the
58
+ `SDV_SAVE_DIR` / `SDV_SAVE_PATH` env var. Set this once in the MCP config and you
59
+ never pass `save_path` again. A CLI flag overrides the env var.
60
+ 3. Auto-discovery (Windows `%APPDATA%\StardewValley\Saves`, macOS/Linux `~/.config`
61
+ + Application Support, Steam Proton). One save = used; several = call `list_saves`
62
+ and pass the path.
63
+
64
+ Either a folder (`.../Saves/FarmName_123456`) or the file
65
+ (`.../Saves/FarmName_123456/FarmName_123456`) works everywhere a save is accepted —
66
+ given a folder, the main save file is auto-located (ignores `_old` backups and
67
+ `SaveGameInfo`).
68
+
69
+ Env-var config example (instead of the CLI flag):
70
+ ```json
71
+ "env": { "SDV_SAVE_DIR": "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456" }
72
+ ``
73
+
74
+ ## Disabling tools
75
+ Any tool you consider cheating/unfair can be turned off so the model never sees it.
76
+ Two knobs, both settable as a CLI arg (wins) or an env var:
77
+
78
+ - **Denylist** — `--disable-tools a,b,c` or `SDV_DISABLE_TOOLS=a,b,c`. Serves everything except those.
79
+ - **Allowlist** — `--enable-tools a,b,c` or `SDV_ENABLE_TOOLS=a,b,c`. Serves *only* those (disable is applied after).
80
+
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "sdv-mcp": {
85
+ "command": "python",
86
+ "args": [
87
+ "/path/to/sdv-mcp/sdv_mcp_server.py",
88
+ "--save-dir", "C:/Users/you/AppData/Roaming/StardewValley/Saves/FarmName_123456",
89
+ "--disable-tools", "find_item,missing_museum,perfection"
90
+ ]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Tools (40)
97
+
98
+ ### Save state
99
+ | Tool | What |
100
+ |------|------|
101
+ | `list_saves` | Discovered saves (farm + path) |
102
+ | `overview` | Date, players, shared money, lifetime earnings, deepest mine, version |
103
+ | `players` | Per-player levels, XP, XP-to-next, professions, spouse, backpack, house |
104
+ | `community_center` | Rooms done/left, incomplete bundles + exact items needed, Vault status |
105
+ | `museum` | Donations / 95 + next milestone (60 = Rusty Key) |
106
+ | `monster_goals` | Guild eradication goals: kills vs target + reward |
107
+ | `friendships` | Villager hearts/points + spouse, per player |
108
+ | `player_tools` | Each player's tools + upgrade tier |
109
+ | `wallet` | Keys/special items (Rusty Key, Skull Key, Club Card, ...) |
110
+ | `feed` | Animals, silo hay, fiber, days of feed covered (+ fiber-as-grass-starters) |
111
+ | `full_report` | All of the above in one shot |
112
+
113
+ ### Inventory + location
114
+ | Tool | What |
115
+ |------|------|
116
+ | `inventory` | Backpacks + chests. `full=True` = all items; `by_container=True` = per-chest |
117
+ | `processing` | Held crops grouped fruit/veg/special by the save's own item category |
118
+ | `chests` | Every container: type (Chest/Stone/Big/special), map + tile, color, contents |
119
+ | `find_item` | Where is X? Searches backpacks, chests, machine outputs. Map + tile + color |
120
+ | `net_worth` | Gold + sellable value of everything held (from each item's own price) |
121
+
122
+ ### Planning + completion
123
+ | Tool | What |
124
+ |------|------|
125
+ | `can_complete_now` | CC bundles you could finish from what's in your chests right now |
126
+ | `missing_museum` | Undonated minerals + artifacts, with where they drop |
127
+ | `perfection` | Real weighted Perfection %: 11 categories, each with have/total + earned % |
128
+ | `daily_briefing` | Morning digest: luck, birthdays, festivals, machines/crops ready, pets due |
129
+ | `gift_helper` | Birthdays (from save) + your hearts + loved gifts, flags what you already hold |
130
+ | `ready_to_collect` | Machines with product ready + crops ready to harvest |
131
+ | `fish_available` | Fish catchable now (season/weather/time), `only_uncaught` filters |
132
+ | `mods` | Detect mods; list what couldn't map to vanilla (modded ids, unmapped bundle/museum) |
133
+
134
+ ### Calculators (save + verified game formulas)
135
+ | Tool | What |
136
+ |------|------|
137
+ | `skill_xp_forecast` | Actions to hit a target skill level (farming XP formula) |
138
+ | `fishing_xp_forecast` | Catches to a target fishing level (difficulty/perfect/treasure/legendary) |
139
+ | `processing_planner` | Kegs/jars to clear the crop backlog in N days + est. gross gold |
140
+ | `processing_value` | Raw vs wine/juice vs jelly/pickle for a crop (Tiller/Artisan/quality aware) |
141
+ | `crop_planner` | Crops that mature in the window + profit/tile (`quality_weighted` optional) |
142
+ | `crop_quality_odds` | Gold/silver/normal/iridium % from farming level + fertilizer + food buff |
143
+ | `sprinkler_plan` | Sprinklers + materials for N tiles, and whether your bars can build them |
144
+ | `fish_pond_forecast` | Days to fill a pond to capacity + roe notes |
145
+ | `friendship_forecast` | Loved gifts + weeks to a target heart level |
146
+ | `animal_product_quality` | Iridium/gold/silver produce odds per animal (friendship + mood + prof) |
147
+ | `animal_product_value` | Raw (Rancher) vs processed (Artisan) value of milk/egg/wool |
148
+ | `list_buffs` | Food buffs that raise a skill level (Farmer's Lunch +3, Trout Soup +1) |
149
+
150
+ ### Wiki verification (live)
151
+ | Tool | What |
152
+ |------|------|
153
+ | `wiki_search` | Search the Stardew Valley Wiki (titles + snippets) |
154
+ | `wiki_page` | A page (or one section) as clean text — to verify facts / pull context |
155
+ | `wiki_infobox` | A page's infobox as structured fields (price/season/location) |
156
+ | `villager_schedule` | A villager's wiki schedule + your save's date/weather/hearts |
157
+
158
+ ## How the model reads the output
159
+ Inputs have per-parameter descriptions and enums for constrained args (`quality` = normal/silver/gold/iridium, `artisan` = auto/true/false, etc.). The 11 calculator tools also declare an **output schema** (field names + types) so the shape is known up front. MCP output schemas can't carry field descriptions, so every result also has a `note` with units/formulas/caveats — read it. Unit conventions in key names: `*_pct` = percent, `*_gold` = gold, `*_days`/`days_*` = days, `*_xp` = XP.
160
+
161
+ ## Mods
162
+ Item classification (keg fruit/veg) is data-driven from each item's own `<category>` in the save, so vanilla content of any version is covered automatically. Modded items get detected (namespaced ids with a dot) and **excluded from vanilla-reference totals but reported by name/qty** — see `mods` and `processing.modded_items_excluded`. Bundle structure is read from the save, so overhaul/remix CCs parse; modded item *names* the parser can't resolve show as `#id`. Full modded-name resolution (loading `Data/Objects` + the `Mods` folder) is intentionally not built yet.
163
+
164
+ ## Verified, not guessed
165
+ The calculator constants were checked against the wiki, not pulled from memory: crop quality formula + multipliers (iridium 2x / gold 1.5x / silver 1.25x), farming + fishing XP formulas, Tiller +10% / Rancher +20% / Artisan +40%, keg/jar multipliers, sprinkler recipes, fish-pond reproduction, Perfection weights, animal-product prices. Reference tables (crops, prices, fish difficulty) live at the top of `sdv_calc.py` and `sdv_parser.py` — extend them, or cross-check anything with the `wiki_*` tools.
166
+
167
+ ## Releasing
168
+ CI publishes to PyPI on a version tag via **Trusted Publishing** (OIDC - no tokens).
169
+ One-time setup on PyPI: your account -> Publishing -> add a *pending* publisher:
170
+ - PyPI project: `sdv-mcp` Owner: `vehemont` Repo: `sdv-mcp`
171
+ - Workflow: `publish.yml` Environment: `pypi`
172
+
173
+ Then, per release:
174
+ ```bash
175
+ # bump version in pyproject.toml, commit, then:
176
+ git tag v0.1.0 && git push --tags
177
+ ```
178
+ `.github/workflows/publish.yml` builds, smoke-tests the wheel, and publishes.
179
+
180
+ First release without waiting on CI (uses your PyPI token):
181
+ ```bash
182
+ uv build && uv publish # prompts for token, or set UV_PUBLISH_TOKEN
183
+ ```
184
+
185
+ ## Packaging
186
+ `pyproject.toml` makes this a real package: `uv build` produces a wheel, and the `sdv-mcp` console script maps to `sdv_mcp_server:main`. Publish with `uv publish`.
187
+
188
+ ## Files
189
+ - `sdv_parser.py` — the read-only save parser (ElementTree)
190
+ - `sdv_wiki.py` — MediaWiki Action API client (api.php; the wiki's rest.php returns empty, so Action API it is), cached + rate-limited
191
+ - `sdv_calc.py` — the calculators + reference tables
192
+ - `sdv_mcp_server.py` — the 40 tools
193
+
194
+ ## Known limits
195
+ - Vanilla + whatever this wiki documents. Modded content lives on separate wikis.
196
+ - Full Shipment / missing-recipes by *name* aren't built yet — `perfection` gives the counts.
197
+ - Wiki tools need outbound network. The save tools don't.
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sdv-mcp"
7
+ version = "0.1.0"
8
+ description = "Read-only MCP server for inspecting Stardew Valley save files: save parser, Stardew Wiki verification, and 17 calculators across 40 tools."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { file = "LICENSE" }
12
+ authors = [{ name = "vehemont" }]
13
+ keywords = ["stardew-valley", "mcp", "model-context-protocol", "savegame"]
14
+ dependencies = ["mcp>=1.2.0"]
15
+
16
+ [project.urls]
17
+ Homepage = "https://github.com/vehemont/sdv-mcp"
18
+ Repository = "https://github.com/vehemont/sdv-mcp"
19
+ Issues = "https://github.com/vehemont/sdv-mcp/issues"
20
+
21
+ [project.scripts]
22
+ sdv-mcp = "sdv_mcp_server:main"
23
+
24
+ [tool.setuptools]
25
+ py-modules = ["sdv_mcp_server", "sdv_parser", "sdv_wiki", "sdv_calc"]