@sassoftware/sas-score-mcp-serverjs 1.0.1-9 → 1.1.1

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 (118) hide show
  1. package/.skills/.claude-plugin/plugin.json +59 -0
  2. package/.skills/agents/sas-score-mcp-serverjs-agent.md +26 -0
  3. package/.skills/copilot-instructions.md +62 -0
  4. package/.skills/skills/README.md +204 -0
  5. package/.skills/skills/detail-strategy/SKILL.md +316 -0
  6. package/.skills/skills/find-library-server/SKILL.md +62 -0
  7. package/.skills/skills/find-resources/SKILL.md +66 -0
  8. package/.skills/skills/list-library/SKILL.md +30 -0
  9. package/.skills/skills/list-mas-job-jobdef/SKILL.md +31 -0
  10. package/.skills/skills/list-tables/SKILL.md +30 -0
  11. package/.skills/skills/read-strategy/SKILL.md +87 -0
  12. package/.skills/skills/request-routing/SKILL.md +112 -0
  13. package/.skills/skills/score-cas/SKILL.md +95 -0
  14. package/.skills/skills/score-job-jobdef/SKILL.md +58 -0
  15. package/.skills/skills/score-mas-scr/SKILL.md +58 -0
  16. package/.skills/skills/score-program/SKILL.md +59 -0
  17. package/.skills/skills/score-strategy/SKILL.md +39 -0
  18. package/README.md +96 -54
  19. package/cli.js +11 -13
  20. package/openApi.yaml +121 -121
  21. package/package.json +16 -14
  22. package/scripts/docs/SCORE_SKILL_REFERENCE.md +17 -16
  23. package/scripts/docs/TOOL_DESCRIPTION_TEMPLATE.md +3 -3
  24. package/scripts/docs/TOOL_UPDATES_SUMMARY.md +65 -63
  25. package/scripts/docs/oauth-http-transport.md +2 -2
  26. package/scripts/docs/sas-mcp-tools-reference.md +43 -32
  27. package/scripts/plot_msrp_usa.py +49 -0
  28. package/scripts/refreshtoken.js +58 -0
  29. package/scripts/runListScr.mjs +16 -0
  30. package/src/createMcpServer.js +4 -1
  31. package/src/expressMcpServer.js +47 -49
  32. package/src/oauthHandlers/authorize.js +4 -1
  33. package/src/oauthHandlers/baseUrl.js +4 -0
  34. package/src/oauthHandlers/callback.js +4 -0
  35. package/src/oauthHandlers/getMetadata.js +4 -0
  36. package/src/oauthHandlers/index.js +4 -0
  37. package/src/oauthHandlers/token.js +4 -0
  38. package/src/openApi.yaml +121 -121
  39. package/src/processHeaders.js +10 -7
  40. package/src/setupSkills.js +1 -18
  41. package/src/toolHelpers/_casScore.js +32 -0
  42. package/src/toolHelpers/_desc.js +14 -0
  43. package/src/toolHelpers/_findJob.js +12 -0
  44. package/src/toolHelpers/_findJobdef.js +10 -0
  45. package/src/toolHelpers/_findLibrary.js +11 -0
  46. package/src/toolHelpers/_findMas.js +13 -0
  47. package/src/toolHelpers/_findScr.js +36 -0
  48. package/src/toolHelpers/_findTable.js +11 -0
  49. package/src/toolHelpers/_listJobdefs.js +12 -2
  50. package/src/toolHelpers/_listJobs.js +19 -8
  51. package/src/toolHelpers/{_listModels.js → _listMas.js} +4 -4
  52. package/src/toolHelpers/_listScr.js +13 -0
  53. package/src/toolHelpers/{_scrInfo.js → _scrDescribe.js} +4 -4
  54. package/src/toolHelpers/_scrScore.js +2 -2
  55. package/src/toolHelpers/_submitCasl.js +19 -17
  56. package/src/toolHelpers/{_tableInfo.js → _tableDescribe.js} +2 -2
  57. package/src/toolHelpers/getLogonPayload.js +2 -2
  58. package/src/toolSet/casModelScore.js +93 -0
  59. package/src/toolSet/casProgramScore.js +105 -0
  60. package/src/toolSet/devaScore.js +11 -6
  61. package/src/toolSet/findJob.js +74 -59
  62. package/src/toolSet/findJobdef.js +67 -64
  63. package/src/toolSet/findLibrary.js +28 -23
  64. package/src/toolSet/findMas.js +72 -0
  65. package/src/toolSet/findScr.js +69 -0
  66. package/src/toolSet/findTable.js +34 -27
  67. package/src/toolSet/getEnv.js +57 -57
  68. package/src/toolSet/jobDescribe.js +65 -0
  69. package/src/toolSet/jobScore.js +90 -0
  70. package/src/toolSet/jobdefDescribe.js +67 -0
  71. package/src/toolSet/jobdefScore.js +85 -0
  72. package/src/toolSet/listJobdefs.js +17 -8
  73. package/src/toolSet/listJobs.js +15 -8
  74. package/src/toolSet/listLibraries.js +16 -10
  75. package/src/toolSet/listMas.js +71 -0
  76. package/src/toolSet/listScr.js +62 -0
  77. package/src/toolSet/listTables.js +78 -66
  78. package/src/toolSet/{runMacro.js → macroScore.js} +86 -82
  79. package/src/toolSet/makeTools.js +39 -25
  80. package/src/toolSet/masDescribe.js +67 -0
  81. package/src/toolSet/masScore.js +95 -0
  82. package/src/toolSet/{runProgram.js → programScore.js} +96 -93
  83. package/src/toolSet/readTable.js +43 -26
  84. package/src/toolSet/sasQuery.js +24 -18
  85. package/src/toolSet/scrDescribe.js +55 -0
  86. package/src/toolSet/scrScore.js +63 -70
  87. package/src/toolSet/searchAssets.js +1 -1
  88. package/src/toolSet/setContext.js +8 -3
  89. package/src/toolSet/superstat.js +61 -61
  90. package/src/toolSet/tableDescribe.js +65 -0
  91. package/.agents/sas-score-mcp-serverjs-agent.md +0 -58
  92. package/.instructions/copilot-instructions.md +0 -201
  93. package/.instructions/enforce-find-resource-strategy.md +0 -35
  94. package/.skills/sas-find-library-smart/SKILL.md +0 -155
  95. package/.skills/sas-find-resource-strategy/SKILL.md +0 -105
  96. package/.skills/sas-list-resource-strategy/SKILL.md +0 -124
  97. package/.skills/sas-list-tables-smart/SKILL.md +0 -128
  98. package/.skills/sas-read-and-score-strategy/SKILL.md +0 -113
  99. package/.skills/sas-read-strategy/SKILL.md +0 -154
  100. package/.skills/sas-request-classifier/SKILL.md +0 -74
  101. package/.skills/sas-score-workflow-strategy/SKILL.md +0 -314
  102. package/scripts/optimize_final.py +0 -140
  103. package/scripts/optimize_tools.py +0 -99
  104. package/scripts/setup-skills.js +0 -34
  105. package/scripts/update_descriptions.py +0 -46
  106. package/src/authpkce.js +0 -219
  107. package/src/handleGetDelete.js +0 -34
  108. package/src/handleRequest.js +0 -112
  109. package/src/hapiMcpServer.js +0 -241
  110. package/src/toolSet/findModel.js +0 -60
  111. package/src/toolSet/listModels.js +0 -56
  112. package/src/toolSet/modelInfo.js +0 -55
  113. package/src/toolSet/modelScore.js +0 -89
  114. package/src/toolSet/runCasProgram.js +0 -98
  115. package/src/toolSet/runJob.js +0 -81
  116. package/src/toolSet/runJobdef.js +0 -82
  117. package/src/toolSet/scrInfo.js +0 -52
  118. package/src/toolSet/tableInfo.js +0 -58
