shabaaspay-mcp-server 1.0.3 → 1.0.5
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/dist/agent-toolkit/ai-sdk.d.ts +5 -0
- package/dist/agent-toolkit/ai-sdk.js +34 -0
- package/dist/agent-toolkit/index.d.ts +16 -0
- package/dist/agent-toolkit/index.js +46 -0
- package/dist/agent-toolkit/langchain.d.ts +5 -0
- package/dist/agent-toolkit/langchain.js +30 -0
- package/dist/agent-toolkit/modelcontextprotocol.d.ts +2 -0
- package/dist/agent-toolkit/modelcontextprotocol.js +7 -0
- package/dist/api/client.d.ts +14 -3
- package/dist/api/client.js +14 -3
- package/dist/index.js +0 -0
- package/dist/mcp-handler/discovery.js +320 -16
- package/dist/mcp-handler/mcp.js +13 -8
- package/dist/mcp-handler/schema-helpers.d.ts +8 -0
- package/dist/mcp-handler/schema-helpers.js +26 -0
- package/dist/mcp-handler/server-card.js +130 -23
- package/dist/mcp-handler/tools/index.d.ts +3 -0
- package/dist/mcp-handler/tools/index.js +24 -3
- package/dist/mcp-handler/utils.d.ts +2 -0
- package/dist/mcp-handler/worker.js +7 -1
- package/dist/server/http-server.js +3 -2
- package/dist/server-http.js +0 -0
- package/dist/tools/index.d.ts +45 -10
- package/dist/tools/payment-agreements.d.ts +42 -10
- package/dist/tools/payment-initiations.d.ts +3 -0
- package/dist/types/index.d.ts +45 -10
- package/dist/types/index.js +28 -8
- package/package.json +6 -2
- package/readme.md +15 -0
- package/server.json +2 -2
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShabaasAgentToolkitAiSdk = void 0;
|
|
4
|
+
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
5
|
+
const index_js_1 = require("./index.js");
|
|
6
|
+
class ShabaasAgentToolkitAiSdk extends index_js_1.ShabaasAgentToolkit {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super(options);
|
|
9
|
+
}
|
|
10
|
+
async getAiSdkTools() {
|
|
11
|
+
let toolFactory;
|
|
12
|
+
try {
|
|
13
|
+
const aiModuleName = 'ai';
|
|
14
|
+
const aiModule = await import(aiModuleName);
|
|
15
|
+
toolFactory = aiModule.tool;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error('AI SDK adapter requires the "ai" package. Install it with: npm install ai');
|
|
19
|
+
}
|
|
20
|
+
const entries = this.getTools().map((toolDef) => {
|
|
21
|
+
const parameters = (0, zod_to_json_schema_1.zodToJsonSchema)(toolDef.inputSchema);
|
|
22
|
+
return [
|
|
23
|
+
toolDef.name,
|
|
24
|
+
toolFactory({
|
|
25
|
+
description: toolDef.description,
|
|
26
|
+
parameters,
|
|
27
|
+
execute: async (args) => toolDef.execute(args ?? {}),
|
|
28
|
+
}),
|
|
29
|
+
];
|
|
30
|
+
});
|
|
31
|
+
return Object.fromEntries(entries);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.ShabaasAgentToolkitAiSdk = ShabaasAgentToolkitAiSdk;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type ShabaasAgentToolkitOptions = {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
environment?: 'sandbox' | 'production';
|
|
4
|
+
};
|
|
5
|
+
export type ShabaasFunctionTool = {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
inputSchema: unknown;
|
|
9
|
+
execute: (args?: Record<string, unknown>) => Promise<unknown>;
|
|
10
|
+
};
|
|
11
|
+
export declare class ShabaasAgentToolkit {
|
|
12
|
+
private readonly apiKey;
|
|
13
|
+
private readonly tools;
|
|
14
|
+
constructor(options: ShabaasAgentToolkitOptions);
|
|
15
|
+
getTools(): ShabaasFunctionTool[];
|
|
16
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShabaasAgentToolkit = void 0;
|
|
4
|
+
const client_js_1 = require("../api/client.js");
|
|
5
|
+
const backend_urls_js_1 = require("../constants/backend-urls.js");
|
|
6
|
+
const index_js_1 = require("../tools/index.js");
|
|
7
|
+
function toToolkitConfig(options) {
|
|
8
|
+
const environment = options.environment ?? 'sandbox';
|
|
9
|
+
return {
|
|
10
|
+
environment,
|
|
11
|
+
shabaasAuthUuid: options.apiKey,
|
|
12
|
+
sandboxUrl: backend_urls_js_1.CANONICAL_SANDBOX_BASE_URL,
|
|
13
|
+
productionUrl: backend_urls_js_1.CANONICAL_PRODUCTION_BASE_URL,
|
|
14
|
+
httpPort: 3001,
|
|
15
|
+
httpHost: '0.0.0.0',
|
|
16
|
+
mcpHttpApiKey: '',
|
|
17
|
+
mcpStdioApiKey: '',
|
|
18
|
+
allowedOrigins: ['*'],
|
|
19
|
+
rateLimitPerMinute: 60,
|
|
20
|
+
rateLimitPerHour: 1000,
|
|
21
|
+
authTokenMaxAgeMinutes: 50,
|
|
22
|
+
policyCacheTtlMs: 300_000,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
class ShabaasAgentToolkit {
|
|
26
|
+
apiKey;
|
|
27
|
+
tools;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
if (!options.apiKey) {
|
|
30
|
+
throw new Error('ShabaasAgentToolkit requires apiKey');
|
|
31
|
+
}
|
|
32
|
+
this.apiKey = options.apiKey;
|
|
33
|
+
const config = toToolkitConfig(options);
|
|
34
|
+
const apiClient = new client_js_1.ShabaasApiClient(config);
|
|
35
|
+
this.tools = (0, index_js_1.createAllTools)(apiClient, config);
|
|
36
|
+
}
|
|
37
|
+
getTools() {
|
|
38
|
+
return Object.values(this.tools).map((tool) => ({
|
|
39
|
+
name: tool.name,
|
|
40
|
+
description: tool.description,
|
|
41
|
+
inputSchema: tool.inputSchema,
|
|
42
|
+
execute: async (args) => tool.execute(args ?? {}, { requestUuid: this.apiKey }),
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.ShabaasAgentToolkit = ShabaasAgentToolkit;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShabaasAgentToolkitLangChain = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const index_js_1 = require("./index.js");
|
|
6
|
+
class ShabaasAgentToolkitLangChain extends index_js_1.ShabaasAgentToolkit {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super(options);
|
|
9
|
+
}
|
|
10
|
+
async getLangChainTools() {
|
|
11
|
+
let DynamicStructuredTool;
|
|
12
|
+
try {
|
|
13
|
+
const langchainToolsModule = '@langchain/core/tools';
|
|
14
|
+
({ DynamicStructuredTool } = await import(langchainToolsModule));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new Error('LangChain adapter requires @langchain/core. Install it with: npm install @langchain/core');
|
|
18
|
+
}
|
|
19
|
+
return this.getTools().map((tool) => new DynamicStructuredTool({
|
|
20
|
+
name: tool.name,
|
|
21
|
+
description: tool.description,
|
|
22
|
+
schema: tool.inputSchema ?? zod_1.z.object({}),
|
|
23
|
+
func: async (args) => {
|
|
24
|
+
const result = await tool.execute(args);
|
|
25
|
+
return JSON.stringify(result);
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.ShabaasAgentToolkitLangChain = ShabaasAgentToolkitLangChain;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpMcpServer = exports.StdioMcpServer = void 0;
|
|
4
|
+
var stdio_server_js_1 = require("../server/stdio-server.js");
|
|
5
|
+
Object.defineProperty(exports, "StdioMcpServer", { enumerable: true, get: function () { return stdio_server_js_1.StdioMcpServer; } });
|
|
6
|
+
var http_server_js_1 = require("../server/http-server.js");
|
|
7
|
+
Object.defineProperty(exports, "HttpMcpServer", { enumerable: true, get: function () { return http_server_js_1.HttpMcpServer; } });
|
package/dist/api/client.d.ts
CHANGED
|
@@ -4,6 +4,16 @@ import { ApiResponse } from '../types/index.js';
|
|
|
4
4
|
export type RequestAuthOptions = {
|
|
5
5
|
requestUuid?: string;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Discoverable auth behavior metadata used by docs/discovery surfaces.
|
|
9
|
+
* Additive-only metadata: does not alter runtime request handling.
|
|
10
|
+
*/
|
|
11
|
+
export declare const AUTH_BEHAVIOR: {
|
|
12
|
+
readonly token_cache_ttl_ms: number;
|
|
13
|
+
readonly accepts_authorization_formats: readonly ["sbp_live_xxx", "Bearer sbp_live_xxx"];
|
|
14
|
+
readonly upstream_token_exchange: true;
|
|
15
|
+
readonly cache_scope: "per_api_key";
|
|
16
|
+
};
|
|
7
17
|
export declare class ShabaasApiClient {
|
|
8
18
|
private client;
|
|
9
19
|
private config;
|
|
@@ -27,10 +37,10 @@ export declare class ShabaasApiClient {
|
|
|
27
37
|
maximum_amount: string;
|
|
28
38
|
frequency: string;
|
|
29
39
|
number_of_transactions_permitted: number;
|
|
30
|
-
pay_id
|
|
40
|
+
pay_id?: string;
|
|
31
41
|
phone_number?: string;
|
|
32
|
-
bsb?: number;
|
|
33
|
-
account_number?: number;
|
|
42
|
+
bsb?: string | number;
|
|
43
|
+
account_number?: string | number;
|
|
34
44
|
agreement_type?: string;
|
|
35
45
|
start_date?: string;
|
|
36
46
|
end_date?: string;
|
|
@@ -41,6 +51,7 @@ export declare class ShabaasApiClient {
|
|
|
41
51
|
payment_agreement_id: string;
|
|
42
52
|
amount: string | number;
|
|
43
53
|
description?: string;
|
|
54
|
+
notes?: string;
|
|
44
55
|
}, options?: RequestAuthOptions): Promise<ApiResponse>;
|
|
45
56
|
getPaymentInitiation(id: string, options?: RequestAuthOptions): Promise<ApiResponse>;
|
|
46
57
|
initiateDirectDebit(data: {
|
package/dist/api/client.js
CHANGED
|
@@ -3,12 +3,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ShabaasApiClient = void 0;
|
|
6
|
+
exports.ShabaasApiClient = exports.AUTH_BEHAVIOR = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const index_js_1 = require("../config/index.js");
|
|
9
9
|
/** Cache bearer token per API key so we don't refetch every request. */
|
|
10
10
|
const tokenCache = new Map();
|
|
11
11
|
const CACHE_TTL_MS = 50 * 60 * 1000; // 50 min
|
|
12
|
+
/**
|
|
13
|
+
* Discoverable auth behavior metadata used by docs/discovery surfaces.
|
|
14
|
+
* Additive-only metadata: does not alter runtime request handling.
|
|
15
|
+
*/
|
|
16
|
+
exports.AUTH_BEHAVIOR = {
|
|
17
|
+
token_cache_ttl_ms: CACHE_TTL_MS,
|
|
18
|
+
accepts_authorization_formats: ['sbp_live_xxx', 'Bearer sbp_live_xxx'],
|
|
19
|
+
upstream_token_exchange: true,
|
|
20
|
+
cache_scope: 'per_api_key',
|
|
21
|
+
};
|
|
12
22
|
class ShabaasApiClient {
|
|
13
23
|
client;
|
|
14
24
|
config;
|
|
@@ -123,8 +133,9 @@ class ShabaasApiClient {
|
|
|
123
133
|
maximum_amount: data.maximum_amount,
|
|
124
134
|
frequency: data.frequency,
|
|
125
135
|
number_of_transactions_permitted: data.number_of_transactions_permitted,
|
|
126
|
-
pay_id: data.pay_id,
|
|
127
136
|
};
|
|
137
|
+
if (data.pay_id != null)
|
|
138
|
+
pa.pay_id = data.pay_id;
|
|
128
139
|
if (data.phone_number != null)
|
|
129
140
|
pa.phone_number = data.phone_number;
|
|
130
141
|
if (data.bsb != null)
|
|
@@ -167,7 +178,7 @@ class ShabaasApiClient {
|
|
|
167
178
|
payment_initiation: {
|
|
168
179
|
payment_agreement_id: data.payment_agreement_id,
|
|
169
180
|
amount,
|
|
170
|
-
|
|
181
|
+
notes: data.notes ?? data.description,
|
|
171
182
|
},
|
|
172
183
|
}, {
|
|
173
184
|
headers: {
|
package/dist/index.js
CHANGED
|
File without changes
|
|
@@ -18,44 +18,348 @@ const index_js_1 = require("./tools/index.js");
|
|
|
18
18
|
*/
|
|
19
19
|
async function listTools(env) {
|
|
20
20
|
const prod = env.SHABAAS_ENVIRONMENT === 'production';
|
|
21
|
+
const sharedExecution = {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
endpoint: '/tools/execute',
|
|
24
|
+
auth: {
|
|
25
|
+
required: true,
|
|
26
|
+
header: 'Authorization',
|
|
27
|
+
accepted_formats: ['sbp_live_xxx', 'Bearer sbp_live_xxx'],
|
|
28
|
+
},
|
|
29
|
+
response_contract: 'StandardResponse<T> with success, data, metadata, insights, summary',
|
|
30
|
+
output_schema: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
required: ['success', 'timestamp', 'data', 'metadata', 'insights', 'summary'],
|
|
33
|
+
additionalProperties: true,
|
|
34
|
+
properties: {
|
|
35
|
+
success: { type: 'boolean' },
|
|
36
|
+
timestamp: { type: 'string', format: 'date-time' },
|
|
37
|
+
data: { type: 'object' },
|
|
38
|
+
metadata: { type: 'object' },
|
|
39
|
+
insights: { type: 'object' },
|
|
40
|
+
summary: { type: 'string' },
|
|
41
|
+
raw: {},
|
|
42
|
+
},
|
|
43
|
+
notes: 'Set include_raw=true to include optional raw upstream response payload.',
|
|
44
|
+
},
|
|
45
|
+
error_schema: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
required: ['error', 'message'],
|
|
48
|
+
additionalProperties: true,
|
|
49
|
+
properties: {
|
|
50
|
+
error: { type: 'string' },
|
|
51
|
+
message: { type: 'string' },
|
|
52
|
+
code: { type: 'string' },
|
|
53
|
+
request_id: { type: 'string' },
|
|
54
|
+
retryable: { type: 'boolean' },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
error_model: {
|
|
58
|
+
transport_errors: [
|
|
59
|
+
{ status: 400, code: 'INVALID_REQUEST', retryable: false },
|
|
60
|
+
{ status: 401, code: 'AUTH_MISSING_OR_INVALID', retryable: true },
|
|
61
|
+
{ status: 403, code: 'TOOL_NOT_PERMITTED', retryable: false },
|
|
62
|
+
{ status: 404, code: 'RESOURCE_NOT_FOUND', retryable: false },
|
|
63
|
+
{ status: 429, code: 'RATE_LIMITED', retryable: true },
|
|
64
|
+
{ status: 500, code: 'INTERNAL_ERROR', retryable: true },
|
|
65
|
+
],
|
|
66
|
+
domain_error_shape: 'Domain-level failures may also be represented in StandardResponse as success=false with summary/raw.error_code.',
|
|
67
|
+
},
|
|
68
|
+
};
|
|
21
69
|
const toolsList = [
|
|
22
70
|
{
|
|
23
71
|
name: 'get_payment_agreement',
|
|
24
|
-
description: 'Retrieve payment agreement details
|
|
25
|
-
|
|
26
|
-
|
|
72
|
+
description: 'Retrieve payment agreement details, state transitions, and AI-facing summary guidance.',
|
|
73
|
+
...sharedExecution,
|
|
74
|
+
openapi_operation: { method: 'get', path: '/api/public/payment_agreement' },
|
|
75
|
+
output_openapi_schema_ref: '#/components/schemas/SuccessPaymentAgreementResponse',
|
|
76
|
+
required_arguments: ['payment_agreement_id'],
|
|
77
|
+
optional_arguments: ['enrich', 'include_raw'],
|
|
78
|
+
argument_hints: {
|
|
79
|
+
payment_agreement_id: 'String ID returned by create_payment_agreement, e.g. 2882PA20251227045450257',
|
|
80
|
+
enrich: 'Boolean, defaults true. Include business guidance for agent decisions.',
|
|
81
|
+
include_raw: 'Boolean, defaults false. Include raw upstream API payload for debugging only.',
|
|
82
|
+
},
|
|
83
|
+
argument_schema: {
|
|
84
|
+
payment_agreement_id: { type: 'string', pattern: '^[0-9]+PA[0-9]+$' },
|
|
85
|
+
enrich: { type: 'boolean', default: true },
|
|
86
|
+
include_raw: { type: 'boolean', default: false },
|
|
87
|
+
},
|
|
27
88
|
example: { tool: 'get_payment_agreement', arguments: { payment_agreement_id: '2882PA20251227045450257' } },
|
|
89
|
+
decision_guidance: {
|
|
90
|
+
when_to_use: 'Use when you have a payment agreement ID and need latest status/details.',
|
|
91
|
+
preconditions: ['Valid payment_agreement_id'],
|
|
92
|
+
retryable_errors: ['AUTH_MISSING_OR_INVALID'],
|
|
93
|
+
non_retryable_errors: ['RESOURCE_NOT_FOUND', 'INVALID_REQUEST'],
|
|
94
|
+
next_best_tool_on_failure: 'create_payment_agreement',
|
|
95
|
+
},
|
|
96
|
+
retry_policy: {
|
|
97
|
+
safe_to_retry: true,
|
|
98
|
+
retry_on_status: [401, 429, 500],
|
|
99
|
+
backoff: 'exponential_jitter',
|
|
100
|
+
},
|
|
101
|
+
idempotency_notes: 'Read-only operation; safe to repeat with same input.',
|
|
102
|
+
error_contract: [
|
|
103
|
+
{ status: 400, code: 'INVALID_REQUEST', when: 'Malformed JSON or missing required field' },
|
|
104
|
+
{ status: 401, code: 'AUTH_MISSING_OR_INVALID', when: 'Session/API key missing or invalid' },
|
|
105
|
+
{ status: 403, code: 'TOOL_NOT_PERMITTED', when: 'Client policy blocks tool' },
|
|
106
|
+
{ status: 404, code: 'RESOURCE_NOT_FOUND', when: 'Agreement ID not found' },
|
|
107
|
+
],
|
|
108
|
+
error_model: {
|
|
109
|
+
domain_errors: [
|
|
110
|
+
{ code: 'RESOURCE_NOT_FOUND', retryable: false, suggested_next_tool: 'create_payment_agreement' },
|
|
111
|
+
{ code: 'INVALID_REQUEST', retryable: false, suggested_next_tool: null },
|
|
112
|
+
],
|
|
113
|
+
},
|
|
28
114
|
},
|
|
29
115
|
{
|
|
30
116
|
name: 'create_payment_agreement',
|
|
31
|
-
description: 'Create a new payment agreement',
|
|
32
|
-
|
|
33
|
-
|
|
117
|
+
description: 'Create a new PayTo payment agreement for payer authorization and recurring collection.',
|
|
118
|
+
...sharedExecution,
|
|
119
|
+
openapi_operation: { method: 'post', path: '/api/public/payment_agreement' },
|
|
120
|
+
output_openapi_schema_ref: '#/components/schemas/SuccessPaymentAgreementResponse',
|
|
121
|
+
required_arguments: ['name', 'type', 'maximum_amount', 'frequency', 'number_of_transactions_permitted'],
|
|
122
|
+
optional_arguments: ['pay_id', 'phone_number', 'bsb', 'account_number', 'agreement_type', 'start_date', 'end_date', 'enrich', 'include_raw'],
|
|
123
|
+
argument_hints: {
|
|
124
|
+
type: 'Allowed identifier types: email, phone, org, abn, or bsb.',
|
|
125
|
+
pay_id: 'Required unless type=bsb.',
|
|
126
|
+
bsb: 'Required with account_number when type=bsb.',
|
|
127
|
+
account_number: 'Required with bsb when type=bsb.',
|
|
128
|
+
frequency: 'Preferred stored codes: ADHO, DAIL, FRTN, INDA, MIAN, MNTH, QURT, WEEK, YEAR. Aliases DAILY and ADHOC are accepted by upstream.',
|
|
129
|
+
maximum_amount: 'String amount in AUD, e.g. 35.00',
|
|
130
|
+
number_of_transactions_permitted: 'Positive integer, e.g. 1',
|
|
131
|
+
},
|
|
132
|
+
argument_schema: {
|
|
133
|
+
name: { type: 'string', minLength: 1 },
|
|
134
|
+
type: { type: 'string', enum: ['email', 'phone', 'org', 'abn', 'bsb'] },
|
|
135
|
+
maximum_amount: { type: 'string', pattern: '^\\d+(\\.\\d{1,2})?$' },
|
|
136
|
+
frequency: { type: 'string', enum: ['ADHO', 'DAIL', 'FRTN', 'INDA', 'MIAN', 'MNTH', 'QURT', 'WEEK', 'YEAR', 'DAILY', 'ADHOC'] },
|
|
137
|
+
number_of_transactions_permitted: { type: 'integer', minimum: 1 },
|
|
138
|
+
pay_id: { type: 'string' },
|
|
139
|
+
bsb: { type: ['string', 'number'] },
|
|
140
|
+
account_number: { type: ['string', 'number'] },
|
|
141
|
+
conditional_requirements: [
|
|
142
|
+
{ if: { type: 'bsb' }, then_required: ['bsb', 'account_number'] },
|
|
143
|
+
{ if_not: { type: 'bsb' }, then_required: ['pay_id'] },
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
example: {
|
|
147
|
+
tool: 'create_payment_agreement',
|
|
148
|
+
arguments: {
|
|
149
|
+
name: 'Gym Membership',
|
|
150
|
+
type: 'email',
|
|
151
|
+
maximum_amount: '35.00',
|
|
152
|
+
frequency: 'MNTH',
|
|
153
|
+
number_of_transactions_permitted: 1,
|
|
154
|
+
pay_id: 'payer@example.com',
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
decision_guidance: {
|
|
158
|
+
when_to_use: 'Use to create a new payer authorization mandate before initiating payments.',
|
|
159
|
+
preconditions: ['name, type, maximum_amount, frequency, number_of_transactions_permitted'],
|
|
160
|
+
retryable_errors: ['AUTH_MISSING_OR_INVALID'],
|
|
161
|
+
non_retryable_errors: ['VALIDATION_OR_BUSINESS_RULE', 'DEVELOPER_CREDITS_EXHAUSTED'],
|
|
162
|
+
next_best_tool_on_failure: 'get_payment_agreement',
|
|
163
|
+
},
|
|
164
|
+
retry_policy: {
|
|
165
|
+
safe_to_retry: false,
|
|
166
|
+
retry_on_status: [401, 429, 500],
|
|
167
|
+
backoff: 'exponential_jitter',
|
|
168
|
+
},
|
|
169
|
+
idempotency_notes: 'Creates a new agreement and is not idempotent without caller-side deduplication.',
|
|
170
|
+
error_contract: [
|
|
171
|
+
{ status: 400, code: 'INVALID_REQUEST', when: 'Missing or invalid input shape' },
|
|
172
|
+
{ status: 401, code: 'AUTH_MISSING_OR_INVALID', when: 'Session/API key missing or invalid' },
|
|
173
|
+
{ status: 402, code: 'DEVELOPER_CREDITS_EXHAUSTED', when: 'Developer credits are exhausted' },
|
|
174
|
+
{ status: 422, code: 'VALIDATION_OR_BUSINESS_RULE', when: 'Upstream validation or business rule failure' },
|
|
175
|
+
],
|
|
176
|
+
error_model: {
|
|
177
|
+
domain_errors: [
|
|
178
|
+
{ code: 'VALIDATION_OR_BUSINESS_RULE', retryable: false, suggested_next_tool: 'get_payment_agreement' },
|
|
179
|
+
{ code: 'DEVELOPER_CREDITS_EXHAUSTED', retryable: false, suggested_next_tool: null },
|
|
180
|
+
],
|
|
181
|
+
},
|
|
34
182
|
},
|
|
35
183
|
{
|
|
36
184
|
name: 'initiate_payment',
|
|
37
|
-
description: 'Initiate a payment against an agreement',
|
|
38
|
-
|
|
39
|
-
|
|
185
|
+
description: 'Initiate a debit payment against an approved payment agreement.',
|
|
186
|
+
...sharedExecution,
|
|
187
|
+
openapi_operation: { method: 'post', path: '/api/public/payment_initiation' },
|
|
188
|
+
output_openapi_schema_ref: '#/components/schemas/SuccessPaymentInitiationResponse',
|
|
189
|
+
required_arguments: ['payment_agreement_id', 'amount'],
|
|
190
|
+
optional_arguments: ['notes', 'description', 'enrich', 'include_raw'],
|
|
191
|
+
argument_hints: {
|
|
192
|
+
amount: 'Number or numeric string greater than zero, e.g. 10.00',
|
|
193
|
+
notes: 'Optional note persisted by backend for this payment initiation.',
|
|
194
|
+
description: 'Legacy alias; if notes is omitted, description is forwarded as notes.',
|
|
195
|
+
},
|
|
196
|
+
argument_schema: {
|
|
197
|
+
payment_agreement_id: { type: 'string', pattern: '^[0-9]+PA[0-9]+$' },
|
|
198
|
+
amount: { oneOf: [{ type: 'number', exclusiveMinimum: 0 }, { type: 'string', pattern: '^\\d+(\\.\\d{1,2})?$' }] },
|
|
199
|
+
notes: { type: 'string' },
|
|
200
|
+
description: { type: 'string' },
|
|
201
|
+
enrich: { type: 'boolean', default: true },
|
|
202
|
+
include_raw: { type: 'boolean', default: false },
|
|
203
|
+
},
|
|
204
|
+
example: {
|
|
205
|
+
tool: 'initiate_payment',
|
|
206
|
+
arguments: { payment_agreement_id: '2882PA20251227045450257', amount: '10.00', notes: 'Invoice 4201' },
|
|
207
|
+
},
|
|
208
|
+
decision_guidance: {
|
|
209
|
+
when_to_use: 'Use to debit an already approved payment agreement.',
|
|
210
|
+
preconditions: ['Active payment_agreement_id', 'amount > 0'],
|
|
211
|
+
retryable_errors: ['AUTH_MISSING_OR_INVALID'],
|
|
212
|
+
non_retryable_errors: ['BUSINESS_RULE_FAILURE', 'AGREEMENT_NOT_FOUND', 'INVALID_AMOUNT_OR_REQUEST'],
|
|
213
|
+
next_best_tool_on_failure: 'get_payment_agreement',
|
|
214
|
+
},
|
|
215
|
+
retry_policy: {
|
|
216
|
+
safe_to_retry: false,
|
|
217
|
+
retry_on_status: [401, 429, 500],
|
|
218
|
+
backoff: 'exponential_jitter',
|
|
219
|
+
},
|
|
220
|
+
idempotency_notes: 'Creates a payment initiation and is non-idempotent without external dedupe keys.',
|
|
221
|
+
error_contract: [
|
|
222
|
+
{ status: 400, code: 'INVALID_AMOUNT_OR_REQUEST', when: 'Amount <= 0 or invalid request body' },
|
|
223
|
+
{ status: 401, code: 'AUTH_MISSING_OR_INVALID', when: 'Session/API key missing or invalid' },
|
|
224
|
+
{ status: 404, code: 'AGREEMENT_NOT_FOUND', when: 'Agreement does not exist for merchant' },
|
|
225
|
+
{ status: 422, code: 'BUSINESS_RULE_FAILURE', when: 'Cooldown, inactive agreement, limits, or scheme rejection' },
|
|
226
|
+
],
|
|
227
|
+
error_model: {
|
|
228
|
+
domain_errors: [
|
|
229
|
+
{ code: 'BUSINESS_RULE_FAILURE', retryable: false, suggested_next_tool: 'get_payment_agreement' },
|
|
230
|
+
{ code: 'AGREEMENT_NOT_FOUND', retryable: false, suggested_next_tool: 'create_payment_agreement' },
|
|
231
|
+
{ code: 'INVALID_AMOUNT_OR_REQUEST', retryable: false, suggested_next_tool: null },
|
|
232
|
+
],
|
|
233
|
+
},
|
|
40
234
|
},
|
|
41
235
|
{
|
|
42
236
|
name: 'get_payment_initiation',
|
|
43
|
-
description: 'Retrieve payment initiation by ID',
|
|
44
|
-
|
|
45
|
-
|
|
237
|
+
description: 'Retrieve a payment initiation status by payment initiation ID.',
|
|
238
|
+
...sharedExecution,
|
|
239
|
+
openapi_operation: { method: 'get', path: '/api/public/payment_initiation' },
|
|
240
|
+
output_openapi_schema_ref: '#/components/schemas/SuccessPaymentInitiationResponse',
|
|
241
|
+
required_arguments: ['payment_initiation_id'],
|
|
242
|
+
optional_arguments: ['enrich', 'include_raw'],
|
|
243
|
+
argument_hints: {
|
|
244
|
+
payment_initiation_id: 'String ID returned by initiate_payment, e.g. 2724PI20250101010101001',
|
|
245
|
+
},
|
|
246
|
+
argument_schema: {
|
|
247
|
+
payment_initiation_id: { type: 'string', pattern: '^[0-9]+PI[0-9]+$' },
|
|
248
|
+
enrich: { type: 'boolean', default: true },
|
|
249
|
+
include_raw: { type: 'boolean', default: false },
|
|
250
|
+
},
|
|
251
|
+
example: { tool: 'get_payment_initiation', arguments: { payment_initiation_id: '2724PI20250101010101001' } },
|
|
252
|
+
decision_guidance: {
|
|
253
|
+
when_to_use: 'Use when you need the latest status of an initiated payment.',
|
|
254
|
+
preconditions: ['Valid payment_initiation_id'],
|
|
255
|
+
retryable_errors: ['AUTH_MISSING_OR_INVALID'],
|
|
256
|
+
non_retryable_errors: ['RESOURCE_NOT_FOUND', 'INVALID_REQUEST'],
|
|
257
|
+
next_best_tool_on_failure: 'initiate_payment',
|
|
258
|
+
},
|
|
259
|
+
retry_policy: {
|
|
260
|
+
safe_to_retry: true,
|
|
261
|
+
retry_on_status: [401, 429, 500],
|
|
262
|
+
backoff: 'exponential_jitter',
|
|
263
|
+
},
|
|
264
|
+
idempotency_notes: 'Read-only operation; safe to repeat with same input.',
|
|
265
|
+
error_contract: [
|
|
266
|
+
{ status: 400, code: 'INVALID_REQUEST', when: 'Missing required field' },
|
|
267
|
+
{ status: 401, code: 'AUTH_MISSING_OR_INVALID', when: 'Session/API key missing or invalid' },
|
|
268
|
+
{ status: 404, code: 'RESOURCE_NOT_FOUND', when: 'Initiation ID not found' },
|
|
269
|
+
],
|
|
270
|
+
error_model: {
|
|
271
|
+
domain_errors: [
|
|
272
|
+
{ code: 'RESOURCE_NOT_FOUND', retryable: false, suggested_next_tool: 'initiate_payment' },
|
|
273
|
+
{ code: 'INVALID_REQUEST', retryable: false, suggested_next_tool: null },
|
|
274
|
+
],
|
|
275
|
+
},
|
|
46
276
|
},
|
|
47
277
|
];
|
|
48
278
|
if (!prod) {
|
|
49
279
|
toolsList.push({
|
|
50
280
|
name: 'get_auth_token',
|
|
51
|
-
description: '
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
281
|
+
description: 'Exchange an API key for a backend bearer token (debug/non-production helper).',
|
|
282
|
+
...sharedExecution,
|
|
283
|
+
openapi_operation: { method: 'post', path: '/api/public/authorization' },
|
|
284
|
+
output_openapi_schema_ref: '#/components/schemas/SuccessAuthorizationResponse',
|
|
285
|
+
required_arguments: [],
|
|
286
|
+
optional_arguments: ['include_token_in_response'],
|
|
287
|
+
argument_hints: {
|
|
288
|
+
include_token_in_response: 'Boolean, defaults false. Keep false for normal agent usage.',
|
|
289
|
+
},
|
|
290
|
+
argument_schema: {
|
|
291
|
+
include_token_in_response: { type: 'boolean', default: false },
|
|
292
|
+
},
|
|
293
|
+
auth_note: 'Uses MCP session auth (OAuth/Authorization header) by default. Stdio clients may provide authorization in tool args when needed.',
|
|
294
|
+
example: { tool: 'get_auth_token', arguments: { include_token_in_response: false } },
|
|
295
|
+
decision_guidance: {
|
|
296
|
+
when_to_use: 'Use only for non-production debugging of auth flow.',
|
|
297
|
+
preconditions: ['Non-production environment'],
|
|
298
|
+
retryable_errors: ['AUTH_MISSING_OR_INVALID'],
|
|
299
|
+
non_retryable_errors: ['TOOL_NOT_PERMITTED_IN_PRODUCTION'],
|
|
300
|
+
next_best_tool_on_failure: 'create_payment_agreement',
|
|
301
|
+
},
|
|
302
|
+
retry_policy: {
|
|
303
|
+
safe_to_retry: true,
|
|
304
|
+
retry_on_status: [401, 429, 500],
|
|
305
|
+
backoff: 'exponential_jitter',
|
|
306
|
+
},
|
|
307
|
+
idempotency_notes: 'Returns current auth state; safe to repeat in non-production.',
|
|
308
|
+
error_contract: [
|
|
309
|
+
{ status: 401, code: 'AUTH_MISSING_OR_INVALID', when: 'Session/API key missing or invalid' },
|
|
310
|
+
{ status: 403, code: 'TOOL_NOT_PERMITTED_IN_PRODUCTION', when: 'Tool disabled in production' },
|
|
311
|
+
],
|
|
312
|
+
error_model: {
|
|
313
|
+
domain_errors: [
|
|
314
|
+
{ code: 'TOOL_NOT_PERMITTED_IN_PRODUCTION', retryable: false, suggested_next_tool: 'create_payment_agreement' },
|
|
315
|
+
],
|
|
316
|
+
},
|
|
55
317
|
});
|
|
56
318
|
}
|
|
57
319
|
const res = (0, utils_js_1.jsonResponse)({
|
|
58
320
|
tools: toolsList,
|
|
321
|
+
metadata: {
|
|
322
|
+
discovery_schema_version: '2026-04-15',
|
|
323
|
+
compatibility: {
|
|
324
|
+
policy: 'backward-compatible additive fields only for discovery metadata',
|
|
325
|
+
deprecation_window_days: 90,
|
|
326
|
+
},
|
|
327
|
+
official_openapi: {
|
|
328
|
+
mcp: 'https://raw.githubusercontent.com/shabaaspay/shabaas-ai/main/openapi/openapi.yaml',
|
|
329
|
+
repository: 'https://github.com/shabaaspay/shabaas-ai',
|
|
330
|
+
},
|
|
331
|
+
auth_behavior: {
|
|
332
|
+
entry_header: 'Authorization',
|
|
333
|
+
accepted_formats: ['sbp_live_xxx', 'Bearer sbp_live_xxx'],
|
|
334
|
+
token_cache_ttl_ms: 3000000,
|
|
335
|
+
cache_scope: 'per_api_key',
|
|
336
|
+
upstream_token_exchange: true,
|
|
337
|
+
},
|
|
338
|
+
error_taxonomy: {
|
|
339
|
+
canonical_error_codes: [
|
|
340
|
+
'AUTH_MISSING_OR_INVALID',
|
|
341
|
+
'TOOL_NOT_PERMITTED',
|
|
342
|
+
'TOOL_NOT_PERMITTED_IN_PRODUCTION',
|
|
343
|
+
'INVALID_REQUEST',
|
|
344
|
+
'INVALID_AMOUNT_OR_REQUEST',
|
|
345
|
+
'RESOURCE_NOT_FOUND',
|
|
346
|
+
'AGREEMENT_NOT_FOUND',
|
|
347
|
+
'DEVELOPER_CREDITS_EXHAUSTED',
|
|
348
|
+
'VALIDATION_OR_BUSINESS_RULE',
|
|
349
|
+
'BUSINESS_RULE_FAILURE',
|
|
350
|
+
],
|
|
351
|
+
transport_errors: [
|
|
352
|
+
{ status: 400, reason: 'Invalid JSON or missing tool name' },
|
|
353
|
+
{ status: 401, reason: 'Missing/invalid API key in Authorization header' },
|
|
354
|
+
{ status: 403, reason: 'Tool blocked by client policy' },
|
|
355
|
+
{ status: 404, reason: 'Unknown tool name' },
|
|
356
|
+
{ status: 429, reason: 'Rate limit exceeded' },
|
|
357
|
+
{ status: 500, reason: 'Unhandled server error' },
|
|
358
|
+
],
|
|
359
|
+
domain_error_codes_reference: 'https://raw.githubusercontent.com/shabaaspay/shabaas-ai/main/openapi/openapi.yaml',
|
|
360
|
+
note: 'Domain-level failures are returned in StandardResponse summary/raw fields and may include upstream error_code values from ShaBaas APIs.',
|
|
361
|
+
},
|
|
362
|
+
},
|
|
59
363
|
direct_api_access: {
|
|
60
364
|
description: 'You can also call ShaBaas API directly through this proxy',
|
|
61
365
|
base_url: '/api',
|