@guiie/buda-mcp 1.0.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/.github/workflows/publish.yml +58 -0
- package/PUBLISH.md +206 -0
- package/README.md +122 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +52 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/tools/markets.d.ts +4 -0
- package/dist/tools/markets.d.ts.map +1 -0
- package/dist/tools/markets.js +22 -0
- package/dist/tools/orderbook.d.ts +4 -0
- package/dist/tools/orderbook.d.ts.map +1 -0
- package/dist/tools/orderbook.js +28 -0
- package/dist/tools/ticker.d.ts +4 -0
- package/dist/tools/ticker.d.ts.map +1 -0
- package/dist/tools/ticker.js +15 -0
- package/dist/tools/trades.d.ts +4 -0
- package/dist/tools/trades.d.ts.map +1 -0
- package/dist/tools/trades.js +32 -0
- package/dist/tools/volume.d.ts +4 -0
- package/dist/tools/volume.d.ts.map +1 -0
- package/dist/tools/volume.js +15 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/marketplace/README.md +67 -0
- package/marketplace/claude-listing.md +97 -0
- package/marketplace/cursor-mcp.json +9 -0
- package/marketplace/gemini-tools.json +87 -0
- package/marketplace/openapi.yaml +349 -0
- package/package.json +53 -0
- package/server.json +20 -0
- package/src/client.ts +57 -0
- package/src/index.ts +26 -0
- package/src/tools/markets.ts +35 -0
- package/src/tools/orderbook.ts +40 -0
- package/src/tools/ticker.ts +25 -0
- package/src/tools/trades.ts +45 -0
- package/src/tools/volume.ts +25 -0
- package/src/types.ts +84 -0
- package/test/run-all.ts +144 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
# ── 1. Build & test ──────────────────────────────────────────────
|
|
9
|
+
test:
|
|
10
|
+
name: Build & test
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version: "20"
|
|
17
|
+
cache: "npm"
|
|
18
|
+
- run: npm ci
|
|
19
|
+
- run: npm run build
|
|
20
|
+
- run: npm test
|
|
21
|
+
|
|
22
|
+
# ── 2. Publish to npm ────────────────────────────────────────────
|
|
23
|
+
npm:
|
|
24
|
+
name: Publish to npm
|
|
25
|
+
needs: test
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
id-token: write
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
- uses: actions/setup-node@v4
|
|
33
|
+
with:
|
|
34
|
+
node-version: "20"
|
|
35
|
+
registry-url: "https://registry.npmjs.org"
|
|
36
|
+
cache: "npm"
|
|
37
|
+
- run: npm ci
|
|
38
|
+
- run: npm run build
|
|
39
|
+
- run: npm publish --access public --provenance
|
|
40
|
+
env:
|
|
41
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
42
|
+
|
|
43
|
+
# ── 3. Publish to MCP Registry ───────────────────────────────────
|
|
44
|
+
mcp-registry:
|
|
45
|
+
name: Publish to MCP Registry
|
|
46
|
+
needs: npm
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
- name: Install mcp-publisher
|
|
51
|
+
run: |
|
|
52
|
+
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz" \
|
|
53
|
+
| tar xz mcp-publisher
|
|
54
|
+
sudo mv mcp-publisher /usr/local/bin/
|
|
55
|
+
- name: Publish to MCP Registry
|
|
56
|
+
run: mcp-publisher publish
|
|
57
|
+
env:
|
|
58
|
+
MCP_REGISTRY_TOKEN: ${{ secrets.MCP_REGISTRY_TOKEN }}
|
package/PUBLISH.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Publishing checklist
|
|
2
|
+
|
|
3
|
+
Everything that could be automated is already done.
|
|
4
|
+
This file contains only what requires your manual action, in order.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What's already done
|
|
9
|
+
|
|
10
|
+
- [x] GitHub repo created and pushed → https://github.com/gtorreal/buda-mcp
|
|
11
|
+
- [x] `package.json` updated with `mcpName`, `repository`, `bin`, `keywords`
|
|
12
|
+
- [x] `server.json` generated for the official MCP registry
|
|
13
|
+
- [x] `marketplace/` assets generated for Cursor, Claude, ChatGPT, Gemini
|
|
14
|
+
- [x] GitHub Actions workflow created (`.github/workflows/publish.yml`)
|
|
15
|
+
- Triggers automatically on every GitHub Release you create
|
|
16
|
+
- Runs: build → test → npm publish → MCP registry publish
|
|
17
|
+
- [x] `mcp-publisher` CLI installed on your machine
|
|
18
|
+
- [x] `NPM_TOKEN` and `MCP_REGISTRY_TOKEN` secret slots created on GitHub
|
|
19
|
+
- They contain placeholder values — you'll fill them in steps 1 and 3 below
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 1 — npm (one-time setup, ~5 min)
|
|
24
|
+
|
|
25
|
+
### 1a. Create an npm account if you don't have one
|
|
26
|
+
https://www.npmjs.com/signup
|
|
27
|
+
|
|
28
|
+
### 1b. Log in and publish
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm login
|
|
32
|
+
# Opens browser → log in → authorize
|
|
33
|
+
|
|
34
|
+
cd ~/Projects/buda-mcp
|
|
35
|
+
npm run build
|
|
36
|
+
npm publish --access public
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 1c. Put your npm token into GitHub Actions
|
|
40
|
+
1. Go to https://www.npmjs.com/settings/gtorreal/tokens
|
|
41
|
+
2. Create a new **Automation** token (type: "Granular Access Token" → select `@guiie/buda-mcp`)
|
|
42
|
+
3. Run:
|
|
43
|
+
```bash
|
|
44
|
+
gh secret set NPM_TOKEN --repo gtorreal/buda-mcp
|
|
45
|
+
# Paste the token when prompted
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
After this, every GitHub Release you create will auto-publish to npm.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Step 2 — Official MCP Registry (~3 min)
|
|
53
|
+
|
|
54
|
+
`mcp-publisher` is already installed. Just run:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd ~/Projects/buda-mcp
|
|
58
|
+
|
|
59
|
+
# Authenticate with GitHub (opens browser, one-time)
|
|
60
|
+
mcp-publisher login github
|
|
61
|
+
|
|
62
|
+
# Publish (uses the server.json already in the repo)
|
|
63
|
+
mcp-publisher publish
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
You'll see: `✓ Successfully published — io.github.gtorreal/buda-mcp version 1.0.0`
|
|
67
|
+
|
|
68
|
+
### 2b. Put your MCP Registry token into GitHub Actions (for auto-publish on release)
|
|
69
|
+
|
|
70
|
+
After `mcp-publisher login github`, your token is stored locally at `~/.config/mcp-publisher/`.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cat ~/.config/mcp-publisher/credentials.json
|
|
74
|
+
# Copy the token value, then:
|
|
75
|
+
gh secret set MCP_REGISTRY_TOKEN --repo gtorreal/buda-mcp
|
|
76
|
+
# Paste the token when prompted
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Step 3 — Community directories (web forms, ~10 min total)
|
|
82
|
+
|
|
83
|
+
These all auto-populate from the official MCP Registry within a week, but submitting
|
|
84
|
+
directly gets you listed faster.
|
|
85
|
+
|
|
86
|
+
### PulseMCP
|
|
87
|
+
URL: https://www.pulsemcp.com/submit
|
|
88
|
+
Fill in:
|
|
89
|
+
- Name: `buda-mcp`
|
|
90
|
+
- GitHub: `https://github.com/gtorreal/buda-mcp`
|
|
91
|
+
- npm: `@guiie/buda-mcp`
|
|
92
|
+
- Description: copy from `marketplace/claude-listing.md`
|
|
93
|
+
|
|
94
|
+
### Glama.ai
|
|
95
|
+
URL: https://glama.ai/mcp/servers → "Add Server" button
|
|
96
|
+
- GitHub URL: `https://github.com/gtorreal/buda-mcp`
|
|
97
|
+
- Glama scans it automatically
|
|
98
|
+
|
|
99
|
+
### mcp.so
|
|
100
|
+
URL: https://mcp.so — look for "Submit" or open a GitHub issue at their repo
|
|
101
|
+
- GitHub URL: `https://github.com/gtorreal/buda-mcp`
|
|
102
|
+
|
|
103
|
+
### mcpcentral.io
|
|
104
|
+
URL: https://mcpcentral.io/submit-server
|
|
105
|
+
- Fill in repo URL and npm package name
|
|
106
|
+
|
|
107
|
+
### awesome-mcp-servers (GitHub PR)
|
|
108
|
+
1. Fork https://github.com/punkpeye/awesome-mcp-servers
|
|
109
|
+
2. Add this line under the **Finance / Crypto** section:
|
|
110
|
+
```
|
|
111
|
+
- [buda-mcp](https://github.com/gtorreal/buda-mcp) — Real-time market data from Buda.com (Chile/Colombia/Peru): prices, order books, trades, volume. No auth required.
|
|
112
|
+
```
|
|
113
|
+
3. Open a PR
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Step 4 — Smithery (~30 min, requires deployment)
|
|
118
|
+
|
|
119
|
+
Smithery requires an HTTP endpoint, not stdio. Steps:
|
|
120
|
+
|
|
121
|
+
### 4a. Create a Railway account
|
|
122
|
+
https://railway.app → sign in with GitHub
|
|
123
|
+
|
|
124
|
+
### 4b. Deploy
|
|
125
|
+
```bash
|
|
126
|
+
npm install -g @railway/cli
|
|
127
|
+
cd ~/Projects/buda-mcp
|
|
128
|
+
railway login
|
|
129
|
+
railway init # select "Empty project"
|
|
130
|
+
railway up
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
You'll get a URL like `https://buda-mcp-production.up.railway.app`.
|
|
134
|
+
|
|
135
|
+
### 4c. Add HTTP transport to the server
|
|
136
|
+
|
|
137
|
+
You'll need to add a Streamable HTTP transport alongside the existing stdio one.
|
|
138
|
+
This requires a small code change — let me know and I'll implement it.
|
|
139
|
+
|
|
140
|
+
### 4d. Submit to Smithery
|
|
141
|
+
URL: https://smithery.ai/new
|
|
142
|
+
- Paste your Railway URL
|
|
143
|
+
- Smithery auto-scans and extracts the 5 tools
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Step 5 — ChatGPT GPT Action (~15 min, requires deployment from Step 4)
|
|
148
|
+
|
|
149
|
+
Once you have the Railway URL from Step 4:
|
|
150
|
+
|
|
151
|
+
1. Open `marketplace/openapi.yaml`
|
|
152
|
+
2. Replace `https://YOUR_DEPLOYED_DOMAIN` with your Railway URL
|
|
153
|
+
3. Go to https://chatgpt.com → Explore GPTs → Create → Configure → Add Action
|
|
154
|
+
4. Paste the contents of `marketplace/openapi.yaml`
|
|
155
|
+
5. Set Authentication to **None**
|
|
156
|
+
6. Save and publish the GPT
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Step 6 — Gemini / Google AI Studio
|
|
161
|
+
|
|
162
|
+
The `marketplace/gemini-tools.json` function declarations are ready to use now — no
|
|
163
|
+
deployment needed. To share them publicly:
|
|
164
|
+
|
|
165
|
+
1. In Google AI Studio (https://aistudio.google.com), create a new prompt
|
|
166
|
+
2. Click "Tools" → "Add function" → paste each declaration from `gemini-tools.json`
|
|
167
|
+
3. Save as a shared prompt and publish the link
|
|
168
|
+
|
|
169
|
+
For the Gemini Extensions marketplace (currently invite-only):
|
|
170
|
+
- Apply at https://ai.google.dev/gemini-api/docs/extensions
|
|
171
|
+
- Use `marketplace/gemini-tools.json` as your tool schema
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Step 7 — Create a GitHub Release (triggers auto-publish)
|
|
176
|
+
|
|
177
|
+
Once npm token and MCP registry token are set in GitHub Actions secrets (Steps 1c and 2b):
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
gh release create v1.0.0 \
|
|
181
|
+
--title "v1.0.0 — Initial release" \
|
|
182
|
+
--notes "5 public market data tools for Buda.com: get_markets, get_ticker, get_orderbook, get_trades, get_market_volume." \
|
|
183
|
+
--latest
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This triggers the Actions workflow: build → test → npm publish → MCP registry publish.
|
|
187
|
+
All future releases will auto-publish the same way.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Summary
|
|
192
|
+
|
|
193
|
+
| Marketplace | Status | Time needed from you |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| GitHub | ✅ Done | — |
|
|
196
|
+
| npm | Needs your login | ~5 min |
|
|
197
|
+
| Official MCP Registry | Needs OAuth | ~3 min |
|
|
198
|
+
| PulseMCP | Web form | ~2 min |
|
|
199
|
+
| Glama.ai | Web form | ~1 min |
|
|
200
|
+
| mcp.so | Web form | ~2 min |
|
|
201
|
+
| mcpcentral.io | Web form | ~2 min |
|
|
202
|
+
| awesome-mcp-servers | GitHub PR | ~3 min |
|
|
203
|
+
| Smithery | Needs deployment | ~30 min |
|
|
204
|
+
| ChatGPT GPT Action | Needs deployment | ~15 min (after Smithery) |
|
|
205
|
+
| Gemini | Ready now | ~5 min |
|
|
206
|
+
| **GitHub Actions auto-publish** | Needs token secrets | ~5 min |
|
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# buda-mcp
|
|
2
|
+
|
|
3
|
+
A production-ready [MCP](https://modelcontextprotocol.io/) server for the [Buda.com](https://www.buda.com/) cryptocurrency exchange public API. Exposes real-time market data tools to any MCP-compatible AI client (Claude Code, Cursor, ChatGPT, etc.).
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
| Tool | Description |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `get_markets` | List all trading pairs, or get details for one market |
|
|
10
|
+
| `get_ticker` | Current price, bid/ask, volume, and price change for a market |
|
|
11
|
+
| `get_orderbook` | Full order book (bids + asks) for a market |
|
|
12
|
+
| `get_trades` | Recent trade history for a market |
|
|
13
|
+
| `get_market_volume` | 24h and 7-day transacted volume for a market |
|
|
14
|
+
|
|
15
|
+
All tools use Buda.com's **public** endpoints — no API key required.
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
- Node.js 18+
|
|
20
|
+
- npm 8+
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git clone https://github.com/gtorreal/buda-mcp.git
|
|
26
|
+
cd buda-mcp
|
|
27
|
+
npm install
|
|
28
|
+
npm run build
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Running the test suite
|
|
32
|
+
|
|
33
|
+
Calls each tool against the live Buda API and prints the results:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm test
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Claude Code
|
|
42
|
+
|
|
43
|
+
Add the server with the `claude` CLI:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
claude mcp add buda-mcp -- node /absolute/path/to/buda-mcp/dist/index.js
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then ask Claude things like:
|
|
50
|
+
|
|
51
|
+
> What is the current BTC-CLP price?
|
|
52
|
+
> Show me the order book for ETH-CLP.
|
|
53
|
+
> How much Bitcoin was traded in the last 7 days on BTC-CLP?
|
|
54
|
+
|
|
55
|
+
### Cursor
|
|
56
|
+
|
|
57
|
+
Add to `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"buda-mcp": {
|
|
63
|
+
"command": "node",
|
|
64
|
+
"args": ["/absolute/path/to/buda-mcp/dist/index.js"]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Restart Cursor and the tools will be available to the AI agent in chat.
|
|
71
|
+
|
|
72
|
+
### ChatGPT (Actions / Custom GPT)
|
|
73
|
+
|
|
74
|
+
ChatGPT does not natively support the stdio MCP transport. To use this server with ChatGPT you need an HTTP bridge. The simplest option is [mcp-server-proxy](https://github.com/sparfenyuk/mcp-proxy):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install mcp-proxy
|
|
78
|
+
mcp-proxy --port 8000 -- node /absolute/path/to/buda-mcp/dist/index.js
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Then register `http://localhost:8000` (or your deployed URL) as a GPT Action endpoint. Use the auto-generated OpenAPI schema that `mcp-proxy` exposes at `/openapi.json`.
|
|
82
|
+
|
|
83
|
+
## Project structure
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
src/
|
|
87
|
+
index.ts — MCP server entry point
|
|
88
|
+
client.ts — BudaClient HTTP wrapper (extend here for auth)
|
|
89
|
+
types.ts — TypeScript types for all API responses
|
|
90
|
+
tools/
|
|
91
|
+
markets.ts — get_markets
|
|
92
|
+
ticker.ts — get_ticker
|
|
93
|
+
orderbook.ts — get_orderbook
|
|
94
|
+
trades.ts — get_trades
|
|
95
|
+
volume.ts — get_market_volume
|
|
96
|
+
test/
|
|
97
|
+
run-all.ts — integration test script
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Adding private endpoints
|
|
101
|
+
|
|
102
|
+
`BudaClient` in `src/client.ts` is structured for easy extension. To add authenticated endpoints (balances, orders, withdrawals):
|
|
103
|
+
|
|
104
|
+
1. Add `apiKey` and `apiSecret` constructor parameters.
|
|
105
|
+
2. Implement HMAC-SHA2 signing in a `signedGet` / `signedPost` method (see [Buda auth docs](https://api.buda.com/en/#rest-api-private-endpoints-authentication)).
|
|
106
|
+
3. Drop new tool files under `src/tools/` and call `register(server, client)` in `src/index.ts`.
|
|
107
|
+
|
|
108
|
+
## Markets available
|
|
109
|
+
|
|
110
|
+
Buda.com operates in Chile, Colombia, and Peru:
|
|
111
|
+
|
|
112
|
+
| Quote currency | Country |
|
|
113
|
+
|---|---|
|
|
114
|
+
| CLP | Chile |
|
|
115
|
+
| COP | Colombia |
|
|
116
|
+
| PEN | Peru |
|
|
117
|
+
|
|
118
|
+
Common markets: `BTC-CLP`, `ETH-CLP`, `BTC-COP`, `ETH-COP`, `BTC-PEN`, `ETH-PEN`, `ETH-BTC`, `XRP-BTC`, etc.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class BudaApiError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly path: string;
|
|
4
|
+
constructor(status: number, path: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class BudaClient {
|
|
7
|
+
private readonly baseUrl;
|
|
8
|
+
constructor(baseUrl?: string);
|
|
9
|
+
/**
|
|
10
|
+
* Perform an authenticated GET request.
|
|
11
|
+
*
|
|
12
|
+
* Private endpoints (balances, orders, etc.) require HMAC-SHA2 signing.
|
|
13
|
+
* To add auth later, extend this method with the `apiKey` + `apiSecret`
|
|
14
|
+
* constructor params and sign the nonce/path headers here before fetching.
|
|
15
|
+
*/
|
|
16
|
+
get<T>(path: string, params?: Record<string, string | number>): Promise<T>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,qBAAa,YAAa,SAAQ,KAAK;aAEnB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,MAAiB;IAItC;;;;;;OAMG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CA6BjF"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const BASE_URL = "https://www.buda.com/api/v2";
|
|
2
|
+
export class BudaApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
path;
|
|
5
|
+
constructor(status, path, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.path = path;
|
|
9
|
+
this.name = "BudaApiError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class BudaClient {
|
|
13
|
+
baseUrl;
|
|
14
|
+
constructor(baseUrl = BASE_URL) {
|
|
15
|
+
this.baseUrl = baseUrl;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Perform an authenticated GET request.
|
|
19
|
+
*
|
|
20
|
+
* Private endpoints (balances, orders, etc.) require HMAC-SHA2 signing.
|
|
21
|
+
* To add auth later, extend this method with the `apiKey` + `apiSecret`
|
|
22
|
+
* constructor params and sign the nonce/path headers here before fetching.
|
|
23
|
+
*/
|
|
24
|
+
async get(path, params) {
|
|
25
|
+
const url = new URL(`${this.baseUrl}${path}.json`);
|
|
26
|
+
if (params) {
|
|
27
|
+
for (const [key, value] of Object.entries(params)) {
|
|
28
|
+
url.searchParams.set(key, String(value));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const response = await fetch(url.toString(), {
|
|
32
|
+
headers: {
|
|
33
|
+
Accept: "application/json",
|
|
34
|
+
"User-Agent": "buda-mcp/1.0.0",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
let detail = response.statusText;
|
|
39
|
+
try {
|
|
40
|
+
const body = (await response.json());
|
|
41
|
+
if (body.message)
|
|
42
|
+
detail = body.message;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore parse error, use statusText
|
|
46
|
+
}
|
|
47
|
+
throw new BudaApiError(response.status, path, `Buda API ${response.status}: ${detail}`);
|
|
48
|
+
}
|
|
49
|
+
return response.json();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=client.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { BudaClient } from "./client.js";
|
|
4
|
+
import * as markets from "./tools/markets.js";
|
|
5
|
+
import * as ticker from "./tools/ticker.js";
|
|
6
|
+
import * as orderbook from "./tools/orderbook.js";
|
|
7
|
+
import * as trades from "./tools/trades.js";
|
|
8
|
+
import * as volume from "./tools/volume.js";
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: "buda-mcp",
|
|
11
|
+
version: "1.0.0",
|
|
12
|
+
});
|
|
13
|
+
const client = new BudaClient();
|
|
14
|
+
// Register all public-endpoint tools
|
|
15
|
+
markets.register(server, client);
|
|
16
|
+
ticker.register(server, client);
|
|
17
|
+
orderbook.register(server, client);
|
|
18
|
+
trades.register(server, client);
|
|
19
|
+
volume.register(server, client);
|
|
20
|
+
// Start the server over stdio (standard MCP transport)
|
|
21
|
+
const transport = new StdioServerTransport();
|
|
22
|
+
await server.connect(transport);
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markets.d.ts","sourceRoot":"","sources":["../../src/tools/markets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA6BpE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function register(server, client) {
|
|
3
|
+
server.tool("get_markets", "List all available trading pairs on Buda.com, or get details for a specific market. " +
|
|
4
|
+
"Returns base/quote currencies, fees, and minimum order sizes.", {
|
|
5
|
+
market_id: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("Optional market ID (e.g. 'BTC-CLP', 'ETH-BTC'). Omit to list all markets."),
|
|
9
|
+
}, async ({ market_id }) => {
|
|
10
|
+
if (market_id) {
|
|
11
|
+
const data = await client.get(`/markets/${market_id.toLowerCase()}`);
|
|
12
|
+
return {
|
|
13
|
+
content: [{ type: "text", text: JSON.stringify(data.market, null, 2) }],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const data = await client.get("/markets");
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text: JSON.stringify(data.markets, null, 2) }],
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=markets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orderbook.d.ts","sourceRoot":"","sources":["../../src/tools/orderbook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkCpE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function register(server, client) {
|
|
3
|
+
server.tool("get_orderbook", "Get the current order book for a Buda.com market. Returns sorted arrays of " +
|
|
4
|
+
"bids (buy orders) and asks (sell orders), each as [price, amount] pairs.", {
|
|
5
|
+
market_id: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
|
|
8
|
+
limit: z
|
|
9
|
+
.number()
|
|
10
|
+
.int()
|
|
11
|
+
.positive()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Maximum number of levels to return per side (default: all)."),
|
|
14
|
+
}, async ({ market_id, limit }) => {
|
|
15
|
+
const data = await client.get(`/markets/${market_id.toLowerCase()}/order_book`);
|
|
16
|
+
const book = data.order_book;
|
|
17
|
+
const result = {
|
|
18
|
+
bids: limit ? book.bids.slice(0, limit) : book.bids,
|
|
19
|
+
asks: limit ? book.asks.slice(0, limit) : book.asks,
|
|
20
|
+
bid_count: book.bids.length,
|
|
21
|
+
ask_count: book.asks.length,
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=orderbook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticker.d.ts","sourceRoot":"","sources":["../../src/tools/ticker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function register(server, client) {
|
|
3
|
+
server.tool("get_ticker", "Get the current ticker for a Buda.com market: last traded price, best bid/ask, " +
|
|
4
|
+
"24h volume, and price change over 24h and 7d.", {
|
|
5
|
+
market_id: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC', 'BTC-COP')."),
|
|
8
|
+
}, async ({ market_id }) => {
|
|
9
|
+
const data = await client.get(`/markets/${market_id.toLowerCase()}/ticker`);
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text: JSON.stringify(data.ticker, null, 2) }],
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ticker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trades.d.ts","sourceRoot":"","sources":["../../src/tools/trades.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAuCpE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function register(server, client) {
|
|
3
|
+
server.tool("get_trades", "Get recent trade history for a Buda.com market. Each entry contains " +
|
|
4
|
+
"[timestamp_ms, amount, price, direction]. Direction is 'buy' or 'sell'.", {
|
|
5
|
+
market_id: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
|
|
8
|
+
limit: z
|
|
9
|
+
.number()
|
|
10
|
+
.int()
|
|
11
|
+
.min(1)
|
|
12
|
+
.max(100)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Number of trades to return (default: 50, max: 100)."),
|
|
15
|
+
timestamp: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Unix timestamp (seconds) to paginate from. Returns trades older than this timestamp."),
|
|
20
|
+
}, async ({ market_id, limit, timestamp }) => {
|
|
21
|
+
const params = {};
|
|
22
|
+
if (limit !== undefined)
|
|
23
|
+
params.limit = limit;
|
|
24
|
+
if (timestamp !== undefined)
|
|
25
|
+
params.timestamp = timestamp;
|
|
26
|
+
const data = await client.get(`/markets/${market_id.toLowerCase()}/trades`, Object.keys(params).length > 0 ? params : undefined);
|
|
27
|
+
return {
|
|
28
|
+
content: [{ type: "text", text: JSON.stringify(data.trades, null, 2) }],
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=trades.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"volume.d.ts","sourceRoot":"","sources":["../../src/tools/volume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function register(server, client) {
|
|
3
|
+
server.tool("get_market_volume", "Get 24h and 7-day transacted volume for a Buda.com market. " +
|
|
4
|
+
"Returns ask (sell) and bid (buy) volumes in the market's base currency.", {
|
|
5
|
+
market_id: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
|
|
8
|
+
}, async ({ market_id }) => {
|
|
9
|
+
const data = await client.get(`/markets/${market_id.toLowerCase()}/volume`);
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text: JSON.stringify(data.volume, null, 2) }],
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=volume.js.map
|