@sassoftware/sas-score-mcp-serverjs 0.3.18 → 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.
Files changed (47) hide show
  1. package/cli.js +141 -26
  2. package/package.json +4 -3
  3. package/skills/mcp-tool-description-optimizer/SKILL.md +129 -0
  4. package/skills/mcp-tool-description-optimizer/references/examples.md +123 -0
  5. package/skills/sas-read-and-score/SKILL.md +91 -0
  6. package/skills/sas-read-strategy/SKILL.md +143 -0
  7. package/skills/sas-score-workflow/SKILL.md +282 -0
  8. package/src/createMcpServer.js +1 -0
  9. package/src/expressMcpServer.js +68 -28
  10. package/src/handleGetDelete.js +6 -3
  11. package/src/hapiMcpServer.js +30 -0
  12. package/src/openAPIJson.js +175 -175
  13. package/src/toolHelpers/_jobSubmit.js +2 -0
  14. package/src/toolHelpers/_listLibrary.js +56 -39
  15. package/src/toolHelpers/getLogonPayload.js +9 -7
  16. package/src/toolHelpers/getStoreOpts.js +1 -2
  17. package/src/toolHelpers/getToken.js +0 -1
  18. package/src/toolHelpers/refreshToken.js +48 -45
  19. package/src/toolHelpers/refreshTokenOauth.js +2 -2
  20. package/src/toolHelpers/tlogon.js +9 -0
  21. package/src/toolSet/devaScore.js +30 -38
  22. package/src/toolSet/findJob.js +23 -49
  23. package/src/toolSet/findJobdef.js +24 -54
  24. package/src/toolSet/findLibrary.js +25 -57
  25. package/src/toolSet/findModel.js +31 -53
  26. package/src/toolSet/findTable.js +25 -54
  27. package/src/toolSet/getEnv.js +20 -38
  28. package/src/toolSet/listJobdefs.js +24 -58
  29. package/src/toolSet/listJobs.js +24 -72
  30. package/src/toolSet/listLibraries.js +37 -47
  31. package/src/toolSet/listModels.js +20 -47
  32. package/src/toolSet/listTables.js +29 -58
  33. package/src/toolSet/makeTools.js +3 -0
  34. package/src/toolSet/modelInfo.js +18 -49
  35. package/src/toolSet/modelScore.js +27 -69
  36. package/src/toolSet/readTable.js +25 -62
  37. package/src/toolSet/runCasProgram.js +23 -43
  38. package/src/toolSet/runJob.js +20 -19
  39. package/src/toolSet/runJobdef.js +21 -23
  40. package/src/toolSet/runMacro.js +20 -20
  41. package/src/toolSet/runProgram.js +24 -71
  42. package/src/toolSet/sasQuery.js +23 -70
  43. package/src/toolSet/scrInfo.js +3 -4
  44. package/src/toolSet/setContext.js +22 -48
  45. package/src/toolSet/tableInfo.js +28 -71
  46. package/src/toolHelpers/getOpts.js +0 -51
  47. package/src/toolHelpers/getOptsViya.js +0 -44
@@ -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 — submit and execute a SAS macro on SAS Viya server.
13
13
 
14
- Submit and execute a SAS macro on a SAS Viya server by generating and sending SAS code.
14
+ USE when: run macro, execute macro with parameters
15
+ DO NOT USE for: arbitrary SAS code (use run-sas-program), jobs, jobdefs
15
16
 
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.
17
+ PARAMETERS
18
+ - macro: string macro name without "%" (required)
19
+ - scenario: string parameters or setup code (optional). Accepts: "x=1, y=abc" or "%let x=1; %let y=abc;"
21
20
 
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.
21
+ ROUTING RULES
22
+ - "run macro abc" { macro: "abc", scenario: "" }
23
+ - "run macro abc with x=1, y=2" → { macro: "abc", scenario: "x=1, y=2" }
24
+ - "run macro xyz with %let a=1; %let b=2;" { macro: "xyz", scenario: "%let a=1; %let b=2;" }
26
25
 
