@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
@@ -1,57 +1,57 @@
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 _getEnv from '../toolHelpers/_getEnv.js';
8
- function getEnv(_appContext) {
9
- let description = `
10
- get-env — retrieve a variable value from the runtime environment.
11
-
12
- USE when: what is the value of, get me, show current, what's the, retrieve environment variable
13
- DO NOT USE for: read table data (use read-table), model info (use model-info), find/run job (use find-job/run-job), set context (use set-context)
14
-
15
- PARAMETERS
16
- - name: string (required) — variable name to retrieve (case-sensitive)
17
-
18
- ROUTING RULES
19
- - "what is the value of <var>" → { name: "<var>" }
20
- - "get me <var>" → { name: "<var>" }
21
- - "show <var>" → { name: "<var>" }
22
- - "get" with no variable → ask "Which variable would you like to retrieve?"
23
- - "what context am I using" → use set-context instead (no params)
24
- - "set <var> to <value>" → use set-context or run-sas-program instead
25
-
26
- EXAMPLES
27
- - "What's the value of myVar" → { name: "myVar" }
28
- - "Get me the configuration variable" → { name: "configuration" }
29
- - "Show the current server setting" → { name: "server" }
30
-
31
- NEGATIVE EXAMPLES (do not route here)
32
- - "Read rows from customers" (use read-table)
33
- - "Get model details for myModel" (use model-info)
34
- - "Set the CAS server to finance-prod" (use set-context)
35
-
36
- ERRORS
37
- Returns variable name with current value, or null if not found. Return structured error with message field.
38
- `;
39
-
40
- let spec = {
41
- name: 'get-env',
42
- description: description,
43
- inputSchema: {
44
- type: 'object',
45
- properties: {
46
- name: { type: 'string' }
47
- },
48
- required: ['name']
49
- },
50
- handler: async (params) => {
51
- return await _getEnv(params);
52
- }
53
- }
54
- return spec;
55
- }
56
- export default getEnv;
57
-
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 _getEnv from '../toolHelpers/_getEnv.js';
8
+ function getEnv(_appContext) {
9
+ let description = `
10
+ get-env — retrieve a variable value from the runtime environment.
11
+
12
+ USE when: what is the value of, get me, show current, what's the, retrieve environment variable
13
+ DO NOT USE for: read table data (use ${_appContext.brand}-read-table), model info (use ${_appContext.brand}-model-info), find/score job (use ${_appContext.brand}-find-job/${_appContext.brand}-job-score), set context (use ${_appContext.brand}-set-context)
14
+
15
+ PARAMETERS
16
+ - name: string (required) — variable name to retrieve (case-sensitive)
17
+
18
+ ROUTING RULES
19
+ - "what is the value of <var>" → { name: "<var>" }
20
+ - "get me <var>" → { name: "<var>" }
21
+ - "show <var>" → { name: "<var>" }
22
+ - "get" with no variable → ask "Which variable would you like to retrieve?"
23
+ - "what context am I using" → use ${_appContext.brand}-set-context instead (no params)
24
+ - "set <var> to <value>" → use ${_appContext.brand}-set-context or ${_appContext.brand}-program-score instead
25
+
26
+ EXAMPLES
27
+ - "What's the value of myVar" → { name: "myVar" }
28
+ - "Get me the configuration variable" → { name: "configuration" }
29
+ - "Show the current server setting" → { name: "server" }
30
+
31
+ NEGATIVE EXAMPLES (do not route here)
32
+ -- "Read rows from customers" (use ${_appContext.brand}-read-table)
33
+ -- "Get model details for myModel" (use ${_appContext.brand}-model-info)
34
+ -- "Set the CAS server to finance-prod" (use ${_appContext.brand}-set-context)
35
+
36
+ ERRORS
37
+ Returns variable name with current value, or null if not found. Return structured error with message field.
38
+ `;
39
+
40
+ let spec = {
41
+ name: 'get-env',
42
+ description: description,
43
+ inputSchema: {
44
+ type: 'object',
45
+ properties: {
46
+ name: { type: 'string' }
47
+ },
48
+ required: ['name']
49
+ },
50
+ handler: async (params) => {
51
+ return await _getEnv(params);
52
+ }
53
+ }
54
+ return spec;
55
+ }
56
+ export default getEnv;
57
+
@@ -0,0 +1,65 @@
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 _findJob from '../toolHelpers/_findJob.js';
7
+ function jobDescribe(_appContext) {
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ job-describe — return input schema for a Job model.
11
+ PARAMS: intent ('describe', required), name (string, required)
12
+ RETURNS: job input variable definitions
13
+ ` : `
14
+ job-describe — return information about a specific SAS Viya job.
15
+
16
+ USE when: describe job, show job details, what does job X do, job metadata, inputs/outputs for job
17
+ DO NOT USE for: find job or verify it exists (use ${_appContext.brand}-find-job), list jobs (use ${_appContext.brand}-list-jobs), score job (use ${_appContext.brand}-job-score)
18
+
19
+ PARAMETERS
20
+ - intent: must be 'describe' — only pass if user explicitly asked to describe/inspect a job. Do NOT use for find or verify existence.
21
+ - name: string (required) — name of job whose details are being requested. Should be exact match to job name.
22
+
23
+ ROUTING RULES
24
+ - "describe job <name>" → { name: "<name>" }
25
+ - "describe model <name.job>"
26
+ - "info for job <name>" → { name: "<name>" }
27
+
28
+ EXAMPLES
29
+ - "describe job cars_job_v4" → { name: "cars_job_v4" }
30
+ - "describe metricsRefresh.job" → { name: "metricsRefresh" }
31
+
32
+ NEGATIVE EXAMPLES (do not route here)
33
+ - "list jobs" (use ${_appContext.brand}-list-jobs)
34
+ - "score job cars_job_v4" (use ${_appContext.brand}-job-score)
35
+ - "score jobdef cars_job_v4" (use ${_appContext.brand}-jobdef-score)
36
+
37
+ ERRORS
38
+ Returns job metadata
39
+ `;
40
+
41
+ let spec = {
42
+ name: 'job-describe',
43
+ description: description,
44
+ inputSchema: z.object({
45
+ intent: z.literal('describe'),
46
+ name: z.string()
47
+ }),
48
+ handler: async (params) => {
49
+ const { intent, ...rest } = params;
50
+ if (rest.name != null && rest.name.endsWith('.job')) {
51
+ rest.name = rest.name.slice(0, -4);
52
+ }
53
+ rest.tool = 'describe';
54
+ let r = await _findJob(rest);
55
+ return r;
56
+ }
57
+ }
58
+
59
+
60
+ /* correct spec for registerTool with inputSchema */
61
+
62
+ return spec;
63
+ }
64
+ export default jobDescribe;
65
+
@@ -0,0 +1,90 @@
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
8
+
9
+ function jobScore(_appContext) {
10
+ const isAgent = _appContext && _appContext.agent;
11
+
12
+ let description = isAgent ? `
13
+ job-score — score by executing a SAS Viya Job model.
14
+ PARAMS: name (string, required), scenario (object, optional)
15
+ RETURNS: job log, ODS output, and any result tables
16
+ ` : `
17
+ job-score — score with a deployed SAS Viya job model.
18
+
19
+ USE when: score with job, run job, execute job model
20
+ DO NOT USE for: arbitrary SAS code (use program-score), macros (use macro-score), list/find jobs
21
+
22
+ PARAMETERS
23
+ - name: string — job name (required)
24
+ - scenario: object — input parameters as JSON (optional, defaults to {}). Example: {month:10, year:2025}
25
+
26
+ ROUTING RULES
27
+ - "score with job xyz" → { name: "xyz" }
28
+ - "score with job xyz with param1=10, param2=val2" → { name: "xyz", scenario: {param1:10, param2:"val2"} }
29
+ - "run job xyz" → { name: "xyz" }
30
+ - "run job xyz with param1=10, param2=val2" → { name: "xyz", scenario: {param1:10, param2:"val2"} }
31
+
32
+ EXAMPLES
33
+ - "score with job xyz" → { name: "xyz" }
34
+ - "score with job monthly_etl with month=10, year=2025" → { name: "monthly_etl", scenario: {month:10, year:2025} }
35
+ - "score with monthly_etl.job with month=10, year=2025" → { name: "monthly_etl", scenario: {month:10, year:2025} }
36
+ - "run job xyz" → { name: "xyz" }
37
+ - "run job monthly_etl with month=10, year=2025" → { name: "monthly_etl", scenario: {month:10, year:2025} }
38
+
39
+ NEGATIVE EXAMPLES (do not route here)
40
+ - "run SAS code" (use program-score)
41
+ - "score macro X" (use macro-score)
42
+ - "list jobs" (use list-jobs)
43
+ - "find job X" (use find-job)
44
+
45
+ ERRORS
46
+ Returns log output, listings, tables from job. Error if job not found.
47
+ `;
48
+
49
+ let spec = {
50
+ name: 'job-score',
51
+ description: description,
52
+ inputSchema: z.object({
53
+ name: z.string(),
54
+ scenario: z.any()
55
+ }),
56
+ handler: async (params) => {
57
+ let {scenario, name} = params;
58
+
59
+ if(name.endsWith('.job')) {
60
+ params.name = name.slice(0, -4);
61
+ }
62
+ // Convert the scenario string to an object
63
+ // Example: "x=1, y=2, z=3" to { x: 1, y: 2, z: 3 }
64
+ let scenarioObj = {};
65
+ let count = 0;
66
+ if (typeof scenario === 'object') {
67
+ scenarioObj = scenario;
68
+ } else if (Array.isArray(scenario)) {
69
+ scenarioObj = scenario[0];
70
+ } else {
71
+ //console.error('Incoming scenario', scenario);
72
+ scenarioObj = scenario.split(',').reduce((acc, pair) => {
73
+ let [key, value] = pair.split('=');
74
+ acc[key.trim()] = value;
75
+ count++;
76
+ return acc;
77
+ }, {});
78
+ }
79
+ params.scenario = scenarioObj;
80
+ params.type = 'job';
81
+ // Provide runtime context for auth and server settings
82
+ let r = await _jobSubmit(params);
83
+ return r;
84
+ }
85
+ };
86
+ return spec;
87
+ }
88
+
89
+ export default jobScore;
90
+
@@ -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
+ import { z } from 'zod';
6
+ import _findJobdef from '../toolHelpers/_findJobdef.js';
7
+ function jobdefDescribe(_appContext) {
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ jobdef-describe — return input schema for a JobDef model.
11
+ PARAMS: intent ('describe', required), name (string, required)
12
+ RETURNS: jobdef input variable definitions
13
+ ` : `
14
+ jobdef-describe — return information about a specific SAS Viya jobdef.
15
+
16
+ USE when: describe jobdef, show jobdef details, what does jobdef X do, jobdef metadata, inputs/outputs for jobdef
17
+ DO NOT USE for: find jobdef or verify it exists (use ${_appContext.brand}-find-jobdef), list jobdefs (use ${_appContext.brand}-list-jobdefs), score jobdef (use ${_appContext.brand}-jobdef-score)
18
+
19
+ PARAMETERS
20
+ - intent: must be 'describe' — only pass if user explicitly asked to describe/inspect a jobdef. Do NOT use for find or verify existence.
21
+ - name: string (required) — name of jobdef whose details are being requested. Should be exact match to jobdef name.
22
+
23
+ ROUTING RULES
24
+ - "describe jobdef <name>" → { name: "<name>" }
25
+ - "describe <name.jobdef>"
26
+ - "describe model <name.jobdef>"
27
+ - "info for jobdef <name>" → { name: "<name>" }
28
+
29
+ EXAMPLES
30
+ - "describe jobdef cars_job_v4" → { name: "cars_job_v4" }
31
+ - "describe metricsRefresh.jobdef" → { name: "metricsRefresh" }
32
+ - "info for jobdef ETL" → { name: "ETL" }
33
+
34
+ NEGATIVE EXAMPLES (do not route here)
35
+ - "list jobdefs" (use ${_appContext.brand}-list-jobdefs)
36
+ - "score jobdef cars_job_v4" (use ${_appContext.brand}-jobdef-score)
37
+ - "execute jobdef cars_job_v4" (use ${_appContext.brand}-jobdef-score)
38
+
39
+ ERRORS
40
+ Returns job metadata
41
+ `;
42
+
43
+ let spec = {
44
+ name: 'jobdef-describe',
45
+ description: description,
46
+ inputSchema: z.object({
47
+ intent: z.literal('describe'),
48
+ name: z.string()
49
+ }),
50
+ handler: async (params) => {
51
+ const { intent, ...rest } = params;
52
+ if (rest.name != null && rest.name.endsWith('.jobdef')) {
53
+ rest.name = rest.name.slice(0, -7);
54
+ }
55
+ rest.tool = 'describe';
56
+ let r = await _findJobdef(rest);
57
+ return r;
58
+ }
59
+ }
60
+
61
+
62
+ /* correct spec for registerTool with inputSchema */
63
+
64
+ return spec;
65
+ }
66
+ export default jobdefDescribe;
67
+
@@ -0,0 +1,85 @@
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
8
+
9
+ function jobdefScore(_appContext) {
10
+ // JSON object for LLM/tooling
11
+ const isAgent = _appContext && _appContext.agent;
12
+ let description = isAgent ? `
13
+ jobdef-score — score by executing a SAS Viya JobDef model.
14
+ PARAMS: name (string, required), scenario (object, optional)
15
+ RETURNS: jobdef log, ODS output, and any result tables
16
+ ` : `
17
+ jobdef-score — score with a deployed SAS Viya job definition model.
18
+
19
+ USE when: score with jobdef, run jobdef, execute jobdef model
20
+ DO NOT USE for: arbitrary SAS code (use program-score), macros (use macro-score), list/find jobdefs
21
+
22
+ PARAMETERS
23
+ - name: string — jobdef name (required)
24
+ - scenario: object — input parameters as JSON (optional, defaults to {}). Example: {month:10, year:2025}
25
+
26
+ ROUTING RULES
27
+ - "score jobdef xyz" → { name: "xyz" }
28
+ - "score jobdef xyz with param1=10, param2=val2" → { name: "xyz", scenario: {param1:10, param2:"val2"} }
29
+
30
+ EXAMPLES
31
+ - "score jobdef xyz" → { name: "xyz" }
32
+ - "score jobdef monthly_report with month=10, year=2025" → { name: "monthly_report", scenario: {month:10, year:2025} }
33
+
34
+ NEGATIVE EXAMPLES (do not route here)
35
+ - "run SAS code" (use program-score)
36
+ - "score macro X" (use macro-score)
37
+ - "list jobdefs" (use list-jobdefs)
38
+ - "find jobdef X" (use find-jobdef)
39
+
40
+ ERRORS
41
+ Returns log output, listings, tables from jobdef. Error if jobdef not found.
42
+ `;
43
+
44
+ let spec = {
45
+ name: 'jobdef-score',
46
+ description: description,
47
+ inputSchema: z.object({
48
+ name: z.string(),
49
+ scenario: z.any()
50
+ }),
51
+ handler: async (params) => {
52
+ let {scenario, name} = params;
53
+
54
+ if (name.endsWith('.job')) {
55
+ params.name = name.slice(0, -4);
56
+ }
57
+ // Convert the scenario string to an object
58
+ // Example: "x=1, y=2, z=3" to { x: 1, y: 2, z: 3 }
59
+ let scenarioObj = {};
60
+ let count = 0;
61
+ if (typeof scenario === 'object') {
62
+ scenarioObj = scenario;
63
+ } else if (Array.isArray(scenario)) {
64
+ scenarioObj = scenario[0];
65
+ } else {
66
+ //console.error('Incoming scenario', scenario);
67
+ scenarioObj = scenario.split(',').reduce((acc, pair) => {
68
+ let [key, value] = pair.split('=');
69
+ acc[key.trim()] = value;
70
+ count++;
71
+ return acc;
72
+ }, {});
73
+ }
74
+ params.scenario = scenarioObj;
75
+ params.type = 'def';
76
+ // Provide runtime context for auth and server settings
77
+ let r = await _jobSubmit(params);
78
+ return r;
79
+ }
80
+ };
81
+ return spec;
82
+ }
83
+
84
+ export default jobdefScore;
85
+
@@ -5,14 +5,19 @@
5
5
  import { z } from 'zod';
