stables-mcp-server 2.0.0 → 2.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 +74 -16
- package/build/http/auth.d.ts +26 -0
- package/build/http/auth.d.ts.map +1 -0
- package/build/http/auth.js +47 -0
- package/build/http/auth.js.map +1 -0
- package/build/http/handler.d.ts +13 -0
- package/build/http/handler.d.ts.map +1 -0
- package/build/http/handler.js +102 -0
- package/build/http/handler.js.map +1 -0
- package/build/index.d.ts +5 -18
- package/build/index.d.ts.map +1 -1
- package/build/index.js +7 -43
- package/build/index.js.map +1 -1
- package/build/lib/stables-client.d.ts +98 -9
- package/build/lib/stables-client.d.ts.map +1 -1
- package/build/lib/stables-client.js +53 -0
- package/build/lib/stables-client.js.map +1 -1
- package/build/serve.d.ts +11 -0
- package/build/serve.d.ts.map +1 -0
- package/build/serve.js +71 -0
- package/build/serve.js.map +1 -0
- package/build/server.d.ts +12 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +32 -0
- package/build/server.js.map +1 -0
- package/build/tools/quotes.js +1 -1
- package/build/tools/quotes.js.map +1 -1
- package/build/tools/sandbox.d.ts +11 -0
- package/build/tools/sandbox.d.ts.map +1 -0
- package/build/tools/sandbox.js +78 -0
- package/build/tools/sandbox.js.map +1 -0
- package/build/tools/transfers.d.ts.map +1 -1
- package/build/tools/transfers.js +1 -2
- package/build/tools/transfers.js.map +1 -1
- package/build/tools/virtual-accounts.d.ts.map +1 -1
- package/build/tools/virtual-accounts.js +95 -38
- package/build/tools/virtual-accounts.js.map +1 -1
- package/build/tools/webhooks.d.ts.map +1 -1
- package/build/tools/webhooks.js +61 -5
- package/build/tools/webhooks.js.map +1 -1
- package/build/worker.d.ts +11 -0
- package/build/worker.d.ts.map +1 -0
- package/build/worker.js +13 -0
- package/build/worker.js.map +1 -0
- package/package.json +12 -5
- package/build/tools/payment-methods.d.ts +0 -12
- package/build/tools/payment-methods.d.ts.map +0 -1
- package/build/tools/payment-methods.js +0 -119
- package/build/tools/payment-methods.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ MCP (Model Context Protocol) is an open standard that provides a standardized wa
|
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
This MCP server provides
|
|
13
|
+
This MCP server provides 26 tools across 7 categories:
|
|
14
14
|
|
|
15
15
|
### Customer Management
|
|
16
16
|
- `create_customer` - Create individual or business customers
|
|
@@ -33,10 +33,12 @@ This MCP server provides 23 tools across 7 categories:
|
|
|
33
33
|
- `create_virtual_account` - Create virtual bank accounts for fiat deposits
|
|
34
34
|
- `list_virtual_accounts` - List virtual accounts for a customer
|
|
35
35
|
- `update_virtual_account` - Update virtual account settings
|
|
36
|
-
- `get_virtual_account_history` - Get
|
|
36
|
+
- `get_virtual_account_history` - Get deposits and their payouts for a payment route
|
|
37
|
+
- `update_route_destination` - Change the payout wallet on an existing route
|
|
37
38
|
|
|
38
|
-
###
|
|
39
|
-
- `
|
|
39
|
+
### Sandbox
|
|
40
|
+
- `simulate_route_deposit` - Simulate a fiat deposit into a payment route (sandbox only)
|
|
41
|
+
- `simulate_transfer_deposit` - Simulate the inbound crypto an off-ramp transfer awaits (sandbox only)
|
|
40
42
|
|
|
41
43
|
### API Keys
|
|
42
44
|
- `create_api_key` - Create a new API key
|
|
@@ -48,8 +50,56 @@ This MCP server provides 23 tools across 7 categories:
|
|
|
48
50
|
- `create_webhook` - Subscribe to events via webhook
|
|
49
51
|
- `list_webhooks` - List all webhook subscriptions
|
|
50
52
|
- `delete_webhook` - Delete a webhook subscription
|
|
53
|
+
- `list_webhook_deliveries` - Recent delivery attempts, status codes and retry state
|
|
51
54
|
|
|
52
|
-
##
|
|
55
|
+
## Hosted server (recommended)
|
|
56
|
+
|
|
57
|
+
The server runs as a hosted service, so there is nothing to install. Point your MCP client at:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
https://mcp.stables.money/mcp
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
and send your Stables API key as a bearer token. The key you get during onboarding is all you need: a `sti_test_…` key reaches sandbox, a `sti_live_…` key reaches production and moves real money. The hosted server keeps no credentials of its own; every request carries yours.
|
|
64
|
+
|
|
65
|
+
### Claude Code
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
claude mcp add --transport http stables https://mcp.stables.money/mcp --header "Authorization: Bearer ${STABLES_API_KEY}"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Cursor, VS Code, Windsurf and other clients with a `url` field
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"stables": {
|
|
77
|
+
"url": "https://mcp.stables.money/mcp",
|
|
78
|
+
"headers": {
|
|
79
|
+
"Authorization": "Bearer sti_test_..."
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Codex
|
|
87
|
+
|
|
88
|
+
```toml
|
|
89
|
+
[mcp_servers.stables]
|
|
90
|
+
url = "https://mcp.stables.money/mcp"
|
|
91
|
+
bearer_token_env_var = "STABLES_API_KEY"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Claude.ai and ChatGPT
|
|
95
|
+
|
|
96
|
+
Claude.ai custom connectors and ChatGPT connectors sign in with OAuth rather than a fixed key. OAuth sign-in for the hosted server is in progress; until it ships, use one of the clients above, or run the server locally as described below.
|
|
97
|
+
|
|
98
|
+
## Running locally
|
|
99
|
+
|
|
100
|
+
The same server also runs as a local process over stdio, which is what `npx stables-mcp-server` does. Use this for a `sti_local_…` key against your own deployment, or when your client cannot reach the internet.
|
|
101
|
+
|
|
102
|
+
### Installation
|
|
53
103
|
|
|
54
104
|
```bash
|
|
55
105
|
# Install from npm
|
|
@@ -62,7 +112,7 @@ npm install
|
|
|
62
112
|
npm run build
|
|
63
113
|
```
|
|
64
114
|
|
|
65
|
-
|
|
115
|
+
### Configuration
|
|
66
116
|
|
|
67
117
|
The server requires the following environment variables:
|
|
68
118
|
|
|
@@ -90,9 +140,9 @@ local deployment.
|
|
|
90
140
|
**Start with a sandbox key.** An agent holding a live key can move real money on
|
|
91
141
|
your behalf; see [agent safety](https://docs.stables.money/get-started/getting-started/quickstart/building-with-ai/agent-safety).
|
|
92
142
|
|
|
93
|
-
|
|
143
|
+
### Usage
|
|
94
144
|
|
|
95
|
-
|
|
145
|
+
#### With Claude Desktop
|
|
96
146
|
|
|
97
147
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
98
148
|
|
|
@@ -113,7 +163,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
113
163
|
|
|
114
164
|
Then restart Claude Desktop.
|
|
115
165
|
|
|
116
|
-
|
|
166
|
+
#### With Cursor, Codex, ChatGPT, or another MCP client
|
|
117
167
|
|
|
118
168
|
Use the same command and environment variables in any MCP-compatible client:
|
|
119
169
|
|
|
@@ -161,7 +211,7 @@ STABLES_API_KEY=your-api-key node build/index.js
|
|
|
161
211
|
|
|
162
212
|
**AI (using MCP tools):**
|
|
163
213
|
1. Calls `create_customer` with email and type
|
|
164
|
-
2. Calls `create_quote` with
|
|
214
|
+
2. Calls `create_quote` with source USDT + network, destination EUR + country, and `destinationNetwork` (`swift` or `bank`)
|
|
165
215
|
3. Returns customer details and quote information
|
|
166
216
|
|
|
167
217
|
### Checking transfer status
|
|
@@ -169,16 +219,24 @@ STABLES_API_KEY=your-api-key node build/index.js
|
|
|
169
219
|
**User:** "What's the status of all my pending transfers?"
|
|
170
220
|
|
|
171
221
|
**AI (using MCP tools):**
|
|
172
|
-
1. Calls `list_transfers` with `status=
|
|
173
|
-
2. Returns formatted list of
|
|
222
|
+
1. Calls `list_transfers` with `status=created` or `status=in_progress` (statuses are lowercase)
|
|
223
|
+
2. Returns a formatted list of in-flight transfers
|
|
174
224
|
|
|
175
225
|
### Setting up auto-payout
|
|
176
226
|
|
|
177
|
-
**User:** "Create a
|
|
227
|
+
**User:** "Create a payment route for customer abc123 that pays AUD deposits out to my Polygon USDT wallet 0x..."
|
|
228
|
+
|
|
229
|
+
**AI (using MCP tools):**
|
|
230
|
+
1. Calls `create_virtual_account` with the customer ID, AUD source currency, and the Polygon destination (the payout address is mandatory)
|
|
231
|
+
2. Returns the deposit instructions to share with the customer
|
|
232
|
+
|
|
233
|
+
### Paying out to a European beneficiary
|
|
234
|
+
|
|
235
|
+
**User:** "Pay 500 EUR to this German bank account"
|
|
178
236
|
|
|
179
237
|
**AI (using MCP tools):**
|
|
180
|
-
1.
|
|
181
|
-
2.
|
|
238
|
+
1. Collects the extra beneficiary details EUR requires — `recipientType`, a full address, and `dateOfBirth` for individuals — before doing anything else
|
|
239
|
+
2. Calls `create_quote`, then `create_transfer` once a human approves
|
|
182
240
|
|
|
183
241
|
## Development
|
|
184
242
|
|
|
@@ -218,7 +276,7 @@ stables-mcp-server/
|
|
|
218
276
|
│ ├── virtual-accounts.ts # Virtual account tools (6)
|
|
219
277
|
│ ├── api-keys.ts # API key tools (4)
|
|
220
278
|
│ ├── webhooks.ts # Webhook tools (3)
|
|
221
|
-
│ └──
|
|
279
|
+
│ └── sandbox.ts # Sandbox deposit simulation (2)
|
|
222
280
|
├── package.json
|
|
223
281
|
├── tsconfig.json
|
|
224
282
|
├── vitest.config.ts
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request authentication for the hosted server.
|
|
3
|
+
*
|
|
4
|
+
* The hosted service holds no credentials of its own. Each request carries the
|
|
5
|
+
* caller's Stables API key, and the key alone decides which environment the
|
|
6
|
+
* request reaches: `sti_test_…` goes to sandbox, `sti_live_…` to production.
|
|
7
|
+
* That is the same rule the stdio server applies to STABLES_API_KEY, so a key
|
|
8
|
+
* issued during onboarding works here with no further setup.
|
|
9
|
+
*/
|
|
10
|
+
import { StablesApiClient } from "../lib/stables-client.js";
|
|
11
|
+
export declare const BEARER_CHALLENGE: string;
|
|
12
|
+
export type AuthResult = {
|
|
13
|
+
ok: true;
|
|
14
|
+
client: StablesApiClient;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
reason: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Read the API key off a request. The Authorization header is the standard
|
|
21
|
+
* place; X-Api-Key is accepted because the Stables API itself accepts it and
|
|
22
|
+
* some MCP clients only let users set that header.
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractApiKey(headers: Headers): string | null;
|
|
25
|
+
export declare function authenticate(headers: Headers): AuthResult;
|
|
26
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/http/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAgB,MAAM,0BAA0B,CAAC;AAE1E,eAAO,MAAM,gBAAgB,QAEiH,CAAC;AAE/I,MAAM,MAAM,UAAU,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAS7D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAiBzD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request authentication for the hosted server.
|
|
3
|
+
*
|
|
4
|
+
* The hosted service holds no credentials of its own. Each request carries the
|
|
5
|
+
* caller's Stables API key, and the key alone decides which environment the
|
|
6
|
+
* request reaches: `sti_test_…` goes to sandbox, `sti_live_…` to production.
|
|
7
|
+
* That is the same rule the stdio server applies to STABLES_API_KEY, so a key
|
|
8
|
+
* issued during onboarding works here with no further setup.
|
|
9
|
+
*/
|
|
10
|
+
import { StablesApiClient, apiUrlForKey } from "../lib/stables-client.js";
|
|
11
|
+
export const BEARER_CHALLENGE = 'Bearer realm="stables", error="invalid_token", ' +
|
|
12
|
+
'error_description="Send your Stables API key as a bearer token: Authorization: Bearer sti_test_... (sandbox) or sti_live_... (production)"';
|
|
13
|
+
/**
|
|
14
|
+
* Read the API key off a request. The Authorization header is the standard
|
|
15
|
+
* place; X-Api-Key is accepted because the Stables API itself accepts it and
|
|
16
|
+
* some MCP clients only let users set that header.
|
|
17
|
+
*/
|
|
18
|
+
export function extractApiKey(headers) {
|
|
19
|
+
const authorization = headers.get("authorization");
|
|
20
|
+
if (authorization) {
|
|
21
|
+
const match = authorization.match(/^Bearer\s+(.+)$/i);
|
|
22
|
+
if (match)
|
|
23
|
+
return match[1].trim();
|
|
24
|
+
}
|
|
25
|
+
const apiKeyHeader = headers.get("x-api-key");
|
|
26
|
+
if (apiKeyHeader)
|
|
27
|
+
return apiKeyHeader.trim();
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
export function authenticate(headers) {
|
|
31
|
+
const apiKey = extractApiKey(headers);
|
|
32
|
+
if (!apiKey) {
|
|
33
|
+
return { ok: false, reason: "Missing API key" };
|
|
34
|
+
}
|
|
35
|
+
const baseUrl = apiUrlForKey(apiKey);
|
|
36
|
+
if (!baseUrl) {
|
|
37
|
+
// A `sti_local_…` key or an unrecognised shape has no environment we can
|
|
38
|
+
// route to. The stdio server lets STABLES_API_URL resolve that; the hosted
|
|
39
|
+
// one has no such channel, and guessing production would be wrong.
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
reason: "Unrecognised API key. The hosted server accepts sti_test_… (sandbox) and sti_live_… (production) keys; for a local deployment run the server locally with STABLES_API_URL",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return { ok: true, client: new StablesApiClient(apiKey, baseUrl) };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/http/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE1E,MAAM,CAAC,MAAM,gBAAgB,GAC3B,iDAAiD;IACjD,4IAA4I,CAAC;AAI/I;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACnD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,yEAAyE;QACzE,2EAA2E;QAC3E,mEAAmE;QACnE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,2KAA2K;SAC9K,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web-standard HTTP handler for the hosted Stables MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Works anywhere a `fetch`-style `Request` → `Response` function runs: a
|
|
5
|
+
* Cloudflare Worker, a Node process (see serve.ts), or any other runtime with
|
|
6
|
+
* the web platform APIs. The server is stateless: each request authenticates
|
|
7
|
+
* from its own headers and gets a fresh MCP server bound to that key, so
|
|
8
|
+
* nothing about one caller survives to the next and no session store is
|
|
9
|
+
* needed.
|
|
10
|
+
*/
|
|
11
|
+
export declare const MCP_PATH = "/mcp";
|
|
12
|
+
export declare function handleRequest(request: Request): Promise<Response>;
|
|
13
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/http/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,eAAO,MAAM,QAAQ,SAAS,CAAC;AAgF/B,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyBvE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web-standard HTTP handler for the hosted Stables MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Works anywhere a `fetch`-style `Request` → `Response` function runs: a
|
|
5
|
+
* Cloudflare Worker, a Node process (see serve.ts), or any other runtime with
|
|
6
|
+
* the web platform APIs. The server is stateless: each request authenticates
|
|
7
|
+
* from its own headers and gets a fresh MCP server bound to that key, so
|
|
8
|
+
* nothing about one caller survives to the next and no session store is
|
|
9
|
+
* needed.
|
|
10
|
+
*/
|
|
11
|
+
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
12
|
+
import { SERVER_NAME, SERVER_VERSION, createStablesMcpServer } from "../server.js";
|
|
13
|
+
import { BEARER_CHALLENGE, authenticate } from "./auth.js";
|
|
14
|
+
export const MCP_PATH = "/mcp";
|
|
15
|
+
const CORS_HEADERS = {
|
|
16
|
+
"access-control-allow-origin": "*",
|
|
17
|
+
"access-control-allow-methods": "GET, POST, DELETE, OPTIONS",
|
|
18
|
+
"access-control-allow-headers": "authorization, x-api-key, content-type, accept, mcp-session-id, mcp-protocol-version, last-event-id",
|
|
19
|
+
"access-control-expose-headers": "mcp-session-id, mcp-protocol-version",
|
|
20
|
+
"access-control-max-age": "86400",
|
|
21
|
+
};
|
|
22
|
+
function withCors(response) {
|
|
23
|
+
const headers = new Headers(response.headers);
|
|
24
|
+
for (const [name, value] of Object.entries(CORS_HEADERS))
|
|
25
|
+
headers.set(name, value);
|
|
26
|
+
return new Response(response.body, { status: response.status, headers });
|
|
27
|
+
}
|
|
28
|
+
function json(body, status = 200, extraHeaders = {}) {
|
|
29
|
+
return new Response(JSON.stringify(body, null, 2), {
|
|
30
|
+
status,
|
|
31
|
+
headers: { "content-type": "application/json", ...extraHeaders },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function unauthorized(reason) {
|
|
35
|
+
return json({
|
|
36
|
+
error: "unauthorized",
|
|
37
|
+
message: reason,
|
|
38
|
+
hint: "Authorization: Bearer <your Stables API key>. A sti_test_ key reaches sandbox, a sti_live_ key reaches production and moves real money.",
|
|
39
|
+
docs: "https://docs.stables.money/get-started/getting-started/quickstart/building-with-ai",
|
|
40
|
+
}, 401, { "www-authenticate": BEARER_CHALLENGE });
|
|
41
|
+
}
|
|
42
|
+
function describe(origin) {
|
|
43
|
+
return json({
|
|
44
|
+
name: SERVER_NAME,
|
|
45
|
+
version: SERVER_VERSION,
|
|
46
|
+
description: "Hosted MCP server for the Stables fiat-to-crypto API. Connect any MCP client to the endpoint below with your Stables API key as a bearer token.",
|
|
47
|
+
endpoint: `${origin}${MCP_PATH}`,
|
|
48
|
+
transport: "streamable-http",
|
|
49
|
+
authentication: {
|
|
50
|
+
type: "bearer",
|
|
51
|
+
header: "Authorization: Bearer <api key>",
|
|
52
|
+
environments: {
|
|
53
|
+
"sti_test_…": "sandbox (https://api.sandbox.stables.money)",
|
|
54
|
+
"sti_live_…": "production (https://api.stables.money)",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
docs: "https://docs.stables.money/get-started/getting-started/quickstart/building-with-ai",
|
|
58
|
+
source: "https://github.com/stables-money/mcp-server",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async function handleMcp(request) {
|
|
62
|
+
const auth = authenticate(request.headers);
|
|
63
|
+
if (!auth.ok)
|
|
64
|
+
return unauthorized(auth.reason);
|
|
65
|
+
const server = createStablesMcpServer(auth.client);
|
|
66
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
67
|
+
// Stateless: no session ids, so any instance (or any edge location) can
|
|
68
|
+
// answer any request, and a client never has to re-initialise after a
|
|
69
|
+
// deploy. Each tool call is one round trip to the Stables API anyway.
|
|
70
|
+
sessionIdGenerator: undefined,
|
|
71
|
+
// Plain JSON bodies rather than SSE frames: nothing here streams partial
|
|
72
|
+
// results, and JSON is the easier contract for clients and for debugging.
|
|
73
|
+
enableJsonResponse: true,
|
|
74
|
+
});
|
|
75
|
+
await server.connect(transport);
|
|
76
|
+
try {
|
|
77
|
+
return await transport.handleRequest(request);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
await transport.close();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export async function handleRequest(request) {
|
|
84
|
+
const url = new URL(request.url);
|
|
85
|
+
if (request.method === "OPTIONS") {
|
|
86
|
+
return withCors(new Response(null, { status: 204 }));
|
|
87
|
+
}
|
|
88
|
+
if (url.pathname === "/" || url.pathname === "") {
|
|
89
|
+
return withCors(describe(url.origin));
|
|
90
|
+
}
|
|
91
|
+
if (url.pathname === "/health") {
|
|
92
|
+
return withCors(json({ status: "ok", version: SERVER_VERSION }));
|
|
93
|
+
}
|
|
94
|
+
if (url.pathname === MCP_PATH || url.pathname === `${MCP_PATH}/`) {
|
|
95
|
+
return withCors(await handleMcp(request));
|
|
96
|
+
}
|
|
97
|
+
return withCors(json({
|
|
98
|
+
error: "not_found",
|
|
99
|
+
message: `Nothing at ${url.pathname}. The MCP endpoint is ${MCP_PATH}.`,
|
|
100
|
+
}, 404));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/http/handler.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Stables MCP Server
|
|
3
|
+
* Stables MCP Server — stdio entry point.
|
|
4
4
|
*
|
|
5
|
-
* This
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* This is what `npx stables-mcp-server` runs: a local process that speaks MCP
|
|
6
|
+
* over stdin/stdout and authenticates to the Stables API with the key in
|
|
7
|
+
* STABLES_API_KEY. The hosted service at https://mcp.stables.money/mcp exposes
|
|
8
|
+
* the same tools over HTTP without installing anything; see README.md.
|
|
8
9
|
*
|
|
9
10
|
* Usage:
|
|
10
11
|
* STABLES_API_KEY=your-key node build/index.js
|
|
11
|
-
*
|
|
12
|
-
* For Claude Desktop, add to ~/Library/Application Support/Claude/claude_desktop_config.json:
|
|
13
|
-
* {
|
|
14
|
-
* "mcpServers": {
|
|
15
|
-
* "stables": {
|
|
16
|
-
* "command": "node",
|
|
17
|
-
* "args": ["/path/to/stables-mcp-server/build/index.js"],
|
|
18
|
-
* "env": {
|
|
19
|
-
* "STABLES_API_KEY": "your-api-key",
|
|
20
|
-
* "STABLES_API_URL": "https://api.stables.money"
|
|
21
|
-
* }
|
|
22
|
-
* }
|
|
23
|
-
* }
|
|
24
|
-
* }
|
|
25
12
|
*/
|
|
26
13
|
export {};
|
|
27
14
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
|
package/build/index.js
CHANGED
|
@@ -1,38 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Stables MCP Server
|
|
3
|
+
* Stables MCP Server — stdio entry point.
|
|
4
4
|
*
|
|
5
|
-
* This
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* This is what `npx stables-mcp-server` runs: a local process that speaks MCP
|
|
6
|
+
* over stdin/stdout and authenticates to the Stables API with the key in
|
|
7
|
+
* STABLES_API_KEY. The hosted service at https://mcp.stables.money/mcp exposes
|
|
8
|
+
* the same tools over HTTP without installing anything; see README.md.
|
|
8
9
|
*
|
|
9
10
|
* Usage:
|
|
10
11
|
* STABLES_API_KEY=your-key node build/index.js
|
|
11
|
-
*
|
|
12
|
-
* For Claude Desktop, add to ~/Library/Application Support/Claude/claude_desktop_config.json:
|
|
13
|
-
* {
|
|
14
|
-
* "mcpServers": {
|
|
15
|
-
* "stables": {
|
|
16
|
-
* "command": "node",
|
|
17
|
-
* "args": ["/path/to/stables-mcp-server/build/index.js"],
|
|
18
|
-
* "env": {
|
|
19
|
-
* "STABLES_API_KEY": "your-api-key",
|
|
20
|
-
* "STABLES_API_URL": "https://api.stables.money"
|
|
21
|
-
* }
|
|
22
|
-
* }
|
|
23
|
-
* }
|
|
24
|
-
* }
|
|
25
12
|
*/
|
|
26
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
27
13
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
28
14
|
import { createStablesClient } from "./lib/stables-client.js";
|
|
29
|
-
import {
|
|
30
|
-
import { registerQuoteTools } from "./tools/quotes.js";
|
|
31
|
-
import { registerTransferTools } from "./tools/transfers.js";
|
|
32
|
-
import { registerVirtualAccountTools } from "./tools/virtual-accounts.js";
|
|
33
|
-
import { registerApiKeyTools } from "./tools/api-keys.js";
|
|
34
|
-
import { registerWebhookTools } from "./tools/webhooks.js";
|
|
35
|
-
import { registerPaymentMethodTools } from "./tools/payment-methods.js";
|
|
15
|
+
import { createStablesMcpServer } from "./server.js";
|
|
36
16
|
// Validate environment
|
|
37
17
|
const apiKey = process.env.STABLES_API_KEY;
|
|
38
18
|
if (!apiKey) {
|
|
@@ -40,24 +20,8 @@ if (!apiKey) {
|
|
|
40
20
|
console.error("Error: STABLES_API_KEY environment variable is required");
|
|
41
21
|
process.exit(1);
|
|
42
22
|
}
|
|
43
|
-
// Create the MCP server
|
|
44
|
-
const server = new McpServer({
|
|
45
|
-
name: "stables-mcp-server",
|
|
46
|
-
version: "2.0.0",
|
|
47
|
-
description: "Stables fiat-to-crypto API for AI agents - manage customers, quotes, transfers, and virtual accounts",
|
|
48
|
-
});
|
|
49
|
-
// Create the Stables API client
|
|
50
|
-
const stablesClient = createStablesClient();
|
|
51
|
-
// Register all tools
|
|
52
|
-
registerCustomerTools(server, stablesClient);
|
|
53
|
-
registerQuoteTools(server, stablesClient);
|
|
54
|
-
registerTransferTools(server, stablesClient);
|
|
55
|
-
registerVirtualAccountTools(server, stablesClient);
|
|
56
|
-
registerApiKeyTools(server, stablesClient);
|
|
57
|
-
registerWebhookTools(server, stablesClient);
|
|
58
|
-
registerPaymentMethodTools(server, stablesClient);
|
|
59
|
-
// Start the server with STDIO transport
|
|
60
23
|
async function main() {
|
|
24
|
+
const server = createStablesMcpServer(createStablesClient());
|
|
61
25
|
const transport = new StdioServerTransport();
|
|
62
26
|
await server.connect(transport);
|
|
63
27
|
}
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,uBAAuB;AACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;AAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,sBAAsB,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -279,27 +279,94 @@ export interface VirtualAccount {
|
|
|
279
279
|
last_deposit_at: string | null;
|
|
280
280
|
};
|
|
281
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* `deposit_handling_mode` is deliberately absent — it is not part of the create
|
|
284
|
+
* schema (the server sets it, defaulting to auto_payout) and was being silently
|
|
285
|
+
* ignored. Change it afterwards with updateVirtualAccount.
|
|
286
|
+
*/
|
|
282
287
|
export interface CreateVirtualAccountRequest {
|
|
283
288
|
source: {
|
|
284
289
|
currency: string;
|
|
285
290
|
};
|
|
286
|
-
|
|
291
|
+
/** Required for fiat_to_crypto, which is the default. */
|
|
287
292
|
destination?: VirtualAccountDestination;
|
|
293
|
+
workflow_type?: "fiat_to_crypto" | "fiat_to_fiat";
|
|
294
|
+
developer_fee_percent?: string;
|
|
288
295
|
metadata?: Record<string, string>;
|
|
289
296
|
}
|
|
290
297
|
export interface ListVirtualAccountsResponse {
|
|
291
298
|
count: number;
|
|
292
299
|
data: VirtualAccount[];
|
|
293
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* One deposit and its payout. The client previously described these as
|
|
303
|
+
* `{type, amount, currency}`, none of which exist, so every row rendered as
|
|
304
|
+
* "undefined: undefined undefined".
|
|
305
|
+
*/
|
|
294
306
|
export interface VirtualAccountHistoryEvent {
|
|
295
307
|
id: string;
|
|
296
|
-
type: string;
|
|
297
|
-
customer_id: string;
|
|
298
308
|
virtual_account_id: string;
|
|
299
|
-
|
|
300
|
-
|
|
309
|
+
deposit_amount?: string;
|
|
310
|
+
deposit_currency?: string;
|
|
301
311
|
deposit_id?: string;
|
|
312
|
+
sender_name?: string;
|
|
313
|
+
sender_reference?: string;
|
|
314
|
+
handling_mode?: string;
|
|
315
|
+
payout_status?: string;
|
|
316
|
+
payout_amount?: string;
|
|
317
|
+
payout_currency?: string;
|
|
318
|
+
payout_network?: string;
|
|
319
|
+
payout_address?: string;
|
|
320
|
+
payout_transaction_hash?: string;
|
|
321
|
+
payout_completed_at?: string;
|
|
322
|
+
platform_fee_amount?: string;
|
|
323
|
+
platform_fee_currency?: string;
|
|
324
|
+
deposited_at?: string;
|
|
325
|
+
created_at?: string;
|
|
326
|
+
}
|
|
327
|
+
/** The envelope is `{data, has_more}` — there is no `count`. */
|
|
328
|
+
export interface VirtualAccountHistoryResponse {
|
|
329
|
+
data: VirtualAccountHistoryEvent[];
|
|
330
|
+
has_more?: boolean;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* A request for information: what a customer must supply before a held
|
|
334
|
+
* verification or payout can proceed. Compliance can raise one at any time, so
|
|
335
|
+
* an integration that never reads them will stall without knowing why.
|
|
336
|
+
*/
|
|
337
|
+
export interface Rfi {
|
|
338
|
+
rfi_id: string;
|
|
339
|
+
type: string;
|
|
340
|
+
status: string;
|
|
341
|
+
customer_id: string;
|
|
342
|
+
kyc_level?: string;
|
|
343
|
+
reasons?: unknown[];
|
|
344
|
+
requirements?: unknown[];
|
|
302
345
|
created_at: string;
|
|
346
|
+
expires_at?: string;
|
|
347
|
+
resolved_at?: string;
|
|
348
|
+
}
|
|
349
|
+
export interface WebhookDelivery {
|
|
350
|
+
deliveryId: string;
|
|
351
|
+
subscriptionId?: string | null;
|
|
352
|
+
subscriptionName?: string | null;
|
|
353
|
+
subscriptionUrl?: string | null;
|
|
354
|
+
eventType: string;
|
|
355
|
+
status: "PENDING" | "SUCCESS" | "FAILED" | "RETRYING";
|
|
356
|
+
attemptCount: number;
|
|
357
|
+
lastAttemptAt?: string | null;
|
|
358
|
+
nextRetryAt?: string | null;
|
|
359
|
+
responseCode?: number | null;
|
|
360
|
+
createdAt?: string | null;
|
|
361
|
+
}
|
|
362
|
+
export interface SandboxDepositRequest {
|
|
363
|
+
amount: string;
|
|
364
|
+
scenario?: "create_only" | "completed" | "failed";
|
|
365
|
+
external_deposit_id?: string;
|
|
366
|
+
sender_name?: string;
|
|
367
|
+
sender_reference?: string;
|
|
368
|
+
failure_code?: string;
|
|
369
|
+
failure_message?: string;
|
|
303
370
|
}
|
|
304
371
|
export type QuoteStatus = "active" | "expired" | "used" | "cancelled" | "preview";
|
|
305
372
|
/**
|
|
@@ -423,10 +490,7 @@ export declare class StablesApiClient {
|
|
|
423
490
|
depositId?: string;
|
|
424
491
|
startingAfter?: string;
|
|
425
492
|
endingBefore?: string;
|
|
426
|
-
}): Promise<
|
|
427
|
-
count: number;
|
|
428
|
-
data: VirtualAccountHistoryEvent[];
|
|
429
|
-
}>;
|
|
493
|
+
}): Promise<VirtualAccountHistoryResponse>;
|
|
430
494
|
listTransfers(params?: {
|
|
431
495
|
status?: string;
|
|
432
496
|
type?: string;
|
|
@@ -455,6 +519,31 @@ export declare class StablesApiClient {
|
|
|
455
519
|
* discover what a corridor demands before spending a short-lived quote.
|
|
456
520
|
*/
|
|
457
521
|
validatePaymentMethod(network: string, destination: BankTransferDestination): Promise<ValidatePaymentMethodResponse>;
|
|
522
|
+
/** Replace the payout wallet on an existing payment route. */
|
|
523
|
+
updateVirtualAccountDestination(customerId: string, virtualAccountId: string, destination: VirtualAccountDestination): Promise<VirtualAccount>;
|
|
524
|
+
/** Compliance requests for information against a customer. */
|
|
525
|
+
listCustomerRfis(customerId: string): Promise<{
|
|
526
|
+
rfis: Rfi[];
|
|
527
|
+
}>;
|
|
528
|
+
getRfi(rfiId: string): Promise<Rfi>;
|
|
529
|
+
/** What verification the customer still owes. */
|
|
530
|
+
getKycCapabilities(customerId: string): Promise<Record<string, unknown>>;
|
|
531
|
+
listAvailableEntitlements(customerId: string): Promise<Record<string, unknown>>;
|
|
532
|
+
/**
|
|
533
|
+
* Sandbox only. Drives a deposit through the route or transfer so an agent can
|
|
534
|
+
* reach a terminal state in test, which is otherwise impossible without a real
|
|
535
|
+
* bank payment.
|
|
536
|
+
*/
|
|
537
|
+
simulateVirtualAccountDeposit(customerId: string, virtualAccountId: string, data: SandboxDepositRequest): Promise<Record<string, unknown>>;
|
|
538
|
+
simulateTransferDeposit(transferId: string, data?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
539
|
+
/** Recent webhook delivery attempts — the first place to look when events go missing. */
|
|
540
|
+
listWebhookDeliveries(params?: {
|
|
541
|
+
pageSize?: number;
|
|
542
|
+
status?: string;
|
|
543
|
+
eventType?: string;
|
|
544
|
+
}): Promise<{
|
|
545
|
+
deliveries: WebhookDelivery[];
|
|
546
|
+
}>;
|
|
458
547
|
listWebhooks(): Promise<{
|
|
459
548
|
subscriptions: WebhookSubscription[];
|
|
460
549
|
}>;
|