@sassoftware/sas-score-mcp-serverjs 0.3.19 → 0.3.29-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/cli.js +23 -24
- package/openApi.yaml +121 -121
- package/package.json +2 -2
- package/src/createMcpServer.js +2 -1
- package/src/expressMcpServer.js +68 -28
- package/src/handleGetDelete.js +6 -3
- package/src/hapiMcpServer.js +30 -0
- package/src/openAPIJson.js +175 -175
- package/src/openApi.yaml +121 -121
- package/src/toolHelpers/getLogonPayload.js +9 -7
- package/src/toolHelpers/getStoreOpts.js +1 -2
- package/src/toolHelpers/getToken.js +0 -1
- package/src/toolHelpers/refreshToken.js +48 -46
- package/src/toolHelpers/refreshTokenOauth.js +2 -2
- package/src/toolHelpers/tlogon.js +9 -0
- package/src/toolSet/devaScore.js +10 -5
- package/src/toolHelpers/getOpts.js +0 -51
- package/src/toolHelpers/getOptsViya.js +0 -44
|
@@ -1,49 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let {host, token} = params;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { Agent, fetch } from 'undici';
|
|
6
|
+
|
|
7
|
+
async function refreshToken(_appContext, params) {
|
|
8
|
+
let { host, token } = params;
|
|
9
|
+
let url = `${host}/SASLogon/oauth/token`;
|
|
10
|
+
|
|
11
|
+
let aconnect = {
|
|
12
|
+
ca: _appContext.contexts.viyaCert.ca, // trust this CA
|
|
13
|
+
rejectUnauthorized: false // or false, if you really want to bypass checks
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const agent = new Agent(aconnect);
|
|
17
|
+
|
|
18
|
+
console.error('[Info] Refreshing token...', token);
|
|
19
|
+
const ibody = {
|
|
20
|
+
grant_type: 'refresh_token',
|
|
21
|
+
refresh_token: token,
|
|
22
|
+
client_id: 'sas.cli'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
let body = new URLSearchParams(ibody);
|
|
26
|
+
try {
|
|
27
|
+
const response = await fetch(url, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: {
|
|
30
|
+
'Accept': 'application/json',
|
|
31
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
32
|
+
dispatcher: agent
|
|
33
|
+
},
|
|
34
|
+
body: body.toString()
|
|
21
35
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'Accept': 'application/json',
|
|
28
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
29
|
-
dispatcher: agent
|
|
30
|
-
},
|
|
31
|
-
body: body.toString()
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
if (!response.ok) {
|
|
35
|
-
const error = await response.text();
|
|
36
|
-
console.error('[Error] Failed to refresh token: ', error);
|
|
37
|
-
throw new Error(error);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const data = await response.json();
|
|
41
|
-
console.error('[Info] Token refreshed successfully: ', data.access_token);
|
|
42
|
-
return data.access_token;
|
|
43
|
-
} catch (err) {
|
|
44
|
-
console.error('[Error] Failed to refresh token: ', err);
|
|
45
|
-
throw err;
|
|
36
|
+
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const error = await response.text();
|
|
39
|
+
console.error('[Error] Failed to refresh token: ', error);
|
|
40
|
+
throw new Error(error);
|
|
46
41
|
}
|
|
42
|
+
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
return data.access_token;
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error('[Error] Failed to refresh token: ', err);
|
|
47
|
+
throw err;
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default refreshToken;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { Agent, fetch } from 'undici';
|
|
6
|
-
import getOpts from './getOpts.js';
|
|
6
|
+
//import getOpts from './getOpts.js';
|
|
7
7
|
async function refreshTokenOauth(_appContext, oauthInfo ){
|
|
8
8
|
|
|
9
9
|
const url = `${process.env.VIYA_SERVER}/SASLogon/oauth/token`;
|
|
10
|
-
let opts =
|
|
10
|
+
let opts = _appContext.contexts.appCert;
|
|
11
11
|
|
|
12
12
|
const agent = new Agent({
|
|
13
13
|
connect: opts
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import getLogonPayload from "./getLogonPayload.js";
|
|
2
|
+
|
|
3
|
+
async function tlogon(_appContext) {
|
|
4
|
+
console.error('[Info] Starting tlogon...');
|
|
5
|
+
let r = await getLogonPayload(_appContext);
|
|
6
|
+
console.error('[Info] tlogon completed');
|
|
7
|
+
return r;
|
|
8
|
+
}
|
|
9
|
+
export default tlogon;
|
package/src/toolSet/devaScore.js
CHANGED
|
@@ -38,7 +38,7 @@ Disambiguation & Clarification
|
|
|
38
38
|
Examples (→ mapped params)
|
|
39
39
|
- "Calculate deva score for 5 and 10" → { a: 5, b: 10 } returns 630
|
|
40
40
|
- "Score 1 and 2" → { a: 1, b: 2 } returns 126
|
|
41
|
-
- For multiple numbers, chain calls:
|
|
41
|
+
- For multiple numbers, chain calls: devaScore(1,2)→126, then devaScore(126,3)→5418
|
|
42
42
|
|
|
43
43
|
Negative Examples (should NOT call deva-score)
|
|
44
44
|
- "Score this customer with the credit model" (use model-score instead)
|
|
@@ -58,12 +58,17 @@ For sequences of numbers, use a left-to-right fold: call devaScore(first, second
|
|
|
58
58
|
a: z.number(),
|
|
59
59
|
b: z.number()
|
|
60
60
|
},
|
|
61
|
-
handler: async ({ a, b
|
|
61
|
+
handler: async ({ a, b }) => {
|
|
62
62
|
console.error( a, b);
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
let r = {score: (a + b) * 42};
|
|
64
|
+
console.error('deva score result', r);
|
|
65
|
+
return {
|
|
66
|
+
content: [{type: 'text', text: 'deva score result: ' + JSON.stringify(r)}],
|
|
67
|
+
structuredContent: r
|
|
68
|
+
};
|
|
69
|
+
}
|
|
65
70
|
}
|
|
66
|
-
|
|
71
|
+
|
|
67
72
|
return spec;
|
|
68
73
|
}
|
|
69
74
|
export default devaScore;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Helper function to get TLS options(for the app server) from specified directory
|
|
7
|
-
* signed certificates
|
|
8
|
-
* for testing you can use mkcert
|
|
9
|
-
* if this function return a null, coreehttp will create unsigned certs
|
|
10
|
-
* @param {Object} _appContext - Application context containing SSLCERT property
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import readCerts from './readCerts.js';
|
|
14
|
-
function getOpts(_appContext) {
|
|
15
|
-
|
|
16
|
-
if (_appContext.tlsOpts != null) {
|
|
17
|
-
return _appContext.tlsOpts;
|
|
18
|
-
}
|
|
19
|
-
let r = readCerts(_appContext.SSLCERT);
|
|
20
|
-
_appContext.tlsOpts = r;
|
|
21
|
-
return r;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/*
|
|
25
|
-
let tlsdir = _appContext.SSLCERT;
|
|
26
|
-
if (tlsdir == null || tlsdir === 'NONE') {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
console.error("[Note] Using TLS dir: " + tlsdir);
|
|
31
|
-
if (fs.existsSync(tlsdir) === false) {
|
|
32
|
-
console.error("[Warning] Specified TLS dir does not exist: " + tlsdir);
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let listOfFiles = fs.readdirSync(tlsdir);
|
|
37
|
-
console.error("[Note] TLS/SSL files found: " + listOfFiles);
|
|
38
|
-
let options = {};
|
|
39
|
-
for(let i=0; i < listOfFiles.length; i++) {
|
|
40
|
-
let fname = listOfFiles[i];
|
|
41
|
-
let name = tlsdir + '/' + listOfFiles[i];
|
|
42
|
-
let key = fname.split('.')[0];
|
|
43
|
-
options[key] = fs.readFileSync(name, { encoding: 'utf8' });
|
|
44
|
-
}
|
|
45
|
-
console.error('TLS FILES', Object.keys(options));
|
|
46
|
-
_appContext.tlsOpts = options;
|
|
47
|
-
return options;
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
export default getOpts;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import readCerts from './readCerts.js';
|
|
6
|
-
function getOptsViya(_appContext) {
|
|
7
|
-
|
|
8
|
-
if (_appContext.contexts.viyaCert != null) {
|
|
9
|
-
console.error('[Note] Using cached viyaOpts');
|
|
10
|
-
return _appContext.contexts.viyaCert;
|
|
11
|
-
}
|
|
12
|
-
let r = readCerts(_appContext.VIYACERT);
|
|
13
|
-
_appContext.contexts.viyaCert = r;
|
|
14
|
-
return r;
|
|
15
|
-
|
|
16
|
-
/*
|
|
17
|
-
let tlsdir = _appContext.VIYACERT;
|
|
18
|
-
if (tlsdir == null || tlsdir === 'NONE') {
|
|
19
|
-
return {};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
console.error(`[Note] Using VIYACERT dir: ` + tlsdir);
|
|
23
|
-
if (fs.existsSync(tlsdir) === false) {
|
|
24
|
-
console.error("[Warning] Specified VIYACERT dir does not exist: " + tlsdir);
|
|
25
|
-
return {};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let listOfFiles = fs.readdirSync(tlsdir);
|
|
29
|
-
console.error("[Note] TLS/SSL files found: " + listOfFiles);
|
|
30
|
-
let options = {};
|
|
31
|
-
for(let i=0; i < listOfFiles.length; i++) {
|
|
32
|
-
let fname = listOfFiles[i];
|
|
33
|
-
let name = tlsdir + '/' + listOfFiles[i];
|
|
34
|
-
let key = fname.split('.')[0];
|
|
35
|
-
console.error('Reading TLS file: ' + name + ' as key: ' + key);
|
|
36
|
-
options[key] = fs.readFileSync(name, { encoding: 'utf8' });
|
|
37
|
-
}
|
|
38
|
-
console.error('VIYACERT FILES', Object.keys(options));
|
|
39
|
-
_appContext.contexts.viyaCert = options;
|
|
40
|
-
return options;
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
export default getOptsViya;
|