@commoditypriceapi/mcp 1.0.1 → 1.2.0

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
@@ -221,38 +221,48 @@ Try these after setup:
221
221
 
222
222
  ## Tool Reference
223
223
 
224
- All 8 tools map 1:1 to CommodityPriceAPI v2 endpoints. Tools that take `symbols` accept a comma-separated list (e.g. `XAU,XAG,BRENTOIL-SPOT`). Use `list_symbols` to look up valid symbols — there are 148 across Metals, Energy, Agriculture, and more.
224
+ All 8 tools map 1:1 to CommodityPriceAPI v3 endpoints. Tools that take `symbols` accept a comma-separated list (e.g. `XAU,XAG,XPT,BRENTOIL-SPOT`). Use `list_symbols` to look up valid symbols — there are 245 across Metals, Energy, Agriculture, and more.
225
+
226
+ Precious metals use ISO 4217 codes: `XAU` (gold), `XAG` (silver), `XPT` (platinum), `XPD` (palladium). Copper is `XCU`. The retired codes `PL`, `PA`, and `HG` still work on v3 — they are auto-resolved to the new symbol (see the note below).
225
227
 
226
228
  ### get_latest_rates
227
229
 
228
- `GET /v2/rates/latest` — latest rates for one or more symbols. Rates may lag up to 10 minutes depending on plan.
230
+ `GET /v3/rates/latest` — latest rates for one or more symbols. Rates may lag up to 10 minutes depending on plan.
229
231
 
230
232
  | Parameter | Required | Description |
231
233
  |-----------|----------|-------------|
232
234
  | `symbols` | Yes | Comma-separated symbols, e.g. `XAU,XAG,BRENTOIL-SPOT` |
233
235
  | `quote` | No | Target quote currency (e.g. `EUR`). Premium/Plus plans only; omit for each symbol's default currency. |
234
236
 
235
- Note: if a symbol in a multi-symbol request is invalid, the API silently omits it from the response rather than returning an error. A missing symbol in the result means the symbol is wrong — check `list_symbols`.
237
+ Note on `unresolved`: v3 appends an `unresolved` map, keyed by the symbol you typed, in three cases. The same applies to `get_historical_rates`, `get_time_series`, and `get_fluctuation`.
238
+
239
+ | Case | HTTP | What the entry holds |
240
+ |------|------|----------------------|
241
+ | Symbol is not a catalogue code but has exactly one match (e.g. `GOLD`, or retired `PL`) | `200` | `message` + `resolvedTo` — the rate was returned under `resolvedTo` in `rates`. Informational, not a failure. |
242
+ | Some symbols could not be returned | `206` | `message` + optional `suggestions` ("did you mean"). Valid rates are still in `rates`. |
243
+ | No symbol resolved | `404` | Tool returns a `SYMBOL_NOT_FOUND` error carrying the same `unresolved` map. |
236
244
 
237
245
  ### get_gold_price
238
246
 
239
- `GET /v2/rates/latest/xau` — shortcut for the latest gold (XAU) rate, including bid/ask.
247
+ `GET /v3/rates/latest/xau` — shortcut for the latest gold (XAU) rate, including bid/ask.
240
248
 
241
249
  | Parameter | Required | Description |
242
250
  |-----------|----------|-------------|
243
251
  | `quote` | No | Target quote currency. Premium/Plus plans only. |
252
+ | `include` | No | `gram`, `carat`, or `tola` — adds a per-gram rate, per-gram rates at each purity from 24k to 8k, or a per-tola rate alongside the ounce rate. |
244
253
 
245
254
  ### get_silver_price
246
255
 
247
- `GET /v2/rates/latest/xag` — shortcut for the latest silver (XAG) rate.
256
+ `GET /v3/rates/latest/xag` — shortcut for the latest silver (XAG) rate, including bid/ask.
248
257
 
249
258
  | Parameter | Required | Description |
250
259
  |-----------|----------|-------------|
251
260
  | `quote` | No | Target quote currency. Premium/Plus plans only. |
