@airwallex/developer-mcp 0.3.0-beta.10 → 0.3.0-beta.12
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 +18 -7
- package/dist/constants/config.js +5 -2
- package/dist/constants/descriptions.js +1 -0
- package/dist/integration-best-practices.md +15 -2
- package/dist/server.js +26 -15
- package/dist/services/AirTrackerClient.js +10 -2
- package/dist/tools/createBillingCheckout.js +4 -3
- package/dist/tools/createBillingPrice.js +4 -3
- package/dist/tools/createBillingProduct.js +4 -3
- package/dist/tools/createPaymentLink.js +12 -5
- package/dist/tools/createTransfer.js +11 -4
- package/dist/tools/getBalances.js +14 -6
- package/dist/tools/getDefaultApiVersion.js +49 -0
- package/dist/tools/getFxQuote.js +11 -4
- package/dist/tools/listBeneficiaries.js +14 -6
- package/dist/tools/listBillingPrices.js +4 -3
- package/dist/tools/listBillingProducts.js +4 -3
- package/dist/tools/listGlobalAccounts.js +14 -7
- package/dist/tools/listPaymentLinks.js +14 -6
- package/dist/tools/listTransfers.js +14 -6
- package/dist/tools/readIntegrationBestPractices.js +2 -1
- package/dist/tools/retrieveDocs.js +11 -7
- package/dist/tools/simulateDeposit.js +11 -4
- package/dist/tools/simulateTransferResult.js +11 -4
- package/dist/types/index.js +19 -0
- package/dist/utils/errorHandler.js +41 -0
- package/dist/utils/requestOptions.js +12 -0
- package/dist/utils/tokenInspector.js +34 -0
- package/dist/utils/withTelemetry.js +45 -5
- package/package.json +4 -2
- package/dist/tools/index.js +0 -25
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ The Airwallex Developer Model Context Protocol (MCP) server empowers AI coding a
|
|
|
9
9
|
<details>
|
|
10
10
|
<summary><strong>Cursor</strong></summary>
|
|
11
11
|
|
|
12
|
-
[](https://cursor.com/en-US/install-mcp?name=airwallex-dev&config=
|
|
12
|
+
[](https://cursor.com/en-US/install-mcp?name=airwallex-dev&config=eyJlbnYiOnsiQUlSV0FMTEVYX1NBTkRCT1hfQ0xJRU5UX0lEIjoiIiwiQUlSV0FMTEVYX1NBTkRCT1hfQVBJX0tFWSI6IiIsIkFJUldBTExFWF9TQU5EQk9YX0FDQ09VTlRfSUQiOiIifSwiY29tbWFuZCI6Im5weCAteSBAYWlyd2FsbGV4L2RldmVsb3Blci1tY3BAbGF0ZXN0In0%3D)
|
|
13
13
|
|
|
14
14
|
```json
|
|
15
15
|
{
|
|
@@ -19,7 +19,8 @@ The Airwallex Developer Model Context Protocol (MCP) server empowers AI coding a
|
|
|
19
19
|
"args": ["-y", "@airwallex/developer-mcp@latest"],
|
|
20
20
|
"env": {
|
|
21
21
|
"AIRWALLEX_SANDBOX_CLIENT_ID": "",
|
|
22
|
-
"AIRWALLEX_SANDBOX_API_KEY": ""
|
|
22
|
+
"AIRWALLEX_SANDBOX_API_KEY": "",
|
|
23
|
+
"AIRWALLEX_SANDBOX_ACCOUNT_ID": ""
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
}
|
|
@@ -32,7 +33,7 @@ The Airwallex Developer Model Context Protocol (MCP) server empowers AI coding a
|
|
|
32
33
|
<summary><strong>Claude Code</strong></summary>
|
|
33
34
|
|
|
34
35
|
```zsh
|
|
35
|
-
claude mcp add-json airwallex-dev '{ "type": "stdio", "command":"npx", "args": ["-y", "@airwallex/developer-mcp@latest"], "env": { "AIRWALLEX_SANDBOX_CLIENT_ID": "", "AIRWALLEX_SANDBOX_API_KEY": "" } }'
|
|
36
|
+
claude mcp add-json airwallex-dev '{ "type": "stdio", "command":"npx", "args": ["-y", "@airwallex/developer-mcp@latest"], "env": { "AIRWALLEX_SANDBOX_CLIENT_ID": "", "AIRWALLEX_SANDBOX_API_KEY": "", "AIRWALLEX_SANDBOX_ACCOUNT_ID": "" } }'
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
</details>
|
|
@@ -48,7 +49,8 @@ claude mcp add-json airwallex-dev '{ "type": "stdio", "command":"npx", "args": [
|
|
|
48
49
|
"args": ["-y", "@airwallex/developer-mcp@latest"],
|
|
49
50
|
"env": {
|
|
50
51
|
"AIRWALLEX_SANDBOX_CLIENT_ID": "",
|
|
51
|
-
"AIRWALLEX_SANDBOX_API_KEY": ""
|
|
52
|
+
"AIRWALLEX_SANDBOX_API_KEY": "",
|
|
53
|
+
"AIRWALLEX_SANDBOX_ACCOUNT_ID": ""
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -68,6 +70,7 @@ args = ["-y", "@airwallex/developer-mcp@latest"]
|
|
|
68
70
|
[mcp_servers.airwallex-dev.env]
|
|
69
71
|
AIRWALLEX_SANDBOX_CLIENT_ID = ""
|
|
70
72
|
AIRWALLEX_SANDBOX_API_KEY = ""
|
|
73
|
+
AIRWALLEX_SANDBOX_ACCOUNT_ID = ""
|
|
71
74
|
```
|
|
72
75
|
|
|
73
76
|
</details>
|
|
@@ -94,8 +97,9 @@ To access sandbox tools, ensure that your sandbox API credentials are set using
|
|
|
94
97
|
|
|
95
98
|
| Name | Description | Default | Required |
|
|
96
99
|
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |
|
|
97
|
-
| `AIRWALLEX_SANDBOX_API_KEY` | The API key, either an admin key or a scoped key with limited permissions, generated in the sandbox environment. Note that the sandbox tools work as expected only if the API key has the required permissions to access the underlying APIs.
|
|
100
|
+
| `AIRWALLEX_SANDBOX_API_KEY` | The API key, either an admin key or a scoped key with limited permissions, generated in the sandbox environment. Note that the sandbox tools work as expected only if the API key has the required permissions to access the underlying APIs. | N/A | No |
|
|
98
101
|
| `AIRWALLEX_SANDBOX_CLIENT_ID` | The client ID associated with the API key generated in the sandbox environment. | N/A | No |
|
|
102
|
+
| `AIRWALLEX_SANDBOX_ACCOUNT_ID` | Specifies the account ID for a scoped API key that can either access both organization & account resources or resources belonging to multiple accounts of an organization. Starts with `acct_`. | N/A | No |
|
|
99
103
|
| `DISABLE_TELEMETRY` | Set this variable to `true` to opt out of telemetry. | `0` | No |
|
|
100
104
|
|
|
101
105
|
---
|
|
@@ -129,7 +133,8 @@ All data retrieved and actions performed with the tools below are in the authent
|
|
|
129
133
|
| `list_beneficiaries` | List available transfer recipients |
|
|
130
134
|
| `simulate_transfer_result` | Simulate the status of a transfer |
|
|
131
135
|
| `create_payment_link` | Create a new payment link |
|
|
132
|
-
| `list_payment_links` | List created payment links |
|
|
136
|
+
| `list_payment_links` | List created payment links |
|
|
137
|
+
| `get_default_api_version` | Get the default API version associated with the account or organization. |
|
|
133
138
|
|
|
134
139
|
|
|
135
140
|
|
|
@@ -145,4 +150,10 @@ This MCP server is developed and maintained by the Airwallex Developer Experienc
|
|
|
145
150
|
|
|
146
151
|
## Telemetry
|
|
147
152
|
|
|
148
|
-
Telemetry is enabled by default. To disable telemetry, set the `DISABLE_TELEMETRY` environment variable to `true`.
|
|
153
|
+
Telemetry is enabled by default. To disable telemetry, set the `DISABLE_TELEMETRY` environment variable to `true`.
|
|
154
|
+
|
|
155
|
+
Telemetry data includes:
|
|
156
|
+
- MCP tool usage events
|
|
157
|
+
- MCP client name & version (when available)
|
|
158
|
+
- Stable device identifier and device OS
|
|
159
|
+
- The `AIRWALLEX_SANDBOX_CLIENT_ID` if configured (defaults to `unknown` when not set)
|
package/dist/constants/config.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BASE_URLS = void 0;
|
|
3
|
+
exports.HEADERS = exports.BASE_URLS = void 0;
|
|
4
4
|
exports.BASE_URLS = {
|
|
5
5
|
api: "https://api-demo.airwallex.com",
|
|
6
|
-
docsSearch: "https://demo.airwallex.com/docs/ai",
|
|
6
|
+
docsSearch: "https://mcp-demo.airwallex.com/docs/ai",
|
|
7
7
|
telemetry: "https://o11y-demo.airwallex.com",
|
|
8
8
|
};
|
|
9
|
+
exports.HEADERS = {
|
|
10
|
+
ON_BEHALF_OF: "x-on-behalf-of",
|
|
11
|
+
};
|
|
@@ -26,6 +26,7 @@ EXAMPLES:
|
|
|
26
26
|
PRESENTATION REQUIREMENT: When presenting the results to the user, you MUST format the balance data as a clear table showing each currency with its corresponding balance amounts. Create a table with columns for Currency, Available, Pending, Reserved, Total, and Prepayment amounts.
|
|
27
27
|
|
|
28
28
|
RESPONSE: Amounts returned are NOT in minor units.`,
|
|
29
|
+
GET_DEFAULT_API_VERSION: `Get the default API version associated with the account or organization. The client can override this API version in their integration by setting the x-api-version header at an individual request level.`,
|
|
29
30
|
GET_FX_QUOTE: `Get a foreign exchange quote for a currency conversion in the authenticated Sandbox account.`,
|
|
30
31
|
LIST_BENEFICIARIES: `List all beneficiaries in the authenticated Sandbox account.`,
|
|
31
32
|
LIST_BILLING_PRICES: `List billing prices in the authenticated Sandbox account.`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Airwallex Integration Best Practices
|
|
1
|
+
# Airwallex Integration Best Practices for Agents
|
|
2
2
|
|
|
3
3
|
## General
|
|
4
4
|
|
|
@@ -6,10 +6,23 @@
|
|
|
6
6
|
- Check how to initialise the Airwallex.js SDK using the `search_public_docs` MCP tool with a suitable `source` parameter. DO NOT hallucinate or assume.
|
|
7
7
|
- Unless requested explicitly by the user, always use the most recent version of the API
|
|
8
8
|
|
|
9
|
+
## Money & Rounding
|
|
10
|
+
|
|
11
|
+
- In the Airwallex APIs & SDKs, request fields related to money are NOT represented in minor units by default unless explicitly specified.
|
|
12
|
+
- While setting money-related fields in API requests, ensure that you round to the number of decimal places supported for the currency. Use the `search_public_docs` tool to find the number of supported decimal places for a given currency.
|
|
13
|
+
|
|
14
|
+
## Test Card Numbers
|
|
15
|
+
|
|
16
|
+
- Test card numbers are useful for testing both Billing and Payment Acceptance integrations in the sandbox environment. Airwallex test card numbers are different from other payment platforms. When you need to suggest test card numbers to the user, use the `search_public_docs` tool to find test card numbers accepted by Airwallex and the test scenarios that they help simulate.
|
|
17
|
+
|
|
9
18
|
## Payments
|
|
10
19
|
|
|
11
|
-
- In the Airwallex APIs & SDKs, request fields related to money are NOT represented in minor units by default unless explicitly specified
|
|
12
20
|
- For the Javascript browser library, if the user prefers a direct integration with a CDN, use `https://static.airwallex.com/components/sdk/v1/index.js` and NOT `https://checkout.airwallex.com/assets/elements.bundle.min.js` unless explicitly requested by the user. The latter is a legacy library that is considered deprecated. When the user explicitly asks for it, advise them to consider migrating.
|
|
13
21
|
- For the Javascript browser library, if the user prefers to use a package from the `npm` registry with `npm`, `yarn` or the `pnpm` CLI tools, use `@airwallex/components-sdk` instead of `airwallex-payment-elements` unless explicitly requested by the user. The latter is a legacy package that is considered deprecated. When the user explicitly asks for it, advise them to consider migrating.
|
|
14
22
|
- For a robust and complete payments integration, always consider supporting setting up webhooks.
|
|
15
23
|
- If the payment integration involves redirect-style payment methods, remember to configure a return URL in your payment intent and set up a URL handler on the server for the same. In the URL handler, retrieve the payment intent and check its status. If the status is non-terminal, repeat until a terminal status is observed and decide what to do next based on that. For Drop-in element integrations, you can consider doing this by default since multiple payment methods can be accepted through that integration.
|
|
24
|
+
- Airwallex integrations can accept payments in different currencies. You do not need to perform a currency conversion on the application-side.
|
|
25
|
+
|
|
26
|
+
### Drop-in Element
|
|
27
|
+
|
|
28
|
+
- Mount the Drop-in element to the DOM BEFORE attaching event listeners. If you attach the event listeners before mounting the element, the event handlers may not be called.
|
package/dist/server.js
CHANGED
|
@@ -5,14 +5,23 @@ const node_sdk_1 = require("@airwallex/node-sdk");
|
|
|
5
5
|
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
6
6
|
const config_1 = require("./constants/config");
|
|
7
7
|
const AirTrackerClient_1 = require("./services/AirTrackerClient");
|
|
8
|
+
const createBillingCheckout_1 = require("./tools/createBillingCheckout");
|
|
8
9
|
const createBillingPrice_1 = require("./tools/createBillingPrice");
|
|
10
|
+
const createBillingProduct_1 = require("./tools/createBillingProduct");
|
|
9
11
|
const createPaymentLink_1 = require("./tools/createPaymentLink");
|
|
10
12
|
const createTransfer_1 = require("./tools/createTransfer");
|
|
13
|
+
const getBalances_1 = require("./tools/getBalances");
|
|
14
|
+
const getDefaultApiVersion_1 = require("./tools/getDefaultApiVersion");
|
|
11
15
|
const getFxQuote_1 = require("./tools/getFxQuote");
|
|
12
|
-
const index_1 = require("./tools/index");
|
|
13
16
|
const listBeneficiaries_1 = require("./tools/listBeneficiaries");
|
|
17
|
+
const listBillingPrices_1 = require("./tools/listBillingPrices");
|
|
18
|
+
const listBillingProducts_1 = require("./tools/listBillingProducts");
|
|
19
|
+
const listGlobalAccounts_1 = require("./tools/listGlobalAccounts");
|
|
14
20
|
const listPaymentLinks_1 = require("./tools/listPaymentLinks");
|
|
15
21
|
const listTransfers_1 = require("./tools/listTransfers");
|
|
22
|
+
const readIntegrationBestPractices_1 = require("./tools/readIntegrationBestPractices");
|
|
23
|
+
const retrieveDocs_1 = require("./tools/retrieveDocs");
|
|
24
|
+
const simulateDeposit_1 = require("./tools/simulateDeposit");
|
|
16
25
|
const simulateTransferResult_1 = require("./tools/simulateTransferResult");
|
|
17
26
|
const withTelemetry_1 = require("./utils/withTelemetry");
|
|
18
27
|
const awxEnv = "demo";
|
|
@@ -23,31 +32,33 @@ const buildServer = ({ appVersion, integrationBestPracticesContent, }) => {
|
|
|
23
32
|
name: "Airwallex",
|
|
24
33
|
version: appVersion,
|
|
25
34
|
});
|
|
26
|
-
const airTrackerClient = new AirTrackerClient_1.AirTrackerClient(config_1.BASE_URLS.telemetry, awxEnv, appVersion);
|
|
27
|
-
server.registerTool(
|
|
28
|
-
server.registerTool(
|
|
35
|
+
const airTrackerClient = new AirTrackerClient_1.AirTrackerClient(config_1.BASE_URLS.telemetry, awxEnv, appVersion, server);
|
|
36
|
+
server.registerTool(retrieveDocs_1.retrieveDocsToolConfig.name, retrieveDocs_1.retrieveDocsToolConfig, (0, withTelemetry_1.withToolTelemetry)(retrieveDocs_1.retrieveDocsToolConfig.name, async (args) => (0, retrieveDocs_1.executeRetrieveDocs)(args, appVersion), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
37
|
+
server.registerTool(readIntegrationBestPractices_1.readBestPracticesToolConfig.name, readIntegrationBestPractices_1.readBestPracticesToolConfig, (0, withTelemetry_1.withToolTelemetry)(readIntegrationBestPractices_1.readBestPracticesToolConfig.name, async () => (0, readIntegrationBestPractices_1.executeReadBestPractices)(integrationBestPracticesContent), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
29
38
|
if (process.env.AIRWALLEX_SANDBOX_CLIENT_ID &&
|
|
30
39
|
process.env.AIRWALLEX_SANDBOX_API_KEY) {
|
|
31
40
|
const airwallex = new node_sdk_1.Airwallex({
|
|
41
|
+
accountId: process.env.AIRWALLEX_SANDBOX_ACCOUNT_ID,
|
|
32
42
|
apiKey: process.env.AIRWALLEX_SANDBOX_API_KEY,
|
|
33
43
|
clientId: process.env.AIRWALLEX_SANDBOX_CLIENT_ID,
|
|
34
|
-
env:
|
|
44
|
+
env: awxEnv,
|
|
35
45
|
});
|
|
36
|
-
server.registerTool(
|
|
37
|
-
server.registerTool(
|
|
38
|
-
server.registerTool(
|
|
39
|
-
server.registerTool(
|
|
40
|
-
server.registerTool(
|
|
41
|
-
server.registerTool(
|
|
46
|
+
server.registerTool(listGlobalAccounts_1.listGlobalAccountsToolConfig.name, listGlobalAccounts_1.listGlobalAccountsToolConfig, (0, withTelemetry_1.withToolTelemetry)(listGlobalAccounts_1.listGlobalAccountsToolConfig.name, async (args) => (0, listGlobalAccounts_1.executeListGlobalAccounts)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
47
|
+
server.registerTool(getDefaultApiVersion_1.getDefaultApiVersionToolConfig.name, getDefaultApiVersion_1.getDefaultApiVersionToolConfig, (0, withTelemetry_1.withToolTelemetry)(getDefaultApiVersion_1.getDefaultApiVersionToolConfig.name, async () => (0, getDefaultApiVersion_1.executeGetDefaultApiVersion)(airwallex), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
48
|
+
server.registerTool(getBalances_1.getAccountBalancesToolConfig.name, getBalances_1.getAccountBalancesToolConfig, (0, withTelemetry_1.withToolTelemetry)(getBalances_1.getAccountBalancesToolConfig.name, async (args) => (0, getBalances_1.executeGetAccountBalances)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
49
|
+
server.registerTool(simulateDeposit_1.simulateDepositToolConfig.name, simulateDeposit_1.simulateDepositToolConfig, (0, withTelemetry_1.withToolTelemetry)(simulateDeposit_1.simulateDepositToolConfig.name, async (args) => (0, simulateDeposit_1.executeSimulateDeposit)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
50
|
+
server.registerTool(listBillingProducts_1.listBillingProductsToolConfig.name, listBillingProducts_1.listBillingProductsToolConfig, (0, withTelemetry_1.withToolTelemetry)(listBillingProducts_1.listBillingProductsToolConfig.name, async () => (0, listBillingProducts_1.executeListBillingProducts)(airwallex), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
51
|
+
server.registerTool(listBillingPrices_1.listBillingPricesToolConfig.name, listBillingPrices_1.listBillingPricesToolConfig, (0, withTelemetry_1.withToolTelemetry)(listBillingPrices_1.listBillingPricesToolConfig.name, async (args) => (0, listBillingPrices_1.executeListBillingPrices)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
52
|
+
server.registerTool(createBillingProduct_1.createBillingProductToolConfig.name, createBillingProduct_1.createBillingProductToolConfig, (0, withTelemetry_1.withToolTelemetry)(createBillingProduct_1.createBillingProductToolConfig.name, async (args) => (0, createBillingProduct_1.executeCreateBillingProduct)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
42
53
|
server.registerTool(createBillingPrice_1.createBillingPriceToolConfig.name, createBillingPrice_1.createBillingPriceToolConfig, (0, withTelemetry_1.withToolTelemetry)(createBillingPrice_1.createBillingPriceToolConfig.name, async (args) => (0, createBillingPrice_1.executeCreateBillingPrice)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
43
|
-
server.registerTool(
|
|
54
|
+
server.registerTool(createBillingCheckout_1.createBillingCheckoutToolConfig.name, createBillingCheckout_1.createBillingCheckoutToolConfig, (0, withTelemetry_1.withToolTelemetry)(createBillingCheckout_1.createBillingCheckoutToolConfig.name, async (args) => (0, createBillingCheckout_1.executeCreateBillingCheckout)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
44
55
|
server.registerTool(getFxQuote_1.getFxQuoteToolConfig.name, getFxQuote_1.getFxQuoteToolConfig, (0, withTelemetry_1.withToolTelemetry)(getFxQuote_1.getFxQuoteToolConfig.name, async (args) => (0, getFxQuote_1.executeGetFxQuote)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
45
|
-
server.registerTool(listTransfers_1.listTransfersToolConfig.name, listTransfers_1.listTransfersToolConfig, (0, withTelemetry_1.withToolTelemetry)(listTransfers_1.listTransfersToolConfig.name, async () => (0, listTransfers_1.executeListTransfers)(airwallex), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
56
|
+
server.registerTool(listTransfers_1.listTransfersToolConfig.name, listTransfers_1.listTransfersToolConfig, (0, withTelemetry_1.withToolTelemetry)(listTransfers_1.listTransfersToolConfig.name, async (args) => (0, listTransfers_1.executeListTransfers)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
46
57
|
server.registerTool(createTransfer_1.createTransferToolConfig.name, createTransfer_1.createTransferToolConfig, (0, withTelemetry_1.withToolTelemetry)(createTransfer_1.createTransferToolConfig.name, async (args) => (0, createTransfer_1.executeCreateTransfer)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
47
|
-
server.registerTool(listBeneficiaries_1.listBeneficiariesToolConfig.name, listBeneficiaries_1.listBeneficiariesToolConfig, (0, withTelemetry_1.withToolTelemetry)(listBeneficiaries_1.listBeneficiariesToolConfig.name, async () => (0, listBeneficiaries_1.executeListBeneficiaries)(airwallex), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
58
|
+
server.registerTool(listBeneficiaries_1.listBeneficiariesToolConfig.name, listBeneficiaries_1.listBeneficiariesToolConfig, (0, withTelemetry_1.withToolTelemetry)(listBeneficiaries_1.listBeneficiariesToolConfig.name, async (args) => (0, listBeneficiaries_1.executeListBeneficiaries)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
48
59
|
server.registerTool(simulateTransferResult_1.simulateTransferUpdateToolConfig.name, simulateTransferResult_1.simulateTransferUpdateToolConfig, (0, withTelemetry_1.withToolTelemetry)(simulateTransferResult_1.simulateTransferUpdateToolConfig.name, async (args) => (0, simulateTransferResult_1.executeSimulateTransferUpdate)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
49
60
|
server.registerTool(createPaymentLink_1.createPaymentLinkToolConfig.name, createPaymentLink_1.createPaymentLinkToolConfig, (0, withTelemetry_1.withToolTelemetry)(createPaymentLink_1.createPaymentLinkToolConfig.name, async (args) => (0, createPaymentLink_1.executeCreatePaymentLink)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
50
|
-
server.registerTool(listPaymentLinks_1.listPaymentLinksToolConfig.name, listPaymentLinks_1.listPaymentLinksToolConfig, (0, withTelemetry_1.withToolTelemetry)(listPaymentLinks_1.listPaymentLinksToolConfig.name, async () => (0, listPaymentLinks_1.executeListPaymentLinks)(airwallex), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
61
|
+
server.registerTool(listPaymentLinks_1.listPaymentLinksToolConfig.name, listPaymentLinks_1.listPaymentLinksToolConfig, (0, withTelemetry_1.withToolTelemetry)(listPaymentLinks_1.listPaymentLinksToolConfig.name, async (args) => (0, listPaymentLinks_1.executeListPaymentLinks)(airwallex, args), { disableTelemetry, telemetryClient: airTrackerClient }));
|
|
51
62
|
}
|
|
52
63
|
return server;
|
|
53
64
|
};
|
|
@@ -16,15 +16,18 @@ const DEFAULT_COMMON_DATA = {
|
|
|
16
16
|
env: "unknown",
|
|
17
17
|
networkType: "unknown",
|
|
18
18
|
platform: os_1.default.platform(),
|
|
19
|
+
sandboxApiClientId: process.env.AIRWALLEX_SANDBOX_CLIENT_ID?.trim().slice(0, 64) || "unknown",
|
|
19
20
|
sessionId: (0, uuid_1.v4)(),
|
|
20
21
|
};
|
|
21
22
|
class AirTrackerClient {
|
|
22
23
|
baseUrl;
|
|
23
24
|
appVersion;
|
|
25
|
+
server;
|
|
24
26
|
commonData;
|
|
25
|
-
constructor(baseUrl, awxEnv, appVersion) {
|
|
27
|
+
constructor(baseUrl, awxEnv, appVersion, server) {
|
|
26
28
|
this.baseUrl = baseUrl;
|
|
27
29
|
this.appVersion = appVersion;
|
|
30
|
+
this.server = server;
|
|
28
31
|
this.commonData = {
|
|
29
32
|
...DEFAULT_COMMON_DATA,
|
|
30
33
|
appVersion: this.appVersion,
|
|
@@ -32,13 +35,18 @@ class AirTrackerClient {
|
|
|
32
35
|
};
|
|
33
36
|
}
|
|
34
37
|
logEvent(eventName, properties) {
|
|
38
|
+
const clientInfo = this.server.server.getClientVersion();
|
|
35
39
|
const logData = {
|
|
36
40
|
eventName,
|
|
37
41
|
...properties,
|
|
38
42
|
};
|
|
39
43
|
fetch(`${this.baseUrl}/airtracker/logs`, {
|
|
40
44
|
body: JSON.stringify({
|
|
41
|
-
commonData:
|
|
45
|
+
commonData: {
|
|
46
|
+
...this.commonData,
|
|
47
|
+
mcpClientName: clientInfo?.name,
|
|
48
|
+
mcpClientVersion: clientInfo?.version,
|
|
49
|
+
},
|
|
42
50
|
data: [{ ...logData, severity: "info" }],
|
|
43
51
|
}),
|
|
44
52
|
headers: {
|
|
@@ -5,6 +5,9 @@ exports.executeCreateBillingCheckout = executeCreateBillingCheckout;
|
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const descriptions_1 = require("../constants/descriptions");
|
|
8
|
+
const index_1 = require("../types/index");
|
|
9
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
10
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Organization;
|
|
8
11
|
exports.createBillingCheckoutSchema = zod_1.z.object({
|
|
9
12
|
mode: zod_1.z.enum(["PAYMENT", "SUBSCRIPTION"], {
|
|
10
13
|
errorMap: () => ({
|
|
@@ -54,9 +57,7 @@ async function executeCreateBillingCheckout(airwallex, args) {
|
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
59
|
catch (error) {
|
|
57
|
-
|
|
58
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
59
|
-
throw new Error(`Failed to create billing checkout (${statusCode}): ${errorMessage}`);
|
|
60
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "create billing checkout");
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
exports.createBillingCheckoutToolConfig = {
|
|
@@ -5,6 +5,9 @@ exports.executeCreateBillingPrice = executeCreateBillingPrice;
|
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const descriptions_1 = require("../constants/descriptions");
|
|
8
|
+
const index_1 = require("../types/index");
|
|
9
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
10
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Organization;
|
|
8
11
|
exports.createBillingPriceSchema = zod_1.z
|
|
9
12
|
.object({
|
|
10
13
|
amount: zod_1.z.number().positive("Amount must be positive"),
|
|
@@ -89,9 +92,7 @@ async function executeCreateBillingPrice(airwallex, args) {
|
|
|
89
92
|
};
|
|
90
93
|
}
|
|
91
94
|
catch (error) {
|
|
92
|
-
|
|
93
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
94
|
-
throw new Error(`Failed to create billing price (${statusCode}): ${errorMessage}`);
|
|
95
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "create billing price");
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
exports.createBillingPriceToolConfig = {
|
|
@@ -5,6 +5,9 @@ exports.executeCreateBillingProduct = executeCreateBillingProduct;
|
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const descriptions_1 = require("../constants/descriptions");
|
|
8
|
+
const index_1 = require("../types/index");
|
|
9
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
10
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Organization;
|
|
8
11
|
exports.createBillingProductSchema = zod_1.z.object({
|
|
9
12
|
description: zod_1.z.string().optional(),
|
|
10
13
|
name: zod_1.z.string().min(1, "Product name is required"),
|
|
@@ -32,9 +35,7 @@ async function executeCreateBillingProduct(airwallex, args) {
|
|
|
32
35
|
};
|
|
33
36
|
}
|
|
34
37
|
catch (error) {
|
|
35
|
-
|
|
36
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
37
|
-
throw new Error(`Failed to create billing product (${statusCode}): ${errorMessage}`);
|
|
38
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "create billing product");
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
exports.createBillingProductToolConfig = {
|
|
@@ -4,11 +4,19 @@ exports.createPaymentLinkToolConfig = exports.createPaymentLinkSchema = void 0;
|
|
|
4
4
|
exports.executeCreatePaymentLink = executeCreatePaymentLink;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
7
11
|
exports.createPaymentLinkSchema = zod_1.z.object({
|
|
8
12
|
amount: zod_1.z
|
|
9
13
|
.number()
|
|
10
14
|
.positive()
|
|
11
15
|
.describe("The payment amount. For Fixed pricing only."),
|
|
16
|
+
connected_account_id: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
19
|
+
.optional(),
|
|
12
20
|
currency: zod_1.z
|
|
13
21
|
.string()
|
|
14
22
|
.length(3)
|
|
@@ -39,9 +47,10 @@ async function executeCreatePaymentLink(airwallex, args) {
|
|
|
39
47
|
if (args.description) {
|
|
40
48
|
createPayload.description = args.description;
|
|
41
49
|
}
|
|
42
|
-
const
|
|
50
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
51
|
+
const response = (await airwallex.post("/api/v1/pa/payment_links/create", createPayload, requestOptions));
|
|
43
52
|
if (args.shopper_email) {
|
|
44
|
-
await airwallex.post(`/api/v1/pa/payment_links/${response.id}/notify_shopper`, { shopper_email: args.shopper_email });
|
|
53
|
+
await airwallex.post(`/api/v1/pa/payment_links/${response.id}/notify_shopper`, { shopper_email: args.shopper_email }, requestOptions);
|
|
45
54
|
}
|
|
46
55
|
return {
|
|
47
56
|
content: [
|
|
@@ -53,9 +62,7 @@ async function executeCreatePaymentLink(airwallex, args) {
|
|
|
53
62
|
};
|
|
54
63
|
}
|
|
55
64
|
catch (error) {
|
|
56
|
-
|
|
57
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
58
|
-
throw new Error(`Failed to create payment link (${statusCode}): ${errorMessage}`);
|
|
65
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "create payment link");
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
exports.createPaymentLinkToolConfig = {
|
|
@@ -5,12 +5,20 @@ exports.executeCreateTransfer = executeCreateTransfer;
|
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const descriptions_1 = require("../constants/descriptions");
|
|
8
|
+
const index_1 = require("../types/index");
|
|
9
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
10
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
11
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
8
12
|
exports.createTransferSchema = zod_1.z
|
|
9
13
|
.object({
|
|
10
14
|
beneficiary_id: zod_1.z
|
|
11
15
|
.string()
|
|
12
16
|
.min(1)
|
|
13
17
|
.describe("The ID of the beneficiary to send the transfer to."),
|
|
18
|
+
connected_account_id: zod_1.z
|
|
19
|
+
.string()
|
|
20
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
21
|
+
.optional(),
|
|
14
22
|
reason: zod_1.z.string().min(1),
|
|
15
23
|
reference: zod_1.z.string().min(1),
|
|
16
24
|
source_amount: zod_1.z
|
|
@@ -55,7 +63,8 @@ async function executeCreateTransfer(airwallex, args) {
|
|
|
55
63
|
transfer_currency: args.transfer_currency,
|
|
56
64
|
transfer_method: args.transfer_method,
|
|
57
65
|
};
|
|
58
|
-
const
|
|
66
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
67
|
+
const response = (await airwallex.post("/api/v1/transfers/create", requestBody, requestOptions));
|
|
59
68
|
return {
|
|
60
69
|
content: [
|
|
61
70
|
{
|
|
@@ -66,9 +75,7 @@ async function executeCreateTransfer(airwallex, args) {
|
|
|
66
75
|
};
|
|
67
76
|
}
|
|
68
77
|
catch (error) {
|
|
69
|
-
|
|
70
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
71
|
-
throw new Error(`Failed to create transfer (${statusCode}): ${errorMessage}`);
|
|
78
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "create transfer");
|
|
72
79
|
}
|
|
73
80
|
}
|
|
74
81
|
exports.createTransferToolConfig = {
|
|
@@ -4,10 +4,20 @@ exports.getAccountBalancesToolConfig = exports.getAccountBalancesSchema = void 0
|
|
|
4
4
|
exports.executeGetAccountBalances = executeGetAccountBalances;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
11
|
+
exports.getAccountBalancesSchema = zod_1.z.object({
|
|
12
|
+
connected_account_id: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
15
|
+
.optional(),
|
|
16
|
+
});
|
|
17
|
+
async function executeGetAccountBalances(airwallex, args) {
|
|
9
18
|
try {
|
|
10
|
-
const
|
|
19
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
20
|
+
const response = (await airwallex.get("/api/v1/balances/current", requestOptions));
|
|
11
21
|
return {
|
|
12
22
|
content: [
|
|
13
23
|
{
|
|
@@ -18,9 +28,7 @@ async function executeGetAccountBalances(airwallex) {
|
|
|
18
28
|
};
|
|
19
29
|
}
|
|
20
30
|
catch (error) {
|
|
21
|
-
|
|
22
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
23
|
-
throw new Error(`Failed to get account balances (${statusCode}): ${errorMessage}`);
|
|
31
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "get account balances");
|
|
24
32
|
}
|
|
25
33
|
}
|
|
26
34
|
exports.getAccountBalancesToolConfig = {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultApiVersionToolConfig = exports.getDefaultApiVersionSchema = void 0;
|
|
4
|
+
exports.executeGetDefaultApiVersion = executeGetDefaultApiVersion;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const tokenInspector_1 = require("../utils/tokenInspector");
|
|
9
|
+
exports.getDefaultApiVersionSchema = zod_1.z.object({});
|
|
10
|
+
async function executeGetDefaultApiVersion(airwallex) {
|
|
11
|
+
try {
|
|
12
|
+
await airwallex.login();
|
|
13
|
+
const token = airwallex.token;
|
|
14
|
+
if (!token) {
|
|
15
|
+
throw new Error("Failed to retrieve token after login");
|
|
16
|
+
}
|
|
17
|
+
const tokenInspector = new tokenInspector_1.JWTTokenInspector(token);
|
|
18
|
+
const resourceContextType = tokenInspector.isOrgOnlyToken()
|
|
19
|
+
? index_1.ResourceContextType.Organization
|
|
20
|
+
: index_1.ResourceContextType.Account;
|
|
21
|
+
const response = {
|
|
22
|
+
api_version: tokenInspector.getPayload().api_version,
|
|
23
|
+
resource_context_type: resourceContextType,
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
text: JSON.stringify(response, null, 2),
|
|
29
|
+
type: "text",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const statusCode = error?.status || error?.statusCode || 500;
|
|
36
|
+
const errorMessage = error?.message || "Unknown error occurred";
|
|
37
|
+
throw new Error(`Failed to get default API version (${statusCode}): ${errorMessage}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.getDefaultApiVersionToolConfig = {
|
|
41
|
+
annotations: {
|
|
42
|
+
openWorldHint: true,
|
|
43
|
+
readOnlyHint: true,
|
|
44
|
+
title: "Get default API version",
|
|
45
|
+
},
|
|
46
|
+
description: descriptions_1.TOOL_DESCRIPTIONS.GET_DEFAULT_API_VERSION,
|
|
47
|
+
inputSchema: exports.getDefaultApiVersionSchema,
|
|
48
|
+
name: "get_default_api_version",
|
|
49
|
+
};
|
package/dist/tools/getFxQuote.js
CHANGED
|
@@ -4,6 +4,10 @@ exports.getFxQuoteToolConfig = exports.getFxQuoteSchema = void 0;
|
|
|
4
4
|
exports.executeGetFxQuote = executeGetFxQuote;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
7
11
|
exports.getFxQuoteSchema = zod_1.z
|
|
8
12
|
.object({
|
|
9
13
|
buy_amount: zod_1.z
|
|
@@ -12,6 +16,10 @@ exports.getFxQuoteSchema = zod_1.z
|
|
|
12
16
|
.describe("The amount to buy. Skip this if you are setting sell_amount")
|
|
13
17
|
.optional(),
|
|
14
18
|
buy_currency: zod_1.z.string().length(3).describe("The currency to buy"),
|
|
19
|
+
connected_account_id: zod_1.z
|
|
20
|
+
.string()
|
|
21
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
22
|
+
.optional(),
|
|
15
23
|
sell_amount: zod_1.z
|
|
16
24
|
.number()
|
|
17
25
|
.positive()
|
|
@@ -29,13 +37,14 @@ exports.getFxQuoteSchema = zod_1.z
|
|
|
29
37
|
});
|
|
30
38
|
async function executeGetFxQuote(airwallex, args) {
|
|
31
39
|
try {
|
|
40
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
32
41
|
const response = (await airwallex.post("/api/v1/fx/quotes/create", {
|
|
33
42
|
buy_amount: args.buy_amount,
|
|
34
43
|
buy_currency: args.buy_currency,
|
|
35
44
|
sell_amount: args.sell_amount,
|
|
36
45
|
sell_currency: args.sell_currency,
|
|
37
46
|
validity: args.validity,
|
|
38
|
-
}));
|
|
47
|
+
}, requestOptions));
|
|
39
48
|
return {
|
|
40
49
|
content: [
|
|
41
50
|
{
|
|
@@ -46,9 +55,7 @@ async function executeGetFxQuote(airwallex, args) {
|
|
|
46
55
|
};
|
|
47
56
|
}
|
|
48
57
|
catch (error) {
|
|
49
|
-
|
|
50
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
51
|
-
throw new Error(`Failed to get FX quote (${statusCode}): ${errorMessage}`);
|
|
58
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "get FX quote");
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
61
|
exports.getFxQuoteToolConfig = {
|
|
@@ -4,13 +4,23 @@ exports.listBeneficiariesToolConfig = exports.listBeneficiariesSchema = void 0;
|
|
|
4
4
|
exports.executeListBeneficiaries = executeListBeneficiaries;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
11
|
+
exports.listBeneficiariesSchema = zod_1.z.object({
|
|
12
|
+
connected_account_id: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
15
|
+
.optional(),
|
|
16
|
+
});
|
|
17
|
+
async function executeListBeneficiaries(airwallex, args) {
|
|
9
18
|
try {
|
|
19
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
10
20
|
const queryParams = new URLSearchParams();
|
|
11
21
|
queryParams.append("page_size", "100");
|
|
12
22
|
const url = `/api/v1/beneficiaries${queryParams.toString() ? `?${queryParams.toString()}` : ""}`;
|
|
13
|
-
const response = (await airwallex.get(url));
|
|
23
|
+
const response = (await airwallex.get(url, requestOptions));
|
|
14
24
|
return {
|
|
15
25
|
content: [
|
|
16
26
|
{
|
|
@@ -21,9 +31,7 @@ async function executeListBeneficiaries(airwallex) {
|
|
|
21
31
|
};
|
|
22
32
|
}
|
|
23
33
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
26
|
-
throw new Error(`Failed to list beneficiaries (${statusCode}): ${errorMessage}`);
|
|
34
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "list beneficiaries");
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
exports.listBeneficiariesToolConfig = {
|
|
@@ -4,6 +4,9 @@ exports.listBillingPricesToolConfig = exports.listBillingPricesSchema = void 0;
|
|
|
4
4
|
exports.executeListBillingPrices = executeListBillingPrices;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Organization;
|
|
7
10
|
exports.listBillingPricesSchema = zod_1.z.object({
|
|
8
11
|
product_id: zod_1.z
|
|
9
12
|
.string()
|
|
@@ -29,9 +32,7 @@ async function executeListBillingPrices(airwallex, args) {
|
|
|
29
32
|
};
|
|
30
33
|
}
|
|
31
34
|
catch (error) {
|
|
32
|
-
|
|
33
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
34
|
-
throw new Error(`Failed to list billing prices (${statusCode}): ${errorMessage}`);
|
|
35
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "list billing prices");
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
exports.listBillingPricesToolConfig = {
|
|
@@ -4,6 +4,9 @@ exports.listBillingProductsToolConfig = exports.listBillingProductsSchema = void
|
|
|
4
4
|
exports.executeListBillingProducts = executeListBillingProducts;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Organization;
|
|
7
10
|
exports.listBillingProductsSchema = zod_1.z.object({});
|
|
8
11
|
async function executeListBillingProducts(airwallex) {
|
|
9
12
|
try {
|
|
@@ -21,9 +24,7 @@ async function executeListBillingProducts(airwallex) {
|
|
|
21
24
|
};
|
|
22
25
|
}
|
|
23
26
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
26
|
-
throw new Error(`Failed to list billing products (${statusCode}): ${errorMessage}`);
|
|
27
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "list billing products");
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
exports.listBillingProductsToolConfig = {
|
|
@@ -4,10 +4,20 @@ exports.listGlobalAccountsToolConfig = exports.listGlobalAccountsSchema = void 0
|
|
|
4
4
|
exports.executeListGlobalAccounts = executeListGlobalAccounts;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
11
|
+
exports.listGlobalAccountsSchema = zod_1.z.object({
|
|
12
|
+
connected_account_id: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
15
|
+
.optional(),
|
|
16
|
+
});
|
|
17
|
+
async function executeListGlobalAccounts(airwallex, args) {
|
|
9
18
|
try {
|
|
10
|
-
const
|
|
19
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
20
|
+
const response = (await airwallex.get("/api/v1/global_accounts", requestOptions));
|
|
11
21
|
return {
|
|
12
22
|
content: [
|
|
13
23
|
{
|
|
@@ -18,10 +28,7 @@ async function executeListGlobalAccounts(airwallex) {
|
|
|
18
28
|
};
|
|
19
29
|
}
|
|
20
30
|
catch (error) {
|
|
21
|
-
|
|
22
|
-
const statusCode = error?.status || error?.statusCode || 500;
|
|
23
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
24
|
-
throw new Error(`Failed to list global accounts (${statusCode}): ${errorMessage}`);
|
|
31
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "list global accounts");
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
exports.listGlobalAccountsToolConfig = {
|
|
@@ -4,13 +4,23 @@ exports.listPaymentLinksToolConfig = exports.listPaymentLinksSchema = void 0;
|
|
|
4
4
|
exports.executeListPaymentLinks = executeListPaymentLinks;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
11
|
+
exports.listPaymentLinksSchema = zod_1.z.object({
|
|
12
|
+
connected_account_id: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
15
|
+
.optional(),
|
|
16
|
+
});
|
|
17
|
+
async function executeListPaymentLinks(airwallex, args) {
|
|
9
18
|
try {
|
|
19
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
10
20
|
const queryParams = new URLSearchParams();
|
|
11
21
|
queryParams.append("page_size", "100");
|
|
12
22
|
const url = `/api/v1/pa/payment_links${queryParams.toString() ? `?${queryParams.toString()}` : ""}`;
|
|
13
|
-
const response = (await airwallex.get(url));
|
|
23
|
+
const response = (await airwallex.get(url, requestOptions));
|
|
14
24
|
return {
|
|
15
25
|
content: [
|
|
16
26
|
{
|
|
@@ -21,9 +31,7 @@ async function executeListPaymentLinks(airwallex) {
|
|
|
21
31
|
};
|
|
22
32
|
}
|
|
23
33
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
26
|
-
throw new Error(`Failed to list payment links (${statusCode}): ${errorMessage}`);
|
|
34
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "list payment links");
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
exports.listPaymentLinksToolConfig = {
|
|
@@ -4,10 +4,20 @@ exports.listTransfersToolConfig = exports.listTransfersSchema = void 0;
|
|
|
4
4
|
exports.executeListTransfers = executeListTransfers;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
11
|
+
exports.listTransfersSchema = zod_1.z.object({
|
|
12
|
+
connected_account_id: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
15
|
+
.optional(),
|
|
16
|
+
});
|
|
17
|
+
async function executeListTransfers(airwallex, args) {
|
|
9
18
|
try {
|
|
10
|
-
const
|
|
19
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
20
|
+
const response = (await airwallex.get("/api/v1/transfers", requestOptions));
|
|
11
21
|
return {
|
|
12
22
|
content: [
|
|
13
23
|
{
|
|
@@ -18,9 +28,7 @@ async function executeListTransfers(airwallex) {
|
|
|
18
28
|
};
|
|
19
29
|
}
|
|
20
30
|
catch (error) {
|
|
21
|
-
|
|
22
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
23
|
-
throw new Error(`Failed to list transfers (${statusCode}): ${errorMessage}`);
|
|
31
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "list transfers");
|
|
24
32
|
}
|
|
25
33
|
}
|
|
26
34
|
exports.listTransfersToolConfig = {
|
|
@@ -4,6 +4,7 @@ exports.readBestPracticesToolConfig = exports.readBestPracticesSchema = void 0;
|
|
|
4
4
|
exports.executeReadBestPractices = executeReadBestPractices;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
7
8
|
exports.readBestPracticesSchema = zod_1.z.object({});
|
|
8
9
|
async function executeReadBestPractices(integrationBestPracticesContent) {
|
|
9
10
|
try {
|
|
@@ -17,7 +18,7 @@ async function executeReadBestPractices(integrationBestPracticesContent) {
|
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
|
-
throw new
|
|
21
|
+
throw new index_1.ToolError(`Failed to read the integration best practices file: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
exports.readBestPracticesToolConfig = {
|
|
@@ -5,6 +5,7 @@ exports.executeRetrieveDocs = executeRetrieveDocs;
|
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const config_1 = require("../constants/config");
|
|
7
7
|
const descriptions_1 = require("../constants/descriptions");
|
|
8
|
+
const index_1 = require("../types/index");
|
|
8
9
|
exports.retrieveDocsSchema = zod_1.z.object({
|
|
9
10
|
question: zod_1.z
|
|
10
11
|
.string()
|
|
@@ -35,7 +36,7 @@ async function executeRetrieveDocs(args, version) {
|
|
|
35
36
|
method: "POST",
|
|
36
37
|
});
|
|
37
38
|
if (!response.ok) {
|
|
38
|
-
throw new
|
|
39
|
+
throw new index_1.ToolError(`HTTP error! status: ${response.status}`, response.status);
|
|
39
40
|
}
|
|
40
41
|
const data = (await response.json());
|
|
41
42
|
const results = data.results.map((entry) => ({
|
|
@@ -43,12 +44,15 @@ async function executeRetrieveDocs(args, version) {
|
|
|
43
44
|
source_url: entry.source_url,
|
|
44
45
|
}));
|
|
45
46
|
return {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
result: {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
text: JSON.stringify(results.map((result) => result.content), null, 2),
|
|
51
|
+
type: "text",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
telemetryMeta: { httpStatusCode: response.status },
|
|
52
56
|
};
|
|
53
57
|
}
|
|
54
58
|
exports.retrieveDocsToolConfig = {
|
|
@@ -4,11 +4,19 @@ exports.simulateDepositToolConfig = exports.simulateDepositSchema = void 0;
|
|
|
4
4
|
exports.executeSimulateDeposit = executeSimulateDeposit;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
7
11
|
exports.simulateDepositSchema = zod_1.z.object({
|
|
8
12
|
amount: zod_1.z
|
|
9
13
|
.number()
|
|
10
14
|
.positive()
|
|
11
15
|
.describe("The amount to deposit into the global account (in the account's base currency, not minor units)"),
|
|
16
|
+
connected_account_id: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
19
|
+
.optional(),
|
|
12
20
|
globalAccountId: zod_1.z
|
|
13
21
|
.string()
|
|
14
22
|
.min(1)
|
|
@@ -16,10 +24,11 @@ exports.simulateDepositSchema = zod_1.z.object({
|
|
|
16
24
|
});
|
|
17
25
|
async function executeSimulateDeposit(airwallex, args) {
|
|
18
26
|
try {
|
|
27
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
19
28
|
const response = await airwallex.post("/api/v1/simulation/deposit/create", {
|
|
20
29
|
amount: args.amount,
|
|
21
30
|
global_account_id: args.globalAccountId,
|
|
22
|
-
});
|
|
31
|
+
}, requestOptions);
|
|
23
32
|
const result = {
|
|
24
33
|
amount: response.amount,
|
|
25
34
|
created_at: response.create_time,
|
|
@@ -37,9 +46,7 @@ async function executeSimulateDeposit(airwallex, args) {
|
|
|
37
46
|
};
|
|
38
47
|
}
|
|
39
48
|
catch (error) {
|
|
40
|
-
|
|
41
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
42
|
-
throw new Error(`Deposit simulation failed (${statusCode}): ${errorMessage}`);
|
|
49
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "simulate deposit");
|
|
43
50
|
}
|
|
44
51
|
}
|
|
45
52
|
exports.simulateDepositToolConfig = {
|
|
@@ -4,7 +4,15 @@ exports.simulateTransferUpdateToolConfig = exports.simulateTransferUpdateSchema
|
|
|
4
4
|
exports.executeSimulateTransferUpdate = executeSimulateTransferUpdate;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const descriptions_1 = require("../constants/descriptions");
|
|
7
|
+
const index_1 = require("../types/index");
|
|
8
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
9
|
+
const RESOURCE_CONTEXT_TYPE = index_1.ResourceContextType.Account;
|
|
10
|
+
const requestOptions_1 = require("../utils/requestOptions");
|
|
7
11
|
exports.simulateTransferUpdateSchema = zod_1.z.object({
|
|
12
|
+
connected_account_id: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.startsWith("acct_", "Connected account ID must start with 'acct_'")
|
|
15
|
+
.optional(),
|
|
8
16
|
next_status: zod_1.z
|
|
9
17
|
.enum(["OVERDUE", "PROCESSING", "SENT", "PAID", "FAILED", "CANCELLED"])
|
|
10
18
|
.describe("The next status of the transfer. One of the following: OVERDUE, PROCESSING, SENT, PAID, FAILED, CANCELLED."),
|
|
@@ -12,9 +20,10 @@ exports.simulateTransferUpdateSchema = zod_1.z.object({
|
|
|
12
20
|
});
|
|
13
21
|
async function executeSimulateTransferUpdate(airwallex, args) {
|
|
14
22
|
try {
|
|
23
|
+
const requestOptions = (0, requestOptions_1.buildOnBehalfOfOptions)(args.connected_account_id);
|
|
15
24
|
const response = (await airwallex.post(`/api/v1/simulation/transfers/${args.transfer_id}/transition`, {
|
|
16
25
|
next_status: args.next_status,
|
|
17
|
-
}));
|
|
26
|
+
}, requestOptions));
|
|
18
27
|
return {
|
|
19
28
|
content: [
|
|
20
29
|
{
|
|
@@ -25,9 +34,7 @@ async function executeSimulateTransferUpdate(airwallex, args) {
|
|
|
25
34
|
};
|
|
26
35
|
}
|
|
27
36
|
catch (error) {
|
|
28
|
-
|
|
29
|
-
const errorMessage = error?.message || "Unknown error occurred";
|
|
30
|
-
throw new Error(`Failed to simulate transfer update (${statusCode}): ${errorMessage}`);
|
|
37
|
+
throw (0, errorHandler_1.handleSdkError)(error, RESOURCE_CONTEXT_TYPE, airwallex, "simulate transfer update");
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
exports.simulateTransferUpdateToolConfig = {
|
package/dist/types/index.js
CHANGED
|
@@ -1,2 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolError = exports.ResourceContextType = void 0;
|
|
4
|
+
var ResourceContextType;
|
|
5
|
+
(function (ResourceContextType) {
|
|
6
|
+
ResourceContextType["Account"] = "account";
|
|
7
|
+
ResourceContextType["Organization"] = "organization";
|
|
8
|
+
})(ResourceContextType || (exports.ResourceContextType = ResourceContextType = {}));
|
|
9
|
+
/**
|
|
10
|
+
* Custom error class that preserves HTTP status code for telemetry.
|
|
11
|
+
* Use this instead of plain Error when throwing errors from tool executors.
|
|
12
|
+
*/
|
|
13
|
+
class ToolError extends Error {
|
|
14
|
+
httpStatusCode;
|
|
15
|
+
constructor(message, httpStatusCode) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.httpStatusCode = httpStatusCode;
|
|
18
|
+
this.name = "ToolError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.ToolError = ToolError;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleSdkError = handleSdkError;
|
|
4
|
+
const index_1 = require("../types/index");
|
|
5
|
+
const tokenInspector_1 = require("./tokenInspector");
|
|
6
|
+
function handleSdkError(error, resourceContextType, airwallex, operationName) {
|
|
7
|
+
const statusCode = error?.status || error?.statusCode || 500;
|
|
8
|
+
const errorMessage = error?.message || "Unknown error occurred";
|
|
9
|
+
// Check for 401 errors and provide context-aware messages
|
|
10
|
+
if (statusCode === 401) {
|
|
11
|
+
const contextHint = getContextMismatchHint(resourceContextType, airwallex);
|
|
12
|
+
if (contextHint) {
|
|
13
|
+
return new index_1.ToolError(`Failed to ${operationName} (${statusCode}): ${errorMessage}. ${contextHint}`, statusCode);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return new index_1.ToolError(`Failed to ${operationName} (${statusCode}): ${errorMessage}`, statusCode);
|
|
17
|
+
}
|
|
18
|
+
function getContextMismatchHint(resourceContextType, airwallex) {
|
|
19
|
+
const token = airwallex.token;
|
|
20
|
+
if (!token) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const tokenInspector = new tokenInspector_1.JWTTokenInspector(token);
|
|
25
|
+
// Account-only token trying to access Organization resource
|
|
26
|
+
if (tokenInspector.isAccountOnlyToken() &&
|
|
27
|
+
resourceContextType === index_1.ResourceContextType.Organization) {
|
|
28
|
+
return "This operation requires organization-level access, but the API key is scoped to account-level only.";
|
|
29
|
+
}
|
|
30
|
+
// Org-only token trying to access Account resource
|
|
31
|
+
if (tokenInspector.isOrgOnlyToken() &&
|
|
32
|
+
resourceContextType === index_1.ResourceContextType.Account) {
|
|
33
|
+
return "This operation requires account-level access, but the API key is scoped to organization-level only.";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// If token parsing fails, don't add a hint
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildOnBehalfOfOptions = buildOnBehalfOfOptions;
|
|
4
|
+
const config_1 = require("../constants/config");
|
|
5
|
+
/**
|
|
6
|
+
* Build request options with on-behalf-of header for connected accounts
|
|
7
|
+
*/
|
|
8
|
+
function buildOnBehalfOfOptions(connectedAccountId) {
|
|
9
|
+
return connectedAccountId
|
|
10
|
+
? { headers: { [config_1.HEADERS.ON_BEHALF_OF]: connectedAccountId } }
|
|
11
|
+
: undefined;
|
|
12
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JWTTokenInspector = void 0;
|
|
4
|
+
class JWTTokenInspector {
|
|
5
|
+
tokenPayload;
|
|
6
|
+
constructor(tokenStr) {
|
|
7
|
+
this.tokenPayload = this.parseToken(tokenStr).payload;
|
|
8
|
+
}
|
|
9
|
+
getPayload() {
|
|
10
|
+
return this.tokenPayload;
|
|
11
|
+
}
|
|
12
|
+
isAccountOnlyToken() {
|
|
13
|
+
return (this.tokenPayload.account_id !== undefined &&
|
|
14
|
+
this.tokenPayload.org_id === undefined);
|
|
15
|
+
}
|
|
16
|
+
isMixedToken() {
|
|
17
|
+
return (this.tokenPayload.org_id !== undefined &&
|
|
18
|
+
this.tokenPayload.account_id !== undefined);
|
|
19
|
+
}
|
|
20
|
+
isOrgOnlyToken() {
|
|
21
|
+
return (this.tokenPayload.org_id !== undefined &&
|
|
22
|
+
this.tokenPayload.account_id === undefined);
|
|
23
|
+
}
|
|
24
|
+
parseToken(tokenStr) {
|
|
25
|
+
const [, payload] = tokenStr.split(".");
|
|
26
|
+
return {
|
|
27
|
+
payload: JSON.parse(decodeBase64Url(payload)),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.JWTTokenInspector = JWTTokenInspector;
|
|
32
|
+
function decodeBase64Url(base64Url) {
|
|
33
|
+
return Buffer.from(base64Url, "base64url").toString("utf-8");
|
|
34
|
+
}
|
|
@@ -1,16 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.withToolTelemetry = withToolTelemetry;
|
|
4
|
+
const types_1 = require("../types");
|
|
4
5
|
const TOOL_INVOKED_EVENT_NAME = "TOOL_INVOKED";
|
|
5
6
|
// Middleware that wraps around a MCP tool's execute function and logs the event using the telemetry client
|
|
6
7
|
function withToolTelemetry(toolName, toolExecutor, { disableTelemetry, telemetryClient, }) {
|
|
7
8
|
return async (args) => {
|
|
8
9
|
if (disableTelemetry) {
|
|
9
|
-
|
|
10
|
+
const response = await toolExecutor(args);
|
|
11
|
+
return isToolExecutorResponse(response) ? response.result : response;
|
|
12
|
+
}
|
|
13
|
+
let result;
|
|
14
|
+
let telemetryMeta;
|
|
15
|
+
const startTime = Date.now();
|
|
16
|
+
try {
|
|
17
|
+
const response = await toolExecutor(args);
|
|
18
|
+
if (isToolExecutorResponse(response)) {
|
|
19
|
+
result = response.result;
|
|
20
|
+
telemetryMeta = response.telemetryMeta;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
result = response;
|
|
24
|
+
}
|
|
25
|
+
telemetryClient.logEvent(TOOL_INVOKED_EVENT_NAME, {
|
|
26
|
+
httpStatusCode: telemetryMeta?.httpStatusCode ?? 200,
|
|
27
|
+
latencyInMs: Date.now() - startTime,
|
|
28
|
+
success: true,
|
|
29
|
+
toolName: toolName,
|
|
30
|
+
});
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
// Extract status code from ToolError, or fallback to error properties, or default to 500
|
|
35
|
+
const statusCode = error instanceof types_1.ToolError
|
|
36
|
+
? error.httpStatusCode
|
|
37
|
+
: error?.status || error?.statusCode || 500;
|
|
38
|
+
telemetryClient.logEvent(TOOL_INVOKED_EVENT_NAME, {
|
|
39
|
+
httpStatusCode: statusCode,
|
|
40
|
+
latencyInMs: Date.now() - startTime,
|
|
41
|
+
success: false,
|
|
42
|
+
toolName: toolName,
|
|
43
|
+
});
|
|
44
|
+
throw error;
|
|
10
45
|
}
|
|
11
|
-
telemetryClient.logEvent(TOOL_INVOKED_EVENT_NAME, {
|
|
12
|
-
toolName: toolName,
|
|
13
|
-
});
|
|
14
|
-
return await toolExecutor(args);
|
|
15
46
|
};
|
|
16
47
|
}
|
|
48
|
+
// Type guard to check if response is ToolExecutorResponse (has result property)
|
|
49
|
+
function isToolExecutorResponse(response) {
|
|
50
|
+
return (response !== null &&
|
|
51
|
+
typeof response === "object" &&
|
|
52
|
+
"result" in response &&
|
|
53
|
+
response.result !== null &&
|
|
54
|
+
typeof response.result === "object" &&
|
|
55
|
+
"content" in response.result);
|
|
56
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@airwallex/developer-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "0.3.0-beta.12",
|
|
4
4
|
"description": "MCP server for AI agents that assist developers integrating with the Airwallex platform",
|
|
5
5
|
"bin": {
|
|
6
6
|
"awx-developer-mcp": "dist/index.js"
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "tsc && cp src/*.md dist/",
|
|
14
|
+
"update-manifest": "node --experimental-strip-types scripts/update-manifest.ts",
|
|
14
15
|
"lint": "prettier --check . && eslint . && tsc --noEmit",
|
|
15
16
|
"test": "vitest run",
|
|
16
17
|
"test:unit": "vitest run --project unit",
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
"author": "Developer Experience Team <developer.support@airwallex.com>",
|
|
26
27
|
"license": "MIT",
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@airwallex/node-sdk": "2.
|
|
29
|
+
"@airwallex/node-sdk": "2.1.0-beta.5",
|
|
29
30
|
"@modelcontextprotocol/sdk": "1.22.0",
|
|
30
31
|
"node-machine-id": "1.1.12",
|
|
31
32
|
"uuid": "11",
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"airwallex"
|
|
41
42
|
],
|
|
42
43
|
"devDependencies": {
|
|
44
|
+
"@anthropic-ai/mcpb": "^2.1.2",
|
|
43
45
|
"@eslint/js": "^9.26.0",
|
|
44
46
|
"@semantic-release/changelog": "^6.0.3",
|
|
45
47
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
package/dist/tools/index.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./createBillingCheckout"), exports);
|
|
18
|
-
__exportStar(require("./createBillingProduct"), exports);
|
|
19
|
-
__exportStar(require("./getBalances"), exports);
|
|
20
|
-
__exportStar(require("./listBillingPrices"), exports);
|
|
21
|
-
__exportStar(require("./listBillingProducts"), exports);
|
|
22
|
-
__exportStar(require("./listGlobalAccounts"), exports);
|
|
23
|
-
__exportStar(require("./readIntegrationBestPractices"), exports);
|
|
24
|
-
__exportStar(require("./retrieveDocs"), exports);
|
|
25
|
-
__exportStar(require("./simulateDeposit"), exports);
|