@sassoftware/sas-score-mcp-serverjs 0.4.0 → 0.4.1-15

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.
Files changed (53) hide show
  1. package/cli.js +112 -33
  2. package/package.json +5 -5
  3. package/skills/sas-list-tables-smart/SKILL.md +123 -0
  4. package/skills/sas-read-and-score/SKILL.md +54 -53
  5. package/skills/sas-read-strategy/SKILL.md +10 -10
  6. package/skills/sas-score-workflow/SKILL.md +19 -1
  7. package/skills/sas-spec-migration/SKILL.md +303 -0
  8. package/src/authpkce.js +219 -0
  9. package/src/createMcpServer.js +16 -6
  10. package/src/expressMcpServer.js +354 -338
  11. package/src/handleGetDelete.js +1 -1
  12. package/src/oauthHandlers/authorize.js +46 -0
  13. package/src/oauthHandlers/baseUrl.js +8 -0
  14. package/src/oauthHandlers/callback.js +93 -0
  15. package/src/oauthHandlers/getMetadata.js +27 -0
  16. package/src/oauthHandlers/index.js +7 -0
  17. package/src/oauthHandlers/token.js +37 -0
  18. package/src/processHeaders.js +88 -0
  19. package/src/toolHelpers/_listLibrary.js +0 -1
  20. package/src/toolHelpers/getLogonPayload.js +5 -1
  21. package/src/toolHelpers/readCerts.js +4 -4
  22. package/src/toolHelpers/refreshTokenOauth.js +3 -3
  23. package/src/toolSet/.claude/settings.local.json +13 -0
  24. package/src/toolSet/devaScore.js +61 -61
  25. package/src/toolSet/findJob.js +9 -16
  26. package/src/toolSet/findJobdef.js +4 -5
  27. package/src/toolSet/findLibrary.js +68 -68
  28. package/src/toolSet/findModel.js +4 -5
  29. package/src/toolSet/findTable.js +6 -6
  30. package/src/toolSet/getEnv.js +10 -7
  31. package/src/toolSet/listJobdefs.js +61 -62
  32. package/src/toolSet/listJobs.js +61 -62
  33. package/src/toolSet/listLibraries.js +78 -80
  34. package/src/toolSet/listModels.js +56 -56
  35. package/src/toolSet/listTables.js +66 -66
  36. package/src/toolSet/makeTools.js +1 -3
  37. package/src/toolSet/modelInfo.js +4 -5
  38. package/src/toolSet/modelScore.js +7 -7
  39. package/src/toolSet/readTable.js +63 -67
  40. package/src/toolSet/runCasProgram.js +9 -9
  41. package/src/toolSet/runJob.js +81 -82
  42. package/src/toolSet/runJobdef.js +82 -83
  43. package/src/toolSet/runMacro.js +82 -82
  44. package/src/toolSet/runProgram.js +8 -13
  45. package/src/toolSet/sasQuery.js +77 -79
  46. package/src/toolSet/sasQueryTemplate.js +4 -5
  47. package/src/toolSet/sasQueryTemplate2.js +4 -5
  48. package/src/toolSet/scrInfo.js +3 -5
  49. package/src/toolSet/scrScore.js +69 -70
  50. package/src/toolSet/searchAssets.js +5 -6
  51. package/src/toolSet/setContext.js +65 -66
  52. package/src/toolSet/superstat.js +61 -60
  53. package/src/toolSet/tableInfo.js +58 -59