27
- Output
28
- - Returns the response produced by \`_submitCode\`, typically including ods, log, list of tables created by the macro
26
+ EXAMPLES
27
+ - "run macro abc" { macro: "abc", scenario: "" }
28
+ - "run macro summarize with x=1, y=2" → { macro: "summarize", scenario: "x=1, y=2" }
29
29
 
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.
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "run SAS code" (use run-sas-program)
32
+ - "run job X" (use run-job)
33
+ - "run jobdef X" (use run-jobdef)
33
34
 
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
- `;
35
+ ERRORS
36
+ Returns log, ods, tables created by macro. Auto-converts "x=1, y=2" to "%let x=1; %let y=2;" format.
37
+ `;
38
38
 
39
39
  let spec = {
40
40
  name: 'run-macro',
@@ -8,84 +8,37 @@ 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
- 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"
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)
21
15
 
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
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
33
22
 
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
56
-
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)
23
+ ROUTING RULES
64
24
  - "run program 'data a; x=1; run;'" → { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
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 }
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 }
68
27
 
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)
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 }
75
31
 
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
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)
82
38
 
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
- `;
39
+ ERRORS
40
+ Returns log, ods, tables array, data (if output specified). Error if execution fails.
41
+ `;
89
42
 
90
43
  let spec = {
91
44
  name: 'run-sas-program',
@@ -5,85 +5,38 @@
5
5
  import {z} from 'zod';
6
6
  import _jobSubmit from '../toolHelpers/_jobSubmit.js';
7
7
 
8
-
9
8
  function sasQuery() {
10
9
 
11
10
  let description = `
12
- ## sas-query — convert natural language questions into SQL queries and execute them
13
-
14
- LLM Invocation Guidance (When to use)
15
- Use THIS tool when:
16
- - User asks a natural language question about table data: "how many customers by region?"
17
- - User wants aggregated analytics: "show total sales by year"
18
- - User needs complex filtering: "find all orders over $1000 from last month"
19
- - User requests joined data: "show products with their category names"
20
- - User wants statistical summaries: "average, min, max salary by department"
21
- - User asks for specific calculations: "percentage of customers by state"
22
-
23
- Do NOT use this tool for:
24
- - Reading raw table data without filtering (use read-table)
25
- - Getting table structure or column info (use table-info)
26
- - Running pre-written SAS programs (use run-sas-program)
27
- - Running jobs or job definitions (use run-job or run-jobdef)
28
- - Executing macros (use run-macro)
29
- - Simple table reads with no aggregation (use read-table)
30
-
31
- Purpose
32
- Convert natural language queries into SAS PROC SQL SELECT statements and execute them to retrieve analyzed data. The LLM generates the SQL from the natural language query, and this tool executes it against the specified table.
33
-
34
- Parameters
35
- - table (string, required): Table name in lib.table format (e.g., "Public.cars", "sashelp.class")
36
- - query (string, required): Natural language description of what data you want
37
- - sql (string, optional): Pre-generated SQL SELECT statement (LLM should generate this from the query)
38
- - job (string, default 'program'): Job name to execute the query (default is 'program')
39
-
40
- Behavior & Processing
41
- - LLM converts the natural language query into a valid SAS PROC SQL SELECT statement
42
- - Do not add semicolons to the end of SQL statements
43
- - SQL reference: https://go.documentation.sas.com/doc/en/pgmsascdc/v_067/sqlproc/n0w2pkrm208upln11i9r4ogwyvow.htm
44
- - Tool executes the generated SQL against the specified table
45
- - Returns data in JSON format
11
+ sas-query — convert natural language questions into SQL queries and execute them.
46
12
 
47
- Response Contract
48
- Returns a JSON object containing:
49
- - rows: Array of row objects with query results
50
- - columns: Column metadata from the query result
51
- - log: Execution log if available
52
- - If error: structured error message
53
- - If more than 10 rows: only first 10 displayed (ask user if they want more)
13
+ 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
54
15
 
55
- Disambiguation & Clarification
56
- - If table missing: ask "Which table should I query (format: lib.tablename)?"
57
- - If query too vague: ask "Can you be more specific about what data or calculation you want?"
58
- - If table format unclear: ask "Please specify table as library.tablename (e.g., Public.cars)"
59
- - If ambiguous calculation: ask for clarification on what to aggregate or filter
16
+ 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
60
21
 