261
+ | `include` | No | `gram`, `carat`, or `tola` — adds a per-gram, per-carat, or per-tola rate alongside the ounce rate. |
252
262
 
253
263
  ### get_historical_rates
254
264
 
255
- `GET /v2/rates/historical` — open/high/low/close rates for one or more symbols on a specific past date, available back to 1990-01-01. If no rate exists for that exact date, the API returns the nearest available date.
265
+ `GET /v3/rates/historical` — open/high/low/close rates for one or more symbols on a specific past date, available back to 1990-01-01. If no rate exists for that exact date, the API returns the nearest available date.
256
266
 
257
267
  | Parameter | Required | Description |
258
268
  |-----------|----------|-------------|
@@ -261,7 +271,7 @@ Note: if a symbol in a multi-symbol request is invalid, the API silently omits i
261
271
 
262
272
  ### get_time_series
263
273
 
264
- `GET /v2/rates/time-series` — daily historical rates for one or more symbols between two dates. Max span: 1 year.
274
+ `GET /v3/rates/time-series` — daily historical rates for one or more symbols between two dates. Max span: 1 year.
265
275
 
266
276
  | Parameter | Required | Description |
267
277
  |-----------|----------|-------------|
@@ -271,7 +281,7 @@ Note: if a symbol in a multi-symbol request is invalid, the API silently omits i
271
281
 
272
282
  ### get_fluctuation
273
283
 
274
- `GET /v2/rates/fluctuation` — how each symbol changed between two dates: start rate, end rate, absolute change, and percent change.
284
+ `GET /v3/rates/fluctuation` — how each symbol changed between two dates: start rate, end rate, absolute change, and percent change.
275
285
 
276
286
  | Parameter | Required | Description |
277
287
  |-----------|----------|-------------|
@@ -281,18 +291,19 @@ Note: if a symbol in a multi-symbol request is invalid, the API silently omits i
281
291
 
282
292
  ### list_symbols
283
293
 
284
- `GET /v2/symbols` — all supported commodity symbols with name, category, quote currency, unit, and update interval. Takes no parameters. Call this before rate tools when unsure of a symbol.
294
+ `GET /v3/symbols` — all supported commodity symbols with name, category, quote currency, unit, and update interval. Takes no parameters. Call this before rate tools when unsure of a symbol.
285
295
 
286
296
  ### get_usage
287
297
 
288
- `GET /v2/usage` — current plan, quota, and usage for the configured API key. Takes no parameters.
298
+ `GET /v3/usage` — current plan, quota, and usage for the configured API key. Takes no parameters.
289
299
 
290
300
  ## Prompt Examples
291
301
 
292
302
  ### Live prices
293
303
 
294
304
  - What's the current gold price?
295
- - Get the latest prices for silver, copper, and WTI crude.
305
+ - What's gold per gram right now?
306
+ - Get the latest prices for silver, platinum, copper, and WTI crude.
296
307
  - What's gold trading at in euros?
297
308
 
298
309
  ### Historical data
@@ -385,6 +396,35 @@ The text answers show what a client might say; exact wording depends on the mode
385
396
  }
