@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,93 +1,96 @@
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
- function runProgram(_appContext) {
10
- let description = `
11
- run-sas-program execute SAS code or programs on SAS Viya server.
12
-
13
- USE when: run program, execute SAS code, run .sas file
14
- DO NOT USE for: macros (use run-macro), jobs (use run-job), jobdefs (use run-jobdef), SQL queries (use sas-query), read data (use read-table)
15
-
16
- PARAMETERS
17
- - src: string — SAS code or .sas filename (required)
18
- - folder: string (default: '') server folder path for .sas files
19
- - scenario: string | object parameter values. Accepts: "x=1, y=2" or {x:1, y:2}
20
- - output: string (default: '') — table name to return (case-sensitive)
21
- - limit: number (default: 100) — max rows from output
22
-
23
- ROUTING RULES
24
- - "run program 'data a; x=1; run;'" { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
25
- - "run sas program sample folder=/Public/models" → { src: "sample", folder: "/Public/models", output: "", limit: 100 }
26
- - "run program with name=John, age=45" → { src: "<code>", scenario: {name:"John", age:45}, output: "", limit: 100 }
27
-
28
- EXAMPLES
29
- - "run program 'data a; x=1; run;'" → { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
30
- - "run sas file sample in /Public" → { src: "sample", folder: "/Public", output: "", limit: 100 }
31
-
32
- NEGATIVE EXAMPLES (do not route here)
33
- - "run macro X" (use run-macro)
34
- - "run job X" (use run-job)
35
- - "run jobdef X" (use run-jobdef)
36
- - "SQL query" (use sas-query)
37
- - "read table" (use read-table)
38
-
39
- ERRORS
40
- Returns log, ods, tables array, data (if output specified). Error if execution fails.
41
- `;
42
-
43
- let spec = {
44
- name: 'run-program',
45
- description: description,
46
- inputSchema: z.object({
47
- src: z.string(),
48
- scenario: z.string().optional(),
49
- output: z.string().optional(),
50
- folder: z.string().optional(),
51
- limit: z.number().optional()
52
- }),
53
- handler: async (params) => {
54
- let {src, folder, scenario, _appContext} = params;
55
- // figure out src
56
- let isrc = src;
57
- if (folder != null && folder.trim().length > 0) {
58
- if (isrc.indexOf('.sas') < 0) {
59
- isrc = isrc + '.sas';
60
- }
61
- isrc = `
62
- filename mcptemp filesrvc folderpath="${folder}";
63
- %include mcptemp("${isrc}");
64
- filename mcptemp clear;
65
- `;
66
- }
67
- // figure out macros
68
-
69
- if (typeof scenario === 'string' && scenario.includes('=')) {
70
- scenario = scenario.split(',').reduce((acc, pair) => {
71
- const [k, ...rest] = pair.split('=');
72
- if (!k) return acc;
73
- acc[k.trim()] = rest.join('=').trim();
74
- return acc;
75
- }, {});
76
- }
77
- let iparms = {
78
- args: scenario,
79
- output: params.output,
80
- limit: params.limit,
81
- src: isrc,
82
- _appContext: _appContext
83
- }
84
- // console.error('iparms', iparms);
85
- let r = await _submitCode(iparms);
86
- return r;
87
- }
88
- }
89
- return spec;
90
- }
91
-
92
- export default runProgram;
93
-
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
+ function programScore(_appContext) {
10
+ const isAgent = _appContext && _appContext.agent;
11
+ let description = isAgent ? `
12
+ program-score — execute a SAS program model.
13
+ PARAMS: src (string, required), folder (string, optional), scenario (string|object, optional), output (string, optional), limit (number, optional)
14
+ RETURNS: log, ODS output, optional output table rows
15
+ ` : `
16
+ program-score — execute a SAS program model on SAS Viya server.
17
+
18
+ USE when: score program, execute SAS code, run .sas file
19
+ DO NOT USE for: macros (use macro-score), jobs (use job-score), jobdefs (use jobdef-score), SQL queries (use sas-query), read data (use read-table)
20
+
21
+ PARAMETERS
22
+ - src: string — SAS code or .sas filename (required)
23
+ - folder: string (default: '') — server folder path for .sas files
24
+ - scenario: string | object parameter values. Accepts: "x=1, y=2" or {x:1, y:2}
25
+ - output: string (default: '') table name to return (case-sensitive)
26
+ - limit: number (default: 100) max rows from output
27
+
28
+ ROUTING RULES
29
+ - "score program 'data a; x=1; run;'" → { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
30
+ - "score sas program sample folder=/Public/models" → { src: "sample", folder: "/Public/models", output: "", limit: 100 }
31
+ - "score program with name=John, age=45" → { src: "<code>", scenario: {name:"John", age:45}, output: "", limit: 100 }
32
+
33
+ EXAMPLES
34
+ - "score program 'data a; x=1; run;'" { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
35
+ - "score sas file sample in /Public" { src: "sample", folder: "/Public", output: "", limit: 100 }
36
+
37
+ NEGATIVE EXAMPLES (do not route here)
38
+ - "score macro X" (use macro-score)
39
+ - "score job X" (use job-score)
40
+ - "score jobdef X" (use jobdef-score)
41
+ - "SQL query" (use sas-query)
42
+ - "read table" (use read-table)
43
+
44
+ ERRORS
45
+ Returns log, ods, tables array, data (if output specified). Error if execution fails.
46
+ `;
47
+
48
+ let spec = {
49
+ name: 'program-score',
50
+ description: description,
51
+ inputSchema: z.object({
52
+ src: z.string(),
53
+ scenario: z.string().optional(),
54
+ output: z.string().optional(),
55
+ folder: z.string().optional(),
56
+ limit: z.number().optional()
57
+ }),
58
+ handler: async (params) => {
59
+ let {src, folder, scenario, _appContext} = params;
60
+ // figure out src
61
+ let isrc = src;
62
+ if (folder != null && folder.trim().length > 0) {
63
+ if (isrc.indexOf('.sas') < 0) {
64
+ isrc = isrc + '.sas';
65
+ }
66
+ isrc = `
67
+ filename mcptemp filesrvc folderpath="${folder}";
68
+ %include mcptemp("${isrc}");
69
+ filename mcptemp clear;
70
+ `;
71
+ }
72
+ // figure out macros
73
+
74
+ if (typeof scenario === 'string' && scenario.includes('=')) {
75
+ scenario = scenario.split(',').reduce((acc, pair) => {
76
+ const [k, ...rest] = pair.split('=');
77
+ if (!k) return acc;
78
+ acc[k.trim()] = rest.join('=').trim();
79
+ return acc;
80
+ }, {});
81
+ }
82
+ let iparms = {
83
+ args: scenario,
84
+ output: params.output,
85
+ limit: params.limit,
86
+ src: isrc,
87
+ _appContext: _appContext
88
+ }
89
+ let r = await _submitCode(iparms);
90
+ return r;
91
+ }
92
+ }
93
+ return spec;
94
+ }
95
+
96
+ export default programScore;
@@ -1,5 +1,5 @@
1
- /*
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { z } from 'zod';
@@ -7,36 +7,52 @@ import debug from 'debug';
7
7
 
8
8
  import _readTable from '../toolHelpers/_readTable.js';
9
9
  function readTable(_appContext) {
10
-
11
- let describe = `
12
- read-table retrieve rows from a table in a CAS or SAS library.
10
+ const isAgent = _appContext && _appContext.agent;
11
+
12
+ let describe = isAgent ? `
13
+ read-table — read rows from a CAS or SAS table.
14
+ PARAMS: lib (string, required), table (string, required), server ('cas'|'sas', required), where (string, optional filter), start (number, default 1), limit (number, default 10)
15
+ RETURNS: array of row objects
16
+ ` : `
17
+ read-table - retrieve rows from a table in a CAS or SAS library.
13
18
 
14
19
  USE when: read table, show rows, read from library, filtered data with WHERE
15
- DO NOT USE for: list tables, table structure (use table-info), SQL queries (use sas-query), SAS programs
20
+ DO NOT USE for: list tables, table structure (use table-describe), SQL queries (use sas-query), SAS programs
16
21
 
17
22
  PARAMETERS
18
- - table: string table name (required)
19
- - lib: string caslib or libref (required)
20
- - server: string (default: 'cas') 'cas' or 'sas'
21
- - start: number (default: 1) 1-based row index
22
- - limit: number (default: 10) max rows (1-1000)
23
- - where: string SQL WHERE clause filter
24
- - format: boolean (default: true) formatted or raw values
23
+ - table: string — table name (required)
24
+ - lib: string — caslib or libref (required)
25
+ - server: string (default: 'cas') — 'cas' or 'sas'
26
+ - start: number (default: 1) — 1-based row index
27
+ - limit: number (default: 10) — max rows (1-1000)
28
+ - where: string — SQL WHERE clause filter
29
+ - format: boolean (default: true) — formatted or raw values
30
+
31
+ PARSING ROWS FROM USER INPUT
32
+ "first N rows/records" → start: 1, limit: N ("first" = count from beginning, never an offset)
33
+ "top N rows" → start: 1, limit: N
34
+ "N rows" / "N records" → start: 1, limit: N
35
+ "read N rows from lib.table" → lib: "lib", table: "table", start: 1, limit: N
36
+ "rows N to M" → start: N, limit: M-N+1
37
+ "starting from row N" → start: N, limit: 10 (default)
38
+ (no count specified) → start: 1, limit: 10 (default)
39
+
40
+ DOTTED FORMAT: "lib.table" → lib: "lib", table: "table" (split on first dot)
25
41
 
26
42
  ROUTING RULES
27
- - "read table cars in Samples" { table: "cars", lib: "Samples", start: 1, limit: 10 }
28
- - "show 25 rows from customers" { table: "customers", lib: "<lib>", limit: 25, start: 1 }
29
- - "read from mylib.orders where status='shipped'" { table: "orders", lib: "mylib", where: "status='shipped'", start: 1, limit: 10 }
43
+ - "read table cars in Samples" → { table: "cars", lib: "Samples", start: 1, limit: 10 }
44
+ - "show 25 rows from customers" → { table: "customers", lib: "<lib>", limit: 25, start: 1 }
45
+ - "read from mylib.orders where status='shipped'" → { table: "orders", lib: "mylib", where: "status='shipped'", start: 1, limit: 10 }
30
46
 
31
47
  EXAMPLES
32
- - "read table cars in Samples" { table: "cars", lib: "Samples", start: 1, limit: 10 }
33
- - "show 25 rows from customers" { table: "customers", lib: "mylib", limit: 25, start: 1 }
48
+ - "read table cars in Samples" → { table: "cars", lib: "Samples", start: 1, limit: 10 }
49
+ - "show 25 rows from customers" → { table: "customers", lib: "mylib", limit: 25, start: 1 }
34
50
 
35
51
  NEGATIVE EXAMPLES (do not route here)
36
52
  - "list tables in Samples" (use list-tables)
37
- - "what columns are in cars" (use table-info)
53
+ - "what columns are in cars" (use table-describe)
38
54
  - "execute SQL query" (use sas-query)
39
- - "run SAS code" (use run-sas-program)
55
+ - "run SAS code" (use program-score)
40
56
 
41
57
  ERRORS
42
58
  Returns rows array, total count, filtered_count, columns metadata. Empty array if no matches.
@@ -46,12 +62,12 @@ Returns rows array, total count, filtered_count, columns metadata. Empty array i
46
62
  name: 'read-table',
47
63
  description: describe,
48
64
  inputSchema: z.object({
49
- table: z.string(),
50
- lib: z.string().optional(),
51
- start: z.number().optional(),
52
- limit: z.number().optional(),
53
- server: z.string().optional(),
54
- where: z.string().optional()
65
+ table: z.string().min(1),
66
+ lib: z.string().min(1).optional(),
67
+ start: z.number().int().min(1).optional(),
68
+ limit: z.number().int().min(1).max(1000).optional(),
69
+ server: z.enum(['cas', 'sas']).optional(),
70
+ where: z.string().min(1).optional()
55
71
  }),
56
72
  handler: async (params) => {
57
73
  let r = await _readTable(params,'query');
@@ -61,3 +77,4 @@ Returns rows array, total count, filtered_count, columns metadata. Empty array i
61
77
  return specs;
62
78
  }
63
79
  export default readTable;
80
+
@@ -1,38 +1,43 @@
1
- /*
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import {z} from 'zod';
6
6
  import _jobSubmit from '../toolHelpers/_jobSubmit.js';
7
7
 
8
- function sasQuery() {
9
-
10
- let description = `
11
- sas-query convert natural language questions into SQL queries and execute them.
8
+ function sasQuery(_appContext) {
9
+ const isAgent = _appContext && _appContext.agent;
10
+
11
+ let description = isAgent ? `
12
+ sas-query — run a SQL aggregation query against a table.
13
+ PARAMS: table (string as lib.table, required), query (string, SQL WHERE/aggregation clause, required)
14
+ RETURNS: aggregated query result rows
15
+ ` : `
16
+ sas-query - convert natural language questions into SQL queries and execute them.
12
17
 
13
18
  USE when: how many/count/total/average by, aggregated analytics, complex filtering, statistical summaries
14
- DO NOT USE for: raw reads without filtering (use read-table), table structure (use table-info), SAS programs (use run-sas-program), jobs/jobdefs
19
+ DO NOT USE for: raw reads without filtering (use read-table), table structure (use table-describe), SAS programs (use program-score), jobs/jobdefs
15
20
 
16
21
  PARAMETERS
17
- - table: string table in lib.table format (required), e.g. "Public.cars" or "sashelp.class"
18
- - query: string natural language question (required)
19
- - sql: string pre-generated SQL SELECT (optional, LLM generates)
20
- - job: string (default: 'program') job name to execute
22
+ - table: string — table in lib.table format (required), e.g. "Public.cars" or "sashelp.class"
23
+ - query: string — natural language question (required)
24
+ - sql: string — pre-generated SQL SELECT (optional, LLM generates)
25
+ - job: string (default: 'program') — job name to execute
21
26
 
22
27
  ROUTING RULES
23
- - "how many cars by make in sashelp.cars" { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
24
- - "average salary by department in Public.employees" { table: "Public.employees", query: "average salary by department", sql: "SELECT department, AVG(salary) FROM Public.employees GROUP BY department" }
28
+ - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
29
+ - "average salary by department in Public.employees" → { table: "Public.employees", query: "average salary by department", sql: "SELECT department, AVG(salary) FROM Public.employees GROUP BY department" }
25
30
 
26
31
  EXAMPLES
27
- - "how many cars by make in sashelp.cars" { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
28
- - "total sales by region from mylib.sales" { table: "mylib.sales", query: "total sales by region", sql: "SELECT region, SUM(amount) FROM mylib.sales GROUP BY region" }
32
+ - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
33
+ - "total sales by region from mylib.sales" → { table: "mylib.sales", query: "total sales by region", sql: "SELECT region, SUM(amount) FROM mylib.sales GROUP BY region" }
29
34
 
30
35
  NEGATIVE EXAMPLES (do not route here)
31
36
  - "read table cars" (use read-table)
32
37
  - "show 10 rows" (use read-table)
33
- - "table structure" (use table-info)
34
- - "run SAS code" (use run-sas-program)
35
- - "run job/macro" (use run-job/run-macro)
38
+ - "table structure" (use table-describe)
39
+ - "run SAS code" (use program-score)
40
+ - "score job/macro" (use job-score/macro-score)
36
41
 
37
42
  ERRORS
38
43
  Returns rows array, columns metadata, log. Returns error if SQL invalid or table not found.
@@ -75,3 +80,4 @@ Returns rows array, columns metadata, log. Returns error if SQL invalid or table
75
80
  }
76
81
  export default sasQuery;
77
82
 
83
+
@@ -0,0 +1,55 @@
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 _scrDescribe from '../toolHelpers/_scrDescribe.js';
8
+
9
+ function scrDescribe(_appContext) {
10
+ const isAgent = _appContext && _appContext.agent;
11
+ let description = isAgent ? `
12
+ scr-describe — return input/output schema for a SCR model.
13
+ PARAMS: intent ('describe', required), name (string, required)
14
+ RETURNS: input/output schema and model metadata
15
+ ` : `
16
+ scr-describe - return the input/output schema and metadata for an SCR (Score Code Runtime) model.
17
+
18
+ Inputs
19
+ - intent: must be 'describe' — only pass if user explicitly asked to describe/inspect an SCR model. Do NOT use for find or verify existence.
20
+ - name (string): The SCR model identifier.
21
+ What it returns
22
+ - A JSON object describing the model's interface, typically including:
23
+ - Input variables (names, types, required/optional)
24
+ - Output variables (predictions, probabilities, scores)
25
+
26
+
27
+ Usage notes
28
+ - Ensure network connectivity and credentials for the remote SCR service when needed.
29
+ - Use scr-score to score data after inspecting the schema.
30
+
31
+ Examples
32
+ - describe scr model "loan"
33
+ - info for scr model "loan"
34
+ `;
35
+
36
+ let spec = {
37
+ name: 'scr-describe',
38
+ description: description,
39
+ inputSchema: z.object({
40
+ intent: z.literal('describe'),
41
+ name: z.string()
42
+ }),
43
+ handler: async (params) => {
44
+ const { intent, name, _appContext } = params;
45
+ if (name === null) {
46
+ return { status: { statusCode: 2, msg: `SCR model ${name} not found` }, results: {} };
47
+ }
48
+ let r = await _scrDescribe({name, _appContext});
49
+ return r;
50
+ }
51
+ }
52
+ return spec;
53
+ }
54
+
55
+ export default scrDescribe;
@@ -1,70 +1,63 @@
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
-
70
- export default scrScore;
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
+ const isAgent = _appContext && _appContext.agent;
11
+ let description = isAgent ? `
12
+ scr-score — score a scenario using a SCR model endpoint.
13
+ PARAMS: name (string, required), scenario (object, optional)
14
+ RETURNS: SCR endpoint response with predictions merged with inputs
15
+ ` : `
16
+ scr-score - score a scenario using a model deployed as a SCR container in Azure or another host.
17
+
18
+ Inputs
19
+ - name (string, required): SCR model identifier (URL)
20
+ - scenario (object, optional): Input values to score as a JSON object (e.g. {age:45, income:60000}). If omitted, defaults to {} and the tool will return the model's input variable definitions.
21
+
22
+ What it returns
23
+ - When scoring: the SCR endpoint response (predictions, probabilities, scores) merged with or alongside the supplied inputs.
24
+ - When \`scenario\` is omitted: metadata describing the model's input variables (names, types, required/optional).
25
+
26
+ Usage notes
27
+ - Run \`scr-describe\` first to inspect the expected input variables and types.
28
+ - Prefer structured objects for numeric/date values to avoid type ambiguity; the simple string parser keeps values as strings.
29
+ - Ensure network connectivity and any required credentials for the target SCR service.
30
+
31
+ Examples
32
+ - scrScore with name="loan" and scenario={age:45, income:60000}
33
+ `;
34
+
35
+ let spec = {
36
+ name: 'scr-score',
37
+ description: description,
38
+ inputSchema: z.object({
39
+ name: z.string(),
40
+ scenario: z.union([z.record(z.any()), z.string()]).optional()
41
+ }),
42
+
43
+ handler: async (params) => {
44
+ let {name, _appContext} = params;
45
+ let scenario = params.scenario;
46
+ if (typeof scenario === 'string') {
47
+ try { scenario = JSON.parse(scenario); } catch { scenario = {}; }
48
+ }
49
+ if (name === null) {
50
+ return { status: { statusCode: 2, msg: `SCR model ${name} was not specified` }, results: {} };
51
+ }
52
+
53
+ const scenarioObj = (scenario != null && typeof scenario === 'object') ? scenario : {};
54
+
55
+ let r = await _scrScore({ name: name, scenario: scenarioObj, _appContext: _appContext});
56
+ return r;
57
+ }
58
+ }
59
+
60
+ return spec;
61
+ }
62
+
63
+ export default scrScore;
@@ -11,7 +11,7 @@ function searchAssets(_appContext) {
11
11
  const log = debug('tools');
12
12
 
13
13
  let description = `
14
- ## searchAssets: Search the SAS Catalog for assets using a flexible search string.
14
+ search-assets - Search the SAS Catalog for assets using a flexible search string.
15
15
 
16
16
  - Supports searching for various asset types (e.g., datasets, dataflows, models).
17
17
  - the default asset type is 'datasets'.
@@ -6,11 +6,16 @@
6
6
  import {z} from 'zod';
7
7
 
8
8
  function setContext(_appContext) {
9
- let description = `
9
+ const isAgent = _appContext && _appContext.agent;
10
+ let description = isAgent ? `
11
+ set-context — set runtime context variables (CAS server, SAS server, etc.).
12
+ PARAMS: cas (string, optional), sas (string, optional), other key=value context fields
13
+ RETURNS: updated context confirmation
14
+ ` : `
10
15
  set-context — set the CAS and SAS server contexts for subsequent tool calls.
11
16
 
12
17
  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)
18
+ DO NOT USE for: get variables (use get-env), read data (use read-table), score programs (use program-score)
14
19
 
15
20
  PARAMETERS
16
21
  - cas: string — CAS server name (optional), e.g. 'cas-shared-default', 'finance-cas-server'
@@ -30,7 +35,7 @@ EXAMPLES
30
35
  NEGATIVE EXAMPLES (do not route here)
31
36
  - "read table cars" (use read-table)
32
37
  - "what's the value of X" (use get-env)
33
- - "run program" (use run-sas-program)
38
+ - "score program" (use program-score)
34
39
 
35
40
  ERRORS
36
41
  Returns current or updated context values {cas, sas}. Error if server not found or invalid name.