@sassoftware/sas-score-mcp-serverjs 0.3.19 → 0.4.0
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 +141 -26
- package/package.json +4 -3
- package/skills/mcp-tool-description-optimizer/SKILL.md +129 -0
- package/skills/mcp-tool-description-optimizer/references/examples.md +123 -0
- package/skills/sas-read-and-score/SKILL.md +91 -0
- package/skills/sas-read-strategy/SKILL.md +143 -0
- package/skills/sas-score-workflow/SKILL.md +282 -0
- package/src/createMcpServer.js +1 -0
- package/src/expressMcpServer.js +68 -28
- package/src/handleGetDelete.js +6 -3
- package/src/hapiMcpServer.js +30 -0
- package/src/openAPIJson.js +175 -175
- package/src/toolHelpers/_jobSubmit.js +2 -0
- package/src/toolHelpers/_listLibrary.js +56 -39
- package/src/toolHelpers/getLogonPayload.js +9 -7
- package/src/toolHelpers/getStoreOpts.js +1 -2
- package/src/toolHelpers/getToken.js +0 -1
- package/src/toolHelpers/refreshToken.js +48 -46
- package/src/toolHelpers/refreshTokenOauth.js +2 -2
- package/src/toolHelpers/tlogon.js +9 -0
- package/src/toolSet/devaScore.js +30 -38
- package/src/toolSet/findJob.js +23 -49
- package/src/toolSet/findJobdef.js +24 -54
- package/src/toolSet/findLibrary.js +25 -57
- package/src/toolSet/findModel.js +31 -53
- package/src/toolSet/findTable.js +25 -54
- package/src/toolSet/getEnv.js +20 -38
- package/src/toolSet/listJobdefs.js +24 -58
- package/src/toolSet/listJobs.js +24 -72
- package/src/toolSet/listLibraries.js +37 -47
- package/src/toolSet/listModels.js +20 -47
- package/src/toolSet/listTables.js +29 -58
- package/src/toolSet/makeTools.js +3 -0
- package/src/toolSet/modelInfo.js +18 -49
- package/src/toolSet/modelScore.js +27 -69
- package/src/toolSet/readTable.js +25 -62
- package/src/toolSet/runCasProgram.js +23 -43
- package/src/toolSet/runJob.js +20 -19
- package/src/toolSet/runJobdef.js +21 -23
- package/src/toolSet/runMacro.js +20 -20
- package/src/toolSet/runProgram.js +24 -71
- package/src/toolSet/sasQuery.js +23 -70
- package/src/toolSet/scrInfo.js +3 -4
- package/src/toolSet/setContext.js +22 -48
- package/src/toolSet/tableInfo.js +28 -71
- package/src/toolHelpers/getOpts.js +0 -51
- package/src/toolHelpers/getOptsViya.js +0 -44
|
@@ -12,64 +12,35 @@ function listTables(_appContext) {
|
|
|
12
12
|
const log = debug('tools');
|
|
13
13
|
|
|
14
14
|
let description = `
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Response Contract
|
|
46
|
-
- JSON: { tables: string[] [, start:number]? }
|
|
47
|
-
- tables array is empty when no matches.
|
|
48
|
-
- Include start = start + limit when length === limit (possible more pages).
|
|
49
|
-
|
|
50
|
-
Pagination Examples
|
|
51
|
-
- First page: { lib:'Samples', start:1, limit:10 }
|
|
52
|
-
- Next page: { lib:'Samples', start:11, limit:10 }
|
|
53
|
-
|
|
54
|
-
Disambiguation & Clarification
|
|
55
|
-
- Missing library name → ask: "Which library do you want to list tables from?"
|
|
56
|
-
- Input only "list tables" → ask for the library unless prior context supplies one.
|
|
57
|
-
- If user mentions multiple libs ("tables in Public and Samples") → request a single library.
|
|
58
|
-
|
|
59
|
-
Negative Examples (should NOT call list-tables)
|
|
60
|
-
- "list libs" (list-libraries)
|
|
61
|
-
- "find lib Public" (find-library)
|
|
62
|
-
- "describe table cars" (table-info)
|
|
63
|
-
- "read table cars from sashelp" (read-table)
|
|
64
|
-
|
|
65
|
-
Usage Tips
|
|
66
|
-
- After listing, call table-info to inspect structure or read-table for sample data.
|
|
67
|
-
- Keep limit moderate; page for very large libraries.
|
|
68
|
-
|
|
69
|
-
Examples (→ mapped params)
|
|
70
|
-
- "list tables in samples" → { lib:"samples", start:1, limit:10 }
|
|
71
|
-
- "show 25 tables in sashelp" → { lib:"sashelp", limit:25, start:1 }
|
|
72
|
-
- "next tables" (after previous {start:1,limit:10}) → { start:11, limit:10, lib:<previousLib> }
|
|
15
|
+
list-tables — enumerate tables within a library.
|
|
16
|
+
|
|
17
|
+
USE when: list tables in <lib>, show tables in <lib>, next page
|
|
18
|
+
DO NOT USE for: find table, list libraries, get table structure (use table-info), read data (use read-table)
|
|
19
|
+
|
|
20
|
+
PARAMETERS
|
|
21
|
+
- lib: string — library to inspect (required)
|
|
22
|
+
- server: string (default: 'cas') — 'cas' or 'sas'
|
|
23
|
+
- limit: number (default: 10) — page size
|
|
24
|
+
- start: number (default: 1) — 1-based offset
|
|
25
|
+
- where: string — optional filter expression
|
|
26
|
+
|
|
27
|
+
ROUTING RULES
|
|
28
|
+
- "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
|
|
29
|
+
- "list 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
|
|
30
|
+
- "list cas tables in Public" → { lib: "Public", server: "cas", start: 1, limit: 10 }
|
|
31
|
+
|
|
32
|
+
EXAMPLES
|
|
33
|
+
- "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
|
|
34
|
+
- "show 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
|
|
35
|
+
|
|
36
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
37
|
+
- "list libs" (use list-libraries)
|
|
38
|
+
- "find lib Public" (use find-library)
|
|
39
|
+
- "describe table cars" (use table-info)
|
|
40
|
+
- "read table cars" (use read-table)
|
|
41
|
+
|
|
42
|
+
ERRORS
|
|
43
|
+
Returns empty array if no tables found.
|
|
73
44
|
`;
|
|
74
45
|
|
|
75
46
|
let spec = {
|
package/src/toolSet/makeTools.js
CHANGED
|
@@ -30,6 +30,7 @@ import findJobdef from './findJobdef.js';
|
|
|
30
30
|
|
|
31
31
|
import sasQuery from './sasQuery.js';
|
|
32
32
|
import setContext from './setContext.js';
|
|
33
|
+
//import scoreSkill from './scoreSkill.js';
|
|
33
34
|
|
|
34
35
|
function makeTools(_appContext) {
|
|
35
36
|
// wrap all tools with
|
|
@@ -64,6 +65,8 @@ function makeTools(_appContext) {
|
|
|
64
65
|
findJobdef(_appContext),
|
|
65
66
|
runJobdef(_appContext),
|
|
66
67
|
|
|
68
|
+
//scoreSkill(_appContext),
|
|
69
|
+
|
|
67
70
|
devaScore(_appContext),
|
|
68
71
|
setContext(_appContext)
|
|
69
72
|
|
package/src/toolSet/modelInfo.js
CHANGED
|
@@ -10,63 +10,32 @@ const log = debug('tools');
|
|
|
10
10
|
|
|
11
11
|
function modelInfo(_appContext) {
|
|
12
12
|
let description = `
|
|
13
|
-
|
|
13
|
+
model-info — retrieve detailed metadata for a deployed model.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- User wants input/output variable information: "What inputs does model X need?"
|
|
18
|
-
- User wants to understand model variables: "Describe model myModel"
|
|
19
|
-
- User wants data types and roles: "Show me the variables for myModel"
|
|
20
|
-
- User wants to prepare data for scoring: "What are the required inputs for model sales_forecast?"
|
|
15
|
+
USE when: what inputs does model need, describe model, show variables for model, model inputs/outputs
|
|
16
|
+
DO NOT USE for: find model, list models, score model, table/job operations
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
- Listing available models (use list-models)
|
|
25
|
-
- Scoring a model (use model-score)
|
|
26
|
-
- Looking up tables or jobs (use respective find/list tools)
|
|
18
|
+
PARAMETERS
|
|
19
|
+
- model: string — model name (required, exact match)
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
ROUTING RULES
|
|
22
|
+
- "what inputs does model X need?" → { model: "X" }
|
|
23
|
+
- "describe model Y" → { model: "Y" }
|
|
24
|
+
- "show variables for Z" → { model: "Z" }
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
- model (string, required): The name of the model as published to MAS. Must be exact match.
|
|
33
|
-
|
|
34
|
-
Response Contract
|
|
35
|
-
Returns a JSON object containing model metadata, typically including:
|
|
36
|
-
- name: The model name
|
|
37
|
-
- inputs: Array of input variable objects with:
|
|
38
|
-
- name: Variable name
|
|
39
|
-
- type: Data type (numeric, character, etc.)
|
|
40
|
-
- role: Role in model (input, key, etc.)
|
|
41
|
-
- allowed_values or range: Optional constraints
|
|
42
|
-
- outputs: Array of output/prediction objects with:
|
|
43
|
-
- name: Prediction/output variable name
|
|
44
|
-
- type: Data type
|
|
45
|
-
- possible_values: For classification models, the class labels
|
|
46
|
-
- model_type: Type of model (regression, classification, etc.)
|
|
47
|
-
- description: Optional model description
|
|
48
|
-
|
|
49
|
-
Disambiguation & Clarification
|
|
50
|
-
- If model name is missing: ask "Which model would you like to see information for?"
|
|
51
|
-
- If user says "variables" without specifying model: ask "Which model would you like the variables for?"
|
|
52
|
-
- Multiple model requests: handle one at a time
|
|
53
|
-
|
|
54
|
-
Examples (→ mapped params)
|
|
26
|
+
EXAMPLES
|
|
55
27
|
- "What inputs does model churnRisk need?" → { model: "churnRisk" }
|
|
56
28
|
- "Describe model creditScore" → { model: "creditScore" }
|
|
57
|
-
- "Show
|
|
58
|
-
- "What are the outputs of model sales_forecast?" → { model: "sales_forecast" }
|
|
29
|
+
- "Show variables for myModel" → { model: "myModel" }
|
|
59
30
|
|
|
60
|
-
|
|
61
|
-
- "
|
|
62
|
-
- "
|
|
63
|
-
- "
|
|
31
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
32
|
+
- "list models" (use list-models)
|
|
33
|
+
- "find model X" (use find-model)
|
|
34
|
+
- "score with model X" (use model-score)
|
|
64
35
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- model-score — to score data using the model
|
|
69
|
-
`;
|
|
36
|
+
ERRORS
|
|
37
|
+
Returns model metadata: inputs (name, type, role), outputs (name, type, possible_values), model_type, description.
|
|
38
|
+
`;
|
|
70
39
|
|
|
71
40
|
let spec = {
|
|
72
41
|
name: 'model-info',
|
|
@@ -10,81 +10,33 @@ const log = debug('tools');
|
|
|
10
10
|
|
|
11
11
|
function modelScore(_appContext) {
|
|
12
12
|
let description = `
|
|
13
|
-
|
|
13
|
+
model-score — score data using a deployed model on MAS.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
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"
|
|
15
|
+
USE when: score with model, predict using model, batch scoring, model predictions
|
|
16
|
+
DO NOT USE for: find model, model metadata, list models, run programs/jobs, query tables
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- Running SAS programs (use run-sas-program)
|
|
29
|
-
- Running jobs (use run-job)
|
|
30
|
-
- Querying tables (use sas-query or read-table)
|
|
18
|
+
PARAMETERS
|
|
19
|
+
- model: string — model name (required, exact match)
|
|
20
|
+
- scenario: string | object | array — input data (required). Accepts: "x=1, y=2", {x:1, y:2}, or array of objects
|
|
21
|
+
- uflag: boolean (default: false) — prefix model fields with underscore when true
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
ROUTING RULES
|
|
24
|
+
- "score with model X using a=1, b=2" → { model: "X", scenario: {a:1, b:2}, uflag: false }
|
|
25
|
+
- "predict using model Y with age=45, income=60000" → { model: "Y", scenario: {age:45, income:60000}, uflag: false }
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
- model
|
|
37
|
-
-
|
|
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.
|
|
27
|
+
EXAMPLES
|
|
28
|
+
- "score with model churn using age=45, income=60000" → { model: "churn", scenario: {age:45, income:60000}, uflag: false }
|
|
29
|
+
- "predict creditScore for credit=700, debt=20000" → { model: "creditScore", scenario: {credit:700, debt:20000}, uflag: false }
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
31
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
32
|
+
- "find model X" (use find-model)
|
|
33
|
+
- "what inputs does model need" (use model-info)
|
|
34
|
+
- "list models" (use list-models)
|
|
35
|
+
- "run job X" (use run-job)
|
|
47
36
|
|
|
48
|
-
|
|
49
|
-
Returns
|
|
50
|
-
|
|
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
|
-
`;
|
|
37
|
+
ERRORS
|
|
38
|
+
Returns predictions, probabilities, scores merged with input data. Returns error if model not found or scoring fails.
|
|
39
|
+
`;
|
|
88
40
|
|
|
89
41
|
|
|
90
42
|
let spec = {
|
|
@@ -119,6 +71,12 @@ Related Tools
|
|
|
119
71
|
}, {});
|
|
120
72
|
}
|
|
121
73
|
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
|
+
|
|
122
80
|
log('modelScore params', params);
|
|
123
81
|
// Check if the params.scenario is a string and parse it
|
|
124
82
|
let r = await _masScoring(params)
|
package/src/toolSet/readTable.js
CHANGED
|
@@ -9,75 +9,38 @@ import _readTable from '../toolHelpers/_readTable.js';
|
|
|
9
9
|
function readTable(_appContext) {
|
|
10
10
|
|
|
11
11
|
let describe = `
|
|
12
|
-
|
|
12
|
+
read-table — retrieve rows from a table in a CAS or SAS library.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
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"
|
|
14
|
+
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
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
17
|
+
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
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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)
|
|
26
|
+
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 }
|
|
60
30
|
|
|
61
|
-
|
|
31
|
+
EXAMPLES
|
|
62
32
|
- "read table cars in Samples" → { table: "cars", lib: "Samples", start: 1, limit: 10 }
|
|
63
|
-
- "show 25 rows from customers" → { table: "customers", lib:
|
|
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 }
|
|
33
|
+
- "show 25 rows from customers" → { table: "customers", lib: "mylib", limit: 25, start: 1 }
|
|
67
34
|
|
|
68
|
-
|
|
69
|
-
- "list tables in Samples" (use list-tables
|
|
70
|
-
- "what columns are in
|
|
71
|
-
- "execute
|
|
72
|
-
- "run
|
|
35
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
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)
|
|
73
40
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
`;
|
|
41
|
+
ERRORS
|
|
42
|
+
Returns rows array, total count, filtered_count, columns metadata. Empty array if no matches.
|
|
43
|
+
`;
|
|
81
44
|
|
|
82
45
|
let specs = {
|
|
83
46
|
name: 'read-table',
|
|
@@ -8,56 +8,36 @@ import _submitCode from '../toolHelpers/_submitCode.js';
|
|
|
8
8
|
|
|
9
9
|
function runCasProgram(_appContext) {
|
|
10
10
|
let description = `
|
|
11
|
-
|
|
11
|
+
run-cas-program — execute a CAS program on SAS Viya server.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
USE when: run cas program, execute cas, submit cas, cas action
|
|
14
|
+
DO NOT USE for: macros (use run-macro), sas code (use run-sas-program), jobs (use run-job), jobdefs (use run-jobdef)
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
- src
|
|
16
|
+
PARAMETERS
|
|
17
|
+
- src: string (required) — CAS program to execute verbatim
|
|
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
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
ROUTING RULES
|
|
24
|
+
- run cas program action echo → { src: action echo }
|
|
25
|
+
- execute cas action simple.summary → { src: action simple.summary }
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
EXAMPLES
|
|
28
|
+
- run cas program action echo → { src: action echo }
|
|
29
|
+
- cas program sample folder=/Public/models → { src: sample, folder: /Public/models }
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- 'submit cas "action echo / code='aaaa'"'
|
|
31
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
32
|
+
- run sas macro (use run-macro)
|
|
33
|
+
- submit sas code (use run-sas-program)
|
|
34
|
+
- run job X (use run-job)
|
|
29
35
|
|
|
36
|
+
NOTES
|
|
37
|
+
Sends src verbatim without validation. For SAS macros use run-macro. For arbitrary SAS code use run-sas-program.
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
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}
|
|
39
|
+
RESPONSE
|
|
40
|
+
Log output and CAS results. If output table specified, returned as markdown table.
|
|
61
41
|
`;
|
|
62
42
|
|
|
63
43
|
let spec = {
|
package/src/toolSet/runJob.js
CHANGED
|
@@ -9,30 +9,31 @@ import _jobSubmit from '../toolHelpers/_jobSubmit.js';
|
|
|
9
9
|
function runJob(_appContext) {
|
|
10
10
|
|
|
11
11
|
let description = `
|
|
12
|
-
|
|
12
|
+
run-job — execute a deployed SAS Viya job.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- You want to run a registered Job Execution asset by name
|
|
17
|
-
- You have simple parameter inputs to pass to the job
|
|
14
|
+
USE when: run job, execute job, run with parameters
|
|
15
|
+
DO NOT USE for: arbitrary SAS code (use run-sas-program), macros (use run-macro), list/find jobs
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- Listing or finding jobs (use list-jobs / find-job)
|
|
17
|
+
PARAMETERS
|
|
18
|
+
- name: string — job name (required)
|
|
19
|
+
- scenario: string | object — input parameters. Accepts: "x=1, y=2" or {x:1, y:2}
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- a comma-separated key=value string (e.g. "x=1, y=2")
|
|
28
|
-
- a JSON object with field names and values (recommended)
|
|
21
|
+
ROUTING RULES
|
|
22
|
+
- "run job xyz" → { name: "xyz" }
|
|
23
|
+
- "run job xyz with param1=10, param2=val2" → { name: "xyz", scenario: {param1:10, param2:"val2"} }
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
-
|
|
25
|
+
EXAMPLES
|
|
26
|
+
- "run job xyz" → { name: "xyz" }
|
|
27
|
+
- "run job monthly_etl with month=10, year=2025" → { name: "monthly_etl", scenario: {month:10, year:2025} }
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
- "run
|
|
35
|
-
- "run
|
|
29
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
30
|
+
- "run SAS code" (use run-sas-program)
|
|
31
|
+
- "run macro X" (use run-macro)
|
|
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.
|
|
36
37
|
`;
|
|
37
38
|
|
|
38
39
|
let spec = {
|
package/src/toolSet/runJobdef.js
CHANGED
|
@@ -6,38 +6,36 @@
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import _jobSubmit from '../toolHelpers/_jobSubmit.js';
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
function runJobdef(_appContext) {
|
|
11
10
|
// JSON object for LLM/tooling
|
|
12
11
|
|
|
13
12
|
let description = `
|
|
14
|
-
|
|
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
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
- You can pass parameters to the job definition
|
|
18
|
+
PARAMETERS
|
|
19
|
+
- name: string — jobdef name (required)
|
|
20
|
+
- scenario: string | object — input parameters. Accepts: "x=1, y=2" or {x:1, y:2}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- Listing or finding jobdefs (use list-jobdefs tool / find-jobdef tool)
|
|
22
|
+
ROUTING RULES
|
|
23
|
+
- "run jobdef xyz" → { name: "xyz" }
|
|
24
|
+
- "run jobdef xyz with param1=10, param2=val2" → { name: "xyz", scenario: {param1:10, param2:"val2"} }
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- a comma-separated key=value string (e.g. "x=1, y=2")
|
|
30
|
-
- a JSON object with field names and values (recommended)
|
|
26
|
+
EXAMPLES
|
|
27
|
+
- "run jobdef xyz" → { name: "xyz" }
|
|
28
|
+
- "run jobdef monthly_report with month=10, year=2025" → { name: "monthly_report", scenario: {month:10, year:2025} }
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
-
|
|
30
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
31
|
+
- "run SAS code" (use run-sas-program)
|
|
32
|
+
- "run macro X" (use run-macro)
|
|
33
|
+
- "list jobdefs" (use list-jobdefs)
|
|
34
|
+
- "find jobdef X" (use find-jobdef)
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
`;
|
|
36
|
+
ERRORS
|
|
37
|
+
Returns log output, listings, tables from jobdef. Error if jobdef not found.
|
|
38
|
+
`;
|
|
41
39
|
|
|
42
40
|
let spec = {
|
|
43
41
|
name: 'run-jobdef',
|