faostat-skills 0.2.1 → 0.2.3

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.
package/README.md CHANGED
@@ -22,10 +22,12 @@ claude plugin install faostat-skills@faostat
22
22
 
23
23
  **OpenAI Codex**
24
24
  ```bash
25
- git clone https://github.com/berba-q/faostat-skills.git ~/.agents/skills/faostat-skills
25
+ # Clone, then copy each skill folder directly into your skills directory
26
+ git clone https://github.com/berba-q/faostat-skills.git /tmp/faostat-skills
27
+ cp -r /tmp/faostat-skills/skills/* ~/.codex/skills/
26
28
  ```
27
29
 
28
- **Other AI assistants** — copy the `skills/` directory to wherever your tool discovers skill files. Consult your provider's documentation for the correct skills directory path.
30
+ **Other AI assistants** — copy the contents of the `skills/` directory to wherever your tool discovers skill files. Consult your provider's documentation for the correct skills directory path.
29
31
 
30
32
  Once installed, try asking:
31
33
  ```
@@ -66,18 +68,24 @@ claude plugin update faostat-skills@faostat
66
68
 
67
69
  ### OpenAI Codex
68
70
 
69
- Clone this repo into your Codex skills directory:
71
+ Each skill folder must sit directly inside your Codex skills directory — not nested inside a parent folder. Clone and copy:
70
72
 
71
73
  ```bash
