@sassoftware/sas-score-mcp-serverjs 0.2.1-0 → 0.2.2
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/.env +14 -23
- package/.envx +13 -0
- package/README.md +34 -23
- package/cli.js +11 -4
- package/devTest/code/.env +12 -0
- package/devTest/code/http.mcp.json +8 -0
- package/devTest/http/.env +13 -0
- package/devTest/http/http.mcp.json +8 -0
- package/devTest/stdio/.env +9 -0
- package/{mcpConfigurations/stdio.json → devTest/stdio/stdio.mcp.json} +7 -5
- package/package.json +3 -3
- package/scripts/viyatls.sh +3 -0
- package/src/expressMcpServer.js +1 -1
- package/src/hapiMcpServer.js +10 -5
- package/src/toolHelpers/getToken.js +5 -5
- package/src/urlOpen.js +9 -8
- /package/{mcpConfigurations → devTest}/README.md +0 -0
- /package/{mcpConfigurations → devTest}/http.json +0 -0
- /package/{mcpConfigurations → devTest}/stdiodev.json +0 -0
package/.env
CHANGED
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SAS_CLI_PROFILE=00m
|
|
16
|
-
SAS_CLI_CONFIG=c:\Users\kumar
|
|
17
|
-
SSLCERT=c:\Users\kumar\.tls
|
|
18
|
-
VIYACERT=c:\Users\kumar\viyaCert
|
|
19
|
-
CAS_SERVER=cas-shared-default
|
|
20
|
-
COMPUTECONTEXT=SAS Job Execution compute context
|
|
21
|
-
SAMESITE=Lax,false
|
|
22
|
-
AUTOSTART=TRUE
|
|
23
|
-
|
|
1
|
+
PORT=8080
|
|
2
|
+
HTTPS=TRUE
|
|
3
|
+
MCPTYPE=http
|
|
4
|
+
AUTHFLOW=sascli
|
|
5
|
+
CLIENTID=mcpserver
|
|
6
|
+
CLIENTSECRET=jellico
|
|
7
|
+
# VIYA_SERVER= set globally
|
|
8
|
+
SSLCERT=c:\Users\kumar\.tls
|
|
9
|
+
VIYACERT=c:\Users\kumar\viyaCert\xf1
|
|
10
|
+
CAS_SERVER=cas-shared-default
|
|
11
|
+
# APPNAME defaults to sas-score-mcp-serverjs but you can override it here
|
|
12
|
+
APPNAME=mcpserver
|
|
13
|
+
COMPUTECONTEXT=SAS Job Execution compute context
|
|
14
|
+
SAMESITE=Lax,secure
|
package/.envx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
PORT=8080
|
|
3
|
+
HTTPS=FALSE
|
|
4
|
+
MCPTYPE=http
|
|
5
|
+
|
|
6
|
+
AUTHFLOW=sascli
|
|
7
|
+
SAS_CLI_PROFILE=xf1
|
|
8
|
+
SAS_CLI_CONFIG=c:\Users\kumar
|
|
9
|
+
SSLCERT=c:\Users\kumar\.tls
|
|
10
|
+
VIYACERT=c:\Users\kumar\viyaCert\xf1\viya
|
|
11
|
+
CAS_SERVER=cas-shared-default
|
|
12
|
+
COMPUTECONTEXT=SAS Job Execution compute context
|
|
13
|
+
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ See this [quick reference](sas-mcp-tools-reference.md) for details.
|
|
|
25
25
|
SAS developers who want to extend the capabilities of the server with their own tools. See the [guide](tool-developer-guide.md) for details.
|
|
26
26
|
|
|
27
27
|
## Configuration Variables
|
|
28
|
-
Typically these are set either in the .env file or as environment variables (or both). This is full list of the configuration variables used the mcp server.
|
|
28
|
+
Typically these are set either in the .env file or as environment variables (or both). This is full list of the configuration variables used the mcp server. You will need only a subset of these for the different [transport,authentication] schemes
|
|
29
29
|
|
|
30
30
|
```env
|
|
31
31
|
|
|
@@ -33,7 +33,7 @@ Typically these are set either in the .env file or as environment variables (or
|
|
|
33
33
|
# http is useful for remote mcp servers
|
|
34
34
|
# If running locally, recommend stdio
|
|
35
35
|
|
|
36
|
-
MCPTYPE
|
|
36
|
+
MCPTYPE=<stdio|http>
|
|
37
37
|
|
|
38
38
|
# Port for http transport(default is 8080)
|
|
39
39
|
|
|
@@ -42,8 +42,7 @@ PORT=8080
|
|
|
42
42
|
# If transport is http, optionally specify if the server
|
|
43
43
|
# is using http or https
|
|
44
44
|
|
|
45
|
-
HTTPS=FALSE
|
|
46
|
-
|
|
45
|
+
HTTPS=TRUE|FALSE
|
|
47
46
|
|
|
48
47
|
# Viya Authentication
|
|
49
48
|
# The mcp server support different ways to authenticate(see section on Authentication)
|
|
@@ -51,9 +50,10 @@ HTTPS=FALSE
|
|
|
51
50
|
# * sascli * will look for tokens created with sas-viya cli
|
|
52
51
|
# * token * a custom token
|
|
53
52
|
# * password * userid/password
|
|
54
|
-
# *
|
|
53
|
+
# * code * Oauth using authorization_code flow(pkce not supported in this release)
|
|
54
|
+
|
|
55
|
+
AUTHFLOW=sascli|token|password|code
|
|
55
56
|
|
|
56
|
-
AUTHFLOW=sascli
|
|
57
57
|
SAS_CLI_CONFIG=your-home-directory
|
|
58
58
|
SAS_CLI_PROFILE=your-sas-cli-profile
|
|
59
59
|
|
|
@@ -64,9 +64,11 @@ VIYA_SERVER= your Viya server url
|
|
|
64
64
|
# if AUTHFLOW=token, specify the file with the token
|
|
65
65
|
TOKENFILE=
|
|
66
66
|
|
|
67
|
-
# if password flow specify these
|
|
67
|
+
# if password flow or oauth flow specify these
|
|
68
68
|
CLIENTID=
|
|
69
69
|
CLIENTSECRET=
|
|
70
|
+
|
|
71
|
+
# specify this if password AUTHFLOW
|
|
70
72
|
PASSWORD=
|
|
71
73
|
|
|
72
74
|
# When HTTPS is TRUE, specify the folder with SSL certificates for the mcp server
|
|
@@ -132,43 +134,44 @@ If this is your use case, set the TOKENFILE to a file containing this token.
|
|
|
132
134
|
|
|
133
135
|
### Oauth - (experimental) Authentication handled by the mcp server
|
|
134
136
|
|
|
135
|
-
In this approach, the mcp client does not participate in the Oauth authentication process. It is handled by the mcp server at startup.
|
|
137
|
+
In this approach, the mcp client does not participate in the Oauth authentication process. It is handled by the mcp server at startup.
|
|
136
138
|
|
|
137
|
-
> This is marked as experimental since
|
|
139
|
+
> This is marked as experimental since the testing is not complete
|
|
138
140
|
|
|
139
141
|
#### SAS viya setup.
|
|
140
142
|
|
|
141
|
-
Create a Oauth client
|
|
143
|
+
Create a Oauth client with the following properties
|
|
142
144
|
|
|
143
145
|
```js
|
|
144
146
|
{
|
|
145
|
-
auth flow: authorization_code
|
|
147
|
+
auth flow: authorization_code|password
|
|
146
148
|
clientid: <your client id>
|
|
147
149
|
clientsecret: <some client secret - pkce not supported at this time>
|
|
148
|
-
redirect: https://localhost:8080/mcpserver
|
|
150
|
+
redirect: https://localhost:8080/mcpserver
|
|
149
151
|
}
|
|
150
152
|
|
|
151
153
|
#### Use an .env file as follows(sample values shown)
|
|
152
154
|
|
|
153
155
|
```env
|
|
156
|
+
PORT=8080
|
|
157
|
+
AUTHFLOW=code
|
|
158
|
+
SSLCERT=c:\Users\kumar\.tls
|
|
159
|
+
VIYACERT=c:\Users\kumar\viyaCert
|
|
160
|
+
CAS_SERVER=cas-shared-default
|
|
161
|
+
COMPUTECONTEXT=SAS Job Execution compute context
|
|
154
162
|
|
|
155
163
|
PORT=8080
|
|
156
164
|
HTTPS=true
|
|
157
165
|
MCPTYPE=http
|
|
158
166
|
USELOGON=FALSE
|
|
159
167
|
USETOKEN=TRUE
|
|
160
|
-
APPNAME=
|
|
161
|
-
APPHOST=localhost
|
|
162
|
-
APPPORT=8080
|
|
168
|
+
APPNAME=sas-score-mcp-serverjs
|
|
163
169
|
|
|
164
170
|
CLIENTID=mcpserver
|
|
165
|
-
CLIENTSECRET=
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
CAS_SERVER=cas-shared-default
|
|
170
|
-
COMPUTECONTEXT=SAS Job Execution compute context
|
|
171
|
-
SAMESITE=Lax,false
|
|
171
|
+
CLIENTSECRET=xxxxxx
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# SAMESITE=Lax,secure
|
|
172
175
|
|
|
173
176
|
```
|
|
174
177
|
|
|
@@ -296,6 +299,14 @@ The implication of this design choice is felt most when the tool needs is creati
|
|
|
296
299
|
## Other Useful Tips
|
|
297
300
|
|
|
298
301
|
### mkcert
|
|
302
|
+
|
|
303
|
+
### Install
|
|
304
|
+
|
|
305
|
+
1. Visit this [site](https://github.com/FiloSottile/mkcert/releases)
|
|
306
|
+
2. Download the proper version
|
|
307
|
+
- rename the file as mkcert (with proper exetension for your os)
|
|
308
|
+
- move it to a directory that is in the PATH value
|
|
309
|
+
|
|
299
310
|
To create a self-signed certificate for localhost:
|
|
300
311
|
|
|
301
312
|
```sh
|
|
@@ -309,7 +320,7 @@ Now go to the location where you want to store the certificates.
|
|
|
309
320
|
Then create the certificates:
|
|
310
321
|
|
|
311
322
|
```sh
|
|
312
|
-
mkcert
|
|
323
|
+
mkcert localhost 127:0.0.1 ::1
|
|
313
324
|
```
|
|
314
325
|
|
|
315
326
|
One last step for windows nodejs users.
|
package/cli.js
CHANGED
|
@@ -29,9 +29,9 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
29
29
|
|
|
30
30
|
let pkg = fs.readFileSync(__dirname + '/package.json', 'utf8');
|
|
31
31
|
|
|
32
|
-
if (process.env.ENVFILE === '
|
|
32
|
+
if (process.env.ENVFILE === 'FALSE') {
|
|
33
33
|
//use this when using remote mcp server and no .env file is desired
|
|
34
|
-
console.error('[Note]: Skipping .env file as ENVFILE is set to
|
|
34
|
+
console.error('[Note]: Skipping .env file as ENVFILE is set to FALSE...');
|
|
35
35
|
} else {
|
|
36
36
|
let envf = __dirname + '\\.env';
|
|
37
37
|
console.error(envf);
|
|
@@ -47,6 +47,10 @@ if (process.env.ENVFILE === 'NONE') {
|
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
if (process.env.APPHOST == null) {
|
|
52
|
+
process.env.APPHOST = 'localhost';
|
|
53
|
+
}
|
|
50
54
|
/********************************* */
|
|
51
55
|
const BRAND = 'sas-score'
|
|
52
56
|
/********************************* */
|
|
@@ -144,10 +148,11 @@ const appEnvBase = {
|
|
|
144
148
|
tlsOpts: null,
|
|
145
149
|
oauthInfo: null,
|
|
146
150
|
contexts: {
|
|
151
|
+
AUTHFLOW: process.env.AUTHFLOW || 'sascli',
|
|
147
152
|
host: process.env.VIYA_SERVER,
|
|
148
153
|
APPHOST: process.env.APPHOST || 'localhost',
|
|
149
|
-
APPNAME: process.env.APPNAME || '
|
|
150
|
-
PORT: process.env.
|
|
154
|
+
APPNAME: process.env.APPNAME || 'sas-score-mcp-serverjs',
|
|
155
|
+
PORT: process.env.PORT || 8080,
|
|
151
156
|
HTTPS: https,
|
|
152
157
|
store: null, /* for restaf users */
|
|
153
158
|
storeConfig: {},
|
|
@@ -167,6 +172,8 @@ const appEnvBase = {
|
|
|
167
172
|
}
|
|
168
173
|
};
|
|
169
174
|
|
|
175
|
+
process.env.APPPORT=appEnvBase.PORT;
|
|
176
|
+
|
|
170
177
|
// setup TLS options for viya calls
|
|
171
178
|
|
|
172
179
|
console.error('[Note]Viya SSL dir set to: ' + appEnvBase.VIYACERT);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
PORT=8080
|
|
3
|
+
HTTPS=FALSE
|
|
4
|
+
MCPTYPE=http
|
|
5
|
+
AUTHFLOW=sascli
|
|
6
|
+
SAS_CLI_PROFILE=xf1
|
|
7
|
+
SAS_CLI_CONFIG=c:\Users\kumar
|
|
8
|
+
SSLCERT=c:\Users\kumar\.tls
|
|
9
|
+
VIYACERT=c:\Users\kumar\viyaCert\xf1\viya
|
|
10
|
+
CAS_SERVER=cas-shared-default
|
|
11
|
+
COMPUTECONTEXT=SAS Job Execution compute context
|
|
12
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
PORT=8080
|
|
3
|
+
HTTPS=TRUE
|
|
4
|
+
MCPTYPE=http
|
|
5
|
+
AUTHFLOW=code
|
|
6
|
+
CLIENTID=mcpserver
|
|
7
|
+
CLIENTSECRET=jellico
|
|
8
|
+
# VIYA_SERVER= set globally
|
|
9
|
+
SSLCERT=c:\Users\kumar\.tls
|
|
10
|
+
VIYACERT=c:\Users\kumar\viyaCert\xf1\viya
|
|
11
|
+
CAS_SERVER=cas-shared-default
|
|
12
|
+
COMPUTECONTEXT=SAS Job Execution compute context
|
|
13
|
+
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
"servers": {
|
|
3
3
|
"sasmcp": {
|
|
4
4
|
"type": "stdio",
|
|
5
|
-
"command": "
|
|
5
|
+
"command": "node",
|
|
6
6
|
"args": [
|
|
7
|
-
"
|
|
7
|
+
"c:\\dev\\github\\sas-score-mcp-serverjs\\cli.js"
|
|
8
8
|
],
|
|
9
9
|
"env": {
|
|
10
10
|
"MCPTYPE": "stdio",
|
|
11
|
-
"AUTHFLOW": "
|
|
12
|
-
"SAS_CLI_PROFILE": "
|
|
11
|
+
"AUTHFLOW": "sascli",
|
|
12
|
+
"SAS_CLI_PROFILE": "xf1",
|
|
13
13
|
"SAS_CLI_CONFIG": "c:\\Users\\kumar",
|
|
14
14
|
"SSLCERT": "c:\\Users\\kumar\\.tls",
|
|
15
|
+
"VIYACERT": "c:\\Users\\kumar\\viyaCert\\xf1\\viya",
|
|
16
|
+
"CAS_SERVER": "cas-shared-default",
|
|
15
17
|
"COMPUTECONTEXT": "SAS Job Execution compute context",
|
|
16
|
-
"
|
|
18
|
+
"ENVFILE": "FALSE"
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sassoftware/sas-score-mcp-serverjs",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A mcp server for SAS Viya",
|
|
5
5
|
"author": "Deva Kumar <deva.kumar@sas.com>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"deploy": "bash ./deploy.sh",
|
|
19
19
|
"push2acr": "bash ./push2acr.sh",
|
|
20
20
|
"bump": "npm version prerelease",
|
|
21
|
-
"pub": "npm publish --tag
|
|
21
|
+
"pub": "npm publish --tag dev --access public"
|
|
22
22
|
},
|
|
23
23
|
"repository": "https://github.com/sassoftware/sas-score-mcp-serverjs",
|
|
24
24
|
"keywords": [
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@sassoftware/restaf": "^5.6.0",
|
|
41
41
|
"@sassoftware/restafedit": "^3.11.1-10",
|
|
42
42
|
"@sassoftware/restaflib": "^5.6.0",
|
|
43
|
-
"@sassoftware/viya-serverjs": "^0.6.
|
|
43
|
+
"@sassoftware/viya-serverjs": "^0.6.3-0",
|
|
44
44
|
"axios": "^1.13.2",
|
|
45
45
|
"body-parser": "^2.2.1",
|
|
46
46
|
"cors": "^2.8.5",
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
kubectl cp $(kubectl get pod | grep "sas-consul-server-0" | awk -F" " '{print $1}'):security/ca.crt ./ca.crt
|
|
2
|
+
kubectl cp $(kubectl get pod | grep "sas-consul-server-0" | awk -F" " '{print $1}'):security/tls.crt ./tls.crt
|
|
3
|
+
kubectl cp $(kubectl get pod | grep "sas-consul-server-0" | awk -F" " '{print $1}'):security/tls.key ./tls.key
|
package/src/expressMcpServer.js
CHANGED
|
@@ -228,7 +228,7 @@ async function expressMcpServer(mcpServer, cache, currentAppEnvContext) {
|
|
|
228
228
|
let appServer;
|
|
229
229
|
|
|
230
230
|
// get TLS options
|
|
231
|
-
if (appEnvBase.HTTPS ===
|
|
231
|
+
if (appEnvBase.HTTPS === 'TRUE') {
|
|
232
232
|
//appEnvBase.tlsOpts = getOpts(appEnvBase);
|
|
233
233
|
if (appEnvBase.tlsOpts == null) {
|
|
234
234
|
appEnvBase.tlsOpts = await getTls(appEnvBase);
|
package/src/hapiMcpServer.js
CHANGED
|
@@ -6,15 +6,20 @@ import appServer from "@sassoftware/viya-serverjs";
|
|
|
6
6
|
import handleRequest from "./handleRequest.js";
|
|
7
7
|
import handleGetDelete from "./handleGetDelete.js";
|
|
8
8
|
import urlOpen from "./urlOpen.js";
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
|
|
11
11
|
async function hapiMcpServer(mcpServer, cache, baseAppEnvContext) {
|
|
12
12
|
|
|
13
|
-
console.error(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
console.error('Starting Hapi MCP server...');
|
|
14
|
+
console.error("[Note]: Hapi MCP server started...", baseAppEnvContext.AUTHFLOW);
|
|
15
|
+
let r = await appServer.asyncCore(mcpHandlers, true, 'app', null);
|
|
16
|
+
console.error('Hapi server running result:', r);
|
|
17
|
+
if (baseAppEnvContext.AUTHFLOW === 'code'){
|
|
18
|
+
await urlOpen(r);
|
|
17
19
|
}
|
|
20
|
+
return r;
|
|
21
|
+
|
|
22
|
+
// add MCP handlers to the app server
|
|
18
23
|
|
|
19
24
|
function mcpHandlers() {
|
|
20
25
|
let routes = [
|
|
@@ -11,20 +11,20 @@ async function getToken(_appContext) {
|
|
|
11
11
|
if (_appContext.SAS_CLI_CONFIG != null) {
|
|
12
12
|
homedir = _appContext.SAS_CLI_CONFIG;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
let sep = (os.platform() === 'win32') ? '\\' : '/';
|
|
16
|
-
console.error('Using sep: ' + sep);
|
|
17
16
|
let credentials = homedir + sep + '.sas' + sep + 'credentials.json';
|
|
18
17
|
let url = homedir + sep + '.sas' + sep + 'config.json';
|
|
19
18
|
console.error('[Note] Using credentials file: ' + credentials);
|
|
20
19
|
console.error('[Note] Using config file: ' + url);
|
|
21
|
-
|
|
20
|
+
let profile = (_appContext.SAS_CLI_PROFILE == null || _appContext.SAS_CLI_PROFILE.toLowerCase() === 'default')
|
|
21
|
+
? 'Default' : _appContext.SAS_CLI_PROFILE;
|
|
22
|
+
console.error('[Note] Using SASCLI profile: ' + profile);
|
|
22
23
|
try {
|
|
23
24
|
|
|
24
25
|
let j = fs.readFileSync(credentials, 'utf8');
|
|
25
26
|
let js = JSON.parse(j);
|
|
26
|
-
|
|
27
|
-
? 'Default' : _appContext.SAS_CLI_PROFILE;
|
|
27
|
+
|
|
28
28
|
let refresh_token = js[profile]['refresh-token'];
|
|
29
29
|
j = fs.readFileSync(url, 'utf8');
|
|
30
30
|
js = JSON.parse(j);
|
package/src/urlOpen.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2026, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
1
5
|
import open from 'open';
|
|
2
6
|
|
|
3
|
-
async function urlOpen(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let urlx = `${protocol}://${appHost}:${appPort}/${appName}`;
|
|
9
|
-
console.log(`Opening URL: ${urlx}`);
|
|
10
|
-
await open(urlx, {wait:true});
|
|
7
|
+
async function urlOpen(url) {
|
|
8
|
+
|
|
9
|
+
console.error(`[Note]Opening URL: ${url} for user authentication`);
|
|
10
|
+
await open(url, {wait:true});
|
|
11
|
+
console.error(`[Note] User has closed the informational window after authentication.`);
|
|
11
12
|
}
|
|
12
13
|
export default urlOpen;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|