@guiie/buda-mcp 1.1.2 → 1.2.1
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/CHANGELOG.md +35 -0
- package/PUBLISH.md +5 -5
- package/PUBLISH_CHECKLIST.md +59 -62
- package/README.md +3 -3
- package/dist/client.d.ts +15 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +56 -52
- package/dist/http.js +30 -148
- package/dist/index.js +2 -1
- package/dist/tools/balances.d.ts +8 -0
- package/dist/tools/balances.d.ts.map +1 -1
- package/dist/tools/balances.js +11 -3
- package/dist/tools/cancel_order.d.ts +30 -0
- package/dist/tools/cancel_order.d.ts.map +1 -1
- package/dist/tools/cancel_order.js +59 -38
- package/dist/tools/compare_markets.d.ts +14 -0
- package/dist/tools/compare_markets.d.ts.map +1 -1
- package/dist/tools/compare_markets.js +17 -3
- package/dist/tools/markets.d.ts +13 -0
- package/dist/tools/markets.d.ts.map +1 -1
- package/dist/tools/markets.js +23 -2
- package/dist/tools/orderbook.d.ts +18 -0
- package/dist/tools/orderbook.d.ts.map +1 -1
- package/dist/tools/orderbook.js +28 -2
- package/dist/tools/orders.d.ts +26 -0
- package/dist/tools/orders.d.ts.map +1 -1
- package/dist/tools/orders.js +36 -2
- package/dist/tools/place_order.d.ts +50 -0
- package/dist/tools/place_order.d.ts.map +1 -1
- package/dist/tools/place_order.js +104 -58
- package/dist/tools/price_history.d.ts +22 -0
- package/dist/tools/price_history.d.ts.map +1 -1
- package/dist/tools/price_history.js +42 -7
- package/dist/tools/spread.d.ts +14 -0
- package/dist/tools/spread.d.ts.map +1 -1
- package/dist/tools/spread.js +24 -2
- package/dist/tools/ticker.d.ts +14 -0
- package/dist/tools/ticker.d.ts.map +1 -1
- package/dist/tools/ticker.js +24 -2
- package/dist/tools/trades.d.ts +22 -0
- package/dist/tools/trades.d.ts.map +1 -1
- package/dist/tools/trades.js +32 -2
- package/dist/tools/volume.d.ts +14 -0
- package/dist/tools/volume.d.ts.map +1 -1
- package/dist/tools/volume.js +24 -2
- package/dist/validation.d.ts +6 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +14 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/marketplace/README.md +1 -1
- package/marketplace/claude-listing.md +2 -2
- package/marketplace/gemini-tools.json +3 -3
- package/marketplace/openapi.yaml +7 -6
- package/package.json +5 -2
- package/scripts/sync-version.mjs +19 -0
- package/server.json +2 -2
- package/src/client.ts +77 -53
- package/src/http.ts +32 -150
- package/src/index.ts +2 -1
- package/src/tools/balances.ts +14 -4
- package/src/tools/cancel_order.ts +77 -43
- package/src/tools/compare_markets.ts +21 -4
- package/src/tools/markets.ts +27 -3
- package/src/tools/orderbook.ts +32 -3
- package/src/tools/orders.ts +41 -3
- package/src/tools/place_order.ts +134 -69
- package/src/tools/price_history.ts +50 -8
- package/src/tools/spread.ts +28 -3
- package/src/tools/ticker.ts +28 -3
- package/src/tools/trades.ts +37 -3
- package/src/tools/volume.ts +28 -3
- package/src/validation.ts +16 -0
- package/src/version.ts +8 -0
- package/test/run-all.ts +13 -1
- package/test/unit.ts +414 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,41 @@ This project uses [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.2.0] – 2026-04-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`src/validation.ts`** — new `validateMarketId` helper that enforces `/^[A-Z0-9]{2,10}-[A-Z0-9]{2,10}$/i` on all market ID inputs before URL interpolation. Returns a structured `isError: true` response with a helpful message on failure. Applied to all tools that accept `market_id`.
|
|
15
|
+
- **`.env.example`** — documents `BUDA_API_KEY` and `BUDA_API_SECRET` with comments and a link to the Buda token management page. Referenced in the README auth section.
|
|
16
|
+
- **`scripts/sync-version.mjs`** — reads `package.json` version and writes it to `server.json`. Run via `npm run sync-version` to keep the MCP registry manifest in sync after a version bump.
|
|
17
|
+
- **`test/unit.ts`** — 23 unit tests (no live API required):
|
|
18
|
+
- **HMAC signing** (3 tests): exact output verified for GET (no body) and POST (with base64 body); determinism check.
|
|
19
|
+
- **Cache deduplication** (3 tests): concurrent `getOrFetch` calls share the same in-flight promise; expiry triggers a new fetch; rejected fetcher clears the entry so the next call retries.
|
|
20
|
+
- **confirmation_token guard** (4 tests): `place_order` and `cancel_order` return `isError: true` without `"CONFIRM"`.
|
|
21
|
+
- **Input sanitization** (9 tests): malformed market IDs (path traversal, no hyphen, empty, oversized segments, special characters) all return a validation error; valid IDs (uppercase, lowercase, USDC) pass.
|
|
22
|
+
- **429 retry** (4 tests): mock 429→200 asserts fetch is called exactly twice and the 200 data is returned; double-429 asserts `BudaApiError` with `retryAfterMs`; `Retry-After: 2` header parsed as 2000 ms (RFC 7231 seconds); absent header defaults to 1000 ms.
|
|
23
|
+
- **`npm run test:unit`** and **`npm run test:integration`** scripts for running test subsets independently.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **Single version source-of-truth** — all version references now derive from `package.json` at startup:
|
|
28
|
+
- `src/version.ts` (new shared module): reads `package.json` via `readFileSync` + `fileURLToPath`.
|
|
29
|
+
- `src/client.ts`, `src/index.ts`, `src/http.ts` import `VERSION` from `src/version.ts`.
|
|
30
|
+
- `server.json` is kept in sync via `npm run sync-version`.
|
|
31
|
+
- **`http.ts` server-card generated programmatically** — the `/.well-known/mcp/server-card.json` endpoint now assembles tool schemas from each tool module's exported `toolSchema` constant instead of a 100-line hardcoded JSON block. Adding a tool only requires exporting its `toolSchema`.
|
|
32
|
+
- **All tool files** export a `toolSchema` constant `{ name, description, inputSchema }` used by both `register()` and the server-card endpoint, ensuring descriptions are always in sync.
|
|
33
|
+
- **`place_order.ts` and `cancel_order.ts`** expose their handler logic via exported `handlePlaceOrder` / `handleCancelOrder` functions, used by the register wrapper and directly testable in unit tests.
|
|
34
|
+
- **`get_price_history`** improvements:
|
|
35
|
+
- Shallow-window limitation moved to the **front** of the description (was buried in a `note` field).
|
|
36
|
+
- UTC bucket boundary format documented explicitly in tool description and `note` field.
|
|
37
|
+
- `limit` max raised from `100` to `1000`; description updated accordingly.
|
|
38
|
+
- **429 retry with Retry-After** — `BudaClient.get`, `.post`, and `.put` now retry once on a 429 response. The `Retry-After` header is parsed as integer seconds (per RFC 7231; Buda's docs describe 429 but do not document the header — the standard interpretation applies). Defaults to 1 second if the header is absent. A double-429 throws `BudaApiError` with `retryAfterMs` set.
|
|
39
|
+
- **`test/run-all.ts`** — integration tests now perform a 3-second connectivity pre-check at startup and skip gracefully (exit 0 with a message) when the Buda API is unreachable, preventing CI failures on networks without internet access.
|
|
40
|
+
- **`package.json`** version bumped to `1.2.0`.
|
|
41
|
+
- **`marketplace/`** and **`PUBLISH_CHECKLIST.md`** updated to reflect v1.2.0 changes.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
10
45
|
## [1.1.2] – 2026-04-10
|
|
11
46
|
|
|
12
47
|
### Fixed
|
package/PUBLISH.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Publishing checklist
|
|
1
|
+
# Publishing checklist — v1.2.0
|
|
2
2
|
|
|
3
3
|
Everything that could be automated is already done.
|
|
4
4
|
This file contains only what requires your manual action, in order.
|
|
@@ -63,7 +63,7 @@ mcp-publisher login github
|
|
|
63
63
|
mcp-publisher publish
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
You'll see: `✓ Successfully published — io.github.gtorreal/buda-mcp version 1.
|
|
66
|
+
You'll see: `✓ Successfully published — io.github.gtorreal/buda-mcp version 1.2.0`
|
|
67
67
|
|
|
68
68
|
### 2b. Put your MCP Registry token into GitHub Actions (for auto-publish on release)
|
|
69
69
|
|
|
@@ -177,9 +177,9 @@ For the Gemini Extensions marketplace (currently invite-only):
|
|
|
177
177
|
Once npm token and MCP registry token are set in GitHub Actions secrets (Steps 1c and 2b):
|
|
178
178
|
|
|
179
179
|
```bash
|
|
180
|
-
gh release create v1.
|
|
181
|
-
--title "v1.
|
|
182
|
-
--notes "
|
|
180
|
+
gh release create v1.2.0 \
|
|
181
|
+
--title "v1.2.0 — Input validation, 429 retry, unit tests" \
|
|
182
|
+
--notes "Input sanitization, 429 Retry-After support, get_price_history limit raised to 1000, 23 unit tests, single version source-of-truth." \
|
|
183
183
|
--latest
|
|
184
184
|
```
|
|
185
185
|
|
package/PUBLISH_CHECKLIST.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Publish Checklist — buda-mcp v1.
|
|
1
|
+
# Publish Checklist — buda-mcp v1.2.0
|
|
2
2
|
|
|
3
|
-
Steps to publish `v1.
|
|
3
|
+
Steps to publish `v1.2.0` to npm, the MCP registry, and notify community directories.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,12 +8,15 @@ Steps to publish `v1.1.0` to npm, the MCP registry, and notify community directo
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
# Confirm version
|
|
11
|
-
node -e "console.log(require('./package.json').version)" # should print 1.
|
|
11
|
+
node -e "console.log(require('./package.json').version)" # should print 1.2.0
|
|
12
12
|
|
|
13
13
|
# Build and test
|
|
14
14
|
npm run build
|
|
15
15
|
npm test
|
|
16
16
|
|
|
17
|
+
# Sync server.json version (already done, but run again to confirm)
|
|
18
|
+
npm run sync-version
|
|
19
|
+
|
|
17
20
|
# Verify no credentials are logged (audit)
|
|
18
21
|
grep -r "apiKey\|apiSecret\|BUDA_API" dist/ --include="*.js" | grep -v "process.env\|hasAuth\|X-SBTC-APIKEY\|authHeaders\|constructor"
|
|
19
22
|
# Should return empty or only header name strings — never credential values
|
|
@@ -36,17 +39,18 @@ Verify: https://www.npmjs.com/package/@guiie/buda-mcp
|
|
|
36
39
|
|
|
37
40
|
```bash
|
|
38
41
|
git add -A
|
|
39
|
-
git commit -m "chore: release v1.
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
git commit -m "chore: release v1.2.0
|
|
43
|
+
|
|
44
|
+
- Single version source-of-truth via src/version.ts (no more hardcoded strings)
|
|
45
|
+
- Programmatic server-card in http.ts (toolSchema exported per tool)
|
|
46
|
+
- .env.example with documented BUDA_API_KEY / BUDA_API_SECRET
|
|
47
|
+
- Input sanitization: validateMarketId regex on all market_id inputs
|
|
48
|
+
- 429 retry with Retry-After (seconds, per RFC 7231), default 1s
|
|
49
|
+
- get_price_history: limit raised to 1000, UTC bucketing documented
|
|
50
|
+
- 23 unit tests: HMAC signing, cache dedup, confirmation guard, sanitization, 429 retry
|
|
51
|
+
- Integration tests: graceful skip when Buda API is unreachable"
|
|
52
|
+
|
|
53
|
+
git tag v1.2.0
|
|
50
54
|
git push origin main --tags
|
|
51
55
|
```
|
|
52
56
|
|
|
@@ -57,25 +61,27 @@ Then create a GitHub Release from the tag with the following release notes:
|
|
|
57
61
|
**Release notes template (GitHub):**
|
|
58
62
|
|
|
59
63
|
```
|
|
60
|
-
## buda-mcp v1.
|
|
64
|
+
## buda-mcp v1.2.0
|
|
61
65
|
|
|
62
66
|
### What's new
|
|
63
67
|
|
|
64
|
-
**
|
|
65
|
-
- `
|
|
66
|
-
- `
|
|
67
|
-
|
|
68
|
+
**Bug fixes & maintenance**
|
|
69
|
+
- Single version source-of-truth: all version strings now read from `package.json` at startup via `src/version.ts` — no more drift between files
|
|
70
|
+
- `http.ts` server-card assembled programmatically from exported `toolSchema` constants — adding a tool no longer requires touching `http.ts`
|
|
71
|
+
|
|
72
|
+
**Security / reliability**
|
|
73
|
+
- Input sanitization: all `market_id` inputs validated against `/^[A-Z0-9]{2,10}-[A-Z0-9]{2,10}$/i` before URL interpolation — rejects path traversal and malformed IDs with structured errors
|
|
74
|
+
- 429 retry: `BudaClient` retries once on rate-limit responses, honoring the `Retry-After` header (seconds, per RFC 7231; defaults to 1s if absent). Double-429 throws `BudaApiError` with `retryAfterMs`.
|
|
68
75
|
|
|
69
|
-
**
|
|
70
|
-
-
|
|
71
|
-
- `
|
|
72
|
-
-
|
|
76
|
+
**DX improvements**
|
|
77
|
+
- `.env.example` added for easy credential setup
|
|
78
|
+
- `get_price_history` limit raised from 100 to 1000 trades; UTC bucketing documented prominently
|
|
79
|
+
- `npm run sync-version` syncs `server.json` from `package.json` automatically
|
|
73
80
|
|
|
74
|
-
**
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
- Updated README with npx quickstart and per-tool examples
|
|
81
|
+
**Test suite**
|
|
82
|
+
- 23 new unit tests (no live API needed): HMAC signing exactness, cache deduplication, confirmation_token guards, input sanitization, 429 retry behavior
|
|
83
|
+
- Integration tests skip gracefully when Buda API is unreachable (CI-friendly)
|
|
84
|
+
- New scripts: `npm run test:unit`, `npm run test:integration`
|
|
79
85
|
|
|
80
86
|
```bash
|
|
81
87
|
npx @guiie/buda-mcp
|
|
@@ -86,16 +92,13 @@ npx @guiie/buda-mcp
|
|
|
86
92
|
|
|
87
93
|
## 4. MCP Registry update
|
|
88
94
|
|
|
89
|
-
The GitHub Actions workflow (`.github/workflows/publish.yml`) runs automatically on GitHub release.
|
|
95
|
+
The GitHub Actions workflow (`.github/workflows/publish.yml`) runs automatically on GitHub release. Verify at:
|
|
90
96
|
|
|
91
97
|
https://registry.modelcontextprotocol.io/servers/io.github.gtorreal/buda-mcp
|
|
92
98
|
|
|
93
99
|
If the workflow doesn't trigger, run manually:
|
|
94
100
|
|
|
95
101
|
```bash
|
|
96
|
-
# Download mcp-publisher from GitHub releases (check for latest version)
|
|
97
|
-
curl -L https://github.com/modelcontextprotocol/mcp-publisher/releases/latest/download/mcp-publisher-macos -o mcp-publisher
|
|
98
|
-
chmod +x mcp-publisher
|
|
99
102
|
MCP_REGISTRY_TOKEN=<token> ./mcp-publisher publish
|
|
100
103
|
```
|
|
101
104
|
|
|
@@ -111,23 +114,22 @@ Verify: https://smithery.ai/server/@guiie/buda-mcp
|
|
|
111
114
|
|
|
112
115
|
## 6. Notify mcp.so
|
|
113
116
|
|
|
114
|
-
**Method:** Submit via the mcp.so listing update form or open a PR to their repository.
|
|
115
|
-
|
|
116
117
|
**Email/message template:**
|
|
117
118
|
|
|
118
119
|
```
|
|
119
|
-
Subject: [Update] buda-mcp v1.
|
|
120
|
+
Subject: [Update] buda-mcp v1.2.0 — input sanitization, 429 retry, 23 unit tests
|
|
120
121
|
|
|
121
122
|
Hi mcp.so team,
|
|
122
123
|
|
|
123
|
-
I've released v1.
|
|
124
|
+
I've released v1.2.0 of buda-mcp (@guiie/buda-mcp on npm).
|
|
124
125
|
|
|
125
126
|
Key changes:
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
127
|
+
- Input sanitization: all market IDs validated against a strict regex before URL use
|
|
128
|
+
- 429 rate-limit retry: honors Retry-After header (seconds, RFC 7231), defaults to 1s
|
|
129
|
+
- get_price_history: limit raised to 1000 trades for deeper history
|
|
130
|
+
- 23 unit tests added (no live API required): HMAC, cache dedup, confirmation guards, sanitization, retry
|
|
131
|
+
- Single version source-of-truth (package.json → all files via src/version.ts)
|
|
132
|
+
- .env.example added for easy credential setup
|
|
131
133
|
|
|
132
134
|
Links:
|
|
133
135
|
- npm: https://www.npmjs.com/package/@guiie/buda-mcp
|
|
@@ -143,31 +145,25 @@ Thank you!
|
|
|
143
145
|
|
|
144
146
|
## 7. Notify Glama.ai
|
|
145
147
|
|
|
146
|
-
**Method:** Use Glama's submission form at https://glama.ai/mcp/servers or open an issue/PR on their directory repository.
|
|
147
|
-
|
|
148
148
|
**Message template:**
|
|
149
149
|
|
|
150
150
|
```
|
|
151
|
-
Subject: [Update] buda-mcp v1.
|
|
151
|
+
Subject: [Update] buda-mcp v1.2.0
|
|
152
152
|
|
|
153
153
|
Hi Glama team,
|
|
154
154
|
|
|
155
|
-
buda-mcp has been updated to v1.
|
|
155
|
+
buda-mcp has been updated to v1.2.0.
|
|
156
156
|
|
|
157
157
|
Package: @guiie/buda-mcp (npm)
|
|
158
158
|
Registry: io.github.gtorreal/buda-mcp (MCP Registry)
|
|
159
|
-
Version: 1.
|
|
160
|
-
|
|
161
|
-
New tools added:
|
|
162
|
-
- get_spread: bid/ask spread for any market
|
|
163
|
-
- compare_markets: cross-currency price comparison for a base asset
|
|
164
|
-
- get_price_history: OHLCV candles from trade history (1h/4h/1d)
|
|
165
|
-
- get_balances, get_orders, place_order, cancel_order (authenticated, local-only)
|
|
159
|
+
Version: 1.2.0
|
|
166
160
|
|
|
167
|
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
170
|
-
-
|
|
161
|
+
Changes:
|
|
162
|
+
- Input validation on all market_id inputs (structured isError: true on failure)
|
|
163
|
+
- 429 retry with Retry-After support (RFC 7231 seconds; default 1s)
|
|
164
|
+
- get_price_history limit raised to 1000 trades; UTC bucket timestamps documented
|
|
165
|
+
- 23 unit tests: HMAC signing, cache deduplication, confirmation guards, sanitization, retry
|
|
166
|
+
- Single version source (package.json); .env.example added
|
|
171
167
|
|
|
172
168
|
Quick start:
|
|
173
169
|
npx @guiie/buda-mcp
|
|
@@ -182,11 +178,12 @@ Thank you!
|
|
|
182
178
|
|
|
183
179
|
## 8. Post-publish verification
|
|
184
180
|
|
|
185
|
-
- [ ] `npx @guiie/buda-mcp@1.
|
|
186
|
-
- [ ] `npm info @guiie/buda-mcp version` returns `1.
|
|
187
|
-
- [ ] GitHub release tag `v1.
|
|
188
|
-
- [ ] MCP Registry entry reflects v1.
|
|
189
|
-
- [ ] Smithery server card lists 8 public tools
|
|
181
|
+
- [ ] `npx @guiie/buda-mcp@1.2.0` starts successfully
|
|
182
|
+
- [ ] `npm info @guiie/buda-mcp version` returns `1.2.0`
|
|
183
|
+
- [ ] GitHub release tag `v1.2.0` is visible
|
|
184
|
+
- [ ] MCP Registry entry reflects v1.2.0
|
|
185
|
+
- [ ] Smithery server card lists 8 public tools (with updated get_price_history description)
|
|
186
|
+
- [ ] `GET /health` returns `"version":"1.2.0"` on Railway deployment
|
|
187
|
+
- [ ] `GET /.well-known/mcp/server-card.json` returns tools with updated schemas (no hardcoded JSON)
|
|
190
188
|
- [ ] mcp.so listing updated
|
|
191
189
|
- [ ] Glama.ai listing updated
|
|
192
|
-
- [ ] Railway deployment health check returns `"version":"1.1.0"` at `/health`
|
package/README.md
CHANGED
|
@@ -161,13 +161,13 @@ Side-by-side ticker data for all pairs of a given base currency (CLP, COP, PEN,
|
|
|
161
161
|
---
|
|
162
162
|
|
|
163
163
|
#### `get_price_history`
|
|
164
|
-
OHLCV candles derived from recent trade history (no native candlestick endpoint
|
|
164
|
+
OHLCV candles derived from recent trade history (Buda has no native candlestick endpoint — candles are aggregated client-side from raw trades). Candle timestamps are UTC bucket boundaries. Increasing `limit` gives deeper history at the cost of a slower response.
|
|
165
165
|
|
|
166
166
|
| Parameter | Type | Required | Description |
|
|
167
167
|
|-----------|------|----------|-------------|
|
|
168
168
|
| `market_id` | string | Yes | Market ID. |
|
|
169
169
|
| `period` | `1h` \| `4h` \| `1d` | No | Candle period (default `1h`). |
|
|
170
|
-
| `limit` | number | No | Raw trades to fetch before aggregation (default 100, max
|
|
170
|
+
| `limit` | number | No | Raw trades to fetch before aggregation (default 100, max 1000). |
|
|
171
171
|
|
|
172
172
|
**Example prompts:**
|
|
173
173
|
- *"Show me hourly price candles for BTC-CLP"*
|
|
@@ -252,7 +252,7 @@ In addition to tools, the server exposes two MCP Resources that clients can read
|
|
|
252
252
|
|
|
253
253
|
The server defaults to **public-only mode** — no API key needed, no breaking changes for existing users.
|
|
254
254
|
|
|
255
|
-
To enable authenticated tools, set environment variables before running:
|
|
255
|
+
To enable authenticated tools, copy `.env.example` to `.env` and fill in your credentials, then set them as environment variables before running:
|
|
256
256
|
|
|
257
257
|
```bash
|
|
258
258
|
BUDA_API_KEY=your_api_key BUDA_API_SECRET=your_api_secret npx @guiie/buda-mcp
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export declare class BudaApiError extends Error {
|
|
2
2
|
readonly status: number;
|
|
3
3
|
readonly path: string;
|
|
4
|
-
|
|
4
|
+
readonly retryAfterMs?: number | undefined;
|
|
5
|
+
constructor(status: number, path: string, message: string, retryAfterMs?: number | undefined);
|
|
5
6
|
}
|
|
6
7
|
export declare class BudaClient {
|
|
7
8
|
private readonly baseUrl;
|
|
@@ -12,6 +13,19 @@ export declare class BudaClient {
|
|
|
12
13
|
private nonce;
|
|
13
14
|
private sign;
|
|
14
15
|
private authHeaders;
|
|
16
|
+
/**
|
|
17
|
+
* Parses the Retry-After header value into milliseconds.
|
|
18
|
+
* Per RFC 7231, Retry-After is an integer number of seconds.
|
|
19
|
+
* Defaults to 1000ms (1 second) if absent or unparseable.
|
|
20
|
+
*/
|
|
21
|
+
private parseRetryAfterMs;
|
|
22
|
+
/**
|
|
23
|
+
* Executes a fetch call with a single 429 retry.
|
|
24
|
+
* On the first 429, waits for Retry-After seconds (default 1s), then retries once.
|
|
25
|
+
* If the retry also returns 429, throws a BudaApiError with retryAfterMs set.
|
|
26
|
+
*/
|
|
27
|
+
private fetchWithRetry;
|
|
28
|
+
private handleResponse;
|
|
15
29
|
get<T>(path: string, params?: Record<string, string | number>): Promise<T>;
|
|
16
30
|
post<T>(path: string, payload: unknown): Promise<T>;
|
|
17
31
|
put<T>(path: string, payload: unknown): Promise<T>;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,qBAAa,YAAa,SAAQ,KAAK;aAEnB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;aAEZ,YAAY,CAAC,EAAE,MAAM;gBAHrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,YAAY,CAAC,EAAE,MAAM,YAAA;CAKxC;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;gBAG7C,OAAO,GAAE,MAAiB,EAC1B,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM;IAOpB,OAAO,IAAI,OAAO;IAIlB,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,WAAW;IAWnB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;;;OAIG;YACW,cAAc;YA2Bd,cAAc;IActB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoB1E,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAmBnD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;CAkBzD"}
|
package/dist/client.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { createHmac } from "crypto";
|
|
2
|
+
import { VERSION } from "./version.js";
|
|
2
3
|
const BASE_URL = "https://www.buda.com/api/v2";
|
|
3
4
|
export class BudaApiError extends Error {
|
|
4
5
|
status;
|
|
5
6
|
path;
|
|
6
|
-
|
|
7
|
+
retryAfterMs;
|
|
8
|
+
constructor(status, path, message, retryAfterMs) {
|
|
7
9
|
super(message);
|
|
8
10
|
this.status = status;
|
|
9
11
|
this.path = path;
|
|
12
|
+
this.retryAfterMs = retryAfterMs;
|
|
10
13
|
this.name = "BudaApiError";
|
|
11
14
|
}
|
|
12
15
|
}
|
|
@@ -45,20 +48,37 @@ export class BudaClient {
|
|
|
45
48
|
"X-SBTC-SIGNATURE": signature,
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Parses the Retry-After header value into milliseconds.
|
|
53
|
+
* Per RFC 7231, Retry-After is an integer number of seconds.
|
|
54
|
+
* Defaults to 1000ms (1 second) if absent or unparseable.
|
|
55
|
+
*/
|
|
56
|
+
parseRetryAfterMs(headers) {
|
|
57
|
+
const raw = headers.get("Retry-After");
|
|
58
|
+
if (!raw)
|
|
59
|
+
return 1000;
|
|
60
|
+
const secs = parseInt(raw, 10);
|
|
61
|
+
return isNaN(secs) ? 1000 : secs * 1000;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Executes a fetch call with a single 429 retry.
|
|
65
|
+
* On the first 429, waits for Retry-After seconds (default 1s), then retries once.
|
|
66
|
+
* If the retry also returns 429, throws a BudaApiError with retryAfterMs set.
|
|
67
|
+
*/
|
|
68
|
+
async fetchWithRetry(url, options, path) {
|
|
69
|
+
const response = await fetch(url.toString(), options);
|
|
70
|
+
if (response.status !== 429)
|
|
71
|
+
return response;
|
|
72
|
+
const retryAfterMs = this.parseRetryAfterMs(response.headers);
|
|
73
|
+
await new Promise((r) => setTimeout(r, retryAfterMs));
|
|
74
|
+
const retry = await fetch(url.toString(), options);
|
|
75
|
+
if (retry.status === 429) {
|
|
76
|
+
const retryAgainMs = this.parseRetryAfterMs(retry.headers);
|
|
77
|
+
throw new BudaApiError(429, path, `Buda API rate limit exceeded. Retry after ${retryAgainMs}ms.`, retryAgainMs);
|
|
54
78
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"User-Agent": "buda-mcp/1.1.1",
|
|
59
|
-
...this.authHeaders("GET", urlPath),
|
|
60
|
-
};
|
|
61
|
-
const response = await fetch(url.toString(), { headers });
|
|
79
|
+
return retry;
|
|
80
|
+
}
|
|
81
|
+
async handleResponse(response, path) {
|
|
62
82
|
if (!response.ok) {
|
|
63
83
|
let detail = response.statusText;
|
|
64
84
|
try {
|
|
@@ -73,6 +93,22 @@ export class BudaClient {
|
|
|
73
93
|
}
|
|
74
94
|
return response.json();
|
|
75
95
|
}
|
|
96
|
+
async get(path, params) {
|
|
97
|
+
const url = new URL(`${this.baseUrl}${path}.json`);
|
|
98
|
+
if (params) {
|
|
99
|
+
for (const [key, value] of Object.entries(params)) {
|
|
100
|
+
url.searchParams.set(key, String(value));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const urlPath = url.pathname + url.search;
|
|
104
|
+
const headers = {
|
|
105
|
+
Accept: "application/json",
|
|
106
|
+
"User-Agent": `buda-mcp/${VERSION}`,
|
|
107
|
+
...this.authHeaders("GET", urlPath),
|
|
108
|
+
};
|
|
109
|
+
const response = await this.fetchWithRetry(url, { headers }, path);
|
|
110
|
+
return this.handleResponse(response, path);
|
|
111
|
+
}
|
|
76
112
|
async post(path, payload) {
|
|
77
113
|
const url = new URL(`${this.baseUrl}${path}.json`);
|
|
78
114
|
const bodyStr = JSON.stringify(payload);
|
|
@@ -80,27 +116,11 @@ export class BudaClient {
|
|
|
80
116
|
const headers = {
|
|
81
117
|
Accept: "application/json",
|
|
82
118
|
"Content-Type": "application/json",
|
|
83
|
-
"User-Agent":
|
|
119
|
+
"User-Agent": `buda-mcp/${VERSION}`,
|
|
84
120
|
...this.authHeaders("POST", urlPath, bodyStr),
|
|
85
121
|
};
|
|
86
|
-
const response = await
|
|
87
|
-
|
|
88
|
-
headers,
|
|
89
|
-
body: bodyStr,
|
|
90
|
-
});
|
|
91
|
-
if (!response.ok) {
|
|
92
|
-
let detail = response.statusText;
|
|
93
|
-
try {
|
|
94
|
-
const body = (await response.json());
|
|
95
|
-
if (body.message)
|
|
96
|
-
detail = body.message;
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
// ignore parse error, use statusText
|
|
100
|
-
}
|
|
101
|
-
throw new BudaApiError(response.status, path, `Buda API ${response.status}: ${detail}`);
|
|
102
|
-
}
|
|
103
|
-
return response.json();
|
|
122
|
+
const response = await this.fetchWithRetry(url, { method: "POST", headers, body: bodyStr }, path);
|
|
123
|
+
return this.handleResponse(response, path);
|
|
104
124
|
}
|
|
105
125
|
async put(path, payload) {
|
|
106
126
|
const url = new URL(`${this.baseUrl}${path}.json`);
|
|
@@ -109,27 +129,11 @@ export class BudaClient {
|
|
|
109
129
|
const headers = {
|
|
110
130
|
Accept: "application/json",
|
|
111
131
|
"Content-Type": "application/json",
|
|
112
|
-
"User-Agent":
|
|
132
|
+
"User-Agent": `buda-mcp/${VERSION}`,
|
|
113
133
|
...this.authHeaders("PUT", urlPath, bodyStr),
|
|
114
134
|
};
|
|
115
|
-
const response = await
|
|
116
|
-
|
|
117
|
-
headers,
|
|
118
|
-
body: bodyStr,
|
|
119
|
-
});
|
|
120
|
-
if (!response.ok) {
|
|
121
|
-
let detail = response.statusText;
|
|
122
|
-
try {
|
|
123
|
-
const body = (await response.json());
|
|
124
|
-
if (body.message)
|
|
125
|
-
detail = body.message;
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
// ignore parse error, use statusText
|
|
129
|
-
}
|
|
130
|
-
throw new BudaApiError(response.status, path, `Buda API ${response.status}: ${detail}`);
|
|
131
|
-
}
|
|
132
|
-
return response.json();
|
|
135
|
+
const response = await this.fetchWithRetry(url, { method: "PUT", headers, body: bodyStr }, path);
|
|
136
|
+
return this.handleResponse(response, path);
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
//# sourceMappingURL=client.js.map
|