@@ -0,0 +1,62 @@
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 _listScr from '../toolHelpers/_listScr.js';
8
+
9
+ function listScr(_appContext) {
10
+ const isAgent = _appContext && _appContext.agent;
11
+ let description = isAgent ? `
12
+ list-scr — list available SCR models.
13
+ PARAMS: start (number, default 1), limit (number, default 10)
14
+ RETURNS: array of SCR model names and metadata
15
+ ` : `
16
+ list-scr — enumerate models published to scr.
17
+
18
+ USE when: list scr, show scr next page
19
+ DO NOT USE for: ${_appContext.brand}-find model, ${_appContext.brand}-find scr, ${_appContext.brand}-model metadata, ${_appContext.brand}-score model, ${_appContext.brand}-list jobs/tables/libraries
20
+
21
+ PARAMETERS
22
+ - limit: number (default: 10) — page size
23
+ - start: number (default: 1) — 1-based offset
24
+
25
+ ROUTING RULES
26
+ - "list scr" → { start:1, limit:10 }
27
+ - "list 25 scr" → { start:1, limit:25 }
28
+ - "next scr" → { start: start+limit, limit:10 }
29
+
30
+ EXAMPLES
31
+ - "list scr" → { start:1, limit:10 }
32
+ - "list 25 scr" → { start:1, limit:25 }
33
+
34
+ NEGATIVE EXAMPLES (do not route here)
35
+ - "find scr X" (use ${_appContext.brand}-find-scr)
36
+ - "describe scr X" (use ${_appContext.brand}-scr-describe)
37
+ - "score scr X" (use ${_appContext.brand}-scr-score)
38
+ - "list jobs" (use ${_appContext.brand}-list-jobs)
39
+
40
+ ERRORS
41
+ Returns empty array if no scrs found.
42
+ `;
43
+
44
+ let spec = {
45
+ name: 'list-scr',
46
+ description: description,
47
+ inputSchema: z.object({
48
+ limit: z.number().optional(),
49
+ start: z.number().optional()
50
+ }),
51
+ handler: async (params) => {
52
+ let r = await _listScr(params);
53
+ return r;
54
+ }
55
+ }
56
+
57
+ return spec;
58
+ }
59
+
60
+ export default listScr;
61
+
62
+
@@ -1,66 +1,78 @@
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 debug from 'debug';
8
- import _listTables from '../toolHelpers/_listTables.js';
9
-
10
-
11
- function listTables(_appContext) {
12
- const log = debug('tools');
13
-
14
- let description = `
15
- list-tables enumerate tables within a library.
16
-
17
- USE when: list tables in <lib>, show tables in <lib>, next page
18
- DO NOT USE for: find table, list libraries, get table structure (use table-info), read data (use read-table)
19
-
20
- PARAMETERS
21
- - lib: string — library to inspect (required)
22
- - server: string (default: 'cas') 'cas' or 'sas'
23
- - limit: number (default: 10) page size
24
- - start: number (default: 1) — 1-based offset
25
- - where: string — optional filter expression
26
-
27
- ROUTING RULES
28
- - "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
29
- - "list 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
30
- - "list cas tables in Public" → { lib: "Public", server: "cas", start: 1, limit: 10 }
31
-
32
- EXAMPLES
33
- - "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
34
- - "show 25 tables in sashelp" { lib: "sashelp", limit: 25, start: 1 }
35
-
36
- NEGATIVE EXAMPLES (do not route here)
37
- - "list libs" (use list-libraries)
38
- - "find lib Public" (use find-library)
39
- - "describe table cars" (use table-info)
40
- - "read table cars" (use read-table)
41
-
42
- ERRORS
43
- Returns empty array if no tables found.
44
- `;
45
-
46
- let spec = {
47
- name: 'list-tables',
48
- description: description,
49
-
50
- inputSchema: z.object({
51
- lib: z.string(),
52
- server: z.string().optional(),
53
- limit: z.number().optional(),
54
- start: z.number().optional(),
55
- where: z.string().optional()
56
- }),
57
- handler: async (params) => {
58
- let r = await _listTables(params);
59
- return r;
60
- }
61
- }
62
- return spec;
63
- }
64
-
65
- export default listTables;
66
-
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 debug from 'debug';
8
+ import _listTables from '../toolHelpers/_listTables.js';
9
+
10
+
11
+ function listTables(_appContext) {
12
+ const isAgent = _appContext && _appContext.agent;
13
+ const log = debug('tools');
14
+
15
+ let description = isAgent ? `
16
+ list-tables — list tables in a library.
17
+ PARAMS: intent ('list', required), lib (string, required), server ('cas'|'sas', optional), start (number, default 1), limit (number, default 10)
18
+ RETURNS: array of table names and metadata
19
+ ` : `
20
+ list-tables — enumerate tables within a library.
21
+
22
+ USE when: list tables in <lib>, show tables in <lib>, next page
23
+ DO NOT USE for: find table, list libraries, get table structure (use ${_appContext.brand}-table-describe), read data (use ${_appContext.brand}-read-table)
24
+
25
+ PARAMETERS
26
+ - intent: must be 'list' — only pass if user explicitly asked to list/enumerate tables. Do NOT use for read, find, or verify.
27
+ - lib: string — library to inspect (required)
28
+ - server: string (default: 'cas') — 'cas' or 'sas'
29
+ - limit: number (default: 10) — page size
30
+ - start: number (default: 1) — 1-based offset
31
+ - where: string — optional filter expression
32
+
33
+ ROUTING RULES
34
+ - "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
35
+ - "list 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
36
+ - "list cas tables in Public" → { lib: "Public", server: "cas", start: 1, limit: 10 }
37
+
38
+ EXAMPLES
39
+ - "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
40
+ - "show 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
41
+
42
+ NEGATIVE EXAMPLES (do not route here)
43
+ -- "list libs" (use ${_appContext.brand}-list-libraries)
44
+ -- "find lib Public" (use ${_appContext.brand}-find-library)
45
+ -- "describe table cars" (use ${_appContext.brand}-table-describe)
46
+ -- "read table cars" (use ${_appContext.brand}-read-table)
47
+ -- "does table cars exist in Samples" (use ${_appContext.brand}-find-table)
48
+ -- "is table iris in Public" (use ${_appContext.brand}-find-table)
49
+ -- "verify table orders in mylib" (use ${_appContext.brand}-find-table)
50
+
51
+ ERRORS
52
+ Returns empty array if no tables found.
53
+ `;
54
+
55
+ let spec = {
56
+ name: 'list-tables',
57
+ description: description,
58
+
59
+ inputSchema: z.object({
60
+ intent: z.literal('list'),
61
+ lib: z.string(),
62
+ server: z.string().optional(),
63
+ limit: z.number().optional(),
64
+ start: z.number().optional(),
65
+ where: z.string().optional()
66
+ }),
67
+ handler: async (params) => {
68
+ const { intent, ...rest } = params;
69
+ let r = await _listTables(rest);
70
+ return r;
71
+ }
72
+ }
73
+ return spec;
74
+ }
75
+
76
+ export default listTables;
77
+
78
+
@@ -1,82 +1,86 @@
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 _submitCode from '../toolHelpers/_submitCode.js';
8
-
9
-
10
- function runMacro(_appContext) {
11
- let description = `
12
- run-macro submit and execute a SAS macro on SAS Viya server.
13
-
14
- USE when: run macro, execute macro with parameters
15
- DO NOT USE for: arbitrary SAS code (use run-sas-program), jobs, jobdefs
16
-
17
- PARAMETERS
18
- - macro: string — macro name without "%" (required)
19
- - scenario: string — parameters or setup code (optional). Accepts: "x=1, y=abc" or "%let x=1; %let y=abc;"
20
-
21
- ROUTING RULES
22
- - "run macro abc" → { macro: "abc", scenario: "" }
23
- - "run macro abc with x=1, y=2" → { macro: "abc", scenario: "x=1, y=2" }
24
- - "run macro xyz with %let a=1; %let b=2;" → { macro: "xyz", scenario: "%let a=1; %let b=2;" }
25
-
26
- EXAMPLES
27
- - "run macro abc" → { macro: "abc", scenario: "" }
28
- - "run macro summarize with x=1, y=2" → { macro: "summarize", scenario: "x=1, y=2" }
29
-
30
- NEGATIVE EXAMPLES (do not route here)
31
- - "run SAS code" (use run-sas-program)
32
- - "run job X" (use run-job)
33
- - "run jobdef X" (use run-jobdef)
34
-
35
- ERRORS
36
- Returns log, ods, tables created by macro. Auto-converts "x=1, y=2" to "%let x=1; %let y=2;" format.
37
- `;
38
-
39
- let spec = {
40
- name: 'run-macro',
41
- description: description,
42
-
43
- inputSchema: z.object({
44
- macro: z.string(),
45
- scenario: z.string().optional()
46
- }),
47
-
48
- handler: async (params) => {
49
- const scenarioRaw = (params.scenario || '').trim();
50
- let setup = '';
51
- if (scenarioRaw) {
52
- // If the scenario already contains macro syntax, send it through unchanged
53
- const hasMacroSyntax = /%let\b|%[a-zA-Z_]\w*\s*\(|%[a-zA-Z_]\w*\s*;/.test(scenarioRaw) || scenarioRaw.includes('%');
54
- if (hasMacroSyntax) {
55
- setup = scenarioRaw;
56
- } else {
57
- // Convert "x=1,y=abc" -> "%let x=1; %let y=abc;"
58
- setup = scenarioRaw.split(',')
59
- .map(p => p.trim())
60
- .filter(Boolean)
61
- .map(p => {
62
- const [k, ...rest] = p.split('=');
63
- if (!k) return '';
64
- const key = k.trim();
65
- const val = rest.join('=').trim();
66
- return `%let ${key}=${val};`;
67
- })
68
- .filter(Boolean)
69
- .join(' ');
70
- }
71
- }
72
- const src = `${setup} %${params.macro};`;
73
- params.src = src;
74
- let r = await _submitCode(params);
75
- return r;
76
- }
77
- }
78
- return spec;
79
- }
80
-
81
- export default runMacro;
82
-
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 _submitCode from '../toolHelpers/_submitCode.js';
8
+
9
+
10
+ function macroScore(_appContext) {
11
+ const isAgent = _appContext && _appContext.agent;
12
+ let description = isAgent ? `
13
+ macro-score — execute a SAS macro model.
14
+ PARAMS: macro (string, required name without %), scenario (string, optional — "x=1,y=2" or %let syntax)
15
+ RETURNS: log, ODS output, and tables created by macro
16
+ ` : `
17
+ macro-score — submit and execute a SAS macro model on SAS Viya server.
18
+
19
+ USE when: score macro, execute macro with parameters
20
+ DO NOT USE for: arbitrary SAS code (use program-score), jobs (use job-score), jobdefs (use jobdef-score)
21
+
22
+ PARAMETERS
23
+ - macro: string macro name without "%" (required)
24
+ - scenario: string parameters or setup code (optional). Accepts: "x=1, y=abc" or "%let x=1; %let y=abc;"
25
+
26
+ ROUTING RULES
27
+ - "score macro abc" → { macro: "abc", scenario: "" }
28
+ - "score macro abc with x=1, y=2" → { macro: "abc", scenario: "x=1, y=2" }
29
+ - "score macro xyz with %let a=1; %let b=2;" → { macro: "xyz", scenario: "%let a=1; %let b=2;" }
30
+
31
+ EXAMPLES
32
+ - "score macro abc" { macro: "abc", scenario: "" }
33
+ - "score macro summarize with x=1, y=2" { macro: "summarize", scenario: "x=1, y=2" }
34
+
35
+ NEGATIVE EXAMPLES (do not route here)
36
+ - "score SAS code" (use program-score)
37
+ - "score job X" (use job-score)
38
+ - "score jobdef X" (use jobdef-score)
39
+
40
+ ERRORS
41
+ Returns log, ods, tables created by macro. Auto-converts "x=1, y=2" to "%let x=1; %let y=2;" format.
42
+ `;
43
+
44
+ let spec = {
45
+ name: 'macro-score',
46
+ description: description,
47
+
48
+ inputSchema: z.object({
49
+ macro: z.string(),
50
+ scenario: z.string().optional()
51
+ }),
52
+
53
+ handler: async (params) => {
54
+ const scenarioRaw = (params.scenario || '').trim();
55
+ let setup = '';
56
+ if (scenarioRaw) {
57
+ // If the scenario already contains macro syntax, send it through unchanged
58
+ const hasMacroSyntax = /%let\b|%[a-zA-Z_]\w*\s*\(|%[a-zA-Z_]\w*\s*;/.test(scenarioRaw) || scenarioRaw.includes('%');
59
+ if (hasMacroSyntax) {
60
+ setup = scenarioRaw;
61
+ } else {
62
+ // Convert "x=1,y=abc" -> "%let x=1; %let y=abc;"
63
+ setup = scenarioRaw.split(',')
64
+ .map(p => p.trim())
65
+ .filter(Boolean)
66
+ .map(p => {
67
+ const [k, ...rest] = p.split('=');
68
+ if (!k) return '';
69
+ const key = k.trim();
70
+ const val = rest.join('=').trim();
71
+ return `%let ${key}=${val};`;
72
+ })
73
+ .filter(Boolean)
74
+ .join(' ');
75
+ }
76
+ }
77
+ const src = `${setup} %${params.macro};`;
78
+ params.src = src;
79
+ let r = await _submitCode(params);
80
+ return r;
81
+ }
82
+ }
83
+ return spec;
84
+ }
85
+
86
+ export default macroScore;
@@ -3,67 +3,81 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
- import listModels from './listModels.js';
7
- import listTables from './listTables.js';
8
- import modelScore from './modelScore.js';
9
- import modelInfo from './modelInfo.js';
6
+ import listMas from './listMas.js';
7
+
8
+
9
+ import masScore from './masScore.js';
10
+ import masDescribe from './masDescribe.js';
11
+ import findMas from './findMas.js';
12
+
10
13
  import findLibrary from './findLibrary.js';
11
- import readTable from './readTable.js';
12
- import tableInfo from './tableInfo.js';
13
14
  import listLibraries from './listLibraries.js';
14
15
 
15
- import scrInfo from './scrInfo.js';
16
+ import listTables from './listTables.js';
17
+ import findTable from './findTable.js';
18
+ import tableDescribe from './tableDescribe.js';
19
+ import readTable from './readTable.js';
20
+
21
+ import findScr from './findScr.js';
22
+ import listScr from './listScr.js';
23
+ import scrDescribe from './scrDescribe.js';
16
24
  import scrScore from './scrScore.js';
17
25
 
18
26
  import devaScore from './devaScore.js';
19
27
 
20
- import findTable from './findTable.js';
21
- import findModel from './findModel.js';
22
- import runProgram from './runProgram.js';
23
- import runMacro from './runMacro.js';
24
- import runJob from './runJob.js';
28
+ import programScore from './programScore.js';
29
+ import casProgramScore from './casProgramScore.js';
30
+ import casModelScore from './casModelScore.js';
31
+ import macroScore from './macroScore.js';
32
+ import jobScore from './jobScore.js';
25
33
  import listJobs from './listJobs.js';
26
- import runJobdef from './runJobdef.js';
34
+ import jobdefScore from './jobdefScore.js';
27
35
  import findJob from './findJob.js';
28
36
  import listJobdefs from './listJobdefs.js';
29
37
  import findJobdef from './findJobdef.js';
38
+ import jobDescribe from './jobDescribe.js';
39
+ import jobdefDescribe from './jobdefDescribe.js';
30
40
 
31
41
  import sasQuery from './sasQuery.js';
32
42
  import setContext from './setContext.js';
33
43
 
34
-
35
44
  function makeTools(_appContext) {
36
45
  // wrap all tools with
37
46
  let customTools = [];
38
47
 
39
48
  // get the tool definitions and handler
40
49
  let list = [
41
- listModels(_appContext),
42
-
43
- findModel(_appContext),
44
- modelInfo(_appContext),
45
- modelScore(_appContext),
50
+ listMas(_appContext),
51
+ listScr(_appContext),
52
+ findMas(_appContext),
53
+ masDescribe(_appContext),
54
+ masScore(_appContext),
46
55
 
47
- scrInfo(_appContext),
56
+ scrDescribe(_appContext),
48
57
  scrScore(_appContext),
58
+ findScr(_appContext),
49
59
 
50
60
  findLibrary(_appContext),
51
61
  listLibraries(_appContext),
52
62
  findTable(_appContext),
53
- tableInfo(_appContext),
63
+ tableDescribe(_appContext),
54
64
  listTables(_appContext),
55
65
  readTable(_appContext),
56
66
  sasQuery(_appContext),
57
67
 
58
- runProgram(_appContext),
59
- runMacro(_appContext),
68
+ programScore(_appContext),
69
+ casProgramScore(_appContext),
70
+ casModelScore(_appContext),
71
+ macroScore(_appContext),
60
72
 
61
73
  findJob(_appContext),
62
74
  listJobs(_appContext),
63
- runJob(_appContext),
75
+ jobScore(_appContext),
64
76
  listJobdefs(_appContext),
65
77
  findJobdef(_appContext),
66
- runJobdef(_appContext),
78
+ jobDescribe(_appContext),
79
+ jobdefDescribe(_appContext),
80
+ jobdefScore(_appContext),
67
81
 
68
82
  devaScore(_appContext),
69
83
  setContext(_appContext)
@@ -0,0 +1,67 @@
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 debug from 'debug';
8
+ import _masDescribe from '../toolHelpers/_masDescribe.js';
9
+ const log = debug('tools');
10
+
11
+ function masDescribe(_appContext) {
12
+ const isAgent = _appContext && _appContext.agent;
13
+ let description = isAgent ? `
14
+ mas-describe — return input/output schema for a MAS model.
15
+ PARAMS: intent ('describe', required), name (string, required)
16
+ RETURNS: input variables, output variables, model type, description
17
+ ` : `
18
+ mas-describe — return detailed information about a specific MAS model, including its inputs, outputs, and metadata.
19
+
20
+ USE when: what inputs does model need, describe model, show variables for model, model inputs/outputs
21
+ DO NOT USE for: find model, list models, score model, table/job operations
22
+
23
+ PARAMETERS
24
+ - intent: must be 'describe' — only pass if user explicitly asked to describe/inspect a MAS model. Do NOT use for find or verify existence.
25
+ - model: string — model name (required, exact match)
26
+
27
+ ROUTING RULES
28
+ - "what inputs does mas X need?" → { model: "X" }
29
+ - "describe mas Y" → { model: "Y" }
30
+ - "describe mas Y.mas" → { model: "Y" }
31
+ - "show variables for mas Z" → { model: "Z" }
32
+
33
+ EXAMPLES
34
+ - "What inputs does mas churnRisk need?" → { model: "churnRisk" }
35
+ - "Describe mas creditScore" → { model: "creditScore" }
36
+ - "Show variables for myModel" → { model: "myModel" }
37
+
38
+ NEGATIVE EXAMPLES (do not route here)
39
+ - "list mas" (use list-models)
40
+ - "find mas X" (use find-model)
41
+ - "score with mas X" (use model-score)
42
+
43
+ ERRORS
44
+ Returns model metadata: inputs (name, type, role), outputs (name, type, possible_values), model_type, description.
45
+ `;
46
+
47
+ let spec = {
48
+ name: 'mas-describe',
49
+ description: description,
50
+ inputSchema: z.object({
51
+ intent: z.literal('describe'),
52
+ model: z.string()
53
+ }),
54
+ handler: async (params) => {
55
+ const { intent, ...rest } = params;
56
+ if (rest.model != null && rest.model.endsWith('.mas')) {
57
+ rest.model = rest.model.slice(0, -4);
58
+ }
59
+ let r = await _masDescribe(rest);
60
+ return r;
61
+ }
62
+ }
63
+ return spec;
64
+ }
65
+
66
+ export default masDescribe;
67
+
@@ -0,0 +1,95 @@
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 debug from 'debug';
8
+ import _masScoring from '../toolHelpers/_masScoring.js';
9
+ const log = debug('tools');
10
+
11
+ function masScore(_appContext) {
12
+ const isAgent = _appContext && _appContext.agent;
13
+ let description = isAgent ? `
14
+ mas-score — score data using a deployed MAS model.
15
+ PARAMS: model (string, required), scenario (object, optional key=value pairs)
16
+ RETURNS: predictions merged with input values
17
+ ` : `
18
+ mas-score — score data using a deployed model on MAS.
19
+
20
+ USE when: score with model, predict using model, batch scoring, model predictions
21
+ DO NOT USE for: find model, model metadata, list models, run programs/jobs, query tables
22
+
23
+ PARAMETERS
24
+ - model: string — model name (required, exact match)
25
+ - scenario: object — input data as JSON (optional, defaults to {}). Example: {age:45, income:60000}
26
+
27
+
28
+ ROUTING RULES
29
+ - "score with mas model X using a=1, b=2" → { model: "X", scenario: {a:1, b:2} }
30
+ - "score Y.mas for a=1, b=2" → { model: "Y", scenario: {a:1, b:2} }
31
+ - "predict using mas model Y with age=45, income=60000" → { model: "Y", scenario: {age:45, income:60000} }
32
+
33
+ EXAMPLES
34
+ - "score with mas model churn using age=45, income=60000" → { model: "churn", scenario: {age:45, income:60000} }
35
+ - "predict mas model creditScore for credit=700, debt=20000" → { model: "creditScore", scenario: {credit:700, debt:20000} }
36
+
37
+ NEGATIVE EXAMPLES (do not route here)
38
+ - "find model X" (use find-model)
39
+ - "what inputs does model need" (use model-info)
40
+ - "list models" (use list-models)
41
+ - "score job X" (use job-score)
42
+
43
+ ERRORS
44
+ Returns predictions, probabilities, scores merged with input data. Returns error if model not found or scoring fails.
45
+ `;
46
+
47
+
48
+ let spec = {
49
+ name: 'mas-score',
50
+ description: description,
51
+ inputSchema: z.object({
52
+ model: z.string(),
53
+ scenario: z.any()
54
+ }),
55
+
56
+ handler: async (iparams) => {
57
+ let params = {...iparams};
58
+ let scenario = params.scenario;
59
+
60
+ // Convert the scenario string to an object
61
+ // Example: "x=1, y=2, z=3" to { x: 1, y: 2, z: 3 }
62
+ let scenarioObj = {};
63
+ let count = 0;
64
+ if (typeof scenario === 'object') {
65
+ scenarioObj = scenario;
66
+ } else if (Array.isArray(scenario)) {
67
+ scenarioObj = scenario[0];
68
+ } else {
69
+ //console.error('Incoming scenario', scenario);
70
+ scenarioObj = scenario.split(',').reduce((acc, pair) => {
71
+ let [key, value] = pair.split('=');
72
+ acc[key.trim()] = value;
73
+ count++;
74
+ return acc;
75
+ }, {});
76
+ }
77
+ params.scenario = scenarioObj;
78
+ // Drop model extension (e.g., .job, .model)
79
+ if (params.model != null) {
80
+ if (params.model.endsWith('.mas')) {
81
+ params.model = params.model.slice(0, -4);
82
+ }
83
+ }
84
+
85
+ log('masScore params', params);
86
+ // Check if the params.scenario is a string and parse it
87
+ let r = await _masScoring(params)
88
+ return r;
89
+ }
90
+ }
91
+ return spec;
92
+ }
93
+
94
+ export default masScore;
95
+