386
397
  ```
387
398
 
399
+ ### Auto-resolved symbol
400
+
401
+ **Prompt:** What's the price of GOLD and platinum?
402
+
403
+ **Example answer:** Gold (XAU) is $4,386.23 and platinum (XPT) is $1,412.50 per troy ounce. Note: `GOLD` isn't a symbol code, so the API returned it under `XAU`.
404
+
405
+ ```json
406
+ {
407
+ "success": true,
408
+ "timestamp": 1786617187,
409
+ "rates": {
410
+ "XAU": 4386.23,
411
+ "XPT": 1412.5
412
+ },
413
+ "metadata": {
414
+ "XAU": { "unit": "T.oz", "quote": "USD" },
415
+ "XPT": { "unit": "T.oz", "quote": "USD" }
416
+ },
417
+ "unresolved": {
418
+ "GOLD": {
419
+ "message": "GOLD is not a symbol code used by this API. Gold is available as \"XAU\", so its rate was returned under that symbol.",
420
+ "resolvedTo": "XAU"
421
+ }
422
+ }
423
+ }
424
+ ```
425
+
426
+ Status is `200` — an entry with `resolvedTo` never downgrades the response.
427
+
388
428
  ## Error Codes
389
429
 
390
430
  Tool calls never crash the server. Upstream errors are returned as structured tool results with `error`, `code`, `message`, and a `guidance` field so the client can explain what went wrong instead of echoing a status code.
@@ -412,7 +452,7 @@ Example error result for an invalid symbol:
412
452
 
413
453
  ## How It Works
414
454
 
415
- This is a stdio MCP server that wraps the CommodityPriceAPI v2 REST API.
455
+ This is a stdio MCP server that wraps the CommodityPriceAPI v3 REST API.
416
456
 
417
457
  At runtime:
418
458
 
@@ -457,7 +497,7 @@ COMMODITYPRICEAPI_KEY=<YOUR_KEY> npx @modelcontextprotocol/inspector node dist/c
457
497
 
458
498
  **401 errors:** Check that `COMMODITYPRICEAPI_KEY` is set in your MCP client config's `env` block.
459
499
 
460
- **A symbol is missing from a multi-symbol response:** The upstream API silently drops invalid symbols instead of erroring. Call `list_symbols` to find the correct symbol — e.g. Brent crude is `BRENTOIL-SPOT`, not `BRENTOIL`.
500
+ **A symbol is missing from a multi-symbol response:** Look at the `unresolved` map in the result. If the entry has `resolvedTo`, nothing is missing — the rate is in `rates` under that symbol (e.g. `GOLD` → `XAU`, `PL` → `XPT`). Otherwise each missing symbol has a message and usually `suggestions` (e.g. `OIL` → `WTIOIL-SPOT`, `BRENTOIL-SPOT`, …). If there are no suggestions, call `list_symbols` to find the correct symbol.
461
501
 
462
502
  **499 timeouts:** The upstream API did not respond in time. Increase `COMMODITYPRICEAPI_REQUEST_TIMEOUT_MS` (default: 15000 ms).
463
503
 
package/dist/client.js CHANGED
@@ -1,14 +1,16 @@
1
- const BASE_URL = "https://api.commoditypriceapi.com/v2";
1
+ const BASE_URL = "https://api.commoditypriceapi.com/v3";
2
2
  export class CommodityApiError extends Error {
3
3
  code;
4
4
  errorType;
5
5
  path;
6
- constructor(code, errorType, message, path) {
6
+ unresolved;
7
+ constructor(code, errorType, message, path, unresolved) {
7
8
  super(message);
8
9
  this.name = "CommodityApiError";
9
10
  this.code = code;
10
11
  this.errorType = errorType;
11
12
  this.path = path;
13
+ this.unresolved = unresolved;
12
14
  }
13
15
  }
14
16
  function getApiKey() {
@@ -19,9 +21,15 @@ function getApiKey() {
19
21
  return key;
20
22
  }
21
23
  /**
22
- * Calls a CommodityPriceAPI v2 endpoint.
24
+ * Calls a CommodityPriceAPI v3 endpoint.
23
25
  * Sends the API key via both the x-api-key header AND the apiKey query
24
26
  * param, since the upstream API accepts either.
27
+ *
28
+ * v3 answers 206 (still `response.ok`) with an `unresolved` map appended to
29
+ * the body when some requested symbols could not be returned, and 200 with an
30
+ * `unresolved` map when a symbol was auto-resolved to its single match
31
+ * (`resolvedTo`). The body is passed through as-is so tool results include
32
+ * those notes and suggestions.
25
33
  */
26
34
  export async function callCommodityApi(path, params = {}) {
27
35
  const apiKey = getApiKey();
@@ -64,7 +72,7 @@ export async function callCommodityApi(path, params = {}) {
64
72
  throw new CommodityApiError(response.status, "INVALID_RESPONSE", `CommodityPriceAPI returned a non-JSON response: ${text.slice(0, 500)}`);
65
73
  }
66
74
  if (!response.ok) {
67
- throw new CommodityApiError(response.status, body.error ?? "UNKNOWN_ERROR", body.message ?? `CommodityPriceAPI request failed with status ${response.status}.`, body.path);
75
+ throw new CommodityApiError(response.status, body.error ?? "UNKNOWN_ERROR", body.message ?? `CommodityPriceAPI request failed with status ${response.status}.`, body.path, body.unresolved);
68
76
  }
69
77
  return body;
70
78
  }
package/dist/server.js CHANGED
@@ -3,8 +3,20 @@ import { z } from "zod";
3
3
  import { callCommodityApi, CommodityApiError } from "./client.js";
4
4
  const symbolsParam = z
5
5
  .string()
6
- .describe("Comma-separated commodity symbols, e.g. 'XAU,XAG,BRENTOIL-SPOT'. See the list_symbols tool for valid values. Invalid symbols in a multi-symbol request are silently omitted from the response, not errored.");
6
+ .describe("Comma-separated commodity symbols, e.g. 'XAU,XAG,XPT,BRENTOIL-SPOT'. Precious metals use ISO 4217 codes (XAU gold, XAG silver, XPT platinum, XPD palladium); copper is XCU. See the list_symbols tool for valid values. " +
7
+ "The response may include an 'unresolved' map keyed by the symbol you typed. Three cases: " +
8
+ "(1) HTTP 200 with an entry carrying 'resolvedTo' — the symbol was not a catalogue code but had exactly one match (e.g. GOLD -> XAU, retired PL -> XPT), so its rate was returned under the 'resolvedTo' symbol in 'rates'; this is informational, not a failure. " +
9
+ "(2) HTTP 206 — some symbols could not be returned; each entry has a message and, where available, 'did you mean' suggestions, while the valid rates are still in 'rates'. " +
10
+ "(3) If none resolve, the error result carries the same 'unresolved' map.");
7
11
  const dateParam = z.string().describe("Date in YYYY-MM-DD format.");
12
+ const quoteParam = z
13
+ .string()
14
+ .optional()
15
+ .describe("Target quote currency code (e.g. 'USD', 'EUR'). Premium/Plus plans only; omit to use each symbol's default currency.");
16
+ const includeParam = z
17
+ .enum(["gram", "carat", "tola"])
18
+ .optional()
19
+ .describe("Add a per-unit breakdown alongside the per-troy-ounce rate: 'gram' adds a per-gram rate, 'tola' adds a per-tola rate, 'carat' adds per-gram rates at each purity from 24k down to 8k. Omit for the ounce rate only.");
8
20
  function textResult(data) {
9
21
  return {
10
22
  content: [
@@ -26,6 +38,7 @@ function errorResult(err) {
26
38
  error: err.errorType,
27
39
  code: err.code,
28
40
  message: err.message,
41
+ ...(err.unresolved ? { unresolved: err.unresolved } : {}),
29
42
  guidance: guidanceFor(err.code, err.errorType),
30
43
  }, null, 2),
31
44
  },
@@ -52,7 +65,7 @@ function guidanceFor(code, errorType) {
52
65
  return "You've hit your API key's usage limit. Upgrade your plan or wait for the quota to reset.";
53
66
  case 404:
54
67
  if (errorType === "SYMBOL_NOT_FOUND") {
55
- return "Call list_symbols to see valid commodity symbols.";
68
+ return "None of the requested symbols are valid. Check the 'unresolved' map above for suggested symbols, or call list_symbols to see all valid commodity symbols.";
56
69
  }
57
70
  return "The requested resource was not found.";
58
71
  case 429:
@@ -64,7 +77,7 @@ function guidanceFor(code, errorType) {
64
77
  export function createServer() {
65
78
  const server = new McpServer({
66
79
  name: "commoditypriceapi-mcp",
67
- version: "1.0.1",
80
+ version: "1.2.0",
68
81
  });
69
82
  server.registerTool("get_usage", {
70
83
  title: "Get API usage",
@@ -81,7 +94,7 @@ export function createServer() {
81
94
  });
82
95
  server.registerTool("list_symbols", {
83
96
  title: "List supported commodity symbols",
84
- description: "Returns all commodity symbols supported by CommodityPriceAPI, including category, default currency, and unit. Use this to look up a symbol before calling rate tools.",
97
+ description: "Returns all commodity symbols supported by CommodityPriceAPI, including category, default currency, and unit. Use this to look up a symbol before calling rate tools. Precious metals use ISO 4217 codes (XAU, XAG, XPT, XPD); copper is XCU.",
85
98
  inputSchema: {},
86
99
  }, async () => {
87
100
  try {
@@ -94,13 +107,10 @@ export function createServer() {
94
107
  });
95
108
  server.registerTool("get_latest_rates", {
96
109
  title: "Get latest commodity rates",
97
- description: "Returns the latest rates for one or more commodity symbols (e.g. gold, silver, crude oil). Rates may lag up to 10 minutes depending on plan. Use 'quote' to convert to a specific currency (Premium/Plus plans only).",
110
+ description: "Returns the latest rates for one or more commodity symbols (e.g. gold, silver, crude oil). Rates may lag up to 10 minutes depending on plan. Use 'quote' to convert to a specific currency (Premium/Plus plans only). Common names with a single match (e.g. GOLD) are auto-resolved to the real symbol and flagged in 'unresolved' with 'resolvedTo'.",
98
111
  inputSchema: {
99
112
  symbols: symbolsParam,
100
- quote: z
101
- .string()
102
- .optional()
103
- .describe("Target quote currency code (e.g. 'USD', 'EUR'). Premium/Plus plans only; omit to use each symbol's default currency."),
113
+ quote: quoteParam,
104
114
  },
105
115
  }, async ({ symbols, quote }) => {
106
116
  try {
@@ -113,16 +123,14 @@ export function createServer() {
113
123
  });
114
124
  server.registerTool("get_gold_price", {
115
125
  title: "Get latest gold (XAU) price",
116
- description: "Shortcut for the latest gold (XAU) rate without needing to pass a symbols list.",
126
+ description: "Shortcut for the latest gold (XAU) rate, with bid/ask, without needing to pass a symbols list. Use 'include' to add a per-gram, per-tola, or per-carat breakdown.",
117
127
  inputSchema: {
118
- quote: z
119
- .string()
120
- .optional()
121
- .describe("Target quote currency code. Premium/Plus plans only."),
128
+ quote: quoteParam,
129
+ include: includeParam,
122
130
  },
123
- }, async ({ quote }) => {
131
+ }, async ({ quote, include }) => {
124
132
  try {
125
- const data = await callCommodityApi("/rates/latest/xau", { quote });
133
+ const data = await callCommodityApi("/rates/latest/xau", { quote, include });
126
134
  return textResult(data);
127
135
  }
128
136
  catch (err) {
@@ -131,16 +139,14 @@ export function createServer() {
131
139
  });
132
140
  server.registerTool("get_silver_price", {
133
141
  title: "Get latest silver (XAG) price",
134
- description: "Shortcut for the latest silver (XAG) rate without needing to pass a symbols list.",
142
+ description: "Shortcut for the latest silver (XAG) rate, with bid/ask, without needing to pass a symbols list. Use 'include' to add a per-gram, per-tola, or per-carat breakdown.",
135
143
  inputSchema: {
136
- quote: z
137
- .string()
138
- .optional()
139
- .describe("Target quote currency code. Premium/Plus plans only."),
144
+ quote: quoteParam,
145
+ include: includeParam,
140
146
  },
141
- }, async ({ quote }) => {
147
+ }, async ({ quote, include }) => {
142
148
  try {
143
- const data = await callCommodityApi("/rates/latest/xag", { quote });
149
+ const data = await callCommodityApi("/rates/latest/xag", { quote, include });
144
150
  return textResult(data);
145
151
  }
146
152
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commoditypriceapi/mcp",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "Official MCP server for CommodityPriceAPI \u2014 real-time and historical commodity rates (gold, silver, oil, and 130+ more) as MCP tools for Claude, Cursor, Windsurf, and any MCP client.",
5
5
  "keywords": [
6
6
  "mcp",