@sassoftware/sas-score-mcp-serverjs 0.4.0 → 0.4.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.
- package/cli.js +9 -127
- package/package.json +2 -3
- package/src/createMcpServer.js +0 -1
- package/src/expressMcpServer.js +27 -53
- package/src/handleGetDelete.js +3 -6
- package/src/hapiMcpServer.js +18 -10
- package/src/toolHelpers/_jobSubmit.js +0 -2
- package/src/toolHelpers/_listLibrary.js +39 -56
- package/src/toolHelpers/getLogonPayload.js +1 -3
- package/src/toolSet/devaScore.js +36 -28
- package/src/toolSet/findJob.js +49 -23
- package/src/toolSet/findJobdef.js +54 -24
- package/src/toolSet/findLibrary.js +57 -25
- package/src/toolSet/findModel.js +53 -31
- package/src/toolSet/findTable.js +54 -25
- package/src/toolSet/getEnv.js +38 -20
- package/src/toolSet/listJobdefs.js +58 -24
- package/src/toolSet/listJobs.js +72 -24
- package/src/toolSet/listLibraries.js +47 -37
- package/src/toolSet/listModels.js +47 -20
- package/src/toolSet/listTables.js +58 -29
- package/src/toolSet/makeTools.js +0 -3
- package/src/toolSet/modelInfo.js +49 -18
- package/src/toolSet/modelScore.js +69 -27
- package/src/toolSet/readTable.js +62 -25
- package/src/toolSet/runCasProgram.js +43 -23
- package/src/toolSet/runJob.js +19 -20
- package/src/toolSet/runJobdef.js +23 -21
- package/src/toolSet/runMacro.js +20 -20
- package/src/toolSet/runProgram.js +71 -24
- package/src/toolSet/sasQuery.js +70 -23
- package/src/toolSet/scrInfo.js +4 -3
- package/src/toolSet/setContext.js +48 -22
- package/src/toolSet/tableInfo.js +71 -28
- package/skills/mcp-tool-description-optimizer/SKILL.md +0 -129
- package/skills/mcp-tool-description-optimizer/references/examples.md +0 -123
- package/skills/sas-read-and-score/SKILL.md +0 -91
- package/skills/sas-read-strategy/SKILL.md +0 -143
- package/skills/sas-score-workflow/SKILL.md +0 -282
|
@@ -10,33 +10,81 @@ const log = debug('tools');
|
|
|
10
10
|
|
|
11
11
|
function modelScore(_appContext) {
|
|
12
12
|
let description = `
|
|
13
|
-
model-score — score data using a deployed model on MAS
|
|
13
|
+
## model-score — score data using a deployed model on MAS
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
LLM Invocation Guidance (When to use)
|
|
16
|
+
Use THIS tool when:
|
|
17
|
+
- User wants to score data with a model: "score this customer with model churnRisk"
|
|
18
|
+
- User provides input values for prediction: "predict using model creditScore with age=45, income=60000"
|
|
19
|
+
- User wants batch scoring: "score these 10 customers with fraud model"
|
|
20
|
+
- User asks for model predictions: "what does the sales forecast model predict for Q4?"
|
|
21
|
+
- User wants to get predictions: "use the risk model to score this applicant"
|
|
22
|
+
- User provides scenario data for a model: "run model cancer1 with age=45, sex=M"
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
24
|
+
Do NOT use this tool for:
|
|
25
|
+
- Checking if a model exists (use find-model)
|
|
26
|
+
- Getting model metadata/variables (use model-info)
|
|
27
|
+
- Listing available models (use list-models)
|
|
28
|
+
- Running SAS programs (use run-sas-program)
|
|
29
|
+
- Running jobs (use run-job)
|
|
30
|
+
- Querying tables (use sas-query or read-table)
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
- "predict using model Y with age=45, income=60000" → { model: "Y", scenario: {age:45, income:60000}, uflag: false }
|
|
32
|
+
Purpose
|
|
33
|
+
Score user-supplied scenario data using a model published to MAS (Model Aggregation Service) on SAS Viya. Returns predictions, probabilities, scores, and other model outputs merged with the input data.
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
35
|
+
Parameters
|
|
36
|
+
- model (string, required): The name of the model as published to MAS. Must be exact match.
|
|
37
|
+
- scenario (string | object | array, required): Data to score. Accepts:
|
|
38
|
+
- A comma-separated key=value string (e.g., "x=1, y=2")
|
|
39
|
+
- A plain object with field names and values (e.g., {x: 1, y: 2})
|
|
40
|
+
- An array of objects for batch scoring
|
|
41
|
+
- uflag (boolean, default false): When true, returned model field names will be prefixed with an underscore.
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- "run job X" (use run-job)
|
|
43
|
+
Parsing & Behavior
|
|
44
|
+
- If scenario is a string, the tool parses comma-separated key=value pairs into an object
|
|
45
|
+
- If scenario is an array, supports batch scoring (processes multiple records)
|
|
46
|
+
- Numeric values in strings remain as strings; validate and cast as needed before scoring
|
|
36
47
|
|
|
37
|
-
|
|
38
|
-
Returns
|
|
39
|
-
|
|
48
|
+
Response Contract
|
|
49
|
+
Returns a JSON object containing:
|
|
50
|
+
- Input fields merged with scoring results
|
|
51
|
+
- Prediction/score field(s) from the model (field names depend on model)
|
|
52
|
+
- Probability fields for classification models (e.g., P_class1, P_class2)
|
|
53
|
+
- Model metadata: model name, version if available
|
|
54
|
+
- _variables_: Variable metadata if uflag=true
|
|
55
|
+
- Error object if scoring fails with error message
|
|
56
|
+
|
|
57
|
+
Disambiguation & Clarification
|
|
58
|
+
- Missing model name: ask "Which model would you like to use for scoring?"
|
|
59
|
+
- Missing scenario data: ask "What input values should I use for scoring?"
|
|
60
|
+
- If model unknown: suggest "Use find-model to verify the model exists or list-models to see available models"
|
|
61
|
+
- If unsure of inputs: suggest "Use model-info to see the required input variables first"
|
|
62
|
+
|
|
63
|
+
Examples (→ mapped params)
|
|
64
|
+
- "score with model churn using age=45, income=60000" → { model: "churn", scenario: { age: "45", income: "60000" }, uflag: false }
|
|
65
|
+
- "predict creditScore for applicant: credit=700, debt=20000" → { model: "creditScore", scenario: { credit: "700", debt: "20000" }, uflag: false }
|
|
66
|
+
- "use fraud model to score transaction amount=500, merchant=online" → { model: "fraud", scenario: { amount: "500", merchant: "online" }, uflag: false }
|
|
67
|
+
- "run model cancer1 with age=45, sex=M, tumor=stage2" → { model: "cancer1", scenario: { age: "45", sex: "M", tumor: "stage2" }, uflag: false }
|
|
68
|
+
|
|
69
|
+
Negative Examples (should NOT call model-score)
|
|
70
|
+
- "find model churnRisk" (use find-model instead)
|
|
71
|
+
- "what inputs does model need?" (use model-info instead)
|
|
72
|
+
- "list all models" (use list-models instead)
|
|
73
|
+
- "run job scoring_job" (use run-job instead)
|
|
74
|
+
- "read table scores from Public" (use read-table instead)
|
|
75
|
+
|
|
76
|
+
Usage Tips
|
|
77
|
+
- Use model-info first to understand required input variables and data types
|
|
78
|
+
- Verify model exists with find-model before attempting to score
|
|
79
|
+
- For batch scoring, provide an array of objects as the scenario parameter
|
|
80
|
+
- Ensure MAS connectivity and credentials are available
|
|
81
|
+
|
|
82
|
+
Related Tools
|
|
83
|
+
- list-models → find-model → model-info → model-score (typical workflow)
|
|
84
|
+
- find-model — to verify model exists before scoring
|
|
85
|
+
- model-info — to understand required inputs and expected outputs
|
|
86
|
+
- list-models — to discover available models
|
|
87
|
+
`;
|
|
40
88
|
|
|
41
89
|
|
|
42
90
|
let spec = {
|
|
@@ -71,12 +119,6 @@ Returns predictions, probabilities, scores merged with input data. Returns error
|
|
|
71
119
|
}, {});
|
|
72
120
|
}
|
|
73
121
|
params.scenario= scenarioObj;
|
|
74
|
-
|
|
75
|
-
// Drop model extension (e.g., .job, .model)
|
|
76
|
-
if (params.model && params.model.includes('.')) {
|
|
77
|
-
params.model = params.model.substring(0, params.model.lastIndexOf('.'));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
122
|
log('modelScore params', params);
|
|
81
123
|
// Check if the params.scenario is a string and parse it
|
|
82
124
|
let r = await _masScoring(params)
|
package/src/toolSet/readTable.js
CHANGED
|
@@ -9,38 +9,75 @@ import _readTable from '../toolHelpers/_readTable.js';
|
|
|
9
9
|
function readTable(_appContext) {
|
|
10
10
|
|
|
11
11
|
let describe = `
|
|
12
|
-
read-table — retrieve rows from a table in a CAS or SAS library
|
|
12
|
+
## read-table — retrieve rows from a table in a CAS or SAS library
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
LLM Invocation Guidance (When to use)
|
|
15
|
+
Use THIS tool when:
|
|
16
|
+
- User wants to read data from a table: "read table xyz.customers"
|
|
17
|
+
- User wants sample rows: "show me 10 rows from lib.sales"
|
|
18
|
+
- User wants filtered data: "read from mylib.orders where status = 'shipped'"
|
|
19
|
+
- User wants from specific library: "read table cars in sashelp"
|
|
20
|
+
- User wants from specific server: "read table from mylib.employees on sas"
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- where: string — SQL WHERE clause filter
|
|
24
|
-
- format: boolean (default: true) — formatted or raw values
|
|
22
|
+
Do NOT use this tool for:
|
|
23
|
+
- Listing tables in a library (use list-tables)
|
|
24
|
+
- Getting table structure/metadata (use table-info)
|
|
25
|
+
- Running SQL queries (use sas-query)
|
|
26
|
+
- Executing SAS programs (use run-sas-program)
|
|
27
|
+
- Running statistical analysis (use appropriate analytics tools)
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
Purpose
|
|
30
|
+
Read one or more rows from a specified table in a CAS caslib or SAS libref. Supports pagination, filtering with WHERE clauses, and formatted/raw value display. Use this to inspect table data, sample rows, or retrieve filtered subsets.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
- table (string, required): Table name to read.
|
|
34
|
+
- lib (string, required): The caslib or libref containing the table.
|
|
35
|
+
- server (string, default 'cas'): Target server: 'cas' or 'sas'.
|
|
36
|
+
- start (number, default 1): 1-based row index to start reading from.
|
|
37
|
+
- limit (number, default 10): Maximum number of rows to return (1-1000 recommended).
|
|
38
|
+
- where (string, optional): SQL-style WHERE clause to filter rows (e.g., "age > 30 AND status = 'active'").
|
|
39
|
+
- format (boolean, default true): When true, return formatted/labeled values; when false return raw values.
|
|
40
|
+
- row (number, optional): Read a single specific row (sets start to this value and limit to 1).
|
|
41
|
+
|
|
42
|
+
Response Contract
|
|
43
|
+
Returns a JSON object containing:
|
|
44
|
+
- rows: Array of row objects with column names as keys
|
|
45
|
+
- total (optional): Total count of rows in table (if available)
|
|
46
|
+
- filtered_count (optional): Count of rows matching WHERE clause (if WHERE used)
|
|
47
|
+
- columns (optional): Column metadata including names and types
|
|
48
|
+
- Empty array if no rows match the criteria
|
|
49
|
+
|
|
50
|
+
Pagination & Filtering
|
|
51
|
+
- First page default: { start: 1, limit: 10 }
|
|
52
|
+
- To get next page: increment start by limit (e.g., { start: 11, limit: 10 })
|
|
53
|
+
- Use WHERE clause for server-side filtering: { where: "age > 30" }
|
|
54
|
+
|
|
55
|
+
Disambiguation & Clarification
|
|
56
|
+
- Missing library: ask "Which library contains the table you want to read?"
|
|
57
|
+
- Missing table: ask "Which table would you like to read?"
|
|
58
|
+
- Ambiguous lib.table format: parse and use as separate parameters
|
|
59
|
+
- Multiple tables: clarify which one (readTable handles one table at a time)
|
|
30
60
|
|
|
31
|
-
|
|
61
|
+
Examples (→ mapped params)
|
|
32
62
|
- "read table cars in Samples" → { table: "cars", lib: "Samples", start: 1, limit: 10 }
|
|
33
|
-
- "show 25 rows from customers" → { table: "customers", lib:
|
|
63
|
+
- "show 25 rows from customers" → { table: "customers", lib: <current_lib>, limit: 25, start: 1 }
|
|
64
|
+
- "read orders where status = 'shipped' limit 50" → { table: "orders", lib: <lib>, where: "status = 'shipped'", limit: 50, start: 1 }
|
|
65
|
+
- "read row 15 from employees in mylib on sas" → { table: "employees", lib: "mylib", server: "sas", row: 15 }
|
|
66
|
+
- "get next 10 rows" (after previous {start:1,limit:10}) → { table: <same>, lib: <same>, start: 11, limit: 10 }
|
|
34
67
|
|
|
35
|
-
|
|
36
|
-
- "list tables in Samples" (use list-tables)
|
|
37
|
-
- "what columns are in cars" (use table-info)
|
|
38
|
-
- "execute SQL query" (use sas-query)
|
|
39
|
-
- "run SAS code" (use run-sas-program)
|
|
68
|
+
Negative Examples (should NOT call read-table)
|
|
69
|
+
- "list tables in Samples" (use list-tables instead)
|
|
70
|
+
- "what columns are in the cars table?" (use table-info instead)
|
|
71
|
+
- "execute this SQL query" (use sas-query instead)
|
|
72
|
+
- "run this SAS code" (use run-sas-program instead)
|
|
40
73
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
74
|
+
Related Tools
|
|
75
|
+
- list-tables — to browse available tables in a library
|
|
76
|
+
- table-info — to inspect table structure, columns, and metadata
|
|
77
|
+
- find-table — to check if a table exists in a library
|
|
78
|
+
- list-libraries — to browse available libraries
|
|
79
|
+
- sas-query — to run complex SQL queries across tables
|
|
80
|
+
`;
|
|
44
81
|
|
|
45
82
|
let specs = {
|
|
46
83
|
name: 'read-table',
|
|
@@ -8,36 +8,56 @@ import _submitCode from '../toolHelpers/_submitCode.js';
|
|
|
8
8
|
|
|
9
9
|
function runCasProgram(_appContext) {
|
|
10
10
|
let description = `
|
|
11
|
-
run-cas-program
|
|
11
|
+
## run-cas-program
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
DO NOT USE for: macros (use run-macro), sas code (use run-sas-program), jobs (use run-job), jobdefs (use run-jobdef)
|
|
13
|
+
Execute a cas program on a SAS Viya server
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- src
|
|
18
|
-
- scenario: string or object (optional) — input parameters
|
|
19
|
-
- folder: string — server folder path for .sas files
|
|
20
|
-
- output: string — table name to return in response
|
|
21
|
-
- limit: number (default: 100) — max rows to return
|
|
15
|
+
Required Parameters
|
|
16
|
+
- src(string, required): The cas program to execute.
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
- run cas program action echo → { src: action echo }
|
|
25
|
-
- execute cas action simple.summary → { src: action simple.summary }
|
|
18
|
+
Optional Parameters:
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
20
|
+
- scenario (string | object ,optional): Input values to program/ Accepts:
|
|
21
|
+
- a comma-separated key=value string (e.g. "x=1, y=2"),
|
|
22
|
+
- a JSON object with field names and values (recommended for typed inputs),
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
24
|
+
LLM Invocation Guidance
|
|
25
|
+
Use THIS tool when the user wants to run a Cas program on the server:
|
|
26
|
+
- "run cas program 'action echo / code='aaaa'"
|
|
27
|
+
- "cas program 'action echo / code='aaaa'"
|
|
28
|
+
- 'submit cas "action echo / code='aaaa'"'
|
|
35
29
|
|
|
36
|
-
NOTES
|
|
37
|
-
Sends src verbatim without validation. For SAS macros use run-macro. For arbitrary SAS code use run-sas-program.
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
Do NOT use this tool when the user wants:
|
|
32
|
+
- run macro -> use run-macro
|
|
33
|
+
- submit sas -> use run-sas-program
|
|
34
|
+
- run job -> use run-job
|
|
35
|
+
- run sas -> use run-sas-program
|
|
36
|
+
- run jobdef -> use run-jobdef
|
|
37
|
+
- run job -> use run-job
|
|
38
|
+
- list jobs -> use list-jobs
|
|
39
|
+
- list jobdefs -> use list-jobdefs
|
|
40
|
+
- find job -> use find-job
|
|
41
|
+
- find jobdef -> use find-jobdef
|
|
42
|
+
- find model -> use find-model
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Behavior & usage notes
|
|
46
|
+
- This tool sends the supplied \`src\` verbatim to the SAS execution helper. It does not modify or validate the SAS code.
|
|
47
|
+
- For invoking pre-defined SAS macros, prefer the \`runMacro\` helper which converts simple parameter formats into \`%let\` statements and invokes the macro cleanly.
|
|
48
|
+
- Be cautious when executing arbitrary code — validate or sanitize inputs in untrusted environments.
|
|
49
|
+
|
|
50
|
+
Response
|
|
51
|
+
- If output is specified and the specified table exists in the response, display the data as a markdown table.
|
|
52
|
+
Examples
|
|
53
|
+
- run program "data a; x=1; run;" - this is the simplest usage -- {src= "data a; x=1; run;", folder=" ", output=" ", limit=100}
|
|
54
|
+
- program "data work.a; x=1; run;" output=a limit=50 -- {src= "data work.a; x=1; run;", folder=" ", output="a", limit=50}
|
|
55
|
+
|
|
56
|
+
- run program sample folder=/Public/models output=A limit=50 -- {src= "sample", folder="/Public/models", output="A", limit=50}
|
|
57
|
+
- run program sample folder=/Public/models scenario="name='John', age=45" output=a limit=50 -- {src= "sample", folder="/Public/models", scenario: {name: "John", age: 45}, output="a", limit=50}
|
|
58
|
+
- run program sample folder=/Public/models with scenario name=John,age=45 output=a limit=50 -- {src= "sample.sas", folder="/Public/models", scenario: {name: "John", age: 45}, output="a", limit=50}
|
|
59
|
+
- this should be the same as the previous example and is just a different syntax. The result should be
|
|
60
|
+
{program: "sample", folder: "/Public/models", scenario: {name: "John", age: 45}, output: "a", limit: 50}
|
|
41
61
|
`;
|
|
42
62
|
|
|
43
63
|
let spec = {
|
package/src/toolSet/runJob.js
CHANGED
|
@@ -9,31 +9,30 @@ import _jobSubmit from '../toolHelpers/_jobSubmit.js';
|
|
|
9
9
|
function runJob(_appContext) {
|
|
10
10
|
|
|
11
11
|
let description = `
|
|
12
|
-
run-job — execute a deployed SAS Viya job
|
|
12
|
+
## run-job — execute a deployed SAS Viya job
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
LLM Invocation Guidance (When to use)
|
|
15
|
+
Use THIS tool when:
|
|
16
|
+
- You want to run a registered Job Execution asset by name
|
|
17
|
+
- You have simple parameter inputs to pass to the job
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
19
|
+
Do NOT use this tool for:
|
|
20
|
+
- Running arbitrary SAS code (use run-sas-program)
|
|
21
|
+
- Invoking pre-defined SAS macros (use run-macro)
|
|
22
|
+
- Listing or finding jobs (use list-jobs / find-job)
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
+
Parameters
|
|
25
|
+
- name (string, required): The job name to execute
|
|
26
|
+
- scenario (string | object, optional): Input values to the job. Accepts:
|
|
27
|
+
- a comma-separated key=value string (e.g. "x=1, y=2")
|
|
28
|
+
- a JSON object with field names and values (recommended)
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
- "run job monthly_etl with month=10, year=2025" → { name: "monthly_etl", scenario: {month:10, year:2025} }
|
|
30
|
+
Response
|
|
31
|
+
- Log output, listings, and tables depending on the job’s design. Table outputs will be displayed when present.
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
- "run
|
|
31
|
-
- "run
|
|
32
|
-
- "list jobs" (use list-jobs)
|
|
33
|
-
- "find job X" (use find-job)
|
|
34
|
-
|
|
35
|
-
ERRORS
|
|
36
|
-
Returns log output, listings, tables from job. Error if job not found.
|
|
33
|
+
Examples (→ mapped params)
|
|
34
|
+
- "run job xyz param1=10,param2=val2" → { name: "xyz", scenario: { param1: 10, param2: "val2" } }
|
|
35
|
+
- "run-job name=monthly_etl, scenario=month=10,year=2025" → { name: "monthly_etl", scenario: { month: 10, year: 2025 } }
|
|
37
36
|
`;
|
|
38
37
|
|
|
39
38
|
let spec = {
|
package/src/toolSet/runJobdef.js
CHANGED
|
@@ -6,36 +6,38 @@
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import _jobSubmit from '../toolHelpers/_jobSubmit.js';
|
|
8
8
|
|
|
9
|
+
|
|
9
10
|
function runJobdef(_appContext) {
|
|
10
11
|
// JSON object for LLM/tooling
|
|
11
12
|
|
|
12
13
|
let description = `
|
|
13
|
-
run-jobdef — execute a SAS Viya job definition
|
|
14
|
-
|
|
15
|
-
USE when: run jobdef, execute jobdef, run with parameters
|
|
16
|
-
DO NOT USE for: arbitrary SAS code (use run-sas-program), macros (use run-macro), list/find jobdefs
|
|
14
|
+
## run-jobdef — execute a SAS Viya job definition
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
16
|
+
LLM Invocation Guidance (When to use)
|
|
17
|
+
Use THIS tool when:
|
|
18
|
+
- You want to run a registered Job Definition by name
|
|
19
|
+
- You can pass parameters to the job definition
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
21
|
+
Do NOT use this tool for:
|
|
22
|
+
- Running arbitrary SAS code (use run-program tool)
|
|
23
|
+
- Invoking SAS macros (use run-macro tool)
|
|
24
|
+
- Listing or finding jobdefs (use list-jobdefs tool / find-jobdef tool)
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
26
|
+
Parameters
|
|
27
|
+
- name (string, required): The job definition name to execute
|
|
28
|
+
- scenario (string | object, optional): Input values. Accepts:
|
|
29
|
+
- a comma-separated key=value string (e.g. "x=1, y=2")
|
|
30
|
+
- a JSON object with field names and values (recommended)
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
- "run macro X" (use run-macro)
|
|
33
|
-
- "list jobdefs" (use list-jobdefs)
|
|
34
|
-
- "find jobdef X" (use find-jobdef)
|
|
32
|
+
Response
|
|
33
|
+
- Log output, listings, and tables depending on the job definition's design. Table outputs will be displayed when present.
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
Examples (→ mapped params)
|
|
36
|
+
- "jobdef xyz param1=10,param2=val2" → { name: "xyz", scenario: { param1: 10, param2: "val2" } }
|
|
37
|
+
- "run jobdef name=monthly_report, scenario=month=10,year=2025" → { name: "monthly_report", scenario: { month: 10, year: 2025 } }
|
|
38
|
+
- "run-jobdef xyz param1=10,param2=val2" → { name: "xyz", scenario: { param1: 10, param2: "val2" } }
|
|
39
|
+
- "jobdef name=monthly_report, scenario=month=10,year=2025" → { name: "monthly_report", scenario: { month: 10, year: 2025 }
|
|
40
|
+
`;
|
|
39
41
|
|
|
40
42
|
let spec = {
|
|
41
43
|
name: 'run-jobdef',
|
package/src/toolSet/runMacro.js
CHANGED
|
@@ -9,32 +9,32 @@ import _submitCode from '../toolHelpers/_submitCode.js';
|
|
|
9
9
|
|
|
10
10
|
function runMacro(_appContext) {
|
|
11
11
|
let description = `
|
|
12
|
-
run-macro
|
|
12
|
+
## run-macro
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
DO NOT USE for: arbitrary SAS code (use run-sas-program), jobs, jobdefs
|
|
14
|
+
Submit and execute a SAS macro on a SAS Viya server by generating and sending SAS code.
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
- macro
|
|
19
|
-
- scenario
|
|
16
|
+
Inputs
|
|
17
|
+
- macro (string, required): The name of the macro to execute (provide the macro identifier without the leading "%").
|
|
18
|
+
- scenario (string, optional): Parameters or SAS setup code to send before invoking the macro. Accepted formats:
|
|
19
|
+
- Comma-separated key=value pairs (e.g. "x=1, y=abc") — converted to SAS %let statements.
|
|
20
|
+
- Raw SAS macro code (e.g. "%let x=1; %let y=abc;") — passed through unchanged when it already contains SAS macro syntax.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
22
|
+
Behavior
|
|
23
|
+
- If \`scenario\` contains SAS macro syntax (contains \`%let\` or other macro markers), it is sent unchanged.
|
|
24
|
+
- Otherwise the tool converts comma-separated parameters into \`%let\` statements (e.g. "x=1,y=abc" → "%let x=1; %let y=abc;") and appends a macro invocation \`%<macro>;\`.
|
|
25
|
+
- The resulting SAS code is submitted via the internal \`_submitCode\` helper and the submission result is returned.
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
- "run macro summarize with x=1, y=2" → { macro: "summarize", scenario: "x=1, y=2" }
|
|
27
|
+
Output
|
|
28
|
+
- Returns the response produced by \`_submitCode\`, typically including ods, log, list of tables created by the macro
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
- "run jobdef X" (use run-jobdef)
|
|
30
|
+
Usage notes
|
|
31
|
+
- Ensure the target SAS environment has the macro defined
|
|
32
|
+
- This helper does not perform advanced input validation or type coercion — validate parameters before calling when needed.
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
Examples
|
|
35
|
+
- run macro \`abc\` with scenario \`x=1, y=2\`
|
|
36
|
+
- run macro \`summarize\` with raw SAS code \`%let x=1; %let y=2;\` (the helper will pass it through unchanged)
|
|
37
|
+
`;
|
|
38
38
|
|
|
39
39
|
let spec = {
|
|
40
40
|
name: 'run-macro',
|
|
@@ -8,37 +8,84 @@ import _submitCode from '../toolHelpers/_submitCode.js';
|
|
|
8
8
|
|
|
9
9
|
function runProgram(_appContext) {
|
|
10
10
|
let description = `
|
|
11
|
-
run-sas-program — execute SAS code or programs on SAS Viya server
|
|
11
|
+
## run-sas-program — execute SAS code or programs on SAS Viya server
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
LLM Invocation Guidance (When to use)
|
|
14
|
+
Use THIS tool when the user wants to run a SAS program on the server:
|
|
15
|
+
- "run program 'data a; x=1; run;'"
|
|
16
|
+
- "execute this SAS code: proc print data=sashelp.cars; run;"
|
|
17
|
+
- "program 'data work.a; x=1; run;' output=a limit=50"
|
|
18
|
+
- "run sas program sample folder=/Public/models output=A limit=50"
|
|
19
|
+
- "run sas program with parameters name=John, age=45"
|
|
20
|
+
- "execute SAS file myprogram.sas from /Public folder"
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
+
Do NOT use this tool when the user wants:
|
|
23
|
+
- run macro -> use run-macro
|
|
24
|
+
- run job -> use run-job
|
|
25
|
+
- run jobdef -> use run-jobdef
|
|
26
|
+
- list jobs -> use list-jobs
|
|
27
|
+
- list jobdefs -> use list-jobdefs
|
|
28
|
+
- find job -> use find-job
|
|
29
|
+
- find jobdef -> use find-jobdef
|
|
30
|
+
- find model -> use find-model
|
|
31
|
+
- Query tables with SQL -> use sas-query
|
|
32
|
+
- Read table data -> use read-table
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
Purpose
|
|
35
|
+
Execute SAS code or programs on a SAS Viya server. Can run inline SAS code or execute .sas files stored on the server. Supports parameter passing via scenario values and can return output tables.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
- src (string, required): The SAS program to execute. Can be either:
|
|
39
|
+
- Inline SAS code as a string (e.g., "data a; x=1; run;")
|
|
40
|
+
- Name of a .sas file stored on the server (used with folder parameter)
|
|
41
|
+
- folder (string, default ''): Server folder path where the .sas file is located (e.g., "/Public/models")
|
|
42
|
+
- scenario (string | object, optional): Input parameter values. Accepts:
|
|
43
|
+
- Comma-separated key=value string (e.g., "x=1, y=2")
|
|
44
|
+
- JSON object with field names and values (recommended)
|
|
45
|
+
- output (string, default ''): Table name to return in response (case-sensitive)
|
|
46
|
+
- limit (number, default 100): Maximum number of rows to return from output table
|
|
47
|
+
|
|
48
|
+
Response Contract
|
|
49
|
+
Returns a JSON object containing:
|
|
50
|
+
- log: Execution log from SAS
|
|
51
|
+
- ods: ODS output if generated
|
|
52
|
+
- tables: Array of table names created during execution
|
|
53
|
+
- data: If output parameter specified, returns the table data (up to limit rows)
|
|
54
|
+
- error: Error message if execution fails
|
|
55
|
+
- Empty content if no results produced
|
|
27
56
|
|
|
28
|
-
|
|
57
|
+
Disambiguation & Clarification
|
|
58
|
+
- Missing SAS code: ask "What SAS program or code would you like to execute?"
|
|
59
|
+
- Inline code vs file unclear: ask "Do you want to run inline SAS code or execute a .sas file from the server?"
|
|
60
|
+
- If output table not returned: clarify "The output table name is case-sensitive. Did you specify the exact name?"
|
|
61
|
+
- If unclear about parameters: ask "What parameter values should I pass to the program?"
|
|
62
|
+
|
|
63
|
+
Examples (→ mapped params)
|
|
29
64
|
- "run program 'data a; x=1; run;'" → { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
|
|
30
|
-
- "
|
|
65
|
+
- "program 'data work.a; x=1; run;' output=a limit=50" → { src: "data work.a; x=1; run;", folder: "", output: "a", limit: 50 }
|
|
66
|
+
- "run sas program sample folder=/Public/models output=A limit=50" → { src: "sample", folder: "/Public/models", output: "A", limit: 50 }
|
|
67
|
+
- "run program mycode.sas in /Public with name=John, age=45" → { src: "mycode", folder: "/Public", scenario: { name: "John", age: 45 }, output: "", limit: 100 }
|
|
68
|
+
|
|
69
|
+
Negative Examples (should NOT call run-sas-program)
|
|
70
|
+
- "run macro summarize" (use run-macro instead)
|
|
71
|
+
- "run job monthly_report" (use run-job instead)
|
|
72
|
+
- "run jobdef etl_process" (use run-jobdef instead)
|
|
73
|
+
- "how many customers by region in Public.customers" (use sas-query instead)
|
|
74
|
+
- "read 10 rows from cars" (use read-table instead)
|
|
31
75
|
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
76
|
+
Behavior & Usage Notes
|
|
77
|
+
- Sends the supplied src verbatim to the SAS execution helper
|
|
78
|
+
- For .sas files, specify the file name (with or without .sas extension) and the folder path
|
|
79
|
+
- For invoking pre-defined SAS macros, prefer run-macro which handles %let statements automatically
|
|
80
|
+
- Scenario values are converted to macro variables when provided
|
|
81
|
+
- Be cautious when executing arbitrary code in production environments
|
|
38
82
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
83
|
+
Related Tools
|
|
84
|
+
- run-macro — for executing predefined SAS macros with parameters
|
|
85
|
+
- run-job — for executing registered Job Execution assets
|
|
86
|
+
- sas-query — for natural language SQL queries
|
|
87
|
+
- read-table — for simple data retrieval
|
|
88
|
+
`;
|
|
42
89
|
|
|
43
90
|
let spec = {
|
|
44
91
|
name: 'run-sas-program',
|