72
- git clone https://github.com/berba-q/faostat-skills.git ~/.agents/skills/faostat-skills
74
+ git clone https://github.com/berba-q/faostat-skills.git /tmp/faostat-skills
75
+ cp -r /tmp/faostat-skills/skills/* ~/.codex/skills/
73
76
  ```
74
77
 
75
- Or symlink the skills directory:
78
+ Or keep the repo for easy updates via `git pull`:
76
79
 
77
80
  ```bash
78
- ln -s /path/to/faostat-skills/skills ~/.agents/skills/faostat
81
+ git clone https://github.com/berba-q/faostat-skills.git ~/faostat-skills
82
+ for dir in ~/faostat-skills/skills/*/; do
83
+ ln -s "$dir" ~/.codex/skills/"$(basename "$dir")"
84
+ done
79
85
  ```
80
86
 
87
+ > Consult the [Codex documentation](https://platform.openai.com/docs/codex) for the exact skills directory path on your system.
88
+
81
89
  ### Other AI Assistants
82
90
 
83
91
  Copy the `skills/` directory to wherever your AI tool discovers skill files. Each skill is a self-contained `SKILL.md` with YAML frontmatter and markdown instructions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "faostat-skills",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Analysis skills for UN FAOSTAT food and agriculture data. Country profiles, commodity briefings, trade analysis, climate assessments, and data visualizations.",
5
5
  "author": "Griffiths Obli-Laryea",
6
6
  "license": "MIT",
@@ -28,7 +28,6 @@
28
28
  "skills/",
29
29
  "commands/",
30
30
  ".claude-plugin/",
31
- "marketplace.json",
32
31
  "README.md",
33
32
  "LICENSE"
34
33
  ]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-analytical-brief
3
- description: Use when the user wants a short, FAOSTAT-style analytical brief — a multi-page PDF policy document in the FAOSTAT house visual style, with a HIGHLIGHTS box, global/regional/country sections, numbered figures with source lines, explanatory notes, and a data appendix. Use when the user asks for "an analytical brief on X", "a FAOSTAT-style brief", "a policy brief", "a FAO-style write-up", or a short policymaker-facing report. Keywords: analytical brief, policy brief, FAOSTAT brief, FAO-style, brief, briefing (policy), policymakers, short report (policy). Do NOT use for journalistic long-reads (use `faostat-story`), academic papers (forthcoming `faostat-scientific-paper`), or single-page visual summaries (forthcoming `faostat-infographic`).
3
+ description: Use when the user wants a short, FAOSTAT-style analytical brief — a multi-page PDF policy document in the FAOSTAT house visual style, with a HIGHLIGHTS box, global/regional/country sections, numbered figures with source lines, explanatory notes, and a data appendix. Use when the user asks for "an analytical brief on X", "a FAOSTAT-style brief", "a policy brief", "a FAO-style write-up", or a short policymaker-facing report. Keywords analytical brief, policy brief, FAOSTAT brief, FAO-style, brief, briefing (policy), policymakers, short report (policy). Do NOT use for journalistic long-reads (use `faostat-story`), academic papers (forthcoming `faostat-scientific-paper`), or single-page visual summaries (forthcoming `faostat-infographic`).
4
4
  ---
5
5
 
6
6
  # FAOSTAT Analytical Brief
@@ -30,6 +30,7 @@ All 6 invariants from the FAOSTAT skill suite apply unchanged:
30
30
  4. **TCL for national trade aggregates, TM only for partner breakdowns.** Never sum TM rows to reconstruct national totals.
31
31
  5. **China composite default (user preference, Apr 2026).** Default to composite `China` (area 351) for country rankings, top-N lists and country-level analysis. Offer `China, mainland` (41) as an opt-in — do not substitute 41 unless the user asks for 41 explicitly. Flag the choice in the Methodology sheet, and include the caveat whenever a China number is quoted: FAOSTAT's own publications default to 41, so a brief using 351 will show a marginally larger "China" value than the FAO data-portal default. (Map figures inside the brief are an exception: they use the disaggregation path — area 41 on the CHN polygon with HKG / MAC / TWN rendered separately — because choropleths cannot sensibly render 351. See the map skill.)
32
32
  6. **`faostat_get_rankings` HTTP-500 fallback.** Reconstruct rankings from `faostat_get_data` + client-side sort; document fallback in the Methodology sheet.
33
+ 7. **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
33
34
 
34
35
  ## Workflow
35
36
 
@@ -64,7 +65,7 @@ For each figure and table, plan a specific `faostat_get_data` call. Log every ca
64
65
  - Use comma-separated year lists.
65
66
  - Use `response_format='compact'`.
66
67
  - Pass `show_unit=True`.
67
- - For trade aggregates, use **TCL** elements (2610 import quantity, 2910 export quantity, 2612 import value, 2912 export value) not TM sums.
68
+ - For trade aggregates, use **TCL** elements — not TM sums. Resolve element codes at runtime: e.g. `faostat_search_codes(domain_code='TCL', dimension_id='element', query='import quantity')` e.g. 2610; similarly for export quantity (~2910), import value (~2612), export value (~2912). Treat any numeric code here as a verified hint to validate against, not a value to pass directly.
68
69
  - For region figures, pull the 6 continental area codes (Africa 5100, Americas 5200, Asia 5300, Europe 5400, Oceania 5500, World 5000) directly — don't compute them client-side.
69
70
  - For top-N country figures, **don't** rely on `faostat_get_rankings`; pull `faostat_get_data` for the domain and element (no area filter) and sort client-side, so an HTTP-500 from `get_rankings` doesn't block the brief.
70
71
  - For China in country rankings and country-level analysis, keep composite `China` (area 351) and drop 41 (mainland), unless the user opted into 41 explicitly. (Map figures inside the brief use the disaggregation path — area 41 + HKG 96 + MAC 128 + TWN 214 — because a choropleth cannot render 351 sensibly.)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-climate
3
- description: Use when the user asks about agricultural emissions, climate impact of farming, agrifood carbon footprint, greenhouse gases from agriculture, deforestation, forest carbon sinks, temperature change, fertilizer emissions, N2O, land use change, emissions intensity, or the climate-agriculture nexus. Keywords: emissions, climate, carbon, greenhouse gas, GHG, deforestation, forest, temperature, warming, N2O, fertilizer emissions, land use, agrifood, emissions intensity, carbon sink. Do NOT use for a full country food security profile → `faostat-country-profile`. Do NOT use for trend ranking across commodities or countries → `faostat-trends`.
3
+ description: Use when the user asks about agricultural emissions, climate impact of farming, agrifood carbon footprint, greenhouse gases from agriculture, deforestation, forest carbon sinks, temperature change, fertilizer emissions, N2O, land use change, emissions intensity, or the climate-agriculture nexus. Keywords emissions, climate, carbon, greenhouse gas, GHG, deforestation, forest, temperature, warming, N2O, fertilizer emissions, land use, agrifood, emissions intensity, carbon sink. Do NOT use for a full country food security profile → `faostat-country-profile`. Do NOT use for trend ranking across commodities or countries → `faostat-trends`.
4
4
  ---
5
5
 
6
6
  # Agrifood Climate Analyzer
@@ -28,13 +28,13 @@ Before starting, verify that the FAOSTAT MCP tools are available: `faostat_searc
28
28
 
29
29
  ## Element Filter Reference
30
30
 
31
- Every `faostat_get_data` call below specifies an `element` filter. Without one, emissions domains return dozens of sub-elements per year and the payload explodes. If an element code is unfamiliar, resolve via `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='...')`.
31
+ Every `faostat_get_data` call below specifies an `element` filter. Without one, emissions domains return dozens of sub-elements per year and the payload explodes.
32
+
33
+ **Rule:** For GT, GF, ET, RL, RFN, RP — the codes below are stable and may be used directly. For **EM domain elements, always resolve at runtime** via `faostat_search_codes(domain_code='EM', dimension_id='element', query='<metric>')` — never hardcode them. The verified codes shown are reference hints only.
32
34
 
33
35
  | Metric | Domain | Filter code |
34
36
  |--------|--------|-------------|
35
37
  | Emissions (CO2eq) | GT | `724313` |
