@sassoftware/sas-score-mcp-serverjs 0.4.1-1 → 0.4.1-15

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 +111 -31
  2. package/package.json +4 -2
  3. package/skills/sas-list-tables-smart/SKILL.md +123 -0
  4. package/skills/sas-read-and-score/SKILL.md +54 -53
  5. package/skills/sas-read-strategy/SKILL.md +10 -10
  6. package/skills/sas-score-workflow/SKILL.md +19 -2
  7. package/skills/sas-spec-migration/SKILL.md +303 -0
  8. package/src/authpkce.js +219 -0
  9. package/src/createMcpServer.js +11 -8
  10. package/src/expressMcpServer.js +354 -338
  11. package/src/oauthHandlers/authorize.js +46 -0
  12. package/src/oauthHandlers/baseUrl.js +8 -0
  13. package/src/oauthHandlers/callback.js +93 -0
  14. package/src/oauthHandlers/getMetadata.js +27 -0
  15. package/src/oauthHandlers/index.js +7 -0
  16. package/src/oauthHandlers/token.js +37 -0
  17. package/src/processHeaders.js +88 -0
  18. package/src/toolHelpers/_listLibrary.js +0 -1
  19. package/src/toolHelpers/getLogonPayload.js +5 -1
  20. package/src/toolHelpers/refreshTokenOauth.js +3 -3
  21. package/src/toolSet/.claude/settings.local.json +13 -0
  22. package/src/toolSet/devaScore.js +61 -61
  23. package/src/toolSet/findJob.js +1 -1
  24. package/src/toolSet/findJobdef.js +2 -2
  25. package/src/toolSet/findLibrary.js +68 -67
  26. package/src/toolSet/findModel.js +2 -2
  27. package/src/toolSet/findTable.js +3 -2
  28. package/src/toolSet/getEnv.js +8 -4
  29. package/src/toolSet/listJobdefs.js +61 -61
  30. package/src/toolSet/listJobs.js +61 -61
  31. package/src/toolSet/listLibraries.js +78 -78
  32. package/src/toolSet/listModels.js +56 -56
  33. package/src/toolSet/listTables.js +66 -65
  34. package/src/toolSet/modelInfo.js +2 -2
  35. package/src/toolSet/modelScore.js +6 -5
  36. package/src/toolSet/readTable.js +63 -65
  37. package/src/toolSet/runCasProgram.js +7 -6
  38. package/src/toolSet/runJob.js +81 -81
  39. package/src/toolSet/runJobdef.js +82 -82
  40. package/src/toolSet/runMacro.js +81 -80
  41. package/src/toolSet/runProgram.js +4 -8
  42. package/src/toolSet/sasQuery.js +77 -78
  43. package/src/toolSet/scrInfo.js +1 -1
  44. package/src/toolSet/scrScore.js +69 -68
  45. package/src/toolSet/setContext.js +65 -65
  46. package/src/toolSet/superstat.js +61 -59
  47. package/src/toolSet/tableInfo.js +58 -57