61
- Examples (→ mapped params)
62
- - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) AS count FROM sashelp.cars GROUP BY make" }
63
- - "average horsepower by origin" → { table: "sashelp.cars", query: "average horsepower by origin", sql: "SELECT origin, AVG(horsepower) AS avg_hp FROM sashelp.cars GROUP BY origin" }
64
- - "total sales over $1000 by region" → { table: "mylib.sales", query: "total sales over $1000 by region", sql: "SELECT region, SUM(amount) AS total FROM mylib.sales WHERE amount > 1000 GROUP BY region" }
65
- - "percentage of students by year in Public.students" → { table: "Public.students", query: "percentage by year", sql: "SELECT year, COUNT(*) * 100.0 / (SELECT COUNT(*) FROM Public.students) AS pct FROM Public.students GROUP BY year" }
22
+ 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" }
66
25
 
67
- Negative Examples (should NOT call sas-query)
68
- - "read table cars from sashelp" (use read-table instead)
69
- - "show me 10 rows from customers" (use read-table instead)
70
- - "what columns are in the sales table?" (use table-info instead)
71
- - "run this SAS code: proc sql; select * from..." (use run-sas-program instead)
72
- - "execute job monthly_report" (use run-job instead)
73
- - "run macro summarize_data" (use run-macro instead)
26
+ 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" }
74
29
 
75
- Usage Tips
76
- - Ensure table is specified in lib.tablename format
77
- - Be specific in natural language queries for better SQL generation
78
- - Use table-info first to understand column names and types
79
- - For simple reads without filtering/aggregation, prefer read-table
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "read table cars" (use read-table)
32
+ - "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)
80
36
 
81
- Related Tools
82
- - read-table for simple data reading without SQL queries
83
- - table-info — to inspect table schema before querying
84
- - run-sas-program — for executing pre-written SAS/SQL code
85
- - find-table — to verify table exists before querying
86
- `;
37
+ ERRORS
38
+ Returns rows array, columns metadata, log. Returns error if SQL invalid or table not found.
39
+ `;
87
40
 
88
41
 