36
- | Share in total emissions (%) | EM | `7231` |
37
- | Emissions per capita (kg CO2eq/person) | EM | `723112` |
38
38
  | Temperature change (°C) | ET | `7271` |
39
39
  | Net forest conversion (area, ha) | GF | `6646` |
40
40
  | Forest land emissions (CO2eq) | GF | `724313` |
@@ -43,6 +43,23 @@ Every `faostat_get_data` call below specifies an `element` filter. Without one,
43
43
  | N fertilizer use (tonnes) | RFN | `5157` |
44
44
  | Pesticide use (tonnes) | RP | `5157` |
45
45
 
46
+ **EM domain — resolve at runtime (hints only):**
47
+
48
+ | Metric | Element query | Verified code |
49
+ |--------|--------------|---------------|
50
+ | Emissions per capita | `query='per capita'` | `7279` |
51
+ | Share of agrifood in national total (CO2eq AR5) | `query='share CO2eq'` | `726313` |
52
+ | Emissions per value of agricultural production | `query='per value'` | `72791` |
53
+
54
+ **EM domain item codes (for filtering the agrifood breakdown):**
55
+
56
+ | Item | Code |
57
+ |------|------|
58
+ | Agrifood systems (broadest total) | `6518` |
59
+ | Farm gate | `6996` |
60
+ | Land-use change | `6516` |
61
+ | Pre- and post-production | `6517` |
62
+
46
63
  Year-range syntax: use explicit comma-separated lists (`year='2014,2015,...,2023'`). Colon ranges (`'2014:2023'`) have returned empty in practice.
47
64
 
48
65
  ## Sub-workflow Detection
@@ -74,12 +91,18 @@ If the question does not clearly match one sub-workflow, present the five option
74
91
  )
75
92
  ```
76
93
  Identify total agrifood emissions trend and the breakdown by source category (farm gate, land use, pre/post production — these come through as different `item` codes within GT).
77
- 4. Pull emissions indicators from the **EM** domain:
94
+ 4. Resolve EM element codes at runtime (do not hardcode):
95
+ ```
96
+ faostat_search_codes(domain_code='EM', dimension_id='element', query='per capita')
97
+ faostat_search_codes(domain_code='EM', dimension_id='element', query='share CO2eq')
98
+ ```
99
+ Use the returned codes (e.g. `7279` for per capita, `726313` for share) in the data call:
78
100
  ```
79
101
  faostat_get_data(
80
102
  domain_code='EM',
81
103
  area='<area_code>',
82
- element='7231,723112', # Share in total (%), per capita (kg CO2eq)
104
+ item='6518', # Agrifood systems total
105
+ element='<per_capita_code>,<share_code>',
83
106
  year='2019,2020,2021,2022,2023',
84
107
  response_format='compact'
85
108
  )
@@ -119,12 +142,17 @@ If the question does not clearly match one sub-workflow, present the five option
119
142
  response_format='compact'
120
143
  )
121
144
  ```
122
- 4. Pull emissions indicators from the **EM** domain for all entities:
145
+ 4. Resolve EM element codes at runtime, then pull indicators for all entities:
146
+ ```
147
+ faostat_search_codes(domain_code='EM', dimension_id='element', query='per capita')
148
+ faostat_search_codes(domain_code='EM', dimension_id='element', query='share CO2eq')
149
+ ```
123
150
  ```
124
151
  faostat_get_data(
125
152
  domain_code='EM',
126
153
  area='<code1>,<code2>,...',
127
- element='7231,723112',
154
+ item='6518', # Agrifood systems total
155
+ element='<per_capita_code>,<share_code>',
128
156
  year='2019,2020,2021,2022,2023',
129
157
  response_format='compact'
130
158
  )
@@ -213,6 +241,7 @@ If the question does not clearly match one sub-workflow, present the five option
213
241
  - **Always pass an `element` filter to `faostat_get_data`.** Emissions domains return dozens of sub-elements per year and the payload explodes without one.
214
242
  - **Always pass an explicit comma-separated `year` list.** Colon ranges like `'2014:2023'` have returned empty in practice.
215
243
  - Always include the source attribution line at the end of any output.
244
+ - **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
216
245
 
217
246
  ## Error Handling and Reliability Notes
218
247
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-commodity
3
- description: Use when the user asks about a specific crop or commodity — global production, top producers, yield trends, trade flows, or a commodity briefing. Keywords: commodity, crop, wheat, rice, maize, coffee, cocoa, soybean, sugar, cotton, palm oil, production rankings, top producers, yield, trade, global supply, briefing, deep dive. Do NOT use for side-by-side entity comparison → `faostat-compare`. Do NOT use for a country food security profile → `faostat-country-profile`. Do NOT use for trend ranking across commodities → `faostat-trends`.
3
+ description: Use when the user asks about a specific crop or commodity — global production, top producers, yield trends, trade flows, or a commodity briefing. Keywords commodity, crop, wheat, rice, maize, coffee, cocoa, soybean, sugar, cotton, palm oil, production rankings, top producers, yield, trade, global supply, briefing, deep dive. Do NOT use for side-by-side entity comparison → `faostat-compare`. Do NOT use for a country food security profile → `faostat-country-profile`. Do NOT use for trend ranking across commodities → `faostat-trends`.
4
4
  ---
