@sassoftware/sas-score-mcp-serverjs 1.0.1-30 → 1.0.1-32
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-score-mcp-serverjs-agent.md +1 -1
- package/.skills/copilot-instructions.md +57 -26
- package/.skills/skills/detail-strategy/SKILL.md +95 -49
- package/.skills/skills/find-resources/SKILL.md +38 -31
- package/.skills/skills/list-resource/SKILL.md +93 -33
- package/.skills/skills/request-routing/SKILL.md +9 -4
- package/.skills/skills/score-strategy/SKILL.md +21 -3
- package/README.md +62 -43
- package/openApi.yaml +121 -121
- package/package.json +7 -5
- package/scripts/docs/oauth-http-transport.md +2 -2
- package/scripts/plot_msrp_usa.py +49 -0
- package/scripts/refreshtoken.js +57 -57
- package/src/createMcpServer.js +0 -1
- package/src/openApi.yaml +121 -121
- package/src/toolHelpers/_findJob.js +12 -0
- package/src/toolHelpers/_findJobdef.js +10 -0
- package/src/toolHelpers/_findLibrary.js +10 -0
- package/src/toolHelpers/_findMas.js +12 -0
- package/src/toolHelpers/_findTable.js +10 -0
- package/src/toolHelpers/_listJobs.js +2 -2
- package/src/toolHelpers/{_listModels.js → _listMas.js} +4 -4
- package/src/toolSet/devaScore.js +61 -61
- package/src/toolSet/findJob.js +2 -1
- package/src/toolSet/findJobdef.js +2 -2
- package/src/toolSet/findLibrary.js +68 -68
- package/src/toolSet/findMas.js +59 -0
- package/src/toolSet/findTable.js +2 -2
- package/src/toolSet/jobInfo.js +59 -0
- package/src/toolSet/jobdefInfo.js +59 -0
- package/src/toolSet/listJobdefs.js +61 -61
- package/src/toolSet/listJobs.js +61 -61
- package/src/toolSet/listLibraries.js +78 -78
- package/src/toolSet/{listModels.js → listMas.js} +61 -56
- package/src/toolSet/listTables.js +66 -66
- package/src/toolSet/makeTools.js +21 -12
- package/src/toolSet/{modelInfo.js → masInfo.js} +12 -12
- package/src/toolSet/{modelScore.js → masScore.js} +3 -3
- package/src/toolSet/readTable.js +63 -63
- package/src/toolSet/runMacro.js +82 -82
- package/src/toolSet/sasQuery.js +77 -77
- package/src/toolSet/setContext.js +65 -65
- package/src/toolSet/superstat.js +61 -61
- package/src/toolSet/tableInfo.js +58 -58
- package/scripts/optimize_final.py +0 -140
- package/scripts/optimize_tools.py +0 -99
- package/scripts/setup-skills.js +0 -34
- package/scripts/token.txt +0 -1
- package/scripts/update_descriptions.py +0 -46
- package/src/toolSet/findModel.js +0 -60
package/src/toolSet/tableInfo.js
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
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 debug from 'debug';
|
|
7
|
-
|
|
8
|
-
import _tableInfo from '../toolHelpers/_tableInfo.js';
|
|
9
|
-
import { type } from 'node:os';
|
|
10
|
-
function tableInfo(_appContext) {
|
|
11
|
-
|
|
12
|
-
let describe = `
|
|
13
|
-
table-info — retrieve metadata about a table in a CAS or SAS library.
|
|
14
|
-
|
|
15
|
-
USE when: what columns, describe structure, show schema, table statistics, column info
|
|
16
|
-
DO NOT USE for: read data (use read-table), list tables (use list-tables), find table (use find-table), queries (use sas-query)
|
|
17
|
-
|
|
18
|
-
PARAMETERS
|
|
19
|
-
- table: string — table name (required)
|
|
20
|
-
- lib: string — caslib or libref (required)
|
|
21
|
-
- server: string (default: 'cas') — 'cas' or 'sas'
|
|
22
|
-
|
|
23
|
-
ROUTING RULES
|
|
24
|
-
- "what columns are in cars" → { table: "cars", lib: "<lib>", server: "cas" }
|
|
25
|
-
- "describe table sales in Public" → { table: "sales", lib: "Public", server: "cas" }
|
|
26
|
-
- "show schema for mylib.iris on sas" → { table: "iris", lib: "mylib", server: "sas" }
|
|
27
|
-
|
|
28
|
-
EXAMPLES
|
|
29
|
-
- "what columns in cars" → { table: "cars", lib: "<lib>", server: "cas" }
|
|
30
|
-
- "describe structure of customers in Public" → { table: "customers", lib: "Public", server: "cas" }
|
|
31
|
-
|
|
32
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
33
|
-
- "read table cars" (use read-table)
|
|
34
|
-
- "list tables in Public" (use list-tables)
|
|
35
|
-
- "does table exist" (use find-table)
|
|
36
|
-
- "query table" (use sas-query)
|
|
37
|
-
|
|
38
|
-
ERRORS
|
|
39
|
-
Returns columns array (name, type, label, format, length) and tableInfo (rowCount, fileSize, created, modified).
|
|
40
|
-
`;
|
|
41
|
-
|
|
42
|
-
let specs = {
|
|
43
|
-
name: 'table-info',
|
|
44
|
-
description: describe,
|
|
45
|
-
inputSchema: z.object({
|
|
46
|
-
table: z.string(),
|
|
47
|
-
lib: z.string().optional(),
|
|
48
|
-
server: z.string().optional()
|
|
49
|
-
}),
|
|
50
|
-
handler: async (params) => {
|
|
51
|
-
params.describe = true;
|
|
52
|
-
let r = await _tableInfo(params);
|
|
53
|
-
return r;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return specs;
|
|
57
|
-
}
|
|
58
|
-
export default tableInfo;
|
|
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 debug from 'debug';
|
|
7
|
+
|
|
8
|
+
import _tableInfo from '../toolHelpers/_tableInfo.js';
|
|
9
|
+
import { type } from 'node:os';
|
|
10
|
+
function tableInfo(_appContext) {
|
|
11
|
+
|
|
12
|
+
let describe = `
|
|
13
|
+
table-info — retrieve metadata about a table in a CAS or SAS library.
|
|
14
|
+
|
|
15
|
+
USE when: what columns, describe structure, show schema, table statistics, column info
|
|
16
|
+
DO NOT USE for: read data (use read-table), list tables (use list-tables), find table (use find-table), queries (use sas-query)
|
|
17
|
+
|
|
18
|
+
PARAMETERS
|
|
19
|
+
- table: string — table name (required)
|
|
20
|
+
- lib: string — caslib or libref (required)
|
|
21
|
+
- server: string (default: 'cas') — 'cas' or 'sas'
|
|
22
|
+
|
|
23
|
+
ROUTING RULES
|
|
24
|
+
- "what columns are in cars" → { table: "cars", lib: "<lib>", server: "cas" }
|
|
25
|
+
- "describe table sales in Public" → { table: "sales", lib: "Public", server: "cas" }
|
|
26
|
+
- "show schema for mylib.iris on sas" → { table: "iris", lib: "mylib", server: "sas" }
|
|
27
|
+
|
|
28
|
+
EXAMPLES
|
|
29
|
+
- "what columns in cars" → { table: "cars", lib: "<lib>", server: "cas" }
|
|
30
|
+
- "describe structure of customers in Public" → { table: "customers", lib: "Public", server: "cas" }
|
|
31
|
+
|
|
32
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
33
|
+
- "read table cars" (use read-table)
|
|
34
|
+
- "list tables in Public" (use list-tables)
|
|
35
|
+
- "does table exist" (use find-table)
|
|
36
|
+
- "query table" (use sas-query)
|
|
37
|
+
|
|
38
|
+
ERRORS
|
|
39
|
+
Returns columns array (name, type, label, format, length) and tableInfo (rowCount, fileSize, created, modified).
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
let specs = {
|
|
43
|
+
name: 'table-info',
|
|
44
|
+
description: describe,
|
|
45
|
+
inputSchema: z.object({
|
|
46
|
+
table: z.string(),
|
|
47
|
+
lib: z.string().optional(),
|
|
48
|
+
server: z.string().optional()
|
|
49
|
+
}),
|
|
50
|
+
handler: async (params) => {
|
|
51
|
+
params.describe = true;
|
|
52
|
+
let r = await _tableInfo(params);
|
|
53
|
+
return r;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return specs;
|
|
57
|
+
}
|
|
58
|
+
export default tableInfo;
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
# Read and replace listJobs
|
|
5
|
-
with open('src/toolSet/listJobs.js', 'r') as f:
|
|
6
|
-
content = f.read()
|
|
7
|
-
|
|
8
|
-
# Find and replace listJobs description - find the full description block
|
|
9
|
-
pattern = r'let description = `\n ## list-jobs.*? `;'
|
|
10
|
-
replacement = r'''let description = `
|
|
11
|
-
list-jobs — enumerate SAS Viya job assets.
|
|
12
|
-
|
|
13
|
-
USE when: list jobs, show jobs, browse jobs, list available jobs, next page of jobs
|
|
14
|
-
DO NOT USE for: find single job (use find-job), execute job (use run-job), run jobdef (use run-jobdef), sas code (use run-sas-program)
|
|
15
|
-
|
|
16
|
-
PARAMETERS
|
|
17
|
-
- limit: number (default: 10) — number of jobs per page
|
|
18
|
-
- start: number (default: 1) — 1-based page offset
|
|
19
|
-
- where: string (default: '') — optional filter expression
|
|
20
|
-
|
|
21
|
-
ROUTING RULES
|
|
22
|
-
- "list jobs" → { start: 1, limit: 10 }
|
|
23
|
-
- "show me 25 jobs" → { start: 1, limit: 25 }
|
|
24
|
-
- "list jobs limit 50" → { start: 1, limit: 50 }
|
|
25
|
-
- "next jobs" (after prior page) → { start: previousStart + previousLimit, limit: previousLimit }
|
|
26
|
-
|
|
27
|
-
EXAMPLES
|
|
28
|
-
- "list jobs" → { start: 1, limit: 10 }
|
|
29
|
-
- "list 25 jobs" → { start: 1, limit: 25 }
|
|
30
|
-
- "next jobs" → { start: 11, limit: 10 }
|
|
31
|
-
|
|
32
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
33
|
-
- "find job abc" (use find-job)
|
|
34
|
-
- "run job abc" (use run-job)
|
|
35
|
-
- "list models" (use list-models)
|
|
36
|
-
|
|
37
|
-
PAGINATION
|
|
38
|
-
If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
|
|
39
|
-
|
|
40
|
-
ERRORS
|
|
41
|
-
Surface backend error directly; never fabricate job names.
|
|
42
|
-
`;'''
|
|
43
|
-
|
|
44
|
-
if re.search(pattern, content, re.DOTALL):
|
|
45
|
-
content = re.sub(pattern, replacement, content, flags=re.DOTALL)
|
|
46
|
-
with open('src/toolSet/listJobs.js', 'w') as f:
|
|
47
|
-
f.write(content)
|
|
48
|
-
print("✓ Updated listJobs.js")
|
|
49
|
-
else:
|
|
50
|
-
print("✗ Pattern not found in listJobs.js")
|
|
51
|
-
|
|
52
|
-
# Read and replace listJobdefs
|
|
53
|
-
with open('src/toolSet/listJobdefs.js', 'r') as f:
|
|
54
|
-
content = f.read()
|
|
55
|
-
|
|
56
|
-
pattern = r'let description = `\n ## list-jobdefs.*? `;'
|
|
57
|
-
replacement = r'''let description = `
|
|
58
|
-
list-jobdefs — enumerate SAS Viya job definitions (jobdefs) assets.
|
|
59
|
-
|
|
60
|
-
USE when: list jobdefs, show jobdefs, browse jobdefs, list available jobdefs, next page
|
|
61
|
-
DO NOT USE for: find single jobdef (use find-jobdef), execute jobdef (use run-jobdef), find job (use find-job), sas code (use run-sas-program)
|
|
62
|
-
|
|
63
|
-
PARAMETERS
|
|
64
|
-
- limit: number (default: 10) — number of jobdefs per page
|
|
65
|
-
- start: number (default: 1) — 1-based page offset
|
|
66
|
-
- where: string (default: '') — optional filter expression
|
|
67
|
-
|
|
68
|
-
ROUTING RULES
|
|
69
|
-
- "list jobdefs" → { start: 1, limit: 10 }
|
|
70
|
-
- "show me 25 jobdefs" → { start: 1, limit: 25 }
|
|
71
|
-
- "next jobdefs" → { start: previousStart + previousLimit, limit: previousLimit }
|
|
72
|
-
|
|
73
|
-
EXAMPLES
|
|
74
|
-
- "list jobdefs" → { start: 1, limit: 10 }
|
|
75
|
-
- "list 25 jobdefs" → { start: 1, limit: 25 }
|
|
76
|
-
- "next jobdefs" → { start: 11, limit: 10 }
|
|
77
|
-
|
|
78
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
79
|
-
- "find jobdef abc" (use find-jobdef)
|
|
80
|
-
- "list jobs" (use list-jobs)
|
|
81
|
-
- "run jobdef abc" (use run-jobdef)
|
|
82
|
-
|
|
83
|
-
PAGINATION
|
|
84
|
-
If returned length === limit, hint: next start = start + limit.
|
|
85
|
-
|
|
86
|
-
ERRORS
|
|
87
|
-
Surface backend error directly; never fabricate jobdef names.
|
|
88
|
-
`;'''
|
|
89
|
-
|
|
90
|
-
if re.search(pattern, content, re.DOTALL):
|
|
91
|
-
content = re.sub(pattern, replacement, content, flags=re.DOTALL)
|
|
92
|
-
with open('src/toolSet/listJobdefs.js', 'w') as f:
|
|
93
|
-
f.write(content)
|
|
94
|
-
print("✓ Updated listJobdefs.js")
|
|
95
|
-
else:
|
|
96
|
-
print("✗ Pattern not found in listJobdefs.js")
|
|
97
|
-
|
|
98
|
-
# Read and replace runCasProgram
|
|
99
|
-
with open('src/toolSet/runCasProgram.js', 'r') as f:
|
|
100
|
-
content = f.read()
|
|
101
|
-
|
|
102
|
-
pattern = r'let description = `\n## run-cas-program.*?Response\n`'
|
|
103
|
-
replacement = r'''let description = `
|
|
104
|
-
run-cas-program — execute a CAS program on SAS Viya server.
|
|
105
|
-
|
|
106
|
-
USE when: run cas program, execute cas, submit cas, run cas code, cas action
|
|
107
|
-
DO NOT USE for: macros (use run-macro), sas code (use run-sas-program), jobs (use run-job/find-job), jobdefs (use run-jobdef/find-jobdef), models (use find-model)
|
|
108
|
-
|
|
109
|
-
PARAMETERS
|
|
110
|
-
- src: string (required) — CAS program code to execute verbatim
|
|
111
|
-
- scenario: string | object (optional) — input parameters. Accepts: "x=1, y=2" or {x:1, y:2}
|
|
112
|
-
|
|
113
|
-
ROUTING RULES
|
|
114
|
-
- "run cas program 'action echo / code=\"xyz\"'" → { src: "action echo / code=\"xyz\"" }
|
|
115
|
-
- "submit cas action echo" → { src: "action echo" }
|
|
116
|
-
- "cas program with param1=10" → { src: "...", scenario: {param1: 10} }
|
|
117
|
-
|
|
118
|
-
EXAMPLES
|
|
119
|
-
- "run cas program 'action echo / code=\"hello\"'" → { src: "action echo / code=\"hello\"" }
|
|
120
|
-
- "execute cas action simple.summary" → { src: "action simple.summary" }
|
|
121
|
-
|
|
122
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
123
|
-
- "run sas macro" (use run-macro)
|
|
124
|
-
- "submit sas code" (use run-sas-program)
|
|
125
|
-
- "run job X" (use run-job)
|
|
126
|
-
|
|
127
|
-
NOTES
|
|
128
|
-
Sends src verbatim without validation. For SAS macros use run-macro. For arbitrary SAS code use run-sas-program.
|
|
129
|
-
|
|
130
|
-
RESPONSE
|
|
131
|
-
Log output, listings, tables from CAS execution. Error if execution fails.
|
|
132
|
-
`'''
|
|
133
|
-
|
|
134
|
-
if re.search(pattern, content, re.DOTALL):
|
|
135
|
-
content = re.sub(pattern, replacement, content, flags=re.DOTALL)
|
|
136
|
-
with open('src/toolSet/runCasProgram.js', 'w') as f:
|
|
137
|
-
f.write(content)
|
|
138
|
-
print("✓ Updated runCasProgram.js")
|
|
139
|
-
else:
|
|
140
|
-
print("✗ Pattern not found in runCasProgram.js")
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
# DevaScore optimization
|
|
5
|
-
deva_old = ''' let description = `
|
|
6
|
-
## deva-score — compute a numeric score based on two input values
|
|
7
|
-
|
|
8
|
-
LLM Invocation Guidance (When to use)
|
|
9
|
-
Use THIS tool when:
|
|
10
|
-
- User wants to calculate the deva score: "Calculate deva score for 5 and 10"
|
|
11
|
-
- User provides two numbers for scoring: "Score these values: 3 and 7"
|
|
12
|
-
- User wants to compute a score in a series: "Calculate scores for [list of numbers]"
|
|
13
|
-
|
|
14
|
-
Do NOT use this tool for:
|
|
15
|
-
- Scoring models (use model-score)
|
|
16
|
-
- Statistical calculations beyond deva scoring
|
|
17
|
-
- Looking up data or metadata
|
|
18
|
-
|
|
19
|
-
Purpose
|
|
20
|
-
Compute a numeric deva score by applying the formula (a + b) * 42 to two input numbers. For scoring more than two numbers, call this tool multiple times using the previous result as the first input (left-to-right fold).
|
|
21
|
-
|
|
22
|
-
Parameters
|
|
23
|
-
- a (number, required): First numeric input value
|
|
24
|
-
- b (number, required): Second numeric input value
|
|
25
|
-
|
|
26
|
-
Response Contract
|
|
27
|
-
Returns a numeric result: (a + b) * 42
|
|
28
|
-
The result is always a number representing the computed deva score.
|
|
29
|
-
|
|
30
|
-
Disambiguation & Clarification
|
|
31
|
-
- If user provides more than two numbers without clear instructions: "Do you want to calculate the deva score by combining these numbers left-to-right?"
|
|
32
|
-
- If user provides non-numeric input: "Please provide numeric values"
|
|
33
|
-
|
|
34
|
-
Examples (→ mapped params)
|
|
35
|
-
- "Calculate deva score for 5 and 10" → { a: 5, b: 10 } returns 630
|
|
36
|
-
- "Score 1 and 2" → { a: 1, b: 2 } returns 126
|
|
37
|
-
- For multiple numbers, chain calls: devaScore(1,2)→126, then devaScore(126,3)→5418
|
|
38
|
-
|
|
39
|
-
Negative Examples (should NOT call deva-score)
|
|
40
|
-
- "Score this customer with the credit model" (use model-score instead)
|
|
41
|
-
- "Calculate the mean of these values" (use run-sas-program or sas-query instead)
|
|
42
|
-
|
|
43
|
-
Related Tools
|
|
44
|
-
- None directly related (this is a specialized scoring tool)
|
|
45
|
-
|
|
46
|
-
Notes
|
|
47
|
-
For sequences of numbers, use a left-to-right fold: call devaScore(first, second), then use that result as the first parameter for devaScore(result, third), and so on.
|
|
48
|
-
`;'''
|
|
49
|
-
|
|
50
|
-
deva_new = ''' let description = `
|
|
51
|
-
deva-score — compute a numeric score based on two input values.
|
|
52
|
-
|
|
53
|
-
USE when: calculate deva score, score these values, compute score for numbers
|
|
54
|
-
DO NOT USE for: model scoring (use model-score), statistical calculations, data lookup
|
|
55
|
-
|
|
56
|
-
PARAMETERS
|
|
57
|
-
- a: number (required) — first input value
|
|
58
|
-
- b: number (required) — second input value
|
|
59
|
-
|
|
60
|
-
FORMULA: (a + b) * 42
|
|
61
|
-
|
|
62
|
-
ROUTING RULES
|
|
63
|
-
- "calculate deva score for 5 and 10" → { a: 5, b: 10 }
|
|
64
|
-
- "score 1 and 2" → { a: 1, b: 2 }
|
|
65
|
-
- "deva score a=3, b=7" → { a: 3, b: 7 }
|
|
66
|
-
- Multiple numbers → chain calls left-to-right: call(first, second), then call(result, third)
|
|
67
|
-
|
|
68
|
-
EXAMPLES
|
|
69
|
-
- "Calculate deva score for 5 and 10" → { a: 5, b: 10 } returns 630
|
|
70
|
-
- "Score 1 and 2" → { a: 1, b: 2 } returns 126
|
|
71
|
-
- "Deva score 20 and 30" → { a: 20, b: 30 } returns 2100
|
|
72
|
-
|
|
73
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
74
|
-
- "Score this customer with credit model" (use model-score)
|
|
75
|
-
- "Calculate the mean of these values" (use run-sas-program or sas-query)
|
|
76
|
-
- "Statistical analysis of numbers" (use sas-query)
|
|
77
|
-
|
|
78
|
-
RESPONSE
|
|
79
|
-
Returns { score: (a + b) * 42 }
|
|
80
|
-
`;'''
|
|
81
|
-
|
|
82
|
-
files = {
|
|
83
|
-
'src/toolSet/devaScore.js': (deva_old, deva_new),
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
for filepath, (old, new) in files.items():
|
|
87
|
-
try:
|
|
88
|
-
with open(filepath, 'r', encoding='utf-8') as f:
|
|
89
|
-
content = f.read()
|
|
90
|
-
|
|
91
|
-
if old in content:
|
|
92
|
-
content = content.replace(old, new)
|
|
93
|
-
with open(filepath, 'w', encoding='utf-8') as f:
|
|
94
|
-
f.write(content)
|
|
95
|
-
print(f"✓ Updated {filepath}")
|
|
96
|
-
else:
|
|
97
|
-
print(f"✗ Pattern not found in {filepath}")
|
|
98
|
-
except Exception as e:
|
|
99
|
-
print(f"✗ Error updating {filepath}: {e}")
|
package/scripts/setup-skills.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import os from 'os';
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
// Paths
|
|
8
|
-
let client = (process.env.CLIENTNAME == null) ? '.github' : `.${process.env.CLIENTNAME.toLowerCase()}`;
|
|
9
|
-
const source = path.join(__dirname, `../.github`);
|
|
10
|
-
const destination = path.join(process.cwd(), client);
|
|
11
|
-
// const destination = path.join(os.homedir(), client)
|
|
12
|
-
console.error(`📁 Copying ${source} to ${destination}...`);
|
|
13
|
-
function copyFolderSync(from, to) {
|
|
14
|
-
if (!fs.existsSync(from)) return;
|
|
15
|
-
if (!fs.existsSync(to)) fs.mkdirSync(to, { recursive: true });
|
|
16
|
-
console.error(`📁 Copying folder: ${from} to ${to}`);
|
|
17
|
-
fs.readdirSync(from).forEach(element => {
|
|
18
|
-
const fromPath = path.join(from, element);
|
|
19
|
-
const toPath = path.join(to, element);
|
|
20
|
-
if (fs.lstatSync(fromPath).isFile()) {
|
|
21
|
-
fs.copyFileSync(fromPath, toPath);
|
|
22
|
-
} else if (fs.lstatSync(fromPath).isDirectory()) {
|
|
23
|
-
copyFolderSync(fromPath, toPath);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
copyFolderSync(source, destination);
|
|
30
|
-
console.error(`✅ Success: ${destination} folder is now in your project root.`);
|
|
31
|
-
} catch (err) {
|
|
32
|
-
console.error('❌ Error copying files:', err.message);
|
|
33
|
-
}
|
|
34
|
-
process.exit(0);
|
package/scripts/token.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
eyJqa3UiOiJodHRwczovL2xvY2FsaG9zdC9TQVNMb2dvbi90b2tlbl9rZXlzIiwia2lkIjoibGVnYWN5LXRva2VuLWtleSIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIxNjQzMmUzNC1kNTFiLTQ0ODUtYmRhNS0xMTBkYWI2ODJkMjAiLCJ1c2VyX25hbWUiOiJkZXZhLmt1bWFyQHNhcy5jb20iLCJvcmlnaW4iOiJleHRlcm5hbF9vYXV0aCIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3QvU0FTTG9nb24vb2F1dGgvdG9rZW4iLCJhdXRob3JpdGllcyI6WyJWU0NvZGVHZW5BSSIsIkRhdGFRdWFsaXR5LkRhdGFRdWFsaXR5TW9uaXRvcmluZ0FkbWluaXN0cmF0b3JzIiwiU2NoZWR1bGVTZXJ2aWNlQWNjb3VudFVzZXJzIiwiQXBwbGljYXRpb25BZG1pbmlzdHJhdG9ycyIsIkJhdGNoU2VydmljZUFjY291bnRVc2VycyIsIkxhdW5jaGVyU3VwZXJVc2VycyIsIkVzcmlVc2VycyIsIkRhdGFBZ2VudEFkbWluaXN0cmF0b3JzIiwiU0NJTSIsIkRhdGFBZ2VudFBvd2VyVXNlcnMiLCJTQVNTY29yZVVzZXJzIiwiU0FTQWRtaW5pc3RyYXRvcnMiLCJHbG9zc2FyeS5HbG9zc2FyeUFkbWluaXN0cmF0b3JzIiwiQ2F0YWxvZy5TdWJqZWN0TWF0dGVyRXhwZXJ0cyIsIkNvbXB1dGVTZXJ2aWNlQWNjb3VudFVzZXJzIiwiQ0FTSG9zdEFjY291bnRSZXF1aXJlZCJdLCJjbGllbnRfaWQiOiJzYXMuY2xpIiwiYXVkIjpbInVhYSIsInNhcy1jb21wdXRlIiwic2FzLXRyYW5zZmVyIiwic2FzLXdvcmtsb2FkLW9yY2hlc3RyYXRvciIsInNhcy1jb25uZWN0Iiwic2FzLWNhcy1tYW5hZ2VtZW50Iiwic2FzLXNjaGVkdWxlciIsImNsaWVudHMiLCJzYXMtcmVwb3J0LXBhY2thZ2VzIiwib3BlbmlkIiwic2FzLWZvbnRzIiwic2FzLWNyZWRlbnRpYWxzIiwic2FzLWNvbmZpZ3VyYXRpb24iLCJzYXMuY2xpIiwic2FzLWF1dGhvcml6YXRpb24iLCJzYXMtZGV2aWNlLW1hbmFnZW1lbnQiLCJzYXMtZm9sZGVycyIsInNhcy1qb2ItZXhlY3V0aW9uIiwic2FzLWF1ZGl0Iiwic2FzLWlkZW50aXRpZXMiLCJzYXMtYmF0Y2giLCJzY2ltIiwic2FzLWxhdW5jaGVyIl0sImV4dF9pZCI6IjAwdTJzcTg3Ynh0YTI2OEhaMnA3IiwicmVtb3RlX2lwIjoiMTQ5LjE3My40NS44OCIsInppZCI6InVhYSIsImdyYW50X3R5cGUiOiJhdXRob3JpemF0aW9uX2NvZGUiLCJ1c2VyX2lkIjoiMTY0MzJlMzQtZDUxYi00NDg1LWJkYTUtMTEwZGFiNjgyZDIwIiwiYXpwIjoic2FzLmNsaSIsInNjb3BlIjpbInNhcy1jb21wdXRlLnVzZXJfaW1wZXJzb25hdGlvbiIsInNhcy1jYXMtbWFuYWdlbWVudC51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtaWRlbnRpdGllcy51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtbGF1bmNoZXIudXNlcl9pbXBlcnNvbmF0aW9uIiwic2FzLWNyZWRlbnRpYWxzLnVzZXJfaW1wZXJzb25hdGlvbiIsInNhcy1hdWRpdC51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtY29uZmlndXJhdGlvbi51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtc2NoZWR1bGVyLnVzZXJfaW1wZXJzb25hdGlvbiIsImNsaWVudHMucmVhZCIsInNhcy1iYXRjaC51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtam9iLWV4ZWN1dGlvbi51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtZGV2aWNlLW1hbmFnZW1lbnQudXNlcl9pbXBlcnNvbmF0aW9uIiwiY2xpZW50cy5zZWNyZXQiLCJvcGVuaWQiLCJzYXMtZm9udHMudXNlcl9pbXBlcnNvbmF0aW9uIiwic2FzLXdvcmtsb2FkLW9yY2hlc3RyYXRvci51c2VyX2ltcGVyc29uYXRpb24iLCJ1YWEuYWRtaW4iLCJjbGllbnRzLmFkbWluIiwic2FzLWF1dGhvcml6YXRpb24udXNlcl9pbXBlcnNvbmF0aW9uIiwic2NpbS5yZWFkIiwidWFhLnVzZXIiLCJzYXMtY29ubmVjdC51c2VyX2ltcGVyc29uYXRpb24iLCJzYXMtcmVwb3J0LXBhY2thZ2VzLnVzZXJfaW1wZXJzb25hdGlvbiIsInNhcy1mb2xkZXJzLnVzZXJfaW1wZXJzb25hdGlvbiIsIlNBU0FkbWluaXN0cmF0b3JzIiwiY2xpZW50cy53cml0ZSIsInNjaW0ud3JpdGUiLCJzYXMtdHJhbnNmZXIudXNlcl9pbXBlcnNvbmF0aW9uIl0sImF1dGhfdGltZSI6MTc3ODY4NjQ5NywiZXhwIjoxNzc4NzAxMTY1LCJpYXQiOjE3Nzg2OTc1NjUsImp0aSI6ImFjNTk0ZGQyMDA0NDQwYTBhYjAzZGJlNzlmMWIzMzI5IiwiZW1haWwiOiJkZXZhLmt1bWFyQHNhcy5jb20iLCJyZXZfc2lnIjoiMmVjZTJiZDAiLCJjbGllbnRfYXV0aF9tZXRob2QiOiJub25lIiwiY2lkIjoic2FzLmNsaSJ9.fBObEchePj1_u3xpdXaXuy3O_7fiZyYSY38fK37LEduGs45ktDaYi_F7hWCQnHEK45b8Ti_ROcyesCVjUcXPzzbw722PYEDT4909qnUM-n0DXEV1tCoOkSbMF7Gv-wbRif7cJP2Q3G-sO5dkw9blGJC-YbvzR04f-TqhcQqmaxQLh7E-G4qIvKtcKtB9j4pCwwc-Dz9LxqIcY5xpEF92wnqYdKtNGSGQsTHyR0cCNAkQBv-dO6snhplBMVZrSGbuo0mGZcA3736n1JJ1jKvPT1rPKn7vtUO30sLfNP3rL21SAEZ6wO3SOs_liJNMllC_cJq5jYytx0rfYuubUH0xZA
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
import re
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
os.chdir('c:/dev/github/sas-score-mcp-serverjs')
|
|
6
|
-
|
|
7
|
-
# Update runJob.js
|
|
8
|
-
file_path = 'src/toolSet/runJob.js'
|
|
9
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
10
|
-
content = f.read()
|
|
11
|
-
|
|
12
|
-
new_desc = """run-job — execute a deployed SAS Viya job.
|
|
13
|
-
|
|
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
|
|
16
|
-
|
|
17
|
-
PARAMETERS
|
|
18
|
-
- name: string — job name (required)
|
|
19
|
-
- scenario: string | object — input parameters. Accepts: "x=1, y=2" or {x:1, y:2}
|
|
20
|
-
|
|
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"} }
|
|
24
|
-
|
|
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} }
|
|
28
|
-
|
|
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."""
|
|
37
|
-
|
|
38
|
-
# Use a more flexible pattern
|
|
39
|
-
pattern = r'let description = `\n## run-job.*?`;\n'
|
|
40
|
-
replacement = f'let description = `\n{new_desc}\n`;\n'
|
|
41
|
-
updated = re.sub(pattern, replacement, content, flags=re.DOTALL)
|
|
42
|
-
|
|
43
|
-
with open(file_path, 'w', encoding='utf-8') as f:
|
|
44
|
-
f.write(updated)
|
|
45
|
-
|
|
46
|
-
print(f"✓ Updated {file_path}")
|
package/src/toolSet/findModel.js
DELETED
|
@@ -1,60 +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
|
-
import { z } from 'zod';
|
|
7
|
-
import _listModels from '../toolHelpers/_listModels.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function findModel(_appContext) {
|
|
11
|
-
let description = `
|
|
12
|
-
find-model — locate a specific MAS model deployed to MAS server
|
|
13
|
-
|
|
14
|
-
USE when: find model, does model exist, is model deployed, lookup model, verify model exists
|
|
15
|
-
DO NOT USE for: list models (use list-models), model info/variables (use model-info), score model (use model-score), find table/job/lib (use respective tools), scr models (use scr-info/scr-score)
|
|
16
|
-
|
|
17
|
-
PARAMETERS
|
|
18
|
-
- name: string (required) — model name to locate; if multiple supplied, use first
|
|
19
|
-
|
|
20
|
-
ROUTING RULES
|
|
21
|
-
- "find model <name>" → { name: "<name>" }
|
|
22
|
-
- "does model <name> exist" → { name: "<name>" }
|
|
23
|
-
- "is model <name> deployed" → { name: "<name>" }
|
|
24
|
-
- "lookup/verify model <name>" → { name: "<name>" }
|
|
25
|
-
- "find model" with no name → ask "Which model name would you like to find?"
|
|
26
|
-
- "find all models / list models" → use list-models instead
|
|
27
|
-
- "score model <name>" → use model-score instead
|
|
28
|
-
- "describe model / model info" → use model-info instead
|
|
29
|
-
|
|
30
|
-
EXAMPLES
|
|
31
|
-
- "find model myModel" → { name: "myModel" }
|
|
32
|
-
- "does model churn_score exist" → { name: "churn_score" }
|
|
33
|
-
- "is model riskModel deployed" → { name: "riskModel" }
|
|
34
|
-
- "lookup model claims_fraud_v1" → { name: "claims_fraud_v1" }
|
|
35
|
-
|
|
36
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
37
|
-
- "list models" (use list-models)
|
|
38
|
-
- "score model myModel" (use model-score)
|
|
39
|
-
- "model info for churnRisk" (use model-info)
|
|
40
|
-
|
|
41
|
-
ERRORS
|
|
42
|
-
Returns { models: [] } if not found; { models: [name, ...] } if found. Never hallucinate model names.
|
|
43
|
-
`;
|
|
44
|
-
|
|
45
|
-
let spec = {
|
|
46
|
-
name: 'find-model',
|
|
47
|
-
description: description,
|
|
48
|
-
inputSchema: z.object({
|
|
49
|
-
name: z.string()
|
|
50
|
-
}),
|
|
51
|
-
handler: async (params) => {
|
|
52
|
-
let r = await _listModels(params);
|
|
53
|
-
return r;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return spec;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default findModel;
|
|
60
|
-
|