89
42
  let spec = {
@@ -15,7 +15,7 @@ Purpose
15
15
  Return the input/output schema and metadata for an SCR (Score Code Runtime) model.
16
16
 
17
17
  Inputs
18
- - name (string): The SCR model identifier.
18
+ - url (string): The SCR model identifier.
19
19
  What it returns
20
20
  - A JSON object describing the model's interface, typically including:
21
21
  - Input variables (names, types, required/optional)
@@ -23,7 +23,6 @@ What it returns
23
23
 
24
24
 
25
25
  Usage notes
26
- - If no local mapping exists and \`name\` looks like a URL, the tool will attempt to fetch the schema from that URL.
27
26
  - Ensure network connectivity and credentials for the remote SCR service when needed.
28
27
  - Use scr-score to score data after inspecting the schema.
29
28
 
@@ -37,9 +36,9 @@ Examples
37
36
  aliases: ['scrInfo','scr info','scr_info'],
38
37
  description: description,
39
38
  schema: {
40
- name: z.string(),
39
+ url: z.string(),
41
40
  },
42
- required: ['name'],
41
+ required: ['url'],
43
42
  handler: async (params) => {
44
43
  let {url, _appContext} = params;
45
44
  if (url === null) {
@@ -7,60 +7,34 @@ import {z} from 'zod';
7
7
 
8
8
  function setContext(_appContext) {
9
9
  let description = `
10
- ## set-context — set the CAS and SAS server contexts for subsequent tool calls
10
+ set-context — set the CAS and SAS server contexts for subsequent tool calls.
11
11
 
12
- LLM Invocation Guidance (When to use)
13
- Use THIS tool when:
14
- - User wants to switch to a different CAS server: "Use the finance-cas-server"
15
- - User wants to change the compute context: "Switch to 'SAS Studio Compute Context'"
16
- - User wants to check current context: "What context am I using?"
17
- - User wants to set both: "Use finance-cas-server for CAS and my-compute for SAS"
12
+ 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
14
 
19
- Do NOT use this tool for:
20
- - Retrieving variable values (use get-env)
21
- - Reading table data (use read-table)
22
- - Running programs or queries (use run-sas-program or sas-query)
23
- - Listing available servers or contexts (no tool for this; would require backend support)
15
+ PARAMETERS
16
+ - cas: string CAS server name (optional), e.g. 'cas-shared-default', 'finance-cas-server'
17
+ - sas: string SAS compute context (optional), e.g. 'SAS Studio Compute Context', 'batch-compute'
24
18
 
25
- Purpose
26
- Set the active CAS server and/or SAS compute context for all subsequent tool calls in this session. This allows switching between different server environments. If neither parameter is provided, the tool returns the current context values.
19
+ ROUTING RULES
20
+ - "use finance-cas-server" { cas: "finance-cas-server" }
21
+ - "switch to SAS Studio Compute Context" → { sas: "SAS Studio Compute Context" }
22
+ - "use finance-cas for CAS and batch-compute for SAS" → { cas: "finance-cas", sas: "batch-compute" }
23
+ - "what context am I using" → { } (no params, returns current)
27
24
 
28
- Parameters
29
- - cas (string, optional): The name of the CAS server to use for subsequent CAS operations. Examples: 'cas-shared-default', 'finance-cas-server', 'analytics-cas'
30
- - sas (string, optional): The name of the SAS compute context to use for subsequent SAS operations. Examples: 'SAS Studio Compute Context', 'my-compute', 'batch-compute'
25
+ EXAMPLES
26
+ - "use finance-cas-server" { cas: "finance-cas-server" }
27
+ - "switch to batch-compute" { sas: "batch-compute" }
28
+ - "what's my current context" → { }
31
29
 
32
- Response Contract
33
- Returns a JSON object containing:
34
- - cas: The current/new CAS server name (string or null)
35
- - sas: The current/new SAS compute context name (string or null)
36
- - If no parameters provided, returns the current context values
37
- - If parameters provided, updates and returns the new context values
38
- - On error: error message if context cannot be set (e.g., invalid server name)
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "read table cars" (use read-table)
32
+ - "what's the value of X" (use get-env)
33
+ - "run program" (use run-sas-program)
39
34
 
40
- Disambiguation & Clarification
41
- - If user says "switch servers" without specifying which: ask "Which server would you like to use: CAS, SAS, or both?"
42
- - If user provides a server name that may not exist: proceed with setting it (the backend will validate)
43
- - If user says "reset context": ask "Should I reset the CAS context, SAS context, or both?"
44
- - If user only says "context": ask "Would you like to check the current context or set a new one?"
45
-
46
- Examples (→ mapped params)
47
- - "Use the finance-cas-server" → { cas: "finance-cas-server" }
48
- - "Switch to SAS Studio Compute Context" → { sas: "SAS Studio Compute Context" }
49
- - "Set CAS to prod-cas and SAS to batch-compute" → { cas: "prod-cas", sas: "batch-compute" }
50
- - "What's my current context?" → { } (no parameters returns current context)
51
- - "Show me the active CAS server" → { } (no parameters returns current context)
52
-
53
- Negative Examples (should NOT call set-context)
54
- - "Read 10 rows from the customers table" (use read-table instead)
55
- - "What's the value of myVariable?" (use get-env instead)
56
- - "Run this SAS program" (use run-sas-program instead)
57
-
58
- Related Tools
59
- - get-env — to retrieve individual environment variable values
60
- - read-table — to read data using the current context
61
- - run-sas-program — to execute SAS programs in the current context
62
- - sas-query — to execute SQL queries in the current context
63
- `;
35
+ ERRORS
36
+ Returns current or updated context values {cas, sas}. Error if server not found or invalid name.
37
+ `;
64
38
 
65
39
  let spec = {
66
40
  name: 'set-context',
@@ -9,77 +9,34 @@ import _tableInfo from '../toolHelpers/_tableInfo.js';
9
9
  function tableInfo(_appContext) {
10
10
 
11
11
  let describe = `
12
- ## table-info — retrieve metadata about a table in a CAS or SAS library
13
-
14
- LLM Invocation Guidance (When to use)
15
- Use THIS tool when:
16
- - User wants table structure/schema: "what columns are in the cars table?"
17
- - User wants column metadata: "describe the structure of customers table"
18
- - User wants to see data types: "show me the schema for sales table in Public"
19
- - User wants table statistics: "how many rows in the orders table?"
20
- - User wants column information: "what are the columns in the iris table?"
21
-
22
- Do NOT use this tool for:
23
- - Reading actual data rows (use read-table)
24
- - Listing tables in a library (use list-tables)
25
- - Checking if a table exists (use find-table)
26
- - Running queries (use sas-query)
27
- - Reading sample data (use read-table)
28
-
29
- Purpose
30
- Return metadata about a table in a specified library (caslib or libref). This includes column names, data types, labels, formats, and table-level statistics such as row count, file size, and timestamps.
31
-
32
- Parameters
33
- - table (string, required): The name of the table to inspect.
34
- - lib (string, required): The caslib or libref containing the table.
35
- - server (string, default 'cas'): Target server, either 'cas' or 'sas'. Defaults to 'cas' when omitted.
36
-
37
- Response Contract
38
- Returns a JSON object containing:
39
- - columns: Array of column objects with:
40
- - name: Column name (string)
41
- - type: Data type (string) - e.g., 'numeric', 'character'
42
- - label: Column label if defined (string)
43
- - format: Display format if defined (string)
44
- - length: Column length for character fields (number)
45
- - tableInfo: Table-level metadata including:
46
- - rowCount: Number of rows (number)
47
- - fileSize: File size if available (number)
48
- - created: Creation timestamp if available (string)
49
- - modified: Last modified timestamp if available (string)
50
- - Empty object if table not found or accessible
51
-
52
- Disambiguation & Clarification
53
- - Missing library: ask "Which library contains the table you want to inspect?"
54
- - Missing table: ask "Which table would you like information about?"
55
- - If user wants data: clarify "Do you want the table structure (use table-info) or actual data rows (use read-table)?"
56
- - Ambiguous lib.table format: parse and use as separate parameters
57
-
58
- Examples (→ mapped params)
59
- - "describe table cars in sashelp" → { table: "cars", lib: "sashelp", server: "sas" }
60
- - "what columns are in orders from Public" → { table: "orders", lib: "Public", server: "cas" }
61
- - "show schema for sales in mylib" → { table: "sales", lib: "mylib", server: "cas" }
62
- - "table info for iris in Samples" → { table: "iris", lib: "Samples", server: "cas" }
63
- - "how many rows in customers on cas" → { table: "customers", lib: <lib>, server: "cas" }
64
-
65
- Negative Examples (should NOT call table-info)
66
- - "read 10 rows from cars" (use read-table instead)
67
- - "list tables in sashelp" (use list-tables instead)
68
- - "does table cars exist in Public?" (use find-table instead)
69
- - "run query on customers table" (use sas-query instead)
70
- - "show me data from the sales table" (use read-table instead)
71
-
72
- Usage Tips
73
- - Use this tool to inspect schema and column types before scoring or reading data.
74
- - After inspecting structure, use read-table to fetch actual data.
75
- - Combine with find-table to verify existence before inspection.
76
-
77
- Related Tools
78
- - find-table → table-info → read-table (typical workflow)
79
- - list-tables — to discover tables before inspecting
80
- - read-table — to fetch actual data after inspecting structure
81
- - find-table — to verify a table exists before inspection
82
- `;
12
+ table-info — retrieve metadata about a table in a CAS or SAS library.
13
+
14
+ USE when: what columns, describe structure, show schema, table statistics, column info
15
+ DO NOT USE for: read data (use read-table), list tables (use list-tables), find table (use find-table), queries (use sas-query)
16
+
17
+ PARAMETERS
18
+ - table: string table name (required)
19
+ - lib: string caslib or libref (required)
20
+ - server: string (default: 'cas') 'cas' or 'sas'
21
+
22
+ ROUTING RULES
23
+ - "what columns are in cars" → { table: "cars", lib: "<lib>", server: "cas" }
24
+ - "describe table sales in Public" { table: "sales", lib: "Public", server: "cas" }
25
+ - "show schema for mylib.iris on sas" → { table: "iris", lib: "mylib", server: "sas" }
26
+
27
+ EXAMPLES
28
+ - "what columns in cars" → { table: "cars", lib: "<lib>", server: "cas" }
29
+ - "describe structure of customers in Public" → { table: "customers", lib: "Public", server: "cas" }
30
+
31
+ NEGATIVE EXAMPLES (do not route here)
32
+ - "read table cars" (use read-table)
33
+ - "list tables in Public" (use list-tables)
34
+ - "does table exist" (use find-table)
35
+ - "query table" (use sas-query)
36
+
37
+ ERRORS
38
+ Returns columns array (name, type, label, format, length) and tableInfo (rowCount, fileSize, created, modified).
39
+ `;
83
40
 
84
41
  let specs = {
85
42
  name: 'table-info',
@@ -1,51 +0,0 @@
1
- /**
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- /**
6
- * Helper function to get TLS options(for the app server) from specified directory
7
- * signed certificates
8
- * for testing you can use mkcert
9
- * if this function return a null, coreehttp will create unsigned certs
10
- * @param {Object} _appContext - Application context containing SSLCERT property
11
- */
12
-
13
- import readCerts from './readCerts.js';
14
- function getOpts(_appContext) {
15
-
16
- if (_appContext.tlsOpts != null) {
17
- return _appContext.tlsOpts;
18
- }
19
- let r = readCerts(_appContext.SSLCERT);
20
- _appContext.tlsOpts = r;
21
- return r;
22
-
23
-
24
- /*
25
- let tlsdir = _appContext.SSLCERT;
26
- if (tlsdir == null || tlsdir === 'NONE') {
27
- return null;
28
- }
29
-
30
- console.error("[Note] Using TLS dir: " + tlsdir);
31
- if (fs.existsSync(tlsdir) === false) {
32
- console.error("[Warning] Specified TLS dir does not exist: " + tlsdir);
33
- return null;
34
- }
35
-
36
- let listOfFiles = fs.readdirSync(tlsdir);
37
- console.error("[Note] TLS/SSL files found: " + listOfFiles);
38
- let options = {};
39
- for(let i=0; i < listOfFiles.length; i++) {
40
- let fname = listOfFiles[i];
41
- let name = tlsdir + '/' + listOfFiles[i];
42
- let key = fname.split('.')[0];
43
- options[key] = fs.readFileSync(name, { encoding: 'utf8' });
44
- }
45
- console.error('TLS FILES', Object.keys(options));
46
- _appContext.tlsOpts = options;
47
- return options;
48
- */
49
-
50
- }
51
- export default getOpts;
@@ -1,44 +0,0 @@
1
- /**
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- import readCerts from './readCerts.js';
6
- function getOptsViya(_appContext) {
7
-
8
- if (_appContext.contexts.viyaCert != null) {
9
- console.error('[Note] Using cached viyaOpts');
10
- return _appContext.contexts.viyaCert;
11
- }
12
- let r = readCerts(_appContext.VIYACERT);
13
- _appContext.contexts.viyaCert = r;
14
- return r;
15
-
16
- /*
17
- let tlsdir = _appContext.VIYACERT;
18
- if (tlsdir == null || tlsdir === 'NONE') {
19
- return {};
20
- }
21
-
22
- console.error(`[Note] Using VIYACERT dir: ` + tlsdir);
23
- if (fs.existsSync(tlsdir) === false) {
24
- console.error("[Warning] Specified VIYACERT dir does not exist: " + tlsdir);
25
- return {};
26
- }
27
-
28
- let listOfFiles = fs.readdirSync(tlsdir);
29
- console.error("[Note] TLS/SSL files found: " + listOfFiles);
30
- let options = {};
31
- for(let i=0; i < listOfFiles.length; i++) {
32
- let fname = listOfFiles[i];
33
- let name = tlsdir + '/' + listOfFiles[i];
34
- let key = fname.split('.')[0];
35
- console.error('Reading TLS file: ' + name + ' as key: ' + key);
36
- options[key] = fs.readFileSync(name, { encoding: 'utf8' });
37
- }
38
- console.error('VIYACERT FILES', Object.keys(options));
39
- _appContext.contexts.viyaCert = options;
40
- return options;
41
- */
42
-
43
- }
44
- export default getOptsViya;