@@ -1,71 +1,70 @@
1
- /*
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- import { z } from 'zod';
7
- import _scrScore from '../toolHelpers/_scrScore.js';
8
-
9
- function scrScore(_appContext) {
10
- let description = `
11
- ## scr-score
12
-
13
- Purpose
14
- Score a scenario using a model deployed as a SCR container in Azure or another host).
15
-
16
- Inputs
17
- - url (string, required): SCR model identifier (URL)
18
- - scenario (string | object | array, optional): Input values to score. Accepts:
19
- - a comma-separated key=value string (e.g. "x=1, y=2"),
20
- - a JSON object with field names and values (recommended for typed inputs),
21
- - an array of objects for batch scoring. If omitted, the tool will return the model's input variable definitions.
22
-
23
- What it returns
24
- - When scoring: the SCR endpoint response (predictions, probabilities, scores) merged with or alongside the supplied inputs.
25
- - When \`scenario\` is omitted: metadata describing the model's input variables (names, types, required/optional).
26
-
27
- Usage notes
28
- - Run \`scr-info\` first to inspect the expected input variables and types.
29
- - Prefer structured objects for numeric/date values to avoid type ambiguity; the simple string parser keeps values as strings.
30
- - Ensure network connectivity and any required credentials for the target SCR service.
31
-
32
- Examples
33
- - scrScore with url="loan" and scenario="age=45, income=60000"
34
- - scrScore with url="https://scr-host/models/loan" and scenario={age:45, income:60000}
35
- `;
36
-
37
- let spec = {
38
- name: 'scr-score',
39
- aliases: ['scrScore','scr score','scr_score'],
40
- description: description,
41
- schema: {
42
- url: z.string(),
43
- scenario: z.any()
44
- },
45
- required: ['url'],
46
- handler: async (params) => {
47
- let {url, scenario,_appContext} = params;
48
-
49
- if (url === null) {
50
- return { status: { statusCode: 2, msg: `SCR model ${url} was not specified` }, results: {} };
51
- }
52
-
53
- // Normalize simple string scenarios like "x=1, y=2" into an object
54
- if (typeof scenario === 'string' && scenario.includes('=')) {
55
- scenario = scenario.split(',').reduce((acc, pair) => {
56
- const [k, ...rest] = pair.split('=');
57
- if (!k) return acc;
58
- acc[k.trim()] = rest.join('=').trim();
59
- return acc;
60
- }, {});
61
- }
62
-
63
- let r = await _scrScore({ url: url, scenario: scenario , _appContext: _appContext});
64
- return r;
65
- }
66
- }
67
-
68
- return spec;
69
- }
70
-
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import _scrScore from '../toolHelpers/_scrScore.js';
8
+
9
+ function scrScore(_appContext) {
10
+ let description = `
11
+ ## scr-score
12
+
13
+ Purpose
14
+ Score a scenario using a model deployed as a SCR container in Azure or another host).
15
+
16
+ Inputs
17
+ - url (string, required): SCR model identifier (URL)
18
+ - scenario (string | object | array, optional): Input values to score. Accepts:
19
+ - a comma-separated key=value string (e.g. "x=1, y=2"),
20
+ - a JSON object with field names and values (recommended for typed inputs),
21
+ - an array of objects for batch scoring. If omitted, the tool will return the model's input variable definitions.
22
+
23
+ What it returns
24
+ - When scoring: the SCR endpoint response (predictions, probabilities, scores) merged with or alongside the supplied inputs.
25
+ - When \`scenario\` is omitted: metadata describing the model's input variables (names, types, required/optional).
26
+
27
+ Usage notes
28
+ - Run \`scr-info\` first to inspect the expected input variables and types.
29
+ - Prefer structured objects for numeric/date values to avoid type ambiguity; the simple string parser keeps values as strings.
30
+ - Ensure network connectivity and any required credentials for the target SCR service.
31
+
32
+ Examples
33
+ - scrScore with url="loan" and scenario="age=45, income=60000"
34
+ - scrScore with url="https://scr-host/models/loan" and scenario={age:45, income:60000}
35
+ `;
36
+
37
+ let spec = {
38
+ name: 'scr-score',
39
+ description: description,
40
+ inputSchema: z.object({
41
+ url: z.string(),
42
+ scenario: z.string().optional()
43
+ }),
44
+
45
+ handler: async (params) => {
46
+ let {url, scenario,_appContext} = params;
47
+
48
+ if (url === null) {
49
+ return { status: { statusCode: 2, msg: `SCR model ${url} was not specified` }, results: {} };
50
+ }
51
+
52
+ // Normalize simple string scenarios like "x=1, y=2" into an object
53
+ if (typeof scenario === 'string' && scenario.includes('=')) {
54
+ scenario = scenario.split(',').reduce((acc, pair) => {
55
+ const [k, ...rest] = pair.split('=');
56
+ if (!k) return acc;
57
+ acc[k.trim()] = rest.join('=').trim();
58
+ return acc;
59
+ }, {});
60
+ }
61
+
62
+ let r = await _scrScore({ url: url, scenario: scenario , _appContext: _appContext});
63
+ return r;
64
+ }
65
+ }
66
+
67
+ return spec;
68
+ }
69
+
71
70
  export default scrScore;
@@ -30,16 +30,15 @@ function searchAssets(_appContext) {
30
30
  `;
31
31
 
32
32
  let specs = {
33
- name: 'searchAssets',
33
+ name: 'search-assets',
34
34
  description: description,
35
- schema: {
35
+ inputSchema: z.object({
36
36
  searchstring: z.string(),
37
37
  assetType: z.string(),
38
- start: z.number().default(0),
39
- limit: z.number().default(10),
38
+ start: z.number(),
39
+ limit: z.number()
40
40
 
41
- },
42
- required: ['assetType'],
41
+ }),
43
42
  handler: async (params) => {
44
43
  log('searchAssets params', params);
45
44
  return await _catalogSearch(params, 'search');
@@ -1,66 +1,65 @@
1
- /*
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- import {z} from 'zod';
7
-
8
- function setContext(_appContext) {
9
- let description = `
10
- set-context — set the CAS and SAS server contexts for subsequent tool calls.
11
-
12
- USE when: switch to CAS server, change compute context, check current context, set both
13
- DO NOT USE for: get variables (use get-env), read data (use read-table), run programs (use run-sas-program)
14
-
15
- PARAMETERS
16
- - cas: string — CAS server name (optional), e.g. 'cas-shared-default', 'finance-cas-server'
17
- - sas: string — SAS compute context (optional), e.g. 'SAS Studio Compute Context', 'batch-compute'
18
-
19
- ROUTING RULES
20
- - "use finance-cas-server" → { cas: "finance-cas-server" }
21
- - "switch to SAS Studio Compute Context" → { sas: "SAS Studio Compute Context" }
22
- - "use finance-cas for CAS and batch-compute for SAS" → { cas: "finance-cas", sas: "batch-compute" }
23
- - "what context am I using" → { } (no params, returns current)
24
-
25
- EXAMPLES
26
- - "use finance-cas-server" → { cas: "finance-cas-server" }
27
- - "switch to batch-compute" → { sas: "batch-compute" }
28
- - "what's my current context" → { }
29
-
30
- NEGATIVE EXAMPLES (do not route here)
31
- - "read table cars" (use read-table)
32
- - "what's the value of X" (use get-env)
33
- - "run program" (use run-sas-program)
34
-
35
- ERRORS
36
- Returns current or updated context values {cas, sas}. Error if server not found or invalid name.
37
- `;
38
-
39
- let spec = {
40
- name: 'set-context',
41
- aliases: ['setContext','set context','set_context'],
42
- description: description,
43
- schema: {
44
- cas: z.string().optional(),
45
- sas: z.string().optional()
46
- },
47
-
48
- handler: async (params) => {
49
-
50
- let {cas, sas} = params;
51
- if (typeof cas === 'string' && cas.trim().length > 0) {
52
- _appContext.contexts.cas = cas.trim();
53
- }
54
- if (typeof sas === 'string' && sas.trim().length > 0) {
55
- _appContext.contexts.sas = sas.trim();
56
- }
57
- // Return a structured response without extraneous keys
58
- return {
59
- content: [{ type: 'text', text: JSON.stringify(_appContext.contexts) }],
60
- structuredContent: _appContext.contexts
61
- };
62
- }
63
- }
64
- return spec;
65
- }
66
- export default setContext;
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import {z} from 'zod';
7
+
8
+ function setContext(_appContext) {
9
+ let description = `
10
+ set-context — set the CAS and SAS server contexts for subsequent tool calls.
11
+
12
+ USE when: switch to CAS server, change compute context, check current context, set both
13
+ DO NOT USE for: get variables (use get-env), read data (use read-table), run programs (use run-sas-program)
14
+
15
+ PARAMETERS
16
+ - cas: string — CAS server name (optional), e.g. 'cas-shared-default', 'finance-cas-server'
17
+ - sas: string — SAS compute context (optional), e.g. 'SAS Studio Compute Context', 'batch-compute'
18
+
19
+ ROUTING RULES
20
+ - "use finance-cas-server" → { cas: "finance-cas-server" }
21
+ - "switch to SAS Studio Compute Context" → { sas: "SAS Studio Compute Context" }
22
+ - "use finance-cas for CAS and batch-compute for SAS" → { cas: "finance-cas", sas: "batch-compute" }
23
+ - "what context am I using" → { } (no params, returns current)
24
+
25
+ EXAMPLES
26
+ - "use finance-cas-server" → { cas: "finance-cas-server" }
27
+ - "switch to batch-compute" → { sas: "batch-compute" }
28
+ - "what's my current context" → { }
29
+
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "read table cars" (use read-table)
32
+ - "what's the value of X" (use get-env)
33
+ - "run program" (use run-sas-program)
34
+
35
+ ERRORS
36
+ Returns current or updated context values {cas, sas}. Error if server not found or invalid name.
37
+ `;
38
+
39
+ let spec = {
40
+ name: 'set-context',
41
+ description: description,
42
+ inputSchema: z.object({
43
+ cas: z.string().optional(),
44
+ sas: z.string().optional()
45
+ }),
46
+ handler: async (params) => {
47
+
48
+ let {cas, sas} = params;
49
+ if (typeof cas === 'string' && cas.trim().length > 0) {
50
+ _appContext.contexts.cas = cas.trim();
51
+ }
52
+ if (typeof sas === 'string' && sas.trim().length > 0) {
53
+ _appContext.contexts.sas = sas.trim();
54
+ }
55
+ // Return a structured response without extraneous keys
56
+ return {
57
+ content: [{ type: 'text', text: JSON.stringify(_appContext.contexts) }],
58
+ structuredContent: _appContext.contexts
59
+ };
60
+ }
61
+ }
62
+ return spec;
63
+ }
64
+ export default setContext;
65
+
@@ -1,60 +1,61 @@
1
- /*
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- import _submitCode from '../toolHelpers/_submitCode.js';
6
- import { z } from 'zod';
7
-
8
- function superstat(_appContext) {
9
- let desc = `
10
- ## superstat: compute superstat for two numbers using SAS programming
11
-
12
- ## Details
13
- This is a tool to demonstrate using SAS programming to score. The SAS program for suprestat is
14
- below. In a real application this would be a more complex program that is
15
- available to the SAS server.
16
-
17
-
18
- ods html style=barrettsblue;
19
- data temp;
20
- superstat = (&a + &b) * 42;
21
- run;
22
- proc print data=temp;
23
- run;
24
- ods html close;
25
- run;
26
-
27
- ## Sample Prompt
28
-
29
- - compute superstat for 1 and 2
30
- - compute superstat for 3,5
31
-
32
- `;
33
- let spec = {
34
- name: 'superstat',
35
- description: desc,
36
- schema: {
37
- a: z.number(),
38
- b: z.number()
39
- },
40
- required: ['a', 'b'],
41
- handler: async (params) => {
42
- let src = `
43
- ods html style=barrettsblue;
44
- data temp;
45
- superstat = (&a + &b) * 42;
46
- run;
47
- proc print data=temp;
48
- run;
49
- ods html close;
50
- run;
51
- `;
52
- params.src = src;
53
- let r = await _submitCode(params);
54
- return r;
55
- }
56
-
57
- };
58
- return spec;
59
- }
60
- export default superstat;
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type } from 'node:os';
6
+ import _submitCode from '../toolHelpers/_submitCode.js';
7
+ import { z } from 'zod';
8
+
9
+ function superstat(_appContext) {
10
+ let desc = `
11
+ ## superstat: compute superstat for two numbers using SAS programming
12
+
13
+ ## Details
14
+ This is a tool to demonstrate using SAS programming to score. The SAS program for suprestat is
15
+ below. In a real application this would be a more complex program that is
16
+ available to the SAS server.
17
+
18
+
19
+ ods html style=barrettsblue;
20
+ data temp;
21
+ superstat = (&a + &b) * 42;
22
+ run;
23
+ proc print data=temp;
24
+ run;
25
+ ods html close;
26
+ run;
27
+
28
+ ## Sample Prompt
29
+
30
+ - compute superstat for 1 and 2
31
+ - compute superstat for 3,5
32
+
33
+ `;
34
+ let spec = {
35
+ name: 'superstat',
36
+ description: desc,
37
+ inputSchema: z.object({
38
+ a: z.number().optional()
39
+ }),
40
+ required: ['a', 'b']
41
+ },
42
+ handler: async (params) => {
43
+ let src = `
44
+ ods html style=barrettsblue;
45
+ data temp;
46
+ superstat = (&a + &b) * 42;
47
+ run;
48
+ proc print data=temp;
49
+ run;
50
+ ods html close;
51
+ run;
52
+ `;
53
+ params.src = src;
54
+ let r = await _submitCode(params);
55
+ return r;
56
+ }
57
+
58
+ };
59
+ return spec;
60
+ }
61
+ export default superstat;
@@ -1,59 +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 { z } from 'zod';
6
- import debug from 'debug';
7
-
8
- import _tableInfo from '../toolHelpers/_tableInfo.js';
9
- function tableInfo(_appContext) {
10
-
11
- let describe = `
12
- table-info retrieve metadata about a table in a CAS or SAS library.
13
-
14
- USE when: what columns, describe structure, show schema, table statistics, column info
15
- DO NOT USE for: read data (use read-table), list tables (use list-tables), find table (use find-table), queries (use sas-query)
16
-
17
- PARAMETERS
18
- - table: string — table name (required)
19
- - lib: string — caslib or libref (required)
20
- - server: string (default: 'cas') 'cas' or 'sas'
21
-
22
- ROUTING RULES
23
- - "what columns are in cars" → { table: "cars", lib: "<lib>", server: "cas" }
24
- - "describe table sales in Public" → { table: "sales", lib: "Public", server: "cas" }
25
- - "show schema for mylib.iris on sas" → { table: "iris", lib: "mylib", server: "sas" }
26
-
27
- EXAMPLES
28
- - "what columns in cars" → { table: "cars", lib: "<lib>", server: "cas" }
29
- - "describe structure of customers in Public" → { table: "customers", lib: "Public", server: "cas" }
30
-
31
- NEGATIVE EXAMPLES (do not route here)
32
- - "read table cars" (use read-table)
33
- - "list tables in Public" (use list-tables)
34
- - "does table exist" (use find-table)
35
- - "query table" (use sas-query)
36
-
37
- ERRORS
38
- Returns columns array (name, type, label, format, length) and tableInfo (rowCount, fileSize, created, modified).
39
- `;
40
-
41
- let specs = {
42
- name: 'table-info',
43
- aliases: ['tableInfo','table info','table_info'],
44
- description: describe,
45
- schema: {
46
- table: z.string(),
47
- lib: z.string(),
48
- server: z.string()
49
- },
50
- required: ['table', 'lib'],
51
- handler: async (params) => {
52
- params.describe = true;
53
- let r = await _tableInfo(params);
54
- return r;
55
- }
56
- }
57
- return specs;
58
- }
59
- export default tableInfo;
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { z } from 'zod';
6
+ import debug from 'debug';
7
+
8
+ import _tableInfo from '../toolHelpers/_tableInfo.js';
9
+ import { type } from 'node:os';
10
+ function tableInfo(_appContext) {
11
+
12
+ let describe = `
13
+ table-info — retrieve metadata about a table in a CAS or SAS library.
14
+
15
+ USE when: what columns, describe structure, show schema, table statistics, column info
16
+ DO NOT USE for: read data (use read-table), list tables (use list-tables), find table (use find-table), queries (use sas-query)
17
+
18
+ PARAMETERS
19
+ - table: string — table name (required)
20
+ - lib: string — caslib or libref (required)
21
+ - server: string (default: 'cas') — 'cas' or 'sas'
22
+
23
+ ROUTING RULES
24
+ - "what columns are in cars" → { table: "cars", lib: "<lib>", server: "cas" }
25
+ - "describe table sales in Public" → { table: "sales", lib: "Public", server: "cas" }
26
+ - "show schema for mylib.iris on sas" → { table: "iris", lib: "mylib", server: "sas" }
27
+
28
+ EXAMPLES
29
+ - "what columns in cars" → { table: "cars", lib: "<lib>", server: "cas" }
30
+ - "describe structure of customers in Public" → { table: "customers", lib: "Public", server: "cas" }
31
+
32
+ NEGATIVE EXAMPLES (do not route here)
33
+ - "read table cars" (use read-table)
34
+ - "list tables in Public" (use list-tables)
35
+ - "does table exist" (use find-table)
36
+ - "query table" (use sas-query)
37
+
38
+ ERRORS
39
+ Returns columns array (name, type, label, format, length) and tableInfo (rowCount, fileSize, created, modified).
40
+ `;
41
+
42
+ let specs = {
43
+ name: 'table-info',
44
+ description: describe,
45
+ inputSchema: z.object({
46
+ table: z.string(),
47
+ lib: z.string().optional(),
48
+ server: z.string().optional()
49
+ }),
50
+ handler: async (params) => {
51
+ params.describe = true;
52
+ let r = await _tableInfo(params);
53
+ return r;
54
+ }
55
+ }
56
+ return specs;
57
+ }
58
+ export default tableInfo;