@sassoftware/sas-score-mcp-serverjs 1.0.1-3 → 1.0.1-31
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/.skills/agents/sas-score-mcp-serverjs-agent.md +190 -0
- package/.skills/copilot-instructions.md +241 -0
- package/.skills/skills/README.md +125 -0
- package/.skills/skills/detail-strategy/SKILL.md +272 -0
- package/.skills/skills/find-resources/SKILL.md +155 -0
- package/.skills/skills/list-resource/SKILL.md +258 -0
- package/.skills/skills/read-strategy/SKILL.md +137 -0
- package/.skills/skills/request-routing/SKILL.md +107 -0
- package/.skills/skills/score-strategy/SKILL.md +231 -0
- package/README.md +96 -54
- package/cli.js +37 -27
- package/openApi.yaml +121 -121
- package/package.json +14 -14
- package/scripts/docs/oauth-http-transport.md +2 -2
- package/scripts/refreshtoken.js +58 -0
- package/src/createMcpServer.js +0 -1
- package/src/expressMcpServer.js +47 -49
- package/src/oauthHandlers/authorize.js +4 -1
- package/src/oauthHandlers/baseUrl.js +4 -0
- package/src/oauthHandlers/callback.js +5 -1
- package/src/oauthHandlers/getMetadata.js +4 -0
- package/src/oauthHandlers/index.js +4 -0
- package/src/oauthHandlers/token.js +4 -0
- package/src/openApi.yaml +121 -121
- package/src/processHeaders.js +10 -7
- package/src/setupSkills.js +12 -7
- package/src/toolHelpers/_findJob.js +12 -0
- package/src/toolHelpers/_findJobdef.js +10 -0
- package/src/toolHelpers/_findLibrary.js +10 -0
- package/src/toolHelpers/_findModel.js +12 -0
- package/src/toolHelpers/_findTable.js +10 -0
- package/src/toolHelpers/_listJobs.js +2 -1
- package/src/toolHelpers/_listLibrary.js +1 -1
- package/src/toolHelpers/_listTables.js +1 -1
- package/src/toolHelpers/getLogonPayload.js +2 -2
- package/src/toolSet/devaScore.js +61 -61
- package/src/toolSet/findJob.js +2 -1
- package/src/toolSet/findJobdef.js +7 -7
- package/src/toolSet/findLibrary.js +68 -68
- package/src/toolSet/findModel.js +2 -2
- package/src/toolSet/findTable.js +2 -2
- package/src/toolSet/jobInfo.js +59 -0
- package/src/toolSet/jobdefInfo.js +59 -0
- package/src/toolSet/listJobdefs.js +61 -61
- package/src/toolSet/listJobs.js +61 -61
- package/src/toolSet/listLibraries.js +78 -78
- package/src/toolSet/listModels.js +56 -56
- package/src/toolSet/listTables.js +66 -66
- package/src/toolSet/makeTools.js +3 -0
- package/src/toolSet/modelInfo.js +1 -1
- package/src/toolSet/modelScore.js +23 -25
- package/src/toolSet/readTable.js +63 -63
- package/src/toolSet/runCasProgram.js +21 -10
- package/src/toolSet/runJob.js +15 -19
- package/src/toolSet/runJobdef.js +15 -19
- package/src/toolSet/runMacro.js +82 -82
- package/src/toolSet/sasQuery.js +77 -77
- package/src/toolSet/scrScore.js +60 -69
- package/src/toolSet/setContext.js +65 -65
- package/src/toolSet/superstat.js +61 -61
- package/src/toolSet/tableInfo.js +58 -58
- package/.skills_claude/README.md +0 -303
- package/.skills_claude/TESTING_GUIDE.md +0 -252
- package/.skills_claude/agents/sas-viya-scoring-expert.md +0 -58
- package/.skills_claude/claude-desktop-config.json +0 -16
- package/.skills_claude/claude-desktop-system-prompt.md +0 -127
- package/.skills_claude/copilot-instructions.md +0 -155
- package/.skills_claude/instructions.md +0 -184
- package/.skills_claude/skills/sas-find-library-smart/SKILL.md +0 -157
- package/.skills_claude/skills/sas-find-resource-strategy/SKILL.md +0 -105
- package/.skills_claude/skills/sas-list-resource-strategy/SKILL.md +0 -124
- package/.skills_claude/skills/sas-list-tables-smart/SKILL.md +0 -126
- package/.skills_claude/skills/sas-read-and-score/SKILL.md +0 -112
- package/.skills_claude/skills/sas-read-strategy/SKILL.md +0 -154
- package/.skills_claude/skills/sas-request-classifier/SKILL.md +0 -69
- package/.skills_claude/skills/sas-score-workflow/SKILL.md +0 -200
- package/.skills_claude/skills-index.md +0 -345
- package/.skills_github/agents/sas-viya-scoring-expert.md +0 -58
- package/.skills_github/copilot-instructions.md +0 -177
- package/.skills_github/skills/sas-find-library-smart/SKILL.md +0 -155
- package/.skills_github/skills/sas-find-resource-strategy/SKILL.md +0 -105
- package/.skills_github/skills/sas-list-resource-strategy/SKILL.md +0 -124
- package/.skills_github/skills/sas-list-tables-smart/SKILL.md +0 -128
- package/.skills_github/skills/sas-read-and-score/SKILL.md +0 -113
- package/.skills_github/skills/sas-read-strategy/SKILL.md +0 -154
- package/.skills_github/skills/sas-request-classifier/SKILL.md +0 -74
- package/.skills_github/skills/sas-score-workflow/SKILL.md +0 -314
- package/scripts/optimize_final.py +0 -140
- package/scripts/optimize_tools.py +0 -99
- package/scripts/setup-skills.js +0 -34
- package/scripts/update_descriptions.py +0 -46
- package/src/authpkce.js +0 -219
- package/src/handleGetDelete.js +0 -34
- package/src/handleRequest.js +0 -112
- package/src/hapiMcpServer.js +0 -241
- package/src/toolSet/.claude/settings.local.json +0 -13
package/cli.js
CHANGED
|
@@ -9,15 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
import coreSSE from './src/coreSSE.js';
|
|
11
11
|
import expressMcpServer from './src/expressMcpServer.js';
|
|
12
|
-
import hapiMcpServer from './src/hapiMcpServer.js';
|
|
13
|
-
|
|
14
12
|
import createMcpServer from './src/createMcpServer.js';
|
|
15
13
|
// import dotenvExpand from 'dotenv-expand';
|
|
16
14
|
import fs from 'fs';
|
|
17
15
|
import { randomUUID } from 'node:crypto';
|
|
18
16
|
|
|
19
|
-
//import refreshToken from './src/toolHelpers/refreshToken.js';
|
|
20
|
-
//import getOptsViya from './src/toolHelpers/getOptsViya.js';
|
|
21
17
|
import readCerts from './src/toolHelpers/readCerts.js';
|
|
22
18
|
|
|
23
19
|
import { fileURLToPath } from 'url';
|
|
@@ -27,7 +23,8 @@ import setupSkills from './src/setupSkills.js';
|
|
|
27
23
|
import { parseArgs } from "node:util";
|
|
28
24
|
|
|
29
25
|
import NodeCache from 'node-cache';
|
|
30
|
-
import { be } from 'zod/locales';
|
|
26
|
+
//import { be } from 'zod/locales';
|
|
27
|
+
//import { auth } from '@modelcontextprotocol/sdk/client/auth';
|
|
31
28
|
//import getOpts from './src/toolHelpers/getOpts.js';
|
|
32
29
|
|
|
33
30
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -72,11 +69,6 @@ const args = parseArgs({
|
|
|
72
69
|
short: 'c',
|
|
73
70
|
description: 'Client ID for authentication'
|
|
74
71
|
},
|
|
75
|
-
clientsecret: {
|
|
76
|
-
type: 'string',
|
|
77
|
-
short: 's',
|
|
78
|
-
description: 'Client Secret for authentication'
|
|
79
|
-
},
|
|
80
72
|
profile: {
|
|
81
73
|
type: 'string',
|
|
82
74
|
description: 'SAS CLI profile name'
|
|
@@ -107,6 +99,17 @@ const args = parseArgs({
|
|
|
107
99
|
alias: 'mcpclient',
|
|
108
100
|
description: 'MCP client name (github, claude...). Defaults to \'github\''
|
|
109
101
|
},
|
|
102
|
+
folder: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
short: 'f',
|
|
105
|
+
description: 'Subfolder under the client folder to copy the skills to, used to have different set of skills for different agents under the same client'
|
|
106
|
+
|
|
107
|
+
},
|
|
108
|
+
skills: {
|
|
109
|
+
type: 'string',
|
|
110
|
+
short: 's',
|
|
111
|
+
description: 'Copies the skills for .github and .claude to the user home directory under .clientname (e.g. .github) or current directory if client name starts with dot (e.g. ./.github), used to have different set of skills for different clients'
|
|
112
|
+
},
|
|
110
113
|
help: {
|
|
111
114
|
type: 'boolean',
|
|
112
115
|
short: 'h',
|
|
@@ -125,28 +128,28 @@ const args = parseArgs({
|
|
|
125
128
|
// Handle help flag
|
|
126
129
|
if (args.values.help) {
|
|
127
130
|
console.error(`
|
|
128
|
-
|
|
131
|
+
sas-score-mcp-serverjs - Version: ${JSON.parse(pkg).version}
|
|
129
132
|
|
|
130
133
|
Usage: npx @sassoftware/sas-score-mcp-serverjs@dev [options]
|
|
131
134
|
|
|
132
135
|
Options:
|
|
133
136
|
Minimal options:
|
|
134
137
|
-v, --viya <url> Viya server URL
|
|
135
|
-
-c, --clientid <id> Client ID for oauth authentication(pkce preferred. default: vscodemcp)
|
|
136
138
|
|
|
137
139
|
MCP server options:
|
|
138
140
|
-t, --mcptype <type> MCP server type: http or stdio (default: http)
|
|
139
141
|
-m, --mcphost <host> MCP server host - can be remote URL - (default: http://localhost:8080)
|
|
140
142
|
|
|
141
|
-
Agent options:
|
|
142
|
-
--agent Enable agent mode with a pre-configured set of skills based on the client specified (default: false)
|
|
143
|
-
--client <name> MCP client name (github, claude...). Defaults to 'github'.Use to install skills
|
|
144
143
|
Authentication options:
|
|
144
|
+
-c, --clientid <id> Client ID for oauth authentication(pkce preferred. default: vscodemcp)
|
|
145
145
|
-a, --authflow <flow> Authentication flow: oauth, oauthclient, sascli, code, token(default oauth)
|
|
146
|
-
-s, --clientsecret <secret> Client Secret for oauth authentication (not needed for pkce)
|
|
147
146
|
--profile <name> SAS CLI profile name for sascli flow (default: Default)
|
|
148
147
|
--config <path> SAS CLI config directory for sascli flow (default: user home directory)
|
|
149
148
|
|
|
149
|
+
Agent/skills options:
|
|
150
|
+
-s, --skills <name> Copies the skills for .github and .claude
|
|
151
|
+
-f, --folder <folder> Subfolder to copy the skills to. ex: ./github/<folder>, used to have different set of skills for different agents under the same client.
|
|
152
|
+
|
|
150
153
|
Other options:
|
|
151
154
|
-p, --port <port> Port to run the server on (default: 8080)
|
|
152
155
|
--https Use HTTPS for the server (default: false)
|
|
@@ -165,6 +168,13 @@ Environment Variables:
|
|
|
165
168
|
`);
|
|
166
169
|
process.exit(0);
|
|
167
170
|
}
|
|
171
|
+
if (args.values.skills) {
|
|
172
|
+
console.error(`[Note] Settings up skills for ${args.values.skills }`);
|
|
173
|
+
setupSkills(args.values.skills, args.values.folder);;
|
|
174
|
+
console.error(`[Note] Skills setup completed. `);
|
|
175
|
+
process.exit(0);
|
|
176
|
+
}
|
|
177
|
+
|
|
168
178
|
console.error('Parsed command line arguments:', args.values);
|
|
169
179
|
// read env file and then override with command line arguments
|
|
170
180
|
if (args.values.env) {
|
|
@@ -194,7 +204,7 @@ process.env.AUTHFLOW = args.values.authflow || process.env.AUTHFLOW || 'oauth';
|
|
|
194
204
|
process.env.MCPCLIENT = args.values.client || process.env.MCPCLIENT || 'github';
|
|
195
205
|
process.env.VIYA_SERVER = args.values.viya || process.env.VIYA_SERVER;
|
|
196
206
|
process.env.CLIENTID = args.values.clientid || process.env.CLIENTID || 'vscodemcp';
|
|
197
|
-
process.env.CLIENTSECRET =
|
|
207
|
+
process.env.CLIENTSECRET = null;
|
|
198
208
|
process.env.SAS_CLI_PROFILE = args.values.profile || process.env.SAS_CLI_PROFILE || 'Default';
|
|
199
209
|
process.env.SAS_CLI_CONFIG = args.values.config || process.env.SAS_CLI_CONFIG || os.homedir(); // default to user home directory
|
|
200
210
|
process.env.CASSERVER = args.values.casserver || process.env.CASSERVER || 'cas-shared-default';
|
|
@@ -219,6 +229,7 @@ if (args.values.version) {
|
|
|
219
229
|
console.error(`[Note] MCP client set to: ${process.env.CLIENT}`);
|
|
220
230
|
|
|
221
231
|
|
|
232
|
+
|
|
222
233
|
/********************************* */
|
|
223
234
|
const BRAND = 'sas-score'
|
|
224
235
|
/********************************* */
|
|
@@ -256,8 +267,10 @@ let mcpHost = process.env.MCPHOST;
|
|
|
256
267
|
if (authFlow === 'oauth' || authFlow === 'oauthclient') {
|
|
257
268
|
authFlow = 'bearer';
|
|
258
269
|
authExternal = (authFlow === 'oauthclient') ? true : false;
|
|
270
|
+
} else if (authFlow === 'bearer') {
|
|
271
|
+
authExternal = true; // in bearer token flow we assume the token is generated externally and passed in via env variable or token file, so we set authExternal to true to indicate that
|
|
259
272
|
}
|
|
260
|
-
let autoLogon = process.env.AUTOLOGON != null ? process.env.AUTOLOGON.toUpperCase() : "FALSE";
|
|
273
|
+
let autoLogon = process.env.AUTOLOGON != null ? process.env.AUTOLOGON.toUpperCase() : "FALSE";
|
|
261
274
|
const appEnvBase = {
|
|
262
275
|
version: version,
|
|
263
276
|
mcpType: mcpType,
|
|
@@ -373,10 +386,13 @@ if (appEnvBase.TOKENFILE != null) {
|
|
|
373
386
|
|
|
374
387
|
// setup skills based on client before mcp initialization
|
|
375
388
|
//
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
376
392
|
if (process.env.AGENT === 'TRUE') {
|
|
377
393
|
if (process.env.CLIENT !== 'none') {
|
|
378
394
|
console.error(`[Note] Setting up skills for client: ${process.env.CLIENT}...`);
|
|
379
|
-
setupSkills(process.env.CLIENT);
|
|
395
|
+
setupSkills(process.env.CLIENT, args.values.folder);
|
|
380
396
|
}
|
|
381
397
|
} else {
|
|
382
398
|
console.error(`[Note] Agent mode not enabled`);
|
|
@@ -453,14 +469,8 @@ if (mcpType === 'stdio') {
|
|
|
453
469
|
|
|
454
470
|
} else {
|
|
455
471
|
console.error('[Note] Starting HTTP MCP server...');
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await hapiMcpServer(mcpServer, sessionCache, appEnvBase);
|
|
459
|
-
console.error('[Note] Using HAPI HTTP server...')
|
|
460
|
-
} else {
|
|
461
|
-
await expressMcpServer(mcpServer, sessionCache, appEnvBase);
|
|
462
|
-
console.error('[Note] MCP HTTP express server started on port ' + appEnvBase.PORT);
|
|
463
|
-
}
|
|
472
|
+
await expressMcpServer(mcpServer, sessionCache, appEnvBase);
|
|
473
|
+
console.error('[Note] MCP HTTP express server started on port ' + appEnvBase.PORT);
|
|
464
474
|
}
|
|
465
475
|
|
|
466
476
|
// custom reader for .env file to avoid dotenv logging to console
|
package/openApi.yaml
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
swagger: "2.0"
|
|
2
|
-
info:
|
|
3
|
-
title: SAS Viya Sample MCP Server API
|
|
4
|
-
version: "1.0.0"
|
|
5
|
-
description: API for interacting with the SAS Viya Sample MCP Server.
|
|
6
|
-
host: localhost:8080
|
|
7
|
-
basePath: /
|
|
8
|
-
schemes:
|
|
9
|
-
- http
|
|
10
|
-
- https
|
|
11
|
-
consumes:
|
|
12
|
-
- application/json
|
|
13
|
-
produces:
|
|
14
|
-
- application/json
|
|
15
|
-
paths:
|
|
16
|
-
/health:
|
|
17
|
-
get:
|
|
18
|
-
summary: Health check
|
|
19
|
-
description: Returns health and version information.
|
|
20
|
-
responses:
|
|
21
|
-
200:
|
|
22
|
-
description: Health information
|
|
23
|
-
schema:
|
|
24
|
-
type: object
|
|
25
|
-
properties:
|
|
26
|
-
name:
|
|
27
|
-
type: string
|
|
28
|
-
version:
|
|
29
|
-
type: string
|
|
30
|
-
description:
|
|
31
|
-
type: string
|
|
32
|
-
endpoints:
|
|
33
|
-
type: object
|
|
34
|
-
usage:
|
|
35
|
-
type: string
|
|
36
|
-
/apiMeta:
|
|
37
|
-
get:
|
|
38
|
-
summary: API metadata
|
|
39
|
-
description: Returns the OpenAPI specification for this server.
|
|
40
|
-
responses:
|
|
41
|
-
200:
|
|
42
|
-
description: OpenAPI document
|
|
43
|
-
schema:
|
|
44
|
-
type: object
|
|
45
|
-
/mcp:
|
|
46
|
-
options:
|
|
47
|
-
summary: CORS preflight
|
|
48
|
-
description: CORS preflight endpoint.
|
|
49
|
-
responses:
|
|
50
|
-
204:
|
|
51
|
-
description: No Content
|
|
52
|
-
post:
|
|
53
|
-
summary: MCP request
|
|
54
|
-
description: Handles MCP JSON-RPC requests.
|
|
55
|
-
parameters:
|
|
56
|
-
- name: body
|
|
57
|
-
in: body
|
|
58
|
-
required: true
|
|
59
|
-
schema:
|
|
60
|
-
type: object
|
|
61
|
-
- name: Authorization
|
|
62
|
-
in: header
|
|
63
|
-
required: false
|
|
64
|
-
type: string
|
|
65
|
-
description: Bearer token for authentication
|
|
66
|
-
- name: X-VIYA-SERVER
|
|
67
|
-
in: header
|
|
68
|
-
required: false
|
|
69
|
-
type: string
|
|
70
|
-
description: Override VIYA server
|
|
71
|
-
- name: X-REFRESH-TOKEN
|
|
72
|
-
in: header
|
|
73
|
-
required: false
|
|
74
|
-
type: string
|
|
75
|
-
description: Refresh token for authentication
|
|
76
|
-
- name: mcp-session-id
|
|
77
|
-
in: header
|
|
78
|
-
required: false
|
|
79
|
-
type: string
|
|
80
|
-
description: Session ID
|
|
81
|
-
responses:
|
|
82
|
-
200:
|
|
83
|
-
description: MCP response
|
|
84
|
-
schema:
|
|
85
|
-
type: object
|
|
86
|
-
500:
|
|
87
|
-
description: Server error
|
|
88
|
-
schema:
|
|
89
|
-
type: object
|
|
90
|
-
get:
|
|
91
|
-
summary: Get MCP session
|
|
92
|
-
description: Retrieves information for an MCP session.
|
|
93
|
-
parameters:
|
|
94
|
-
- name: mcp-session-id
|
|
95
|
-
in: header
|
|
96
|
-
required: true
|
|
97
|
-
type: string
|
|
98
|
-
description: Session ID
|
|
99
|
-
responses:
|
|
100
|
-
200:
|
|
101
|
-
description: Session information
|
|
102
|
-
schema:
|
|
103
|
-
type: object
|
|
104
|
-
400:
|
|
105
|
-
description: Invalid or missing session ID
|
|
106
|
-
delete:
|
|
107
|
-
summary: Delete MCP session
|
|
108
|
-
description: Deletes an MCP session.
|
|
109
|
-
parameters:
|
|
110
|
-
- name: mcp-session-id
|
|
111
|
-
in: header
|
|
112
|
-
required: true
|
|
113
|
-
type: string
|
|
114
|
-
description: Session ID
|
|
115
|
-
responses:
|
|
116
|
-
200:
|
|
117
|
-
description: Session deleted
|
|
118
|
-
schema:
|
|
119
|
-
type: object
|
|
120
|
-
400:
|
|
121
|
-
description: Invalid or missing session ID
|
|
1
|
+
swagger: "2.0"
|
|
2
|
+
info:
|
|
3
|
+
title: SAS Viya Sample MCP Server API
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
description: API for interacting with the SAS Viya Sample MCP Server.
|
|
6
|
+
host: localhost:8080
|
|
7
|
+
basePath: /
|
|
8
|
+
schemes:
|
|
9
|
+
- http
|
|
10
|
+
- https
|
|
11
|
+
consumes:
|
|
12
|
+
- application/json
|
|
13
|
+
produces:
|
|
14
|
+
- application/json
|
|
15
|
+
paths:
|
|
16
|
+
/health:
|
|
17
|
+
get:
|
|
18
|
+
summary: Health check
|
|
19
|
+
description: Returns health and version information.
|
|
20
|
+
responses:
|
|
21
|
+
200:
|
|
22
|
+
description: Health information
|
|
23
|
+
schema:
|
|
24
|
+
type: object
|
|
25
|
+
properties:
|
|
26
|
+
name:
|
|
27
|
+
type: string
|
|
28
|
+
version:
|
|
29
|
+
type: string
|
|
30
|
+
description:
|
|
31
|
+
type: string
|
|
32
|
+
endpoints:
|
|
33
|
+
type: object
|
|
34
|
+
usage:
|
|
35
|
+
type: string
|
|
36
|
+
/apiMeta:
|
|
37
|
+
get:
|
|
38
|
+
summary: API metadata
|
|
39
|
+
description: Returns the OpenAPI specification for this server.
|
|
40
|
+
responses:
|
|
41
|
+
200:
|
|
42
|
+
description: OpenAPI document
|
|
43
|
+
schema:
|
|
44
|
+
type: object
|
|
45
|
+
/mcp:
|
|
46
|
+
options:
|
|
47
|
+
summary: CORS preflight
|
|
48
|
+
description: CORS preflight endpoint.
|
|
49
|
+
responses:
|
|
50
|
+
204:
|
|
51
|
+
description: No Content
|
|
52
|
+
post:
|
|
53
|
+
summary: MCP request
|
|
54
|
+
description: Handles MCP JSON-RPC requests.
|
|
55
|
+
parameters:
|
|
56
|
+
- name: body
|
|
57
|
+
in: body
|
|
58
|
+
required: true
|
|
59
|
+
schema:
|
|
60
|
+
type: object
|
|
61
|
+
- name: Authorization
|
|
62
|
+
in: header
|
|
63
|
+
required: false
|
|
64
|
+
type: string
|
|
65
|
+
description: Bearer token for authentication
|
|
66
|
+
- name: X-VIYA-SERVER
|
|
67
|
+
in: header
|
|
68
|
+
required: false
|
|
69
|
+
type: string
|
|
70
|
+
description: Override VIYA server
|
|
71
|
+
- name: X-REFRESH-TOKEN
|
|
72
|
+
in: header
|
|
73
|
+
required: false
|
|
74
|
+
type: string
|
|
75
|
+
description: Refresh token for authentication
|
|
76
|
+
- name: mcp-session-id
|
|
77
|
+
in: header
|
|
78
|
+
required: false
|
|
79
|
+
type: string
|
|
80
|
+
description: Session ID
|
|
81
|
+
responses:
|
|
82
|
+
200:
|
|
83
|
+
description: MCP response
|
|
84
|
+
schema:
|
|
85
|
+
type: object
|
|
86
|
+
500:
|
|
87
|
+
description: Server error
|
|
88
|
+
schema:
|
|
89
|
+
type: object
|
|
90
|
+
get:
|
|
91
|
+
summary: Get MCP session
|
|
92
|
+
description: Retrieves information for an MCP session.
|
|
93
|
+
parameters:
|
|
94
|
+
- name: mcp-session-id
|
|
95
|
+
in: header
|
|
96
|
+
required: true
|
|
97
|
+
type: string
|
|
98
|
+
description: Session ID
|
|
99
|
+
responses:
|
|
100
|
+
200:
|
|
101
|
+
description: Session information
|
|
102
|
+
schema:
|
|
103
|
+
type: object
|
|
104
|
+
400:
|
|
105
|
+
description: Invalid or missing session ID
|
|
106
|
+
delete:
|
|
107
|
+
summary: Delete MCP session
|
|
108
|
+
description: Deletes an MCP session.
|
|
109
|
+
parameters:
|
|
110
|
+
- name: mcp-session-id
|
|
111
|
+
in: header
|
|
112
|
+
required: true
|
|
113
|
+
type: string
|
|
114
|
+
description: Session ID
|
|
115
|
+
responses:
|
|
116
|
+
200:
|
|
117
|
+
description: Session deleted
|
|
118
|
+
schema:
|
|
119
|
+
type: object
|
|
120
|
+
400:
|
|
121
|
+
description: Invalid or missing session ID
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sassoftware/sas-score-mcp-serverjs",
|
|
3
|
-
"version": "1.0.1-
|
|
3
|
+
"version": "1.0.1-31",
|
|
4
4
|
"description": "A mcp server for SAS Viya",
|
|
5
5
|
"author": "Deva Kumar <deva.kumar@sas.com>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
"test": "cd test && node",
|
|
16
16
|
"debug": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 node --inspect-brk cli.js",
|
|
17
17
|
"getViyatls": "bash ./scripts/getViyaca.sh",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
18
|
+
"push2acr": "bash ./push2acr.sh",
|
|
19
|
+
"push2ghcr": "bash ./push2ghcr.sh",
|
|
20
20
|
"bump": "npm version prerelease",
|
|
21
|
-
"pub": "npm publish --tag dev --access public"
|
|
22
|
-
"setup-skills": "node scripts/setup-skills.js"
|
|
21
|
+
"pub": "npm publish --tag dev --access public"
|
|
23
22
|
},
|
|
24
23
|
"repository": "https://github.com/sassoftware/sas-score-mcp-serverjs",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/sassoftware/sas-score-mcp-serverjs/issues"
|
|
26
|
+
},
|
|
25
27
|
"keywords": [
|
|
26
28
|
"SAS Viya",
|
|
27
29
|
"mcp-serverjs",
|
|
@@ -42,16 +44,14 @@
|
|
|
42
44
|
"openApi.json",
|
|
43
45
|
"openApi.yaml",
|
|
44
46
|
"scripts",
|
|
45
|
-
".
|
|
46
|
-
".skills_claude"
|
|
47
|
+
".skills"
|
|
47
48
|
],
|
|
48
49
|
"dependencies": {
|
|
49
50
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
50
|
-
"@sassoftware/restaf": "^5.
|
|
51
|
-
"@sassoftware/restafedit": "^3.
|
|
52
|
-
"@sassoftware/restaflib": "^5.
|
|
53
|
-
"
|
|
54
|
-
"axios": "^1.13.2",
|
|
51
|
+
"@sassoftware/restaf": "^5.7.2",
|
|
52
|
+
"@sassoftware/restafedit": "^3.10.5",
|
|
53
|
+
"@sassoftware/restaflib": "^5.7.2",
|
|
54
|
+
"axios": "^1.13.5",
|
|
55
55
|
"body-parser": "^2.2.1",
|
|
56
56
|
"cors": "^2.8.5",
|
|
57
57
|
"cross-env": "^10.1.0",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"node-cache": "^5.1.2",
|
|
64
64
|
"open": "^11.0.0",
|
|
65
65
|
"selfsigned": "^5.2.0",
|
|
66
|
-
"undici": "^7.
|
|
67
|
-
"uuid": "^
|
|
66
|
+
"undici": "^7.24.0",
|
|
67
|
+
"uuid": "^14.0.0",
|
|
68
68
|
"zod": "^4.2.1"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
TBD
|
|
7
7
|
|
|
8
|
-
## VSCODE
|
|
8
|
+
## VSCODE Github Copilot
|
|
9
9
|
|
|
10
10
|
### Scenario:
|
|
11
11
|
|
|
@@ -35,7 +35,7 @@ It appears that the / at the end of the redirect URI is important]
|
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
### pkce clientid when mcp server does
|
|
38
|
+
### pkce clientid when mcp server does the oauth flow
|
|
39
39
|
|
|
40
40
|
```js
|
|
41
41
|
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
import fs from "fs";
|
|
7
|
+
|
|
8
|
+
refreshToken()
|
|
9
|
+
.then (token => {
|
|
10
|
+
console.log(token);
|
|
11
|
+
fs.writeFileSync('token.txt', `"AUTHORIZATION": "Bearer ${token}"`, 'utf8');
|
|
12
|
+
})
|
|
13
|
+
.catch (err => {
|
|
14
|
+
console.error('[Error] Failed to refresh token: ', err);
|
|
15
|
+
});
|
|
16
|
+
async function refreshToken(){
|
|
17
|
+
let host = process.env.VIYA_SERVER;
|
|
18
|
+
let token = process.env.REFRESH_TOKEN;
|
|
19
|
+
let url = `${host}/SASLogon/oauth/token`;
|
|
20
|
+
|
|
21
|
+
let aconnect = {
|
|
22
|
+
rejectUnauthorized: false // or false, if you really want to bypass checks
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const agent = new Agent(aconnect);
|
|
26
|
+
|
|
27
|
+
console.error('[Info] Refreshing token...', token);
|
|
28
|
+
const ibody = {
|
|
29
|
+
grant_type: 'refresh_token',
|
|
30
|
+
refresh_token: token,
|
|
31
|
+
client_id: 'sas.cli'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
let body = new URLSearchParams(ibody);
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(url, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Accept': 'application/json',
|
|
40
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
41
|
+
dispatcher: agent
|
|
42
|
+
},
|
|
43
|
+
body: body.toString()
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const error = await response.text();
|
|
48
|
+
console.error('[Error] Failed to refresh token: ', error);
|
|
49
|
+
throw new Error(error);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
return data.access_token;
|
|
54
|
+
} catch (err) {
|
|
55
|
+
console.error('[Error] Failed to refresh token: ', err);
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/createMcpServer.js
CHANGED
|
@@ -86,7 +86,6 @@ async function createMcpServer(cache, _appContext) {
|
|
|
86
86
|
inputSchema: tool.inputSchema
|
|
87
87
|
}
|
|
88
88
|
let toolHandler = wrapf(cache, tool.handler);
|
|
89
|
-
// console.error(`[Note] Registering tool ${toolName} with config: ${JSON.stringify(config)}`);
|
|
90
89
|
let r = mcpServer.registerTool(toolName, config, toolHandler);
|
|
91
90
|
toolNames.push(toolName);
|
|
92
91
|
});
|