6
6
  import _listJobdefs from '../toolHelpers/_listJobdefs.js';
7
7
  function listJobdefs(_appContext) {
8
-
9
- let description = `
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ list-jobdefs — list available JobDef models.
11
+ PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
12
+ RETURNS: array of jobdef names and metadata
13
+ ` : `
10
14
  list-jobdefs — enumerate SAS Viya job definitions (jobdefs) assets.
11
15
 
12
16
  USE when: list jobdefs, show jobdefs, browse jobdefs, list available jobdefs, next page
13
- DO NOT USE for: find single jobdef (use find-jobdef), execute jobdef (use run-jobdef), find job (use find-job), sas code (use run-sas-program)
17
+ DO NOT USE for: find single jobdef (use ${_appContext.brand}-find-jobdef), score jobdef (use ${_appContext.brand}-jobdef-score), find job (use ${_appContext.brand}-find-job), sas code (use ${_appContext.brand}-program-score)
14
18
 
15
19
  PARAMETERS
20
+ - intent: must be 'list' — only pass if user explicitly asked to list/enumerate jobdefs. Do NOT use for find, verify, or execute.
16
21
  - limit: number (default: 10) — number of jobdefs per page
17
22
  - start: number (default: 1) — 1-based page offset
18
23
  - where: string (default: '') — optional filter expression
@@ -28,10 +33,12 @@ EXAMPLES
28
33
  - next jobdefs → { start: 11, limit: 10 }
29
34
 
30
35
  NEGATIVE EXAMPLES (do not route here)
31
- - find jobdef abc (use find-jobdef)
32
- - list jobs (use list-jobs)
33
- - run jobdef abc (use run-jobdef)
34
- - list models (use list-models)
36
+ - find jobdef abc (use ${_appContext.brand}-find-jobdef)
37
+ - does jobdef X exist (use ${_appContext.brand}-find-jobdef)
38
+ - is jobdef X available (use ${_appContext.brand}-find-jobdef)
39
+ - list jobs (use ${_appContext.brand}-list-jobs)
40
+ - score jobdef abc (use ${_appContext.brand}-jobdef-score)
41
+ - list models (use ${_appContext.brand}-list-models)
35
42
 
36
43
  PAGINATION
37
44
  If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
@@ -44,6 +51,7 @@ Surface backend error directly; never fabricate jobdef names.
44
51
  name: 'list-jobdefs',
45
52
  description: description,
46
53
  inputSchema: z.object({
54
+ intent: z.literal('list'),
47
55
  limit: z.number().optional(),
48
56
  start: z.number().optional(),
49
57
  where: z.string().optional()
@@ -51,7 +59,8 @@ Surface backend error directly; never fabricate jobdef names.
51
59
  // No 'server' required; backend context is implicit in helper
52
60
  handler: async (params) => {
53
61
  // _listJobdefs handles all validation and defaults
54
- const result = await _listJobdefs(params);
62
+ const { intent, ...rest } = params;
63
+ const result = await _listJobdefs(rest);
55
64
  return result;
56
65
  }
57
66
  }
@@ -5,14 +5,19 @@
5
5
  import { z } from 'zod';
6
6
  import _listJobs from '../toolHelpers/_listJobs.js';
7
7
  function listJobs(_appContext) {
8
-
9
- let description = `
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ list-jobs — list available Job models.
11
+ PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
12
+ RETURNS: array of job names and metadata
13
+ ` : `
10
14
  list-jobs — enumerate SAS Viya job assets.
11
15
 
12
16
  USE when: list jobs, show jobs, browse jobs, list available jobs, next page
13
- DO NOT USE for: find single job (use find-job), execute job (use run-job), run job def (use run-jobdef), sas code (use run-sas-program)
17
+ DO NOT USE for: find single job (use ${_appContext.brand}-find-job), score job (use ${_appContext.brand}-job-score), score jobdef (use ${_appContext.brand}-jobdef-score), sas code (use ${_appContext.brand}-program-score)
14
18
 
15
19
  PARAMETERS
20
+ - intent: must be 'list' — only pass if user explicitly asked to list/enumerate jobs. Do NOT use for find, verify, or execute.
16
21
  - limit: number (default: 10) — number of jobs per page
17
22
  - start: number (default: 1) — 1-based page offset
18
23
  - where: string (default: '') — optional filter expression
@@ -28,10 +33,10 @@ EXAMPLES
28
33
  - next jobs → { start: 11, limit: 10 }
29
34
 
30
35
  NEGATIVE EXAMPLES (do not route here)
31
- - find job abc (use find-job)
32
- - run job abc (use run-job)
33
- - list models (use list-models)
34
- - list tables in lib xyz (use list-tables)
36
+ - find job abc (use ${_appContext.brand}-find-job)
37
+ - score job abc (use ${_appContext.brand}-job-score)
38
+ - list models (use ${_appContext.brand}-list-models)
39
+ - list tables in lib xyz (use ${_appContext.brand}-list-tables)
35
40
 
36
41
  PAGINATION
37
42
  If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
@@ -44,6 +49,7 @@ Surface backend error directly; never fabricate job names.
44
49
  name: 'list-jobs',
45
50
  description: description,
46
51
  inputSchema: z.object({
52
+ intent: z.literal('list'),
47
53
  limit: z.number().optional(),
48
54
  start: z.number().optional(),
49
55
  where: z.string().optional()
@@ -51,7 +57,8 @@ Surface backend error directly; never fabricate job names.
51
57
  // No 'server' required; backend context is implicit in helper
52
58
  handler: async (params) => {
53
59
  // _listJob handles all validation and defaults
54
- const result = await _listJobs(params);
60
+ const { intent, ...rest } = params;
61
+ const result = await _listJobs(rest);
55
62
  return result;
56
63
  }
57
64
  }
@@ -5,13 +5,19 @@
5
5
  import { z } from 'zod';
6
6
  import _listLibrary from '../toolHelpers/_listLibrary.js';
7
7
  function listLibraries(_appContext) {
8
- let description = `
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ list-libraries — list available libraries.
11
+ PARAMS: intent ('list', required), server ('cas'|'sas'|'all', optional), start (number, default 1), limit (number, default 10)
12
+ RETURNS: array of library names and server assignments
13
+ ` : `
9
14
  list-libraries — enumerate CAS or SAS libraries.
10
15
 
11
- USE when user asks to: list/show/enumerate libraries, caslibs, sas libs, or available libraries.
12
- DO NOT USE for: listing tables in a library (→ list-tables), column/table metadata, job execution, models, scoring.
16
+ USE ONLY when: user explicitly asks to list, browse, or enumerate libraries — "list libraries", "show all libs", "browse libraries", "what libraries are available", "next page". Never use to verify if a specific library exists.
17
+ DO NOT USE for: verify or check if a specific library exists (use ${_appContext.brand}-find-library instead), listing tables in a library (→ ${_appContext.brand}-list-tables), column/table metadata, job execution, models, scoring.
13
18
 
14
19
  PARAMETERS
20
+ - intent: must be 'list' — only pass if user explicitly asked to list/enumerate libraries. Do NOT use for read, find, or verify.
15
21
  - server: 'cas' | 'sas' | 'all' (default: 'all')
16
22
  - limit: integer > 0 (default: 10)
17
23
  - start: 1-based offset (default: 1)
@@ -38,9 +44,9 @@ EXAMPLES
38
44
  - "filter cas libs" (no filter given) → ask: "What filter expression should I apply?"
39
45
 
40
46
  NEGATIVE EXAMPLES (do not route here)
41
- - "list tables in SASHELP" → list-tables
42
- - "list models / jobs / jobdefs"→ respective tools
43
- - "run a program to create a lib" → run-sas-program
47
+ -- "list tables in SASHELP" → ${_appContext.brand}-list-tables
48
+ -- "list models / jobs / jobdefs"→ respective tools
49
+ -- "score a program to create a lib" → ${_appContext.brand}-program-score
44
50
 
45
51
  PAGINATION
46
52
  If returned item count === limit, hint: next start = start + limit.
@@ -58,6 +64,7 @@ Return structured error with a message field. Never hallucinate library names.
58
64
  name: 'list-libraries',
59
65
  description: description,
60
66
  inputSchema: z.object({
67
+ intent: z.literal('list'),
61
68
  server: z.string().optional(),
62
69
  limit: z.number().optional(),
63
70
  start: z.number().optional(),
@@ -65,10 +72,9 @@ Return structured error with a message field. Never hallucinate library names.
65
72
  }),
66
73
  // 'server' has a default so we don't mark it required
67
74
  handler: async (params) => {
68
- // normalize server just in case caller sends 'CAS'/'SAS'
69
- params.server = (params.server || 'all').toLowerCase();
70
-
71
- let r = await _listLibrary(params);
75
+ const { intent, ...rest } = params;
76
+ rest.server = (rest.server || 'all').toLowerCase();
77
+ let r = await _listLibrary(rest);
72
78
  return r;
73
79
  }
74
80
  };
@@ -0,0 +1,71 @@
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 _listMas from '../toolHelpers/_listMas.js';
8
+
9
+ function listMas(_appContext) {
10
+ const isAgent = _appContext && _appContext.agent;
11
+ let description = isAgent ? `
12
+ list-mas — list available MAS models.
13
+ PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
14
+ RETURNS: array of MAS model names and metadata
15
+ ` : `
16
+ list-mas — enumerate models published to MAS.
17
+
18
+ USE ONLY when: user explicitly asks to browse or enumerate models — "list models", "show all models", "list mas", "next page". Never use to verify if a specific model exists.
19
+ DO NOT USE for: verify or check if a specific model exists (use ${_appContext.brand}-find-mas or ${_appContext.brand}-find-model instead), find model, find mas, model metadata, score model, list jobs/tables/libraries
20
+
21
+ PARAMETERS
22
+ - intent: must be 'list' — only pass if user explicitly asked to list/enumerate MAS models. Do NOT use for read, find, or verify.
23
+ - limit: number (default: 10) — page size
24
+ - start: number (default: 1) — 1-based offset
25
+
26
+ ROUTING RULES
27
+ - "list models" → { start:1, limit:10 }
28
+ - "list 25 models" → { start:1, limit:25 }
29
+ - "next models" → { start: start+limit, limit:10 }
30
+ - "list mas" → { start:1, limit:10 }
31
+ - "list 25 mas" → { start:1, limit:25 }
32
+ - "next mas" → { start: start+limit, limit:10 }
33
+
34
+ EXAMPLES
35
+ - "list models" → { start:1, limit:10 }
36
+ - "list 25 models" → { start:1, limit:25 }
37
+ - "list mas" → { start:1, limit:10 }
38
+ - "list 25 mas" → { start:1, limit:25 }
39
+
40
+ NEGATIVE EXAMPLES (do not route here)
41
+ - "find model X" (use ${_appContext.brand}-find-mas)
42
+ - "does model churn_predictor exist" (use ${_appContext.brand}-find-mas)
43
+ - "is model X published to MAS" (use ${_appContext.brand}-find-mas)
44
+ - "describe model X" (use ${_appContext.brand}-model-info)
45
+ - "score model X" (use ${_appContext.brand}-model-score)
46
+ - "list jobs" (use ${_appContext.brand}-list-jobs)
47
+
48
+ ERRORS
49
+ Returns empty array if no models found.
50
+ `;
51
+
52
+ let spec = {
53
+ name: 'list-mas',
54
+ description: description,
55
+ inputSchema: z.object({
56
+ intent: z.literal('list'),
57
+ limit: z.number().optional(),
58
+ start: z.number().optional()
59
+ }),
60
+ handler: async (params) => {
61
+ const { intent, ...rest } = params;
62
+ let r = await _listMas(rest);
63
+ return r;
64
+ }
65
+ }
66
+
67
+ return spec;
68
+ }
69
+
70
+ export default listMas;
71
+