@@ -1,65 +1,66 @@
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 debug from 'debug';
8
- import _listTables from '../toolHelpers/_listTables.js';
9
-
10
-
11
- function listTables(_appContext) {
12
- const log = debug('tools');
13
-
14
- let description = `
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.
44
- `;
45
-
46
- let spec = {
47
- name: 'list-tables',
48
- description: description,
49
-
50
- inputSchema: z.object({
51
- 'lib': z.string(),
52
- 'server': z.string(),
53
- 'limit': z.number(),
54
- 'start': z.number()
55
- }),
56
- handler: async (params) => {
57
- let r = await _listTables(params);
58
- return r;
59
- }
60
- }
61
- return spec;
62
- }
63
-
64
- export default listTables;
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
+ import debug from 'debug';
8
+ import _listTables from '../toolHelpers/_listTables.js';
9
+
10
+
11
+ function listTables(_appContext) {
12
+ const log = debug('tools');
13
+
14
+ let description = `
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.
44
+ `;
45
+
46
+ let spec = {
47
+ name: 'list-tables',
48
+ description: description,
49
+
50
+ inputSchema: z.object({
51
+ lib: z.string(),
52
+ server: z.string().optional(),
53
+ limit: z.number().optional(),
54
+ start: z.number().optional(),
55
+ where: z.string().optional()
56
+ }),
57
+ handler: async (params) => {
58
+ let r = await _listTables(params);
59
+ return r;
60
+ }
61
+ }
62
+ return spec;
63
+ }
64
+
65
+ export default listTables;
66
+
@@ -41,7 +41,7 @@ Returns model metadata: inputs (name, type, role), outputs (name, type, possible
41
41
  name: 'model-info',
42
42
  description: description,
43
43
  inputSchema: z.object({
44
- 'model': z.string()
44
+ model: z.string()
45
45
  }),
46
46
  handler: async (params) => {
47
47
  let r = await _masDescribe(params);
@@ -52,4 +52,4 @@ Returns model metadata: inputs (name, type, role), outputs (name, type, possible
52
52
  }
53
53
 
54
54
  export default modelInfo;
55
-
55
+
@@ -42,11 +42,12 @@ Returns predictions, probabilities, scores merged with input data. Returns error
42
42
  let spec = {
43
43
  name: 'model-score',
44
44
  description: description,
45
- inputSchema: z.object({
46
- 'model': z.string(),
47
- 'scenario': z.any(),
48
- 'uflag': z.boolean()
45
+ inputSchema:z.object({
46
+ model: z.string(),
47
+ scenario: z.string(),
48
+ uflag: z.boolean().optional()
49
49
  }),
50
+
50
51
  handler: async (iparams) => {
51
52
  let params = {...iparams};
52
53
  let scenario = params.scenario;
@@ -85,4 +86,4 @@ Returns predictions, probabilities, scores merged with input data. Returns error
85
86
  }
86
87
 
87
88
  export default modelScore;
88
-
89
+
@@ -1,65 +1,63 @@
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 _readTable from '../toolHelpers/_readTable.js';
9
- function readTable(_appContext) {
10
-
11
- let describe = `
12
- read-table — retrieve rows from a table in a CAS or SAS library.
13
-
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
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
- - 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
25
-
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 }
30
-
31
- EXAMPLES
32
- - "read table cars in Samples" → { table: "cars", lib: "Samples", start: 1, limit: 10 }
33
- - "show 25 rows from customers" → { table: "customers", lib: "mylib", limit: 25, start: 1 }
34
-
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)
40
-
41
- ERRORS
42
- Returns rows array, total count, filtered_count, columns metadata. Empty array if no matches.
43
- `;
44
-
45
- let specs = {
46
- name: 'read-table',
47
- description: describe,
48
- inputSchema: z.object({
49
- table: z.string(),
50
- lib: z.string(),
51
- start: z.number(),
52
- limit: z.number(),
53
- server: z.string(),
54
- where: z.string(),
55
- format: z.boolean()
56
-
57
- }),
58
- handler: async (params) => {
59
- let r = await _readTable(params,'query');
60
- return r;
61
- }
62
- }
63
- return specs;
64
- }
65
- export default readTable;
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 _readTable from '../toolHelpers/_readTable.js';
9
+ function readTable(_appContext) {
10
+
11
+ let describe = `
12
+ read-table — retrieve rows from a table in a CAS or SAS library.
13
+
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
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
+ - 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
25
+
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 }
30
+
31
+ EXAMPLES
32
+ - "read table cars in Samples" → { table: "cars", lib: "Samples", start: 1, limit: 10 }
33
+ - "show 25 rows from customers" → { table: "customers", lib: "mylib", limit: 25, start: 1 }
34
+
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)
40
+
41
+ ERRORS
42
+ Returns rows array, total count, filtered_count, columns metadata. Empty array if no matches.
43
+ `;
44
+
45
+ let specs = {
46
+ name: 'read-table',
47
+ description: describe,
48
+ inputSchema: z.object({
49
+ table: z.string(),
50
+ lib: z.string().optional(),
51
+ start: z.number().optional(),
52
+ limit: z.number().optional(),
53
+ server: z.string().optional(),
54
+ where: z.string().optional()
55
+ }),
56
+ handler: async (params) => {
57
+ let r = await _readTable(params,'query');
58
+ return r;
59
+ }
60
+ }
61
+ return specs;
62
+ }
63
+ export default readTable;
@@ -43,13 +43,14 @@ Log output and CAS results. If output table specified, returned as markdown tabl
43
43
  let spec = {
44
44
  name: 'run-cas-program',
45
45
  description: description,
46
- inputSchema: z.object({
46
+ inputSchema:z.object({
47
47
  src: z.string(),
48
- scenario: z.any(),
49
- output: z.string(),
50
- folder: z.string(),
51
- limit: z.number()
52
- },
48
+ scenario: z.string(),
49
+ output: z.string().optional,
50
+ folder: z.string().optional,
51
+ limit: z.number().optional
52
+ }),
53
+
53
54
  // NOTE: Previously 'required' incorrectly listed 'program' which does not
54
55
  // exist in the schema. This prevented execution in some orchestrators that
55
56
  // enforce required parameter presence, causing only descriptions to appear.
@@ -1,81 +1,81 @@
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
8
-
9
- function runJob(_appContext) {
10
-
11
- let description = `
12
- 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
-
39
- let spec = {
40
- name: 'run-job',
41
- description: description,
42
- inputSchema: z.object({
43
- name: z.string(),
44
- scenario: z.any(),
45
- }),
46
- handler: async (params) => {
47
- let scenario = params.scenario;
48
- let scenarioObj = {};
49
- let count = 0;
50
- //
51
- if (scenario == null) {
52
- scenarioObj = {};
53
- } else if (typeof scenario === 'object') {
54
- scenarioObj = scenario;
55
- } else if (Array.isArray(scenario)) {
56
- scenarioObj = scenario[0];
57
- } else if (typeof scenario === 'string') {
58
- if (scenario.trim() === '') {
59
- scenarioObj = {};
60
- } else {
61
- // console.error('Incoming scenario', scenario);
62
- scenarioObj = scenario.split(',').reduce((acc, pair) => {
63
- let [key, value] = pair.split('=');
64
- acc[key.trim()] = value;
65
- count++;
66
- return acc;
67
- }, {});
68
- }
69
- }
70
- params.type = 'job';
71
- params.scenario = scenarioObj;
72
- // Provide runtime context for auth and server settings
73
- let r = await _jobSubmit(params);
74
- return r;
75
- }
76
- };
77
- return spec;
78
- }
79
-
80
- export default runJob;
81
-
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
8
+
9
+ function runJob(_appContext) {
10
+
11
+ let description = `
12
+ 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
+
39
+ let spec = {
40
+ name: 'run-job',
41
+ description: description,
42
+ inputSchema: z.object({
43
+ name: z.string(),
44
+ scenario: z.string().optional()
45
+ }),
46
+ handler: async (params) => {
47
+ let scenario = params.scenario;
48
+ let scenarioObj = {};
49
+ let count = 0;
50
+ //
51
+ if (scenario == null) {
52
+ scenarioObj = {};
53
+ } else if (typeof scenario === 'object') {
54
+ scenarioObj = scenario;
55
+ } else if (Array.isArray(scenario)) {
56
+ scenarioObj = scenario[0];
57
+ } else if (typeof scenario === 'string') {
58
+ if (scenario.trim() === '') {
59
+ scenarioObj = {};
60
+ } else {
61
+ // console.error('Incoming scenario', scenario);
62
+ scenarioObj = scenario.split(',').reduce((acc, pair) => {
63
+ let [key, value] = pair.split('=');
64
+ acc[key.trim()] = value;
65
+ count++;
66
+ return acc;
67
+ }, {});
68
+ }
69
+ }
70
+ params.type = 'job';
71
+ params.scenario = scenarioObj;
72
+ // Provide runtime context for auth and server settings
73
+ let r = await _jobSubmit(params);
74
+ return r;
75
+ }
76
+ };
77
+ return spec;
78
+ }
79
+
80
+ export default runJob;
81
+
@@ -1,82 +1,82 @@
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
8
-
9
- function runJobdef(_appContext) {
10
- // JSON object for LLM/tooling
11
-
12
- let description = `
13
- run-jobdef — execute a SAS Viya job definition.
14
-
15
- USE when: run jobdef, execute jobdef, run with parameters
16
- DO NOT USE for: arbitrary SAS code (use run-sas-program), macros (use run-macro), list/find jobdefs
17
-
18
- PARAMETERS
19
- - name: string — jobdef name (required)
20
- - scenario: string | object — input parameters. Accepts: "x=1, y=2" or {x:1, y:2}
21
-
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
-
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} }
29
-
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)
35
-
36
- ERRORS
37
- Returns log output, listings, tables from jobdef. Error if jobdef not found.
38
- `;
39
-
40
- let spec = {
41
- name: 'run-jobdef',
42
- description: description,
43
- inputSchema: z.object({
44
- name: z.string(),
45
- scenario: z.any()
46
- }),
47
- handler: async (params) => {
48
- let scenario = params.scenario;
49
- let scenarioObj = {};
50
- let count = 0;
51
- //
52
- if (scenario == null) {
53
- scenarioObj = {};
54
- } else if (typeof scenario === 'object') {
55
- scenarioObj = scenario;
56
- } else if (Array.isArray(scenario)) {
57
- scenarioObj = scenario[0];
58
- } else if (typeof scenario === 'string') {
59
- if (scenario.trim() === '') {
60
- scenarioObj = {};
61
- } else {
62
- // console.error('Incoming scenario', scenario);
63
- scenarioObj = scenario.split(',').reduce((acc, pair) => {
64
- let [key, value] = pair.split('=');
65
- acc[key.trim()] = value;
66
- count++;
67
- return acc;
68
- }, {});
69
- }
70
- }
71
- params.type = 'def';
72
- params.scenario = scenarioObj;
73
- // Provide runtime context for auth and server settings
74
- let r = await _jobSubmit(params);
75
- return r;
76
- }
77
- };
78
- return spec;
79
- }
80
-
81
- export default runJobdef;
82
-
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
8
+
9
+ function runJobdef(_appContext) {
10
+ // JSON object for LLM/tooling
11
+
12
+ let description = `
13
+ run-jobdef — execute a SAS Viya job definition.
14
+
15
+ USE when: run jobdef, execute jobdef, run with parameters
16
+ DO NOT USE for: arbitrary SAS code (use run-sas-program), macros (use run-macro), list/find jobdefs
17
+
18
+ PARAMETERS
19
+ - name: string — jobdef name (required)
20
+ - scenario: string | object — input parameters. Accepts: "x=1, y=2" or {x:1, y:2}
21
+
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
+
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} }
29
+
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)
35
+
36
+ ERRORS
37
+ Returns log output, listings, tables from jobdef. Error if jobdef not found.
38
+ `;
39
+
40
+ let spec = {
41
+ name: 'run-jobdef',
42
+ description: description,
43
+ inputSchema: z.object({
44
+ name: z.string(),
45
+ scenario: z.string().optional()
46
+ }),
47
+ handler: async (params) => {
48
+ let scenario = params.scenario;
49
+ let scenarioObj = {};
50
+ let count = 0;
51
+ //
52
+ if (scenario == null) {
53
+ scenarioObj = {};
54
+ } else if (typeof scenario === 'object') {
55
+ scenarioObj = scenario;
56
+ } else if (Array.isArray(scenario)) {
57
+ scenarioObj = scenario[0];
58
+ } else if (typeof scenario === 'string') {
59
+ if (scenario.trim() === '') {
60
+ scenarioObj = {};
61
+ } else {
62
+ // console.error('Incoming scenario', scenario);
63
+ scenarioObj = scenario.split(',').reduce((acc, pair) => {
64
+ let [key, value] = pair.split('=');
65
+ acc[key.trim()] = value;
66
+ count++;
67
+ return acc;
68
+ }, {});
69
+ }
70
+ }
71
+ params.type = 'def';
72
+ params.scenario = scenarioObj;
73
+ // Provide runtime context for auth and server settings
74
+ let r = await _jobSubmit(params);
75
+ return r;
76
+ }
77
+ };
78
+ return spec;
79
+ }
80
+
81
+ export default runJobdef;
82
+