paygate-mcp 10.2.0 → 10.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -1
- package/dist/cli-completions.d.ts +10 -0
- package/dist/cli-completions.d.ts.map +1 -0
- package/dist/cli-completions.js +248 -0
- package/dist/cli-completions.js.map +1 -0
- package/dist/cli-init.d.ts +8 -0
- package/dist/cli-init.d.ts.map +1 -0
- package/dist/cli-init.js +201 -0
- package/dist/cli-init.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +47 -3
- package/dist/cli.js.map +1 -1
- package/dist/dynamic-discovery.d.ts +48 -0
- package/dist/dynamic-discovery.d.ts.map +1 -0
- package/dist/dynamic-discovery.js +176 -0
- package/dist/dynamic-discovery.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +127 -0
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -126,6 +126,7 @@ const config_profiles_1 = require("./config-profiles");
|
|
|
126
126
|
const scheduled_reports_1 = require("./scheduled-reports");
|
|
127
127
|
const approval_workflows_1 = require("./approval-workflows");
|
|
128
128
|
const gateway_hooks_1 = require("./gateway-hooks");
|
|
129
|
+
const dynamic_discovery_1 = require("./dynamic-discovery");
|
|
129
130
|
/** Max request body size: 1MB */
|
|
130
131
|
const MAX_BODY_SIZE = 1_048_576;
|
|
131
132
|
/**
|
|
@@ -495,6 +496,8 @@ class PayGateServer {
|
|
|
495
496
|
scheduledReports;
|
|
496
497
|
approvalWorkflows;
|
|
497
498
|
gatewayHooks;
|
|
499
|
+
/** Cached backend tool list for dynamic discovery mode. */
|
|
500
|
+
cachedBackendTools = null;
|
|
498
501
|
/** The active request handler — either proxy or router */
|
|
499
502
|
get handler() {
|
|
500
503
|
return (this.router || this.proxy);
|
|
@@ -1996,6 +1999,130 @@ class PayGateServer {
|
|
|
1996
1999
|
}
|
|
1997
2000
|
return;
|
|
1998
2001
|
}
|
|
2002
|
+
// ─── Dynamic Discovery Mode ──────────────────────────────────────────────
|
|
2003
|
+
// When discoveryMode === 'dynamic', intercept tools/list and meta-tool calls.
|
|
2004
|
+
if (this.config.discoveryMode === 'dynamic') {
|
|
2005
|
+
// Intercept tools/list → return meta-tools instead of backend tools
|
|
2006
|
+
if (request.method === 'tools/list') {
|
|
2007
|
+
// Cache backend tools on first tools/list (lazy initialization)
|
|
2008
|
+
if (!this.cachedBackendTools) {
|
|
2009
|
+
try {
|
|
2010
|
+
const backendResponse = await this.handler.handleRequest(request, apiKey, clientIp, scopedTokenTools, countryCode);
|
|
2011
|
+
const backendResult = backendResponse.result;
|
|
2012
|
+
this.cachedBackendTools = (backendResult?.tools || []).map(t => ({
|
|
2013
|
+
name: t.name,
|
|
2014
|
+
description: t.description,
|
|
2015
|
+
inputSchema: t.inputSchema,
|
|
2016
|
+
}));
|
|
2017
|
+
}
|
|
2018
|
+
catch {
|
|
2019
|
+
this.cachedBackendTools = [];
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
const metaTools = (0, dynamic_discovery_1.getMetaTools)();
|
|
2023
|
+
const rateLimitHeaders = this.buildRateLimitHeaders(apiKey, request);
|
|
2024
|
+
const accept = req.headers['accept'] || '';
|
|
2025
|
+
const wantsSse = accept.includes('text/event-stream');
|
|
2026
|
+
const metaResponse = {
|
|
2027
|
+
jsonrpc: '2.0',
|
|
2028
|
+
id: request.id,
|
|
2029
|
+
result: { tools: metaTools },
|
|
2030
|
+
};
|
|
2031
|
+
if (wantsSse) {
|
|
2032
|
+
(0, session_1.writeSseHeaders)(res, { 'Mcp-Session-Id': sessionId, ...rateLimitHeaders });
|
|
2033
|
+
(0, session_1.writeSseEvent)(res, metaResponse, 'message');
|
|
2034
|
+
res.end();
|
|
2035
|
+
}
|
|
2036
|
+
else {
|
|
2037
|
+
res.writeHead(200, {
|
|
2038
|
+
'Content-Type': 'application/json',
|
|
2039
|
+
'Mcp-Session-Id': sessionId,
|
|
2040
|
+
...rateLimitHeaders,
|
|
2041
|
+
});
|
|
2042
|
+
res.end(JSON.stringify(metaResponse));
|
|
2043
|
+
}
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
// Intercept tools/call for meta-tools
|
|
2047
|
+
if (request.method === 'tools/call') {
|
|
2048
|
+
const metaToolName = request.params?.name || '';
|
|
2049
|
+
if (metaToolName === 'paygate_call_tool') {
|
|
2050
|
+
// Unwrap paygate_call_tool → rewrite as a regular tools/call
|
|
2051
|
+
const metaArgs = request.params?.arguments || {};
|
|
2052
|
+
const realToolName = String(metaArgs.name || '');
|
|
2053
|
+
const realArgs = metaArgs.arguments || {};
|
|
2054
|
+
if (!realToolName) {
|
|
2055
|
+
const rateLimitHeaders = this.buildRateLimitHeaders(apiKey, request);
|
|
2056
|
+
const accept = req.headers['accept'] || '';
|
|
2057
|
+
const wantsSse = accept.includes('text/event-stream');
|
|
2058
|
+
const errResp = {
|
|
2059
|
+
jsonrpc: '2.0',
|
|
2060
|
+
id: request.id,
|
|
2061
|
+
error: { code: -32602, message: 'paygate_call_tool requires "name" argument' },
|
|
2062
|
+
};
|
|
2063
|
+
if (wantsSse) {
|
|
2064
|
+
(0, session_1.writeSseHeaders)(res, { 'Mcp-Session-Id': sessionId, ...rateLimitHeaders });
|
|
2065
|
+
(0, session_1.writeSseEvent)(res, errResp, 'message');
|
|
2066
|
+
res.end();
|
|
2067
|
+
}
|
|
2068
|
+
else {
|
|
2069
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Mcp-Session-Id': sessionId, ...rateLimitHeaders });
|
|
2070
|
+
res.end(JSON.stringify(errResp));
|
|
2071
|
+
}
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
// Rewrite the request to call the real tool
|
|
2075
|
+
request = {
|
|
2076
|
+
...request,
|
|
2077
|
+
params: { name: realToolName, arguments: realArgs },
|
|
2078
|
+
};
|
|
2079
|
+
}
|
|
2080
|
+
else if (metaToolName === 'paygate_list_tools' || metaToolName === 'paygate_search_tools') {
|
|
2081
|
+
// Handle list/search meta-tools locally (no credits charged, no gating)
|
|
2082
|
+
if (!this.cachedBackendTools) {
|
|
2083
|
+
try {
|
|
2084
|
+
const listReq = { jsonrpc: '2.0', id: 'discovery-init', method: 'tools/list', params: {} };
|
|
2085
|
+
const backendResponse = await this.handler.handleRequest(listReq, null, clientIp);
|
|
2086
|
+
const backendResult = backendResponse.result;
|
|
2087
|
+
this.cachedBackendTools = (backendResult?.tools || []).map(t => ({
|
|
2088
|
+
name: t.name,
|
|
2089
|
+
description: t.description,
|
|
2090
|
+
inputSchema: t.inputSchema,
|
|
2091
|
+
}));
|
|
2092
|
+
}
|
|
2093
|
+
catch {
|
|
2094
|
+
this.cachedBackendTools = [];
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
const metaArgs = request.params?.arguments || {};
|
|
2098
|
+
const discoveryConfig = {
|
|
2099
|
+
defaultCreditsPerCall: this.config.defaultCreditsPerCall,
|
|
2100
|
+
toolPricing: this.config.toolPricing,
|
|
2101
|
+
globalRateLimitPerMin: this.config.globalRateLimitPerMin,
|
|
2102
|
+
};
|
|
2103
|
+
const metaResult = (0, dynamic_discovery_1.handleMetaToolCall)(metaToolName, metaArgs, this.cachedBackendTools, discoveryConfig);
|
|
2104
|
+
const rateLimitHeaders = this.buildRateLimitHeaders(apiKey, request);
|
|
2105
|
+
const accept = req.headers['accept'] || '';
|
|
2106
|
+
const wantsSse = accept.includes('text/event-stream');
|
|
2107
|
+
const metaResponse = {
|
|
2108
|
+
jsonrpc: '2.0',
|
|
2109
|
+
id: request.id,
|
|
2110
|
+
result: metaResult || { content: [{ type: 'text', text: '{}' }] },
|
|
2111
|
+
};
|
|
2112
|
+
if (wantsSse) {
|
|
2113
|
+
(0, session_1.writeSseHeaders)(res, { 'Mcp-Session-Id': sessionId, ...rateLimitHeaders });
|
|
2114
|
+
(0, session_1.writeSseEvent)(res, metaResponse, 'message');
|
|
2115
|
+
res.end();
|
|
2116
|
+
}
|
|
2117
|
+
else {
|
|
2118
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Mcp-Session-Id': sessionId, ...rateLimitHeaders });
|
|
2119
|
+
res.end(JSON.stringify(metaResponse));
|
|
2120
|
+
}
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
// If not a meta-tool, fall through to normal tools/call handling
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
1999
2126
|
// Plugin: beforeToolCall — let plugins modify the request before forwarding
|
|
2000
2127
|
let pluginRequest = request;
|
|
2001
2128
|
if (this.plugins.count > 0 && request.method === 'tools/call') {
|