@sassoftware/sas-score-mcp-serverjs 0.4.1 → 1.0.1-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/.skills/agents/sas-viya-scoring-expert.md +58 -0
- package/.skills/copilot-instructions.md +155 -0
- package/.skills/skills/sas-find-library-smart/SKILL.md +154 -0
- package/.skills/skills/sas-list-tables-smart/SKILL.md +127 -0
- package/.skills/skills/sas-read-and-score/SKILL.md +111 -0
- package/.skills/skills/sas-read-strategy/SKILL.md +156 -0
- package/.skills/skills/sas-request-classifier/SKILL.md +69 -0
- package/.skills/skills/sas-score-workflow/SKILL.md +314 -0
- package/cli.js +311 -70
- package/package.json +7 -7
- package/scripts/docs/SCORE_SKILL_REFERENCE.md +142 -0
- package/scripts/docs/TOOL_DESCRIPTION_TEMPLATE.md +157 -0
- package/scripts/docs/TOOL_UPDATES_SUMMARY.md +208 -0
- package/scripts/docs/mcp-localhost-config-guide.md +184 -0
- package/scripts/docs/oauth-http-transport.md +96 -0
- package/scripts/docs/sas-mcp-tools-reference.md +600 -0
- package/scripts/getViyaca.sh +1 -0
- package/scripts/optimize_final.py +140 -0
- package/scripts/optimize_tools.py +99 -0
- package/scripts/setup-skills.js +34 -0
- package/scripts/update_descriptions.py +46 -0
- package/scripts/viyatls.sh +3 -0
- package/src/authpkce.js +219 -0
- package/src/createMcpServer.js +16 -5
- package/src/expressMcpServer.js +350 -308
- package/src/handleGetDelete.js +6 -3
- package/src/hapiMcpServer.js +10 -18
- package/src/oauthHandlers/authorize.js +46 -0
- package/src/oauthHandlers/baseUrl.js +8 -0
- package/src/oauthHandlers/callback.js +96 -0
- package/src/oauthHandlers/getMetadata.js +27 -0
- package/src/oauthHandlers/index.js +7 -0
- package/src/oauthHandlers/token.js +37 -0
- package/src/processHeaders.js +88 -0
- package/src/setupSkills.js +46 -0
- package/src/toolHelpers/_jobSubmit.js +2 -0
- package/src/toolHelpers/_listLibrary.js +55 -39
- package/src/toolHelpers/getLogonPayload.js +7 -1
- package/src/toolHelpers/readCerts.js +4 -4
- package/src/toolHelpers/refreshToken.js +3 -2
- package/src/toolHelpers/refreshTokenOauth.js +3 -3
- package/src/toolSet/.claude/settings.local.json +13 -0
- package/src/toolSet/devaScore.js +61 -69
- package/src/toolSet/findJob.js +38 -71
- package/src/toolSet/findJobdef.js +28 -59
- package/src/toolSet/findLibrary.js +68 -100
- package/src/toolSet/findModel.js +35 -58
- package/src/toolSet/findTable.js +31 -60
- package/src/toolSet/getEnv.js +30 -45
- package/src/toolSet/listJobdefs.js +61 -96
- package/src/toolSet/listJobs.js +61 -110
- package/src/toolSet/listLibraries.js +78 -90
- package/src/toolSet/listModels.js +56 -83
- package/src/toolSet/listTables.js +66 -95
- package/src/toolSet/makeTools.js +1 -0
- package/src/toolSet/modelInfo.js +22 -54
- package/src/toolSet/modelScore.js +35 -77
- package/src/toolSet/readTable.js +63 -104
- package/src/toolSet/runCasProgram.js +32 -52
- package/src/toolSet/runJob.js +24 -24
- package/src/toolSet/runJobdef.js +26 -29
- package/src/toolSet/runMacro.js +82 -82
- package/src/toolSet/runProgram.js +32 -84
- package/src/toolSet/sasQuery.js +77 -126
- package/src/toolSet/sasQueryTemplate.js +4 -5
- package/src/toolSet/sasQueryTemplate2.js +4 -5
- package/src/toolSet/scrInfo.js +4 -7
- package/src/toolSet/scrScore.js +69 -70
- package/src/toolSet/searchAssets.js +5 -6
- package/src/toolSet/setContext.js +65 -92
- package/src/toolSet/superstat.js +61 -60
- package/src/toolSet/tableInfo.js +58 -102
package/src/toolSet/sasQuery.js
CHANGED
|
@@ -1,126 +1,77 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import {z} from 'zod';
|
|
6
|
-
import _jobSubmit from '../toolHelpers/_jobSubmit.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- Use table-info first to understand column names and types
|
|
79
|
-
- For simple reads without filtering/aggregation, prefer read-table
|
|
80
|
-
|
|
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
|
-
`;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
let spec = {
|
|
90
|
-
name: 'sas-query',
|
|
91
|
-
aliases: ['sasQuery','sas query','sas_query'],
|
|
92
|
-
description: description,
|
|
93
|
-
schema: {
|
|
94
|
-
query: z.string(),
|
|
95
|
-
table: z.string(),
|
|
96
|
-
sql: z.string().optional(),
|
|
97
|
-
job: z.string().default('program')
|
|
98
|
-
},
|
|
99
|
-
required: ['query', 'table'],
|
|
100
|
-
handler: async (params) => {
|
|
101
|
-
let {table,query, sql, job, _appContext} = params;
|
|
102
|
-
let sqlinput = (sql == null) ? ' ' : sql.replaceAll(';', ' ').replaceAll('\n', ' ').replaceAll('\r', ' ');
|
|
103
|
-
|
|
104
|
-
let iparams = {
|
|
105
|
-
scenario: {
|
|
106
|
-
table: table,
|
|
107
|
-
prompt: query,
|
|
108
|
-
sql: sqlinput
|
|
109
|
-
},
|
|
110
|
-
name: (job == null) ? 'program' : job,
|
|
111
|
-
type: 'job',
|
|
112
|
-
query: true,
|
|
113
|
-
_appContext: _appContext
|
|
114
|
-
};
|
|
115
|
-
if (sql == null || sql.trim().length === 0) {
|
|
116
|
-
return { content: [{ type: 'text', text: 'Error: The SQL statement generated is blank. Please provide a valid natural language query that can be converted to SQL.' }] };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
let r = await _jobSubmit(iparams);
|
|
120
|
-
return r;
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return spec;
|
|
125
|
-
}
|
|
126
|
-
export default sasQuery;
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import {z} from 'zod';
|
|
6
|
+
import _jobSubmit from '../toolHelpers/_jobSubmit.js';
|
|
7
|
+
|
|
8
|
+
function sasQuery() {
|
|
9
|
+
|
|
10
|
+
let description = `
|
|
11
|
+
sas-query — convert natural language questions into SQL queries and execute them.
|
|
12
|
+
|
|
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
|
|
15
|
+
|
|
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
|
|
21
|
+
|
|
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" }
|
|
25
|
+
|
|
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" }
|
|
29
|
+
|
|
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)
|
|
36
|
+
|
|
37
|
+
ERRORS
|
|
38
|
+
Returns rows array, columns metadata, log. Returns error if SQL invalid or table not found.
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
let spec = {
|
|
43
|
+
name: 'sas-query',
|
|
44
|
+
description: description,
|
|
45
|
+
inputSchema: z.object({
|
|
46
|
+
query: z.string(),
|
|
47
|
+
table: z.string(),
|
|
48
|
+
sql: z.string().optional()
|
|
49
|
+
}),
|
|
50
|
+
handler: async (params) => {
|
|
51
|
+
let {table,query, sql, job, _appContext} = params;
|
|
52
|
+
let sqlinput = (sql == null) ? ' ' : sql.replaceAll(';', ' ').replaceAll('\n', ' ').replaceAll('\r', ' ');
|
|
53
|
+
|
|
54
|
+
let iparams = {
|
|
55
|
+
scenario: {
|
|
56
|
+
table: table,
|
|
57
|
+
prompt: query,
|
|
58
|
+
sql: sqlinput
|
|
59
|
+
},
|
|
60
|
+
name: (job == null) ? 'program' : job,
|
|
61
|
+
type: 'job',
|
|
62
|
+
query: true,
|
|
63
|
+
_appContext: _appContext
|
|
64
|
+
};
|
|
65
|
+
if (sql == null || sql.trim().length === 0) {
|
|
66
|
+
return { content: [{ type: 'text', text: 'Error: The SQL statement generated is blank. Please provide a valid natural language query that can be converted to SQL.' }] };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let r = await _jobSubmit(iparams);
|
|
70
|
+
return r;
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return spec;
|
|
75
|
+
}
|
|
76
|
+
export default sasQuery;
|
|
77
|
+
|
|
@@ -108,13 +108,12 @@ async function sasQueryTemplate(uparams) {
|
|
|
108
108
|
name: toolname,
|
|
109
109
|
description: description,
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
inputSchema: z.object({
|
|
112
112
|
query: z.string(),
|
|
113
113
|
table: z.string().default(uTable),
|
|
114
|
-
sql: z.string()
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
handler: async (params) => {
|
|
114
|
+
sql: z.string()
|
|
115
|
+
}),
|
|
116
|
+
handler: async (params) => {
|
|
118
117
|
|
|
119
118
|
|
|
120
119
|
let { table, query, sql, _appContext} = params;
|
|
@@ -102,14 +102,13 @@ async function sasQueryTemplate2(uparams) {
|
|
|
102
102
|
name: toolname,
|
|
103
103
|
description: description,
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
inputSchema: z.object({
|
|
106
106
|
query: z.string(),
|
|
107
107
|
table: z.string().default(uTable),
|
|
108
|
-
sql: z.string()
|
|
108
|
+
sql: z.string(),
|
|
109
109
|
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
handler: async (params) => {
|
|
110
|
+
}),
|
|
111
|
+
handler: async (params) => {
|
|
113
112
|
|
|
114
113
|
let { table, query, sql } = params;
|
|
115
114
|
let sqlinput = (sql == null) ? ' ' : sql.replaceAll(';', ' ').replaceAll('\n', ' ').replaceAll('\r', ' ');
|
package/src/toolSet/scrInfo.js
CHANGED
|
@@ -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
|
-
-
|
|
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
|
|
|
@@ -34,12 +33,10 @@ Examples
|
|
|
34
33
|
|
|
35
34
|
let spec = {
|
|
36
35
|
name: 'scr-info',
|
|
37
|
-
aliases: ['scrInfo','scr info','scr_info'],
|
|
38
36
|
description: description,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
42
|
-
required: ['name'],
|
|
37
|
+
inputSchema: z.object({
|
|
38
|
+
url: z.string()
|
|
39
|
+
}),
|
|
43
40
|
handler: async (params) => {
|
|
44
41
|
let {url, _appContext} = params;
|
|
45
42
|
if (url === null) {
|
package/src/toolSet/scrScore.js
CHANGED
|
@@ -1,71 +1,70 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import _scrScore from '../toolHelpers/_scrScore.js';
|
|
8
|
-
|
|
9
|
-
function scrScore(_appContext) {
|
|
10
|
-
let description = `
|
|
11
|
-
## scr-score
|
|
12
|
-
|
|
13
|
-
Purpose
|
|
14
|
-
Score a scenario using a model deployed as a SCR container in Azure or another host).
|
|
15
|
-
|
|
16
|
-
Inputs
|
|
17
|
-
- url (string, required): SCR model identifier (URL)
|
|
18
|
-
- scenario (string | object | array, optional): Input values to score. Accepts:
|
|
19
|
-
- a comma-separated key=value string (e.g. "x=1, y=2"),
|
|
20
|
-
- a JSON object with field names and values (recommended for typed inputs),
|
|
21
|
-
- an array of objects for batch scoring. If omitted, the tool will return the model's input variable definitions.
|
|
22
|
-
|
|
23
|
-
What it returns
|
|
24
|
-
- When scoring: the SCR endpoint response (predictions, probabilities, scores) merged with or alongside the supplied inputs.
|
|
25
|
-
- When \`scenario\` is omitted: metadata describing the model's input variables (names, types, required/optional).
|
|
26
|
-
|
|
27
|
-
Usage notes
|
|
28
|
-
- Run \`scr-info\` first to inspect the expected input variables and types.
|
|
29
|
-
- Prefer structured objects for numeric/date values to avoid type ambiguity; the simple string parser keeps values as strings.
|
|
30
|
-
- Ensure network connectivity and any required credentials for the target SCR service.
|
|
31
|
-
|
|
32
|
-
Examples
|
|
33
|
-
- scrScore with url="loan" and scenario="age=45, income=60000"
|
|
34
|
-
- scrScore with url="https://scr-host/models/loan" and scenario={age:45, income:60000}
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
let spec = {
|
|
38
|
-
name: 'scr-score',
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
acc
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import _scrScore from '../toolHelpers/_scrScore.js';
|
|
8
|
+
|
|
9
|
+
function scrScore(_appContext) {
|
|
10
|
+
let description = `
|
|
11
|
+
## scr-score
|
|
12
|
+
|
|
13
|
+
Purpose
|
|
14
|
+
Score a scenario using a model deployed as a SCR container in Azure or another host).
|
|
15
|
+
|
|
16
|
+
Inputs
|
|
17
|
+
- url (string, required): SCR model identifier (URL)
|
|
18
|
+
- scenario (string | object | array, optional): Input values to score. Accepts:
|
|
19
|
+
- a comma-separated key=value string (e.g. "x=1, y=2"),
|
|
20
|
+
- a JSON object with field names and values (recommended for typed inputs),
|
|
21
|
+
- an array of objects for batch scoring. If omitted, the tool will return the model's input variable definitions.
|
|
22
|
+
|
|
23
|
+
What it returns
|
|
24
|
+
- When scoring: the SCR endpoint response (predictions, probabilities, scores) merged with or alongside the supplied inputs.
|
|
25
|
+
- When \`scenario\` is omitted: metadata describing the model's input variables (names, types, required/optional).
|
|
26
|
+
|
|
27
|
+
Usage notes
|
|
28
|
+
- Run \`scr-info\` first to inspect the expected input variables and types.
|
|
29
|
+
- Prefer structured objects for numeric/date values to avoid type ambiguity; the simple string parser keeps values as strings.
|
|
30
|
+
- Ensure network connectivity and any required credentials for the target SCR service.
|
|
31
|
+
|
|
32
|
+
Examples
|
|
33
|
+
- scrScore with url="loan" and scenario="age=45, income=60000"
|
|
34
|
+
- scrScore with url="https://scr-host/models/loan" and scenario={age:45, income:60000}
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
let spec = {
|
|
38
|
+
name: 'scr-score',
|
|
39
|
+
description: description,
|
|
40
|
+
inputSchema: z.object({
|
|
41
|
+
url: z.string(),
|
|
42
|
+
scenario: z.string().optional()
|
|
43
|
+
}),
|
|
44
|
+
|
|
45
|
+
handler: async (params) => {
|
|
46
|
+
let {url, scenario,_appContext} = params;
|
|
47
|
+
|
|
48
|
+
if (url === null) {
|
|
49
|
+
return { status: { statusCode: 2, msg: `SCR model ${url} was not specified` }, results: {} };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Normalize simple string scenarios like "x=1, y=2" into an object
|
|
53
|
+
if (typeof scenario === 'string' && scenario.includes('=')) {
|
|
54
|
+
scenario = scenario.split(',').reduce((acc, pair) => {
|
|
55
|
+
const [k, ...rest] = pair.split('=');
|
|
56
|
+
if (!k) return acc;
|
|
57
|
+
acc[k.trim()] = rest.join('=').trim();
|
|
58
|
+
return acc;
|
|
59
|
+
}, {});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let r = await _scrScore({ url: url, scenario: scenario , _appContext: _appContext});
|
|
63
|
+
return r;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return spec;
|
|
68
|
+
}
|
|
69
|
+
|
|
71
70
|
export default scrScore;
|
|
@@ -30,16 +30,15 @@ function searchAssets(_appContext) {
|
|
|
30
30
|
`;
|
|
31
31
|
|
|
32
32
|
let specs = {
|
|
33
|
-
name: '
|
|
33
|
+
name: 'search-assets',
|
|
34
34
|
description: description,
|
|
35
|
-
|
|
35
|
+
inputSchema: z.object({
|
|
36
36
|
searchstring: z.string(),
|
|
37
37
|
assetType: z.string(),
|
|
38
|
-
start: z.number()
|
|
39
|
-
limit: z.number()
|
|
38
|
+
start: z.number(),
|
|
39
|
+
limit: z.number()
|
|
40
40
|
|
|
41
|
-
},
|
|
42
|
-
required: ['assetType'],
|
|
41
|
+
}),
|
|
43
42
|
handler: async (params) => {
|
|
44
43
|
log('searchAssets params', params);
|
|
45
44
|
return await _catalogSearch(params, 'search');
|
|
@@ -1,92 +1,65 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {z} from 'zod';
|
|
7
|
-
|
|
8
|
-
function setContext(_appContext) {
|
|
9
|
-
let description = `
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
name: 'set-context',
|
|
67
|
-
aliases: ['setContext','set context','set_context'],
|
|
68
|
-
description: description,
|
|
69
|
-
schema: {
|
|
70
|
-
cas: z.string().optional(),
|
|
71
|
-
sas: z.string().optional()
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
handler: async (params) => {
|
|
75
|
-
|
|
76
|
-
let {cas, sas} = params;
|
|
77
|
-
if (typeof cas === 'string' && cas.trim().length > 0) {
|
|
78
|
-
_appContext.contexts.cas = cas.trim();
|
|
79
|
-
}
|
|
80
|
-
if (typeof sas === 'string' && sas.trim().length > 0) {
|
|
81
|
-
_appContext.contexts.sas = sas.trim();
|
|
82
|
-
}
|
|
83
|
-
// Return a structured response without extraneous keys
|
|
84
|
-
return {
|
|
85
|
-
content: [{ type: 'text', text: JSON.stringify(_appContext.contexts) }],
|
|
86
|
-
structuredContent: _appContext.contexts
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return spec;
|
|
91
|
-
}
|
|
92
|
-
export default setContext;
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {z} from 'zod';
|
|
7
|
+
|
|
8
|
+
function setContext(_appContext) {
|
|
9
|
+
let description = `
|
|
10
|
+
set-context — set the CAS and SAS server contexts for subsequent tool calls.
|
|
11
|
+
|
|
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)
|
|
14
|
+
|
|
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'
|
|
18
|
+
|
|
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)
|
|
24
|
+
|
|
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" → { }
|
|
29
|
+
|
|
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)
|
|
34
|
+
|
|
35
|
+
ERRORS
|
|
36
|
+
Returns current or updated context values {cas, sas}. Error if server not found or invalid name.
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
let spec = {
|
|
40
|
+
name: 'set-context',
|
|
41
|
+
description: description,
|
|
42
|
+
inputSchema: z.object({
|
|
43
|
+
cas: z.string().optional(),
|
|
44
|
+
sas: z.string().optional()
|
|
45
|
+
}),
|
|
46
|
+
handler: async (params) => {
|
|
47
|
+
|
|
48
|
+
let {cas, sas} = params;
|
|
49
|
+
if (typeof cas === 'string' && cas.trim().length > 0) {
|
|
50
|
+
_appContext.contexts.cas = cas.trim();
|
|
51
|
+
}
|
|
52
|
+
if (typeof sas === 'string' && sas.trim().length > 0) {
|
|
53
|
+
_appContext.contexts.sas = sas.trim();
|
|
54
|
+
}
|
|
55
|
+
// Return a structured response without extraneous keys
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: 'text', text: JSON.stringify(_appContext.contexts) }],
|
|
58
|
+
structuredContent: _appContext.contexts
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return spec;
|
|
63
|
+
}
|
|
64
|
+
export default setContext;
|
|
65
|
+
|