5
5
 
6
6
  # Commodity Deep Dive
@@ -75,10 +75,11 @@ faostat_get_rankings(
75
75
  **If `faostat_get_rankings` returns an HTTP 500 or other error** (this happens — the endpoint is intermittently unreliable), fall back to pulling all countries via `faostat_get_data` and sorting client-side:
76
76
 
77
77
  ```
78
+ # Resolve element at runtime: faostat_search_codes(domain_code='QCL', dimension_id='element', query='production') → e.g. 2510
78
79
  faostat_get_data(
79
80
  domain_code='QCL',
80
81
  item='<item_code>',
81
- element='2510', # FILTER code for Production
82
+ element='<resolved_production_code>',
82
83
  year='<recent_year>',
83
84
  response_format='compact',
84
85
  limit=300, # cover all reporter countries
@@ -92,6 +93,8 @@ Then sort the returned rows by value descending and take the top 10. Exclude reg
92
93
 
93
94
  **Important code-system note:** `faostat_get_rankings` uses DISPLAY element codes (Production = `5510`). `faostat_get_data` uses FILTER element codes (Production = `2510`, Area harvested = `2312`, Yield = `2413`). These are different code systems — don't mix them.
94
95
 
96
+ > Element codes above are verified hints. Resolve at runtime via `faostat_search_codes` before use.
97
+
95
98
  ### Step 4: Pull annual yield, production, and area series for the top 5
96
99
 
97
100
  For each of the top 5 producers from Step 3, pull a full 10-year annual series rather than just endpoints. This is worth the extra rows because year-to-year volatility (droughts, disease outbreaks, policy shocks) is part of the story and a 2-point comparison can hide it.
@@ -99,19 +102,24 @@ For each of the top 5 producers from Step 3, pull a full 10-year annual series r
99
102
  Three calls, each for the top-5 area codes as a comma-separated list:
100
103
 
101
104
  ```
105
+ # Resolve elements at runtime:
106
+ # faostat_search_codes(domain_code='QCL', dimension_id='element', query='production') → e.g. 2510
107
+ # faostat_search_codes(domain_code='QCL', dimension_id='element', query='area harvested') → e.g. 2312
108
+ # faostat_search_codes(domain_code='QCL', dimension_id='element', query='yield') → e.g. 2413
109
+
102
110
  # Production
103
111
  faostat_get_data(domain_code='QCL', area='<top5_area_codes>', item='<item_code>',
104
- element='2510', year='2014:2023', response_format='compact',
112
+ element='<resolved_production_code>', year='2014:2023', response_format='compact',
105
113
  limit=100, show_unit=True)
106
114
 
107
115
  # Area harvested
108
116
  faostat_get_data(domain_code='QCL', area='<top5_area_codes>', item='<item_code>',
109
- element='2312', year='2014:2023', response_format='compact',
117
+ element='<resolved_area_harvested_code>', year='2014:2023', response_format='compact',
110
118
  limit=100, show_unit=True)
111
119
 
112
120
  # Yield
113
121
  faostat_get_data(domain_code='QCL', area='<top5_area_codes>', item='<item_code>',
114
- element='2413', year='2014:2023', response_format='compact',
122
+ element='<resolved_yield_code>', year='2014:2023', response_format='compact',
115
123
  limit=100, show_unit=True)
116
124
  ```
117
125
 
@@ -122,15 +130,19 @@ Update the year window if you used a different reference year in Step 3 (aim for
122
130
  **Use the `TCL` domain** (Trade — Crops and Livestock Products) for aggregate country-level import and export totals. TCL gives you each country's total exports and total imports of the commodity as single rows — which is what you need for a top-exporters and top-importers table.
123
131
 
124
132
  ```
125
- # Top exporters by value (or switch to quantity element 5910)
133
+ # Resolve elements at runtime:
134
+ # faostat_search_codes(domain_code='TCL', dimension_id='element', query='export value') → e.g. 5922
135
+ # faostat_search_codes(domain_code='TCL', dimension_id='element', query='import value') → e.g. 5622
136
+
137
+ # Top exporters by value (or switch to quantity element resolved via faostat_search_codes)
126
138
  faostat_get_data(domain_code='TCL', item='<item_code>',
127
- element='5922', # Export Value (USD 1000)
139
+ element='<resolved_export_value_code>',
128
140
  year='<recent_year>', response_format='compact',
129
141
  limit=200, show_unit=True)
130
142
 
131
143
  # Top importers
132
144
  faostat_get_data(domain_code='TCL', item='<item_code>',
133
- element='5622', # Import Value (USD 1000)
145
+ element='<resolved_import_value_code>',
134
146
  year='<recent_year>', response_format='compact',
135
147
  limit=200, show_unit=True)
136
148
  ```
@@ -148,8 +160,9 @@ Based on the classification from Step 2, pull one additional dataset:
148
160
  **Food staple — Consumption & Food Security:** pull Food Balance Sheet data via the `FBS` domain. Look for food supply (kg/capita/yr), calories (kcal/capita/day), and protein (g/capita/day) at the world level plus the top 5 producer/consumer countries.
149
161
 
150
162
  ```
163
+ # Resolve element at runtime: faostat_search_codes(domain_code='FBS', dimension_id='element', query='food supply') → e.g. 645 / 664 / 674
151
164
  faostat_get_data(domain_code='FBS', item='<fbs_item_code>',
152
- element='<645 or 664 or 674>', year='<recent_year>',
165
+ element='<resolved_food_supply_code>', year='<recent_year>',
153
166
  response_format='compact', limit=50, show_unit=True)
154
167
  ```
155
168
 
@@ -158,8 +171,9 @@ You'll need to resolve the FBS item code separately via `faostat_search_codes(do
158
171
  **Cash crop — Price Dynamics:** pull producer-price series via the `PP` domain for the top 5 producers over the last 5 years. Report year-over-year changes and note any recent shocks.
159
172
 
160
173
  ```
174
+ # Resolve element at runtime: faostat_search_codes(domain_code='PP', dimension_id='element', query='producer price') → e.g. 5532
161
175
  faostat_get_data(domain_code='PP', area='<top5_area_codes>', item='<item_code>',
162
- element='5532', # Producer Price, USD/tonne
176
+ element='<resolved_producer_price_code>',
163
177
  year='<5yr_range>', response_format='compact',
164
178
  limit=100, show_unit=True)
165
179
  ```
@@ -217,6 +231,10 @@ End the briefing with a methodology footer and source line:
217
231
 
218
232
  Do not omit the source line — it's how users verify figures and know when the data was pulled.
219
233
 
234
+ ## Important Rules
235
+
236
+ **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
237
+
220
238
  ## Error handling and reliability notes
221
239
 
222
240
  - **`faostat_get_rankings` returns HTTP 500 intermittently.** This is the most common failure you'll hit. The Step 3 fallback (pull all countries with `faostat_get_data` and sort client-side) is the documented workaround. Don't spend many retries on the rankings endpoint — try once, fall back, and move on.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-compare
3
- description: Use ONLY when the user explicitly asks to compare two or more specific named entities (countries, commodities, or regions) side by side. Keywords: compare, comparison, versus, vs, benchmark, countries, crops, production, yield, area harvested, trade, growth rate. Do NOT use for a global commodity briefing → `faostat-commodity`. Do NOT use for a country food security profile → `faostat-country-profile`. Do NOT use for trend ranking (fastest growing/declining) → `faostat-trends`. Do NOT use for import dependency or supply chain risk → `faostat-trade`.
3
+ description: Use ONLY when the user explicitly asks to compare two or more specific named entities (countries, commodities, or regions) side by side. Keywords compare, comparison, versus, vs, benchmark, countries, crops, production, yield, area harvested, trade, growth rate. Do NOT use for a global commodity briefing → `faostat-commodity`. Do NOT use for a country food security profile → `faostat-country-profile`. Do NOT use for trend ranking (fastest growing/declining) → `faostat-trends`. Do NOT use for import dependency or supply chain risk → `faostat-trade`.
4
4
  ---
5
5
 
6
6
  # Comparative Agricultural Analysis
@@ -34,6 +34,9 @@ Determine from the user's message (or ask if unclear):
34
34
  - Agrifood emissions: **GT**; temperature change: **ET**; land use: **RL**
35
35
 
36
36
  Map the metric to the correct FAOSTAT element FILTER codes:
37
+
38
+ > Element codes below are verified hints. Resolve at runtime via `faostat_search_codes` before use.
39
+
37
40
  - Production (QCL): `'2510'`
38
41
  - Yield (QCL): `'2413'`
39
42
  - Area harvested (QCL): `'2312'`
@@ -60,7 +63,7 @@ For each entity combination, call `faostat_get_data` with:
60
63
  - `domain_code='<domain>'`
61
64
  - `area='<area_code>'` (or comma-separated codes if comparing multiple countries for one item)
62
65
  - `item='<item_code>'` (or comma-separated codes if comparing multiple items)
63
- - `element='<element_filter_code>'`
66
+ - `element='<element_filter_code>'` — resolve first: `faostat_search_codes(domain_code='<domain>', dimension_id='element', query='<metric name>')` → use the returned FILTER code; reference hints in Step 1 to validate
64
67
  - `year='2014,2015,2016,2017,2018,2019,2020,2021,2022,2023'` — use an **explicit comma-separated year list**. Colon ranges like `'2014:2023'` have returned empty in practice; avoid them.
65
68
  - `response_format='compact'` (saves tokens for multi-entity queries)
66
69
  - `limit=200` (increase limit for multi-year, multi-entity queries)
@@ -103,6 +106,10 @@ End with:
103
106
 
104
107
  > Source: FAOSTAT (FAO), accessed [current date].
105
108
 
109
+ ## Important Rules
110
+
111
+ **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
112
+
106
113
  ## Error Handling
107
114
 
108
115
  - If data is missing for some years for an entity, note the gap and compute metrics on available data only.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-country-profile
3
- description: Use when the user asks for a food security profile, country agricultural overview, country hunger or nutrition assessment, or food system summary for a specific country. Keywords: country profile, food security, undernourishment, production, trade, nutrition, calorie supply, dietary energy. Do NOT use for import dependence and supply chain risk → `faostat-trade`. Do NOT use for a global commodity briefing → `faostat-commodity`. Do NOT use for side-by-side country comparison → `faostat-compare`.
3
+ description: Use when the user asks for a food security profile, country agricultural overview, country hunger or nutrition assessment, or food system summary for a specific country. Keywords country profile, food security, undernourishment, production, trade, nutrition, calorie supply, dietary energy. Do NOT use for import dependence and supply chain risk → `faostat-trade`. Do NOT use for a global commodity briefing → `faostat-commodity`. Do NOT use for side-by-side country comparison → `faostat-compare`.
4
4
  ---
5
5
 
6
6
  # Country Food Security Profile
@@ -29,6 +29,8 @@ If any tool is missing, inform the user: "This skill requires the FAOSTAT MCP se
29
29
 
30
30
  ## Element Code Reference
31
31
 
32
+ > Element codes below are verified hints. Resolve at runtime via `faostat_search_codes` before use.
33
+
32
34
  - **Production quantity (QCL)**: filter `2510`, display `5510`
33
35
  - **Import quantity (TCL)**: filter `2610`; **Export quantity (TCL)**: filter `2910`
34
36
  - **Import value (TCL, USD 1000)**: filter `2612`; **Export value (TCL, USD 1000)**: filter `2912`
@@ -61,7 +63,7 @@ Store the confirmed `area` code for all subsequent queries.
61
63
  Call `faostat_get_data` with:
62
64
  - `domain_code='QCL'`
63
65
  - `area='<resolved_area_code>'`
64
- - `element='2510'` (Production — this is the FILTER code)
66
+ - `element='<resolved_production_code>'` — resolve at runtime: `faostat_search_codes(domain_code='QCL', dimension_id='element', query='production quantity')` → e.g. `2510` (Production — this is the FILTER code)
65
67
  - `year='<most_recent_year>'` (try the current year minus 2; if no data, try minus 3)
66
68
  - `response_format='compact'`
67
69
  - `limit=20`
@@ -74,7 +76,7 @@ Sort the results by value descending and identify the **top 5 crops by productio
74
76
  Call `faostat_get_data` with specific element filters so the payload stays small:
75
77
  - `domain_code='FS'`
76
78
  - `area='<resolved_area_code>'`
77
- - `element='210041,210011'` (prevalence of undernourishment, number undernourished). Add other FS element codes if needed — resolve via `faostat_search_codes(domain_code='FS', dimension_id='element', query='...')`.
79
+ - `element='<resolved_fs_codes>'` — resolve at runtime: `faostat_search_codes(domain_code='FS', dimension_id='element', query='undernourishment')` → e.g. `210041,210011` (prevalence of undernourishment, number undernourished). Add other FS element codes if needed — resolve via `faostat_search_codes(domain_code='FS', dimension_id='element', query='...')`.
78
80
  - `year='2014,2015,2016,2017,2018,2019,2020,2021,2022,2023'` (use explicit comma list — colon ranges like `'2014:2023'` have returned empty in practice)
79
81
  - `response_format='compact'`
80
82
 
@@ -91,7 +93,7 @@ If data is sparse, note which indicators are unavailable.
91
93
  Call `faostat_get_data` with:
92
94
  - `domain_code='FBS'`
93
95
  - `area='<resolved_area_code>'`
94
- - `element='664,674,684,645'` (kcal/cap/day, protein g/cap/day, fat g/cap/day, food kg/cap/yr)
96
+ - `element='<resolved_fbs_codes>'` — resolve at runtime: `faostat_search_codes(domain_code='FBS', dimension_id='element', query='food supply kcal')` and similar queries for protein/fat → e.g. `664,674,684,645` (kcal/cap/day, protein g/cap/day, fat g/cap/day, food kg/cap/yr)
95
97
  - `year='<latest 2-3 years available — FBS typically lags QCL by 1 year>'`
96
98
  - `item='2901'` (Grand Total for headline metrics); for item-specific breakdown (e.g., wheat contribution) resolve via `faostat_search_codes`
97
99
  - `response_format='compact'`
@@ -106,11 +108,16 @@ Extract:
106
108
  ### Step 6: Pull Trade Summary (TCL, not TM)
107
109
 
108
110
  Use **TCL** (country-level aggregate trade) for total imports and exports:
109
- ```
111
+ ```python
112
+ # Resolve elements at runtime:
113
+ # faostat_search_codes(domain_code='TCL', dimension_id='element', query='import quantity') → e.g. 2610
114
+ # faostat_search_codes(domain_code='TCL', dimension_id='element', query='export quantity') → e.g. 2910
115
+ # faostat_search_codes(domain_code='TCL', dimension_id='element', query='import value') → e.g. 2612
116
+ # faostat_search_codes(domain_code='TCL', dimension_id='element', query='export value') → e.g. 2912
110
117
  faostat_get_data(
111
118
  domain_code='TCL',
112
119
  area='<resolved_area_code>',
113
- element='2610,2910,2612,2912', # import qty, export qty, import value, export value
120
+ element='<resolved_import_qty>,<resolved_export_qty>,<resolved_import_val>,<resolved_export_val>',
114
121
  year='<latest 3 years>',
115
122
  response_format='compact',
116
123
  limit=500
@@ -149,6 +156,10 @@ End the report with:
149
156
 
150
157
  > Source: FAOSTAT (FAO), accessed [current date]. Data may reflect reporting lags of 1-3 years.
151
158
 
159
+ ## Important Rules
160
+
161
+ **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
162
+
152
163
  ## Error Handling
153
164
 
154
165
  - If a domain returns no data for the country, note it in the report and continue with available data.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-explore
3
- description: Use when the user wants to discover what data is available in FAOSTAT, browse domains, understand what a domain contains, or is new to FAOSTAT and wants a guided tour. Use when the user mentions a topic and wants to know what FAOSTAT data covers it. Keywords: explore, discover, browse, what data, available, domains, catalog, tour, overview, what can I find, show me, help me understand, new to FAOSTAT, getting started
3
+ description: Use when the user wants to discover what data is available in FAOSTAT, browse domains, understand what a domain contains, or is new to FAOSTAT and wants a guided tour. Use when the user mentions a topic and wants to know what FAOSTAT data covers it. Keywords explore, discover, browse, what data, available, domains, catalog, tour, overview, what can I find, show me, help me understand, new to FAOSTAT, getting started
4
4
  ---
5
5
 
6
6
  # FAOSTAT Explorer
@@ -110,6 +110,10 @@ If the user wants to query, use `faostat_search_codes` to resolve any entity nam
110
110
 
111
111
  **Important:** Element FILTER codes differ from DISPLAY codes. When calling `faostat_get_data`, use the filter code for the `element` parameter. When calling `faostat_get_rankings`, use the DISPLAY code. If unsure, use `faostat_search_codes` with `dimension_id='element'` to find the correct code.
112
112
 
113
+ ## Important Rules
114
+
115
+ **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
116
+
113
117
  ### Step 7 — Attribution
114
118
 
115
119
  When presenting any data, always include:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: faostat-export-dataset
3
- description: Use when the user wants a clean, documented tabular export of FAOSTAT data — "export FAOSTAT", "download the data", "give me the CSV / xlsx of [indicator]", "I want the raw numbers", "tabular data pull", "export to spreadsheet". The deliverable is a bundle: one multi-sheet .xlsx (README / Data_tidy / Data_wide / Methodology / Sources) + one tidy-long .csv mirror + a data-dictionary .md. No prose, no charts, no narrative — just the data with full provenance. Do NOT use for reports, briefs, papers, infographics, or visualisations — those skills embed their own xlsx appendices. Use this skill when the data itself IS the deliverable.
3
+ description: Use when the user wants a clean, documented tabular export of FAOSTAT data — "export FAOSTAT", "download the data", "give me the CSV / xlsx of [indicator]", "I want the raw numbers", "tabular data pull", "export to spreadsheet". The deliverable is a bundle one multi-sheet .xlsx (README / Data_tidy / Data_wide / Methodology / Sources) + one tidy-long .csv mirror + a data-dictionary .md. No prose, no charts, no narrative — just the data with full provenance. Do NOT use for reports, briefs, papers, infographics, or visualisations — those skills embed their own xlsx appendices. Use this skill when the data itself IS the deliverable.
4
4
  ---
5
5
 
6
6
  # FAOSTAT Data Export
@@ -24,12 +24,14 @@ Cross-skill invariants (all six — violations are skill bugs):
24
24
  5. **China composite default (Apr 2026 user preference).** Default: composite `China` (area 351). `China, mainland` (41) is an opt-in; full disaggregation (41 + 96 + 128 + 214) is also opt-in. Record the choice in the README sheet with the FAOSTAT-default-41 caveat.
25
25
  6. **`faostat_get_rankings` HTTP-500 fallback.** On failure, reconstruct by pulling `faostat_get_data` across all reporting countries and sorting client-side. Note the fallback in Methodology.
26
26
 
27
+ 7. **Element and item code resolution.** Never use a hardcoded numeric element or item code as the primary value in a `faostat_get_data` call. Always resolve at runtime: `faostat_search_codes(domain_code='<dom>', dimension_id='element', query='<metric name>')` for elements; `faostat_search_codes(domain_code='<dom>', dimension_id='item', query='<item name>')` for items. Numeric codes shown in reference tables and code examples are verified hints — use them to validate the search result, not as the authoritative source. Domain letter-codes (QCL, TCL, GT, EM, FBS, FS…) are stable and may be used directly.
28
+
27
29
  Export-specific invariants:
28
30
 
29
- 7. **Every value traces to an API call.** The Methodology sheet logs one row per `faostat_get_data` call with domain / area / element / item / year list / timestamp / rows-returned. No value appears in the export that did not come from a documented call.
30
- 8. **FAO-native units kept as-is.** No auto-conversion. Values stay in FAOSTAT's native units (kt CO₂eq, tonnes, USD 1000, etc.). Unit is a column in tidy-long and a header row in wide. If the user explicitly asks for normalised units, add normalised columns **alongside** the native ones — never in place of.
31
- 9. **No FAO branding.** No FAO logo, "Food and Agriculture Organization of the United Nations" masthead, ISSN, "FAO Statistics Division" stamp, or "Required citation: FAO. …" line. CC-BY-4.0 attribution to FAOSTAT (source, licence, access date) IS kept — that's a property of the source data.
32
- 10. **Both shapes in the xlsx.** `Data_tidy` (long) and `Data_wide` (years-as-columns pivot) are both always present. The CSV mirror is tidy-long only. A wide CSV is produced only if the user asks.
31
+ 8. **Every value traces to an API call.** The Methodology sheet logs one row per `faostat_get_data` call with domain / area / element / item / year list / timestamp / rows-returned. No value appears in the export that did not come from a documented call.
32
+ 9. **FAO-native units kept as-is.** No auto-conversion. Values stay in FAOSTAT's native units (kt CO₂eq, tonnes, USD 1000, etc.). Unit is a column in tidy-long and a header row in wide. If the user explicitly asks for normalised units, add normalised columns **alongside** the native ones — never in place of.
33
+ 10. **No FAO branding.** No FAO logo, "Food and Agriculture Organization of the United Nations" masthead, ISSN, "FAO Statistics Division" stamp, or "Required citation: FAO. …" line. CC-BY-4.0 attribution to FAOSTAT (source, licence, access date) IS kept — that's a property of the source data.
34
+ 11. **Both shapes in the xlsx.** `Data_tidy` (long) and `Data_wide` (years-as-columns pivot) are both always present. The CSV mirror is tidy-long only. A wide CSV is produced only if the user asks.
33
35
 
34
36
  ## Workflow
35
37
 
@@ -38,7 +40,7 @@ Export-specific invariants:
38
40
  Required from the user (prompt via `AskUserQuestion` in Cowork, inline otherwise):
39
41
 
40
42
  - **Domain** — e.g., GT, QCL, TCL, ET, PP, FBS, FS.
41
- - **Element(s)** — FILTER code(s).
43
+ - **Element(s)** — FILTER code(s). If the user supplies a name rather than a code, resolve via `faostat_search_codes` (invariant 7) before use.
42
44
  - **Year range** — list of years (will be passed comma-separated).
43
45
  - **Area scope** — World, specific regions, specific country list, or "all reporting countries". Default if unspecified: all reporting countries plus regional aggregates (5000/5100/5200/5300/5400/5500).
44
46
 
@@ -51,7 +53,7 @@ Optional:
51
53
 
52
54
  ### Step 2 — Resolve codes
53
55
 
54
- If the user gave names rather than codes, call `faostat_search_codes(domain_code=…, dimension_id='item'|'area', query=…)`. Print the resolved codes back in a short confirmation block before the heavy pull so mismatches surface early.
56
+ Always resolve element and item codes at runtime before the data pull (invariant 7). Call `faostat_search_codes(domain_code=…, dimension_id='element'|'item'|'area', query=…)` for every numeric code needed — even when the user supplies a code directly, verify it matches. Print the resolved codes back in a short confirmation block before the heavy pull so mismatches surface early.
55
57
 
56
58
  ### Step 3 — Pull data
57
59