@venlyfinance/settlement-mcp 0.1.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/LICENSE +20 -0
- package/README.md +226 -0
- package/dist/client/http-client.d.ts +58 -0
- package/dist/client/http-client.js +163 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +25 -0
- package/dist/reconcile.d.ts +23 -0
- package/dist/reconcile.js +38 -0
- package/dist/safety.d.ts +35 -0
- package/dist/safety.js +46 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.js +21 -0
- package/dist/tools/read-tools.d.ts +6 -0
- package/dist/tools/read-tools.js +196 -0
- package/dist/tools/write-tools.d.ts +12 -0
- package/dist/tools/write-tools.js +161 -0
- package/dist/tools/x402-tools.d.ts +13 -0
- package/dist/tools/x402-tools.js +95 -0
- package/dist/types.d.ts +177 -0
- package/dist/types.js +17 -0
- package/package.json +55 -0
- package/skills/four-eyes-approval.md +39 -0
- package/skills/payment-link-lifecycle.md +44 -0
- package/skills/reconcile-by-reference-code.md +40 -0
- package/skills/stage-and-confirm-transfer.md +39 -0
- package/skills/x402-quote-walkthrough.md +39 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain types + the injectable VenlyClient interface.
|
|
3
|
+
*
|
|
4
|
+
* These shapes are a minimal projection of the vendored OpenAPI specs at
|
|
5
|
+
* projects/venly-docs-rebuild/api-reference/finance.yaml (servers:
|
|
6
|
+
* https://api.venlyfinance.com/api/v1) and fundflow.yaml (servers:
|
|
7
|
+
* https://api-fundflow.venly.io). Only the fields the tools actually read or
|
|
8
|
+
* echo are modeled. Fields are intentionally loose (optional) because this is a
|
|
9
|
+
* thin wrapper, not a full SDK.
|
|
10
|
+
*
|
|
11
|
+
* TRANSPORT NOTE: the bundled HttpVenlyClient is a deliberately minimal fetch
|
|
12
|
+
* transport (see client/http-client.ts). A future release replaces it with a
|
|
13
|
+
* thin adapter over `@venlyfinance/sdk` with no change to this interface;
|
|
14
|
+
* until then the minimal transport is what ships. When that lands, replace
|
|
15
|
+
* HttpVenlyClient with a thin adapter over it and delete the vendored transport.
|
|
16
|
+
*/
|
|
17
|
+
/** Ramp request status flow, per fundflow.yaml overview. */
|
|
18
|
+
export type RampStatus = "AWAITING_APPROVAL" | "AWAITING_FUNDS" | "PROCESSING" | "SUCCEEDED" | "FAILED" | "BLOCKED" | "DENIED" | "REJECTED" | "CANCELLED";
|
|
19
|
+
export type RampType = "ON_RAMP" | "OFF_RAMP";
|
|
20
|
+
/** Simplified ramp request for list views (fundflow RampRequestListItem). */
|
|
21
|
+
export interface RampRequestListItem {
|
|
22
|
+
id: string;
|
|
23
|
+
paymentReference?: string;
|
|
24
|
+
rampType?: RampType;
|
|
25
|
+
status?: RampStatus;
|
|
26
|
+
fiatAmount?: number;
|
|
27
|
+
fiatCurrency?: string;
|
|
28
|
+
cryptoAmount?: number;
|
|
29
|
+
cryptoCurrency?: string;
|
|
30
|
+
createdAt?: string;
|
|
31
|
+
createdBy?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Full ramp request detail (fundflow RampRequestDto). `version` drives the
|
|
34
|
+
* four-eyes optimistic-locking approve/reject calls. */
|
|
35
|
+
export interface RampRequestDto {
|
|
36
|
+
id: string;
|
|
37
|
+
companyId?: string;
|
|
38
|
+
companyName?: string;
|
|
39
|
+
rampType?: RampType;
|
|
40
|
+
status?: RampStatus;
|
|
41
|
+
fiatAmount?: number;
|
|
42
|
+
fiatNetAmount?: number;
|
|
43
|
+
cryptoAmount?: number;
|
|
44
|
+
fiatFeeAmount?: number;
|
|
45
|
+
exchangeRate?: number;
|
|
46
|
+
feePercentage?: number;
|
|
47
|
+
paymentReference?: string;
|
|
48
|
+
paymentReceived?: boolean;
|
|
49
|
+
blockchainTransactionHash?: string;
|
|
50
|
+
createdAt?: string;
|
|
51
|
+
createdBy?: string;
|
|
52
|
+
version?: number;
|
|
53
|
+
}
|
|
54
|
+
/** Finance Account (finance getAccount). */
|
|
55
|
+
export interface Account {
|
|
56
|
+
id: string;
|
|
57
|
+
status?: string;
|
|
58
|
+
reference?: string;
|
|
59
|
+
createdAt?: string;
|
|
60
|
+
updatedAt?: string;
|
|
61
|
+
[key: string]: unknown;
|
|
62
|
+
}
|
|
63
|
+
/** Finance VirtualBankAccount. `referenceCode` is the reconciliation key. */
|
|
64
|
+
export interface VirtualBankAccount {
|
|
65
|
+
id: string;
|
|
66
|
+
accountId?: string;
|
|
67
|
+
bankAccountType?: string;
|
|
68
|
+
name?: string;
|
|
69
|
+
status?: string;
|
|
70
|
+
currency?: string;
|
|
71
|
+
targetCryptocurrency?: string;
|
|
72
|
+
iban?: string;
|
|
73
|
+
bic?: string;
|
|
74
|
+
bankName?: string;
|
|
75
|
+
beneficiaryName?: string;
|
|
76
|
+
referenceCode?: string;
|
|
77
|
+
createdAt?: string;
|
|
78
|
+
updatedAt?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Finance Transfer (finance getTransfer). */
|
|
81
|
+
export interface Transfer {
|
|
82
|
+
id: string;
|
|
83
|
+
status?: string;
|
|
84
|
+
fiatAmount?: string | number;
|
|
85
|
+
fiatCurrency?: string;
|
|
86
|
+
cryptocurrency?: string;
|
|
87
|
+
createdAt?: string;
|
|
88
|
+
[key: string]: unknown;
|
|
89
|
+
}
|
|
90
|
+
/** Finance Party (finance listParties). */
|
|
91
|
+
export interface Party {
|
|
92
|
+
id: string;
|
|
93
|
+
type?: string;
|
|
94
|
+
status?: string;
|
|
95
|
+
[key: string]: unknown;
|
|
96
|
+
}
|
|
97
|
+
/** A payment link (finance PaymentLink). */
|
|
98
|
+
export interface PaymentLink {
|
|
99
|
+
id: string;
|
|
100
|
+
accountId?: string;
|
|
101
|
+
paymentUrl?: string;
|
|
102
|
+
externalRef?: string;
|
|
103
|
+
status?: string;
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* An observed incoming bank transaction on a vIBAN. This is operator- or
|
|
108
|
+
* bank-feed-supplied data (there is no list-vIBAN-transactions endpoint in the
|
|
109
|
+
* Release 1 specs), matched against a vIBAN referenceCode during reconciliation.
|
|
110
|
+
*/
|
|
111
|
+
export interface ObservedBankTransaction {
|
|
112
|
+
/** The reference code carried in the payment (payment reference / remittance). */
|
|
113
|
+
referenceCode: string;
|
|
114
|
+
amount: number;
|
|
115
|
+
currency: string;
|
|
116
|
+
remitterName?: string;
|
|
117
|
+
valueDate?: string;
|
|
118
|
+
bankTransactionId?: string;
|
|
119
|
+
}
|
|
120
|
+
/** Query params for listing ramp requests (fundflow getAll). */
|
|
121
|
+
export interface ListRampRequestsParams {
|
|
122
|
+
rampType?: RampType;
|
|
123
|
+
status?: RampStatus;
|
|
124
|
+
fromDate?: string;
|
|
125
|
+
toDate?: string;
|
|
126
|
+
paymentReference?: string;
|
|
127
|
+
page?: number;
|
|
128
|
+
size?: number;
|
|
129
|
+
}
|
|
130
|
+
/** Body for the fiat transfer POST (finance CreateFiatTransferInput). */
|
|
131
|
+
export interface CreateFiatTransferInput {
|
|
132
|
+
receiverAccountId: string;
|
|
133
|
+
receiverExternalId?: string;
|
|
134
|
+
fiatAmount: string;
|
|
135
|
+
fiatCurrency: string;
|
|
136
|
+
cryptocurrency?: string;
|
|
137
|
+
description?: string;
|
|
138
|
+
merchantReference?: string;
|
|
139
|
+
}
|
|
140
|
+
/** Body for approve/reject (fundflow UpdateWithOptimisticLockingRequest). */
|
|
141
|
+
export interface OptimisticLockingBody {
|
|
142
|
+
version: number;
|
|
143
|
+
}
|
|
144
|
+
/** Body for the payment link POST (finance CreatePaymentLinkRequest). */
|
|
145
|
+
export interface CreatePaymentLinkRequest {
|
|
146
|
+
inAmount: string;
|
|
147
|
+
inCurrency: string;
|
|
148
|
+
outCryptocurrency?: string;
|
|
149
|
+
redirectUrl?: string;
|
|
150
|
+
externalRef?: string;
|
|
151
|
+
metadata?: Record<string, string>;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The injectable Venly transport. HttpVenlyClient is the real fetch-based
|
|
155
|
+
* implementation; tests inject a mock. The MCP layer depends ONLY on this
|
|
156
|
+
* interface, never on a concrete transport, which is what makes the fail-closed
|
|
157
|
+
* write path testable without a network.
|
|
158
|
+
*/
|
|
159
|
+
export interface VenlyClient {
|
|
160
|
+
listRampRequests(params?: ListRampRequestsParams): Promise<RampRequestListItem[]>;
|
|
161
|
+
getRampRequest(id: string): Promise<RampRequestDto>;
|
|
162
|
+
getAccount(accountId: string): Promise<Account>;
|
|
163
|
+
listVirtualBankAccounts(accountId: string): Promise<VirtualBankAccount[]>;
|
|
164
|
+
getTransfer(accountId: string, transferId: string): Promise<Transfer>;
|
|
165
|
+
listParties(params?: {
|
|
166
|
+
page?: number;
|
|
167
|
+
size?: number;
|
|
168
|
+
}): Promise<Party[]>;
|
|
169
|
+
getSupportedChains(): Promise<unknown[]>;
|
|
170
|
+
getFiatCurrencies(): Promise<unknown[]>;
|
|
171
|
+
getCryptocurrencies(): Promise<unknown[]>;
|
|
172
|
+
getCompanyFees(): Promise<unknown>;
|
|
173
|
+
createFiatTransfer(senderAccountId: string, body: CreateFiatTransferInput): Promise<Transfer>;
|
|
174
|
+
approveRampRequest(id: string, body: OptimisticLockingBody): Promise<RampRequestDto>;
|
|
175
|
+
rejectRampRequest(id: string, body: OptimisticLockingBody): Promise<RampRequestDto>;
|
|
176
|
+
createPaymentLink(accountId: string, body: CreatePaymentLinkRequest): Promise<PaymentLink>;
|
|
177
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain types + the injectable VenlyClient interface.
|
|
3
|
+
*
|
|
4
|
+
* These shapes are a minimal projection of the vendored OpenAPI specs at
|
|
5
|
+
* projects/venly-docs-rebuild/api-reference/finance.yaml (servers:
|
|
6
|
+
* https://api.venlyfinance.com/api/v1) and fundflow.yaml (servers:
|
|
7
|
+
* https://api-fundflow.venly.io). Only the fields the tools actually read or
|
|
8
|
+
* echo are modeled. Fields are intentionally loose (optional) because this is a
|
|
9
|
+
* thin wrapper, not a full SDK.
|
|
10
|
+
*
|
|
11
|
+
* TRANSPORT NOTE: the bundled HttpVenlyClient is a deliberately minimal fetch
|
|
12
|
+
* transport (see client/http-client.ts). A future release replaces it with a
|
|
13
|
+
* thin adapter over `@venlyfinance/sdk` with no change to this interface;
|
|
14
|
+
* until then the minimal transport is what ships. When that lands, replace
|
|
15
|
+
* HttpVenlyClient with a thin adapter over it and delete the vendored transport.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@venlyfinance/settlement-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Venly Settlement MCP server. Human-gated operator surface over the Venly Finance and Fundflow APIs, plus an x402 machine-to-machine quote stub. Read-only by default, write tools fail closed.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"venly-settlement-mcp": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"skills",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"test": "node --import tsx --test test/*.test.ts",
|
|
19
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
26
|
+
"zod": "^3.23.8"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.10.0",
|
|
30
|
+
"tsx": "^4.19.2",
|
|
31
|
+
"typescript": "^5.7.2"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/timdierckxsens/venly-sdk.git",
|
|
37
|
+
"directory": "settlement-mcp"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/timdierckxsens/venly-sdk/tree/main/settlement-mcp#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/timdierckxsens/venly-sdk/issues"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"mcp",
|
|
45
|
+
"model-context-protocol",
|
|
46
|
+
"stablecoin",
|
|
47
|
+
"settlement",
|
|
48
|
+
"payments",
|
|
49
|
+
"x402",
|
|
50
|
+
"venly",
|
|
51
|
+
"fintech",
|
|
52
|
+
"eur",
|
|
53
|
+
"viban"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Skill: Walk a ramp through four-eyes approval
|
|
2
|
+
|
|
3
|
+
Move a ramp request from `AWAITING_APPROVAL` to `AWAITING_FUNDS` (approve) or to
|
|
4
|
+
`REJECTED` (reject), preserving four-eyes control.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
A Company Manager created a ramp request. A Company Admin (a different identity)
|
|
9
|
+
must review and approve or reject it.
|
|
10
|
+
|
|
11
|
+
## Tools
|
|
12
|
+
|
|
13
|
+
- `list_ramp_requests` (read)
|
|
14
|
+
- `get_ramp_request` (read)
|
|
15
|
+
- `approve_ramp_request` (write, disarmed by default)
|
|
16
|
+
- `reject_ramp_request` (write, disarmed by default)
|
|
17
|
+
|
|
18
|
+
## Steps
|
|
19
|
+
|
|
20
|
+
1. `list_ramp_requests` with `status: "AWAITING_APPROVAL"` to find pending
|
|
21
|
+
requests. Note `id` and `createdBy`.
|
|
22
|
+
2. `get_ramp_request` for the chosen `id`. Read the amounts, the `paymentReference`,
|
|
23
|
+
and the `version`. The `version` is required for the optimistic-locking write.
|
|
24
|
+
3. Decide. Four-eyes: the approving identity must differ from `createdBy`. The
|
|
25
|
+
Fundflow API enforces this; the tool surfaces the state, it does not bypass it.
|
|
26
|
+
4. Call `approve_ramp_request` (or `reject_ramp_request`) with `id` and the
|
|
27
|
+
`version` from step 2.
|
|
28
|
+
- By default the tool returns a dry-run object showing the exact POST it would
|
|
29
|
+
send. Review it.
|
|
30
|
+
- To execute live, all three must hold: `confirm: true`, `VENLY_MCP_LIVE=1`,
|
|
31
|
+
and credentials present. Arming is a deliberate human decision.
|
|
32
|
+
5. On a version conflict (HTTP 409) in live mode, re-fetch with `get_ramp_request`
|
|
33
|
+
to get the new `version` and retry.
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
|
|
37
|
+
- Approve transitions `AWAITING_APPROVAL` to `AWAITING_FUNDS`. Reject transitions
|
|
38
|
+
to `REJECTED`.
|
|
39
|
+
- The dry-run is the safe default. Read the request body before arming.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Skill: Create and track a payment link
|
|
2
|
+
|
|
3
|
+
Stand up a fiat-to-crypto payment link for an account, hand the URL to a payer,
|
|
4
|
+
and follow the payment through to settlement.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
An operator wants to collect a fiat payment that settles as stablecoin into an
|
|
9
|
+
account's wallet, without building a checkout: invoicing, one-off B2B
|
|
10
|
+
collections, top-ups.
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
- `get_account` (read)
|
|
15
|
+
- `list_virtual_bank_accounts` (read)
|
|
16
|
+
- `create_payment_link` (write, disarmed by default)
|
|
17
|
+
- `get_transfer` (read)
|
|
18
|
+
|
|
19
|
+
## Steps
|
|
20
|
+
|
|
21
|
+
1. `get_account` for the collecting account. Confirm `status: "ACTIVE"` - an
|
|
22
|
+
unverified or suspended account cannot collect.
|
|
23
|
+
2. Optional context: `list_virtual_bank_accounts` shows the account's existing
|
|
24
|
+
collection surfaces (IBAN + referenceCode); a payment link is the hosted
|
|
25
|
+
alternative for payers who won't do a bank transfer.
|
|
26
|
+
3. `create_payment_link` with the `accountId` and an `externalRef` your own
|
|
27
|
+
system can reconcile on later.
|
|
28
|
+
- By default the tool returns a dry-run object with the exact POST it would
|
|
29
|
+
send. Review it.
|
|
30
|
+
- Live execution needs all three: `confirm: true`, `VENLY_MCP_LIVE=1`, and
|
|
31
|
+
credentials present.
|
|
32
|
+
4. Share the returned `paymentUrl` with the payer. Status starts at `CREATED` /
|
|
33
|
+
`PENDING_PAYMENT`.
|
|
34
|
+
5. After payment, the received fiat converts and lands on-chain. Track the
|
|
35
|
+
resulting movement with `get_transfer` and reconcile on your `externalRef`.
|
|
36
|
+
|
|
37
|
+
## Notes
|
|
38
|
+
|
|
39
|
+
- Payment links expire (`expiresAt`); a link that was never paid ends at
|
|
40
|
+
`EXPIRED`, not `FAILED`.
|
|
41
|
+
- Statuses walk `CREATED → PENDING_PAYMENT → PAYMENT_RECEIVED → CONVERTING →
|
|
42
|
+
MINTING → COMPLETED`, with `FAILED`, `CANCELLED`, `REFUNDING`, `REFUNDED` as
|
|
43
|
+
exits. Only treat `COMPLETED` as settled.
|
|
44
|
+
- The dry-run is the safe default. Read the request body before arming.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Skill: Reconcile a EUR payment by referenceCode
|
|
2
|
+
|
|
3
|
+
Match an incoming EUR bank payment on a virtual IBAN (vIBAN) to the vIBAN that
|
|
4
|
+
issued its reference code, using only read tools. No mutation.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
An operator sees an incoming EUR transfer (from a bank feed, statement, or
|
|
9
|
+
notification) and needs to know which account and vIBAN it belongs to, and
|
|
10
|
+
whether the expected funds have arrived.
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
- `list_virtual_bank_accounts` (read)
|
|
15
|
+
- `reconcile_by_reference_code` (read, composite)
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
|
|
19
|
+
1. Identify the settlement `accountId` in question.
|
|
20
|
+
2. Collect the observed incoming transactions. Each needs at least a
|
|
21
|
+
`referenceCode`, `amount`, and `currency` (add `remitterName`, `valueDate`,
|
|
22
|
+
`bankTransactionId` when available).
|
|
23
|
+
3. Call `reconcile_by_reference_code` with `accountId`, the target
|
|
24
|
+
`referenceCode`, and the `transactions` array. The tool fetches the account's
|
|
25
|
+
vIBANs and matches.
|
|
26
|
+
4. Read the result:
|
|
27
|
+
- `matched: true` plus a `virtualBankAccount` and `matchedTransactions`: the
|
|
28
|
+
payment is reconciled. `totalAmount` is the summed value.
|
|
29
|
+
- `matched: false` with a `virtualBankAccount` but no transactions: the vIBAN
|
|
30
|
+
exists, funds have not arrived. Awaiting funds.
|
|
31
|
+
- `matched: false` with `virtualBankAccount: null` but transactions present:
|
|
32
|
+
the payment references a code no vIBAN on this account carries. Possible
|
|
33
|
+
misdirected payment, investigate.
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
|
|
37
|
+
- There is no list-vIBAN-transactions endpoint in Release 1, so the transactions
|
|
38
|
+
are supplied by the operator or an upstream bank feed. The tool does the
|
|
39
|
+
matching, not the fetching of bank transactions.
|
|
40
|
+
- Read-only. This skill never approves, transfers, or mutates anything.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Skill: Stage and confirm a transfer
|
|
2
|
+
|
|
3
|
+
Prepare a fiat-to-crypto transfer, review the exact request, then execute it only
|
|
4
|
+
behind the explicit confirm and arming gate.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
An operator needs to move funds from a sender account to a receiver, converting
|
|
9
|
+
fiat to crypto.
|
|
10
|
+
|
|
11
|
+
## Tools
|
|
12
|
+
|
|
13
|
+
- `get_account` (read)
|
|
14
|
+
- `stage_transfer` (write, disarmed by default)
|
|
15
|
+
- `get_transfer` (read)
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
|
|
19
|
+
1. `get_account` for the `senderAccountId` to confirm it is active.
|
|
20
|
+
2. Stage the transfer: call `stage_transfer` with `senderAccountId`,
|
|
21
|
+
`receiverAccountId`, `fiatAmount` (decimal string), `fiatCurrency`, and
|
|
22
|
+
optionally `cryptocurrency`, `description`, `merchantReference`. Omit
|
|
23
|
+
`confirm` (or set it false).
|
|
24
|
+
3. The tool returns a dry-run object: the exact `POST /accounts/{senderAccountId}/transfers/fiat`
|
|
25
|
+
body it would send, plus the gate decision. Review the amount, currency, and
|
|
26
|
+
receiver.
|
|
27
|
+
4. To execute live, re-call with `confirm: true` AND the server armed with
|
|
28
|
+
`VENLY_MCP_LIVE=1` AND credentials present. If any leg is missing, the tool
|
|
29
|
+
dry-runs again and does not touch the API.
|
|
30
|
+
5. After a live execution, use `get_transfer` with the returned account and
|
|
31
|
+
transfer id to confirm status.
|
|
32
|
+
|
|
33
|
+
## Notes
|
|
34
|
+
|
|
35
|
+
- Dry-run first is the default and the safe path. Confirm and arming are separate,
|
|
36
|
+
deliberate steps.
|
|
37
|
+
- Idempotency keys are handled by the transport on live POSTs.
|
|
38
|
+
- The fiat transfer endpoint is documented in the rebuild specs but marked a stub
|
|
39
|
+
pending live annotation. Cross-check the live schema before a production run.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Skill: Read an x402 settlement quote
|
|
2
|
+
|
|
3
|
+
Get an HTTP-402-shaped quote for a settlement action and understand what each
|
|
4
|
+
field commits to, without moving any funds.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
An agent (or an operator evaluating agent payments) wants to know what a
|
|
9
|
+
machine-to-machine settlement over the x402 rail would cost and where it would
|
|
10
|
+
pay, before any decision to execute anything.
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
- `quote_x402_payment` (stub - never executes, never calls a facilitator)
|
|
15
|
+
- `get_reference_data` (read; chains and currencies for context)
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
|
|
19
|
+
1. Call `quote_x402_payment` with the settlement action you are pricing.
|
|
20
|
+
2. Read the returned `PaymentRequirements`-shaped quote:
|
|
21
|
+
- `price`: the amount the counterparty would require.
|
|
22
|
+
- `asset`: the settlement asset (typically USDC).
|
|
23
|
+
- `payTo`: the receiving address.
|
|
24
|
+
- `chain`: where settlement would occur (CAIP-2 style network reference).
|
|
25
|
+
3. Cross-check `chain` and `asset` against `get_reference_data` - a quote on an
|
|
26
|
+
unsupported chain/currency pair is a configuration error, not an offer.
|
|
27
|
+
4. Stop. This tool states Venly's position on the x402 rail; it does not settle.
|
|
28
|
+
|
|
29
|
+
## Notes
|
|
30
|
+
|
|
31
|
+
- Position of record: the MCP is the human-gated operator surface; x402 is the
|
|
32
|
+
machine-to-machine rail. This server ships the quote shape so integrators can
|
|
33
|
+
build against it today.
|
|
34
|
+
- Live x402 settlement requires a facilitator decision (who submits the signed
|
|
35
|
+
payment on-chain, under whose licence) that deliberately sits outside this
|
|
36
|
+
server. No `confirm` flag, no env var, and no credential arms this tool into
|
|
37
|
+
executing - it has no execution path.
|
|
38
|
+
- The x402 pattern: a server answers `402 Payment Required` with these fields;
|
|
39
|
+
the payer signs (EIP-3009/Permit2 style) and a facilitator submits on-chain.
|