@sassoftware/sas-score-mcp-serverjs 1.0.1-9 → 1.1.2

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 (118) hide show
  1. package/.skills/.claude-plugin/plugin.json +59 -0
  2. package/.skills/agents/sas-score-mcp-serverjs-agent.md +26 -0
  3. package/.skills/copilot-instructions.md +62 -0
  4. package/.skills/skills/README.md +204 -0
  5. package/.skills/skills/detail-strategy/SKILL.md +316 -0
  6. package/.skills/skills/find-library-server/SKILL.md +62 -0
  7. package/.skills/skills/find-resources/SKILL.md +66 -0
  8. package/.skills/skills/list-library/SKILL.md +30 -0
  9. package/.skills/skills/list-mas-job-jobdef/SKILL.md +31 -0
  10. package/.skills/skills/list-tables/SKILL.md +30 -0
  11. package/.skills/skills/read-strategy/SKILL.md +87 -0
  12. package/.skills/skills/request-routing/SKILL.md +112 -0
  13. package/.skills/skills/score-cas/SKILL.md +95 -0
  14. package/.skills/skills/score-job-jobdef/SKILL.md +58 -0
  15. package/.skills/skills/score-mas-scr/SKILL.md +58 -0
  16. package/.skills/skills/score-program/SKILL.md +59 -0
  17. package/.skills/skills/score-strategy/SKILL.md +39 -0
  18. package/README.md +96 -54
  19. package/cli.js +11 -13
  20. package/openApi.yaml +121 -121
  21. package/package.json +16 -14
  22. package/scripts/docs/SCORE_SKILL_REFERENCE.md +17 -16
  23. package/scripts/docs/TOOL_DESCRIPTION_TEMPLATE.md +3 -3
  24. package/scripts/docs/TOOL_UPDATES_SUMMARY.md +65 -63
  25. package/scripts/docs/oauth-http-transport.md +2 -2
  26. package/scripts/docs/sas-mcp-tools-reference.md +43 -32
  27. package/scripts/plot_msrp_usa.py +49 -0
  28. package/scripts/refreshtoken.js +58 -0
  29. package/scripts/runListScr.mjs +16 -0
  30. package/src/createMcpServer.js +4 -1
  31. package/src/expressMcpServer.js +47 -49
  32. package/src/oauthHandlers/authorize.js +4 -1
  33. package/src/oauthHandlers/baseUrl.js +4 -0
  34. package/src/oauthHandlers/callback.js +4 -0
  35. package/src/oauthHandlers/getMetadata.js +4 -0
  36. package/src/oauthHandlers/index.js +4 -0
  37. package/src/oauthHandlers/token.js +4 -0
  38. package/src/openApi.yaml +121 -121
  39. package/src/processHeaders.js +10 -7
  40. package/src/setupSkills.js +1 -18
  41. package/src/toolHelpers/_casScore.js +32 -0
  42. package/src/toolHelpers/_desc.js +14 -0
  43. package/src/toolHelpers/_findJob.js +12 -0
  44. package/src/toolHelpers/_findJobdef.js +10 -0
  45. package/src/toolHelpers/_findLibrary.js +11 -0
  46. package/src/toolHelpers/_findMas.js +13 -0
  47. package/src/toolHelpers/_findScr.js +36 -0
  48. package/src/toolHelpers/_findTable.js +11 -0
  49. package/src/toolHelpers/_listJobdefs.js +12 -2
  50. package/src/toolHelpers/_listJobs.js +19 -8
  51. package/src/toolHelpers/{_listModels.js → _listMas.js} +4 -4
  52. package/src/toolHelpers/_listScr.js +13 -0
  53. package/src/toolHelpers/{_scrInfo.js → _scrDescribe.js} +4 -4
  54. package/src/toolHelpers/_scrScore.js +2 -2
  55. package/src/toolHelpers/_submitCasl.js +19 -17
  56. package/src/toolHelpers/{_tableInfo.js → _tableDescribe.js} +2 -2
  57. package/src/toolHelpers/getLogonPayload.js +2 -2
  58. package/src/toolSet/casModelScore.js +93 -0
  59. package/src/toolSet/casProgramScore.js +105 -0
  60. package/src/toolSet/devaScore.js +66 -61
  61. package/src/toolSet/findJob.js +24 -9
  62. package/src/toolSet/findJobdef.js +22 -19
  63. package/src/toolSet/findLibrary.js +73 -68
  64. package/src/toolSet/findMas.js +72 -0
  65. package/src/toolSet/findScr.js +69 -0
  66. package/src/toolSet/findTable.js +34 -27
  67. package/src/toolSet/getEnv.js +6 -6
  68. package/src/toolSet/jobDescribe.js +65 -0
  69. package/src/toolSet/jobScore.js +90 -0
  70. package/src/toolSet/jobdefDescribe.js +67 -0
  71. package/src/toolSet/jobdefScore.js +85 -0
  72. package/src/toolSet/listJobdefs.js +70 -61
  73. package/src/toolSet/listJobs.js +68 -61
  74. package/src/toolSet/listLibraries.js +84 -78
  75. package/src/toolSet/listMas.js +71 -0
  76. package/src/toolSet/listScr.js +62 -0
  77. package/src/toolSet/listTables.js +78 -66
  78. package/src/toolSet/{runMacro.js → macroScore.js} +86 -82
  79. package/src/toolSet/makeTools.js +39 -25
  80. package/src/toolSet/masDescribe.js +67 -0
  81. package/src/toolSet/masScore.js +95 -0
  82. package/src/toolSet/{runProgram.js → programScore.js} +21 -18
  83. package/src/toolSet/readTable.js +80 -63
  84. package/src/toolSet/sasQuery.js +83 -77
  85. package/src/toolSet/scrDescribe.js +55 -0
  86. package/src/toolSet/scrScore.js +63 -70
  87. package/src/toolSet/searchAssets.js +1 -1
  88. package/src/toolSet/setContext.js +70 -65
  89. package/src/toolSet/superstat.js +61 -61
  90. package/src/toolSet/tableDescribe.js +65 -0
  91. package/.agents/sas-score-mcp-serverjs-agent.md +0 -58
  92. package/.instructions/copilot-instructions.md +0 -201
  93. package/.instructions/enforce-find-resource-strategy.md +0 -35
  94. package/.skills/sas-find-library-smart/SKILL.md +0 -155
  95. package/.skills/sas-find-resource-strategy/SKILL.md +0 -105
  96. package/.skills/sas-list-resource-strategy/SKILL.md +0 -124
  97. package/.skills/sas-list-tables-smart/SKILL.md +0 -128
  98. package/.skills/sas-read-and-score-strategy/SKILL.md +0 -113
  99. package/.skills/sas-read-strategy/SKILL.md +0 -154
  100. package/.skills/sas-request-classifier/SKILL.md +0 -74
  101. package/.skills/sas-score-workflow-strategy/SKILL.md +0 -314
  102. package/scripts/optimize_final.py +0 -140
  103. package/scripts/optimize_tools.py +0 -99
  104. package/scripts/setup-skills.js +0 -34
  105. package/scripts/update_descriptions.py +0 -46
  106. package/src/authpkce.js +0 -219
  107. package/src/handleGetDelete.js +0 -34
  108. package/src/handleRequest.js +0 -112
  109. package/src/hapiMcpServer.js +0 -241
  110. package/src/toolSet/findModel.js +0 -60
  111. package/src/toolSet/listModels.js +0 -56
  112. package/src/toolSet/modelInfo.js +0 -55
  113. package/src/toolSet/modelScore.js +0 -89
  114. package/src/toolSet/runCasProgram.js +0 -98
  115. package/src/toolSet/runJob.js +0 -81
  116. package/src/toolSet/runJobdef.js +0 -82
  117. package/src/toolSet/scrInfo.js +0 -52
  118. package/src/toolSet/tableInfo.js +0 -58
@@ -1,61 +1,66 @@
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
-
7
- function devaScore(_appContext) {
8
-
9
- let description = `
10
- deva-score compute a numeric score based on two input values.
11
-
12
- USE when: calculate deva score, score these values, compute score for numbers
13
- DO NOT USE for: model scoring (use model-score), statistical calculations, data lookup
14
-
15
- PARAMETERS
16
- - a: number (required) — first input value
17
- - b: number (required) second input value
18
-
19
- FORMULA: (a + b) * 42
20
-
21
- ROUTING RULES
22
- - "calculate deva score for 5 and 10" → { a: 5, b: 10 }
23
- - "score 1 and 2" → { a: 1, b: 2 }
24
- - "deva score a=3, b=7" → { a: 3, b: 7 }
25
- - Multiple numbers → chain calls left-to-right: call(first, second), then call(result, third)
26
-
27
- EXAMPLES
28
- - "Calculate deva score for 5 and 10" → { a: 5, b: 10 } returns 630
29
- - "Score 1 and 2" → { a: 1, b: 2 } returns 126
30
- - "Deva score 20 and 30" → { a: 20, b: 30 } returns 2100
31
-
32
- NEGATIVE EXAMPLES (do not route here)
33
- - "Score this customer with credit model" (use model-score)
34
- - "Calculate the mean of these values" (use run-sas-program or sas-query)
35
- - "Statistical analysis of numbers" (use sas-query)
36
-
37
- RESPONSE
38
- Returns { score: (a + b) * 42 }
39
- `;
40
- let spec = {
41
- name: 'deva-score',
42
- description: description,
43
- inputSchema: z.object({
44
- a: z.number(),
45
- b: z.number(),
46
- }),
47
- handler: async ({ a, b }) => {
48
- console.error(a, b);
49
- let r = { score: (a + b) * 42 };
50
- console.error('deva score result', r);
51
- return {
52
- content: [{ type: 'text', text: 'deva score result: ' + JSON.stringify(r) }],
53
- structuredContent: r
54
- };
55
- }
56
- }
57
-
58
- return spec;
59
- }
60
- export default devaScore;
61
-
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
+
7
+ function devaScore(_appContext) {
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let brand = _appContext.brand + '-';
10
+ let description = isAgent ? `
11
+ deva-score — run a demonstration scoring calculation.
12
+ PARAMS: a (number, required), b (number, required)
13
+ RETURNS: computed result for a and b
14
+ ` : `
15
+ deva-score — compute a numeric score based on two input values.
16
+
17
+ USE when: calculate deva score, score these values, compute score for numbers
18
+ DO NOT USE for: model scoring (use ${brand}model-score), statistical calculations, data lookup
19
+
20
+ PARAMETERS
21
+ - a: number (required) — first input value
22
+ - b: number (required) second input value
23
+
24
+ FORMULA: (a + b) * 42
25
+
26
+ ROUTING RULES
27
+ - "calculate deva score for 5 and 10" → { a: 5, b: 10 }
28
+ - "score 1 and 2" → { a: 1, b: 2 }
29
+ - "deva score a=3, b=7" → { a: 3, b: 7 }
30
+ - Multiple numbers chain calls left-to-right: call(first, second), then call(result, third)
31
+
32
+ EXAMPLES
33
+ - "Calculate deva score for 5 and 10" { a: 5, b: 10 } returns 630
34
+ - "Score 1 and 2" { a: 1, b: 2 } returns 126
35
+ - "Deva score 20 and 30" { a: 20, b: 30 } returns 2100
36
+
37
+ NEGATIVE EXAMPLES (do not route here)
38
+ - "Score this customer with credit model" (use ${brand}model-score)
39
+ - "Calculate the mean of these values" (use ${brand}program-score or ${brand}sas-query)
40
+ - "Statistical analysis of numbers" (use ${brand}sas-query)
41
+
42
+ RESPONSE
43
+ Returns { score: (a + b) * 42 }
44
+ `;
45
+ let spec = {
46
+ name: 'deva-score',
47
+ description: description,
48
+ inputSchema: z.object({
49
+ a: z.number(),
50
+ b: z.number(),
51
+ }),
52
+ handler: async ({ a, b }) => {
53
+ console.error(a, b);
54
+ let r = { score: (a + b) * 42 };
55
+ console.error('deva score result', r);
56
+ return {
57
+ content: [{ type: 'text', text: 'deva score result: ' + JSON.stringify(r) }],
58
+ structuredContent: r
59
+ };
60
+ }
61
+ }
62
+
63
+ return spec;
64
+ }
65
+ export default devaScore;
66
+
@@ -4,25 +4,34 @@
4
4
  */
5
5
  import { z } from 'zod';
6
6
  import _listJobs from '../toolHelpers/_listJobs.js';
7
+ import _findJob from '../toolHelpers/_findJob.js';
7
8
  function findJob(_appContext) {
8
-
9
- let description = `
9
+ const isAgent = _appContext && _appContext.agent;
10
+ let description = isAgent ? `
11
+ find-job — verify a Job model exists.
12
+ PARAMS: name (string, required)
13
+ RETURNS: job metadata if found, error if not found
14
+ ` : `
10
15
  find-job — locate a specific SAS Viya job.
11
16
 
12
17
  USE when: find job, does job exist, is there a job named, lookup job, verify job exists
13
- DO NOT USE for: list jobs (use list-jobs), run job (use run-job), execute jobdef (use run-jobdef), find lib/table/model (use respective tools)
18
+ DO NOT USE for: list jobs (use ${_appContext.brand}-list-jobs), score job (use ${_appContext.brand}-job-score), score jobdef (use ${_appContext.brand}-jobdef-score), find lib/table/model (use respective tools)
14
19
 
15
20
  PARAMETERS
16
21
  - name: string (required) — job name to locate; if multiple supplied, use first
17
22
 
23
+ Naming Rules:
24
+ - If user provides name with "job" suffix ".job", strip the suffix (e.g., "cars_job_v4.job"), and look for "cars_job_v4".
25
+
18
26
  ROUTING RULES
19
27
  - "find job <name>" → { name: "<name>" }
28
+ - "find name.job" → { name: "<name>" }
20
29
  - "does job <name> exist" → { name: "<name>" }
21
30
  - "is there a job named <name>" → { name: "<name>" }
22
31
  - "lookup/verify job <name>" → { name: "<name>" }
23
32
  - "find job" with no name → ask "Which job name would you like to find?"
24
- - "find all jobs / list jobs" → use list-jobs instead
25
- - "run job <name>" → use run-job instead
33
+ - "find all jobs / list jobs" → use ${_appContext.brand}-list-jobs instead
34
+ - "score job <name>" → use ${_appContext.brand}-job-score instead
26
35
 
27
36
  EXAMPLES
28
37
  - "find job cars_job_v4" → { name: "cars_job_v4" }
@@ -30,9 +39,9 @@ EXAMPLES
30
39
  - "is there a job named metricsRefresh" → { name: "metricsRefresh" }
31
40
 
32
41
  NEGATIVE EXAMPLES (do not route here)
33
- - "list jobs" (use list-jobs)
34
- - "run job cars_job_v4" (use run-job)
35
- - "execute jobdef cars_job_v4" (use run-jobdef)
42
+ - "list jobs" (use ${_appContext.brand}-list-jobs)
43
+ - "score job cars_job_v4" (use ${_appContext.brand}-job-score)
44
+ - "score jobdef cars_job_v4" (use ${_appContext.brand}-jobdef-score)
36
45
 
37
46
  ERRORS
38
47
  Returns { jobs: [] } if not found; { jobs: [name, ...] } if found. Never hallucinate job names.
@@ -45,7 +54,13 @@ Returns { jobs: [] } if not found; { jobs: [name, ...] } if found. Never halluci
45
54
  name: z.string()
46
55
  }),
47
56
  handler: async (params) => {
48
- let r = await _listJobs(params);
57
+ if (params.name != null) {
58
+ if (params.name.endsWith('.job')) {
59
+ params.name = params.name.slice(0, -4);
60
+ }
61
+ }
62
+ params.tool = 'find';
63
+ let r = await _findJob(params);
49
64
  return r;
50
65
  }
51
66
  }
@@ -3,34 +3,31 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { z } from 'zod';
6
- import _listJobdefs from '../toolHelpers/_listJobdefs.js';
6
+ import _findJobdef from '../toolHelpers/_findJobdef.js';
7
7
  function findJobdef(_appContext) {
8
- let llmDescription= {
9
- "purpose": "Map natural language requests to find a jobdef (job definition) in SAS Viya and return structured results.",
10
- "param_mapping": {
11
- "name": "required - single name. If missing, ask 'Which jobdef name would you like to find?'.",
12
-
13
- },
14
- "response_schema": "{ jobs: Array<string|object> }",
15
- "behavior": "Return only JSON matching response_schema when invoked by an LLM. If no matches, return { jobs: [] }"
16
- };
17
- let description = `
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ find-jobdef — verify a JobDef model exists.
11
+ PARAMS: name (string, required)
12
+ RETURNS: jobdef metadata if found, error if not found
13
+ ` : `
18
14
  find-jobdef — locate a specific SAS Viya job definition.
19
15
 
20
16
  USE when: find jobdef, does jobdef exist, is there a jobdef named, lookup jobdef, verify jobdef exists
21
- DO NOT USE for: list jobdefs (use list-jobdefs), run jobdef (use run-jobdef), find job/lib/table/model (use respective tools)
17
+ DO NOT USE for: list jobdefs (use ${_appContext.brand}-list-jobdefs), score jobdef (use ${_appContext.brand}-jobdef-score), find job/lib/table/model (use respective tools)
22
18
 
23
19
  PARAMETERS
24
20
  - name: string (required) — jobdef name to locate; if multiple supplied, use first
25
21
 
26
22
  ROUTING RULES
27
23
  - "find jobdef <name>" → { name: "<name>" }
24
+ - "find name.jobdef" → { name: "<name>" }
28
25
  - "does jobdef <name> exist" → { name: "<name>" }
29
26
  - "is there a jobdef named <name>" → { name: "<name>" }
30
27
  - "lookup/verify jobdef <name>" → { name: "<name>" }
31
28
  - "find jobdef" with no name → ask "Which jobdef name would you like to find?"
32
- - "find all jobdefs / list jobdefs" → use list-jobdefs instead
33
- - "run jobdef <name>" → use run-jobdef instead
29
+ - "find all jobdefs / list jobdefs" → use ${_appContext.brand}-list-jobdefs instead
30
+ - "score jobdef <name>" → use ${_appContext.brand}-jobdef-score instead
34
31
 
35
32
  EXAMPLES
36
33
  - "find jobdef cars_job_v4" → { name: "cars_job_v4" }
@@ -38,10 +35,10 @@ EXAMPLES
38
35
  - "is there a jobdef named metricsRefresh" → { name: "metricsRefresh" }
39
36
 
40
37
  NEGATIVE EXAMPLES (do not route here)
41
- - "list jobdefs" (use list-jobdefs)
42
- - "run jobdef cars_job_v4" (use run-jobdef)
43
- - "find job ETL" (use find-job)
44
- - "find table cars" (use find-table)
38
+ - "list jobdefs" (use ${_appContext.brand}-list-jobdefs)
39
+ - "score jobdef cars_job_v4" (use ${_appContext.brand}-jobdef-score)
40
+ - "find job ETL" (use ${_appContext.brand}-find-job)
41
+ - "find table cars" (use ${_appContext.brand}-find-table)
45
42
 
46
43
  ERRORS
47
44
  Returns { jobdefs: [] } if not found; { jobdefs: [name, ...] } if found. Never hallucinate jobdef names.
@@ -54,7 +51,13 @@ Returns { jobdefs: [] } if not found; { jobdefs: [name, ...] } if found. Never h
54
51
  name: z.string()
55
52
  }),
56
53
  handler: async (params) => {
57
- let r = await _listJobdefs(params);
54
+ if (params.name != null) {
55
+ if (params.name.endsWith('.jobdef')) {
56
+ params.name = params.name.slice(0, -7);
57
+ }
58
+ }
59
+ params.tool = 'find';
60
+ let r = await _findJobdef(params);
58
61
  return r;
59
62
  }
60
63
  }
@@ -1,68 +1,73 @@
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 _listLibrary from '../toolHelpers/_listLibrary.js';
7
- function findLibrary(_appContext) {
8
-
9
- let description = `
10
- find-library — locate a specific CAS or SAS library.
11
-
12
- USE when: find library, find lib, does library exist, is library available, lookup library
13
- DO NOT USE for: list libraries (use list-libraries), find table/job/jobdef/model (use respective tools), table structure (use table-info), create library (use run-sas-program)
14
-
15
- PARAMETERS
16
- - name: string (required) library/caslib name; if multiple supplied, use first
17
- - server: 'cas' | 'sas' (default: 'cas') target environment
18
-
19
- ROUTING RULES
20
- - "find lib <name>" { name: "<name>", server: "cas" }
21
- - "find lib <name> in cas" { name: "<name>", server: "cas" }
22
- - "find library <name> in sas" → { name: "<name>", server: "sas" }
23
- - "does library <name> exist" → { name: "<name>", server: "cas" }
24
- - "find lib" with no name → ask "Which library name would you like to find?"
25
- - "list libraries / list libs" use list-libraries instead
26
- - "tables in <lib>" use list-tables instead
27
-
28
- EXAMPLES
29
- - "find lib Public" { name: "Public", server: "cas" }
30
- - "find library sasuser in sas" { name: "sasuser", server: "sas" }
31
- - "does library Formats exist" → { name: "Formats", server: "cas" }
32
-
33
- NEGATIVE EXAMPLES (do not route here)
34
- - "list libs" (use list-libraries)
35
- - "show tables in Public" (use list-tables)
36
- - "find table cars in sashelp" (use find-table)
37
- - "find job cars_job" (use find-job)
38
-
39
- ERRORS
40
- Returns { libraries: [] } if not found; { libraries: [name, ...] } if found. Never hallucinate library names.
41
- `;
42
-
43
- let spec = {
44
- name: 'find-library',
45
- description: description,
46
- inputSchema: z.object({
47
- name: z.string(),
48
- server: z.string().optional()
49
- }),
50
-
51
- handler: async (params) => {
52
- // normalize server to lowercase & default
53
- if (!params.server) params.server = 'cas';
54
- params.server = params.server.toLowerCase();
55
-
56
- // If multiple names passed (comma or space separated), take the first token (defensive)
57
- if (params.name && /[,\s]+/.test(params.name.trim())) {
58
- params.name = params.name.split(/[,\s]+/).filter(Boolean)[0];
59
- }
60
-
61
- let r = await _listLibrary(params);
62
- return r;
63
- }
64
- }
65
- return spec;
66
- }
67
- export default findLibrary;
68
-
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 _listLibrary from '../toolHelpers/_listLibrary.js';
7
+ function findLibrary(_appContext) {
8
+ const isAgent = _appContext && _appContext.agent;
9
+ let description = isAgent ? `
10
+ find-library — verify a library exists.
11
+ PARAMS: name (string, required), server ('cas'|'sas', required)
12
+ RETURNS: library metadata if found, error if not found
13
+ ` : `
14
+ find-library — locate a specific CAS or SAS library.
15
+
16
+ USE when: find library, find lib, does library exist, is library available, lookup library
17
+ DO NOT USE for: list libraries (use ${_appContext.brand}-list-libraries), find table/job/jobdef/model (use respective tools), table structure (use ${_appContext.brand}-table-describe), create library (use ${_appContext.brand}-program-score)
18
+
19
+ PARAMETERS
20
+ - name: string (required) — library/caslib name; if multiple supplied, use first
21
+ - server: 'cas' | 'sas' (required) — target environment
22
+
23
+ ROUTING RULES
24
+ - "find lib <name>" → { name: "<name>", server: "cas" }
25
+ - "find lib <name> in cas" → { name: "<name>", server: "cas" }
26
+ - "find library <name> in sas" → { name: "<name>", server: "sas" }
27
+ - "does library <name> exist" → { name: "<name>", server: "cas" }
28
+ - "find lib" with no name → ask "Which library name would you like to find?"
29
+ - "list libraries / list libs" → use ${_appContext.brand}-list-libraries instead
30
+ - "tables in <lib>" → use ${_appContext.brand}-list-tables instead
31
+
32
+ EXAMPLES
33
+ - "find lib Public" → { name: "Public", server: "cas" }
34
+ - "find library sasuser in sas" → { name: "sasuser", server: "sas" }
35
+ - "does library Formats exist" → { name: "Formats", server: "cas" }
36
+
37
+ NEGATIVE EXAMPLES (do not route here)
38
+ - "list libs" (use ${_appContext.brand}-list-libraries)
39
+ - "show tables in Public" (use ${_appContext.brand}-list-tables)
40
+ - "find table cars in sashelp" (use ${_appContext.brand}-find-table)
41
+ - "find job cars_job" (use ${_appContext.brand}-find-job)
42
+
43
+ ERRORS
44
+ Returns { libraries: [] } if not found; { libraries: [name, ...] } if found. Never hallucinate library names.
45
+ `;
46
+
47
+ let spec = {
48
+ name: 'find-library',
49
+ description: description,
50
+ inputSchema: z.object({
51
+ name: z.string(),
52
+ server: z.string().optional()
53
+ }),
54
+
55
+ handler: async (params) => {
56
+ // normalize server to lowercase & default
57
+ if (!params.server) params.server = 'cas';
58
+ params.server = params.server.toLowerCase();
59
+
60
+ // If multiple names passed (comma or space separated), take the first token (defensive)
61
+ if (params.name && /[,\s]+/.test(params.name.trim())) {
62
+ params.name = params.name.split(/[,\s]+/).filter(Boolean)[0];
63
+ }
64
+ params.tool = 'find';
65
+ let r = await _listLibrary(params);
66
+ return r;
67
+ }
68
+ }
69
+ return spec;
70
+ }
71
+ export default findLibrary;
72
+
73
+
@@ -0,0 +1,72 @@
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 _findMas from '../toolHelpers/_findMas.js';
8
+
9
+
10
+ function findMas(_appContext) {
11
+ const isAgent = _appContext && _appContext.agent;
12
+ let description = isAgent ? `
13
+ find-mas — verify a MAS model exists.
14
+ PARAMS: name (string, required)
15
+ RETURNS: model metadata if found, error if not found
16
+ ` : `
17
+ find-mas — locate a specific MAS mas deployed to MAS server
18
+
19
+ USE when: find mas, does mas exist, is mas deployed, lookup mas, verify mas exists
20
+ DO NOT USE for: list mass (use ${_appContext.brand}-list-mass), mas info/variables (use ${_appContext.brand}-mas-describe), score mas (use ${_appContext.brand}-mas-score), find table/job/lib (use respective tools), scr mass (use ${_appContext.brand}-scr-describe/${_appContext.brand}-scr-score)
21
+
22
+ PARAMETERS
23
+ - name: string (required) — mas name to locate; if multiple supplied, use first
24
+
25
+ ROUTING RULES
26
+ - "find mas <name>" → { name: "<name>" }
27
+ - "find name.mas" → { name: "<name>" }
28
+ - "does mas <name> exist" → { name: "<name>" }
29
+ - "is mas <name> deployed" → { name: "<name>" }
30
+ - "lookup/verify mas <name>" → { name: "<name>" }
31
+ - "find mas" with no name → ask "Which mas name would you like to find?"
32
+ - "find all mass / list mass" → use ${_appContext.brand}-list-mas instead
33
+ - "describe mas / mas info" → use ${_appContext.brand}-mas-describe instead
34
+
35
+ EXAMPLES
36
+ - "find mas mymas" → { name: "mymas" }
37
+ - "does mas churn_score exist" → { name: "churn_score" }
38
+ - "is mas riskmas deployed" → { name: "riskmas" }
39
+ - "lookup mas claims_fraud_v1" → { name: "claims_fraud_v1" }
40
+
41
+ NEGATIVE EXAMPLES (do not route here)
42
+ - "list mass" (use ${_appContext.brand}-list-mas)
43
+ - "score mas mymas" (use ${_appContext.brand}-mas-score)
44
+ - "mas info for churnRisk" (use ${_appContext.brand}-mas-describe)
45
+
46
+ ERRORS
47
+ Returns { mass: [] } if not found; { mass: [name, ...] } if found. Never hallucinate mas names.
48
+ `;
49
+
50
+ let spec = {
51
+ name: 'find-mas',
52
+ description: description,
53
+ inputSchema: z.object({
54
+ name: z.string()
55
+ }),
56
+ handler: async (params) => {
57
+ if (params.name != null) {
58
+ if (params.name.endsWith('.mas')) {
59
+ params.name = params.name.slice(0, -4);
60
+ }
61
+ }
62
+ params.tool = 'find';
63
+ let r = await _findMas(params);
64
+ return r;
65
+ }
66
+ }
67
+ return spec;
68
+ }
69
+
70
+ export default findMas;
71
+
72
+
@@ -0,0 +1,69 @@
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 _findScr from '../toolHelpers/_findScr.js';
8
+
9
+
10
+ function findScr(_appContext) {
11
+ const isAgent = _appContext && _appContext.agent;
12
+ let description = isAgent ? `
13
+ find-scr — verify an SCR model exists.
14
+ PARAMS: name (string, required)
15
+ RETURNS: SCR model metadata if found, error if not found
16
+ ` : `
17
+ find-scr — locate a specific SCR scr deployed to SCR server
18
+
19
+ USE when: find scr, does scr exist, is scr deployed, lookup scr, verify scr exists
20
+ DO NOT USE for: list scrs (use list-scr), scr info/variables (use scr-describe), score scr (use scr-score), find table/job/lib (use respective tools), mas scr (use mas-describe/mas-score)
21
+
22
+
23
+ PARAMETERS
24
+ - name: string (required) — scr name to locate; if multiple supplied, use first
25
+
26
+ ROUTING RULES
27
+ - "find scr <name>" → { name: "<name>" }
28
+ - "does scr <name> exist" → { name: "<name>" }
29
+ - "is scr <name> deployed" → { name: "<name>" }
30
+ - "lookup/verify scr <name>" → { name: "<name>" }
31
+ - "find scr" with no name → ask "Which scr name would you like to find?"
32
+ - "describe scr / scr info" → use scr-describe instead
33
+
34
+ EXAMPLES
35
+ - "find scr myscr" → { name: "myscr" }
36
+ - "does scr churn_score exist" → { name: "churn_score" }
37
+ - "is scr riskscr deployed" → { name: "riskscr" }
38
+ - "lookup scr claims_fraud_v1" → { name: "claims_fraud_v1" }
39
+
40
+ NEGATIVE EXAMPLES (do not route here)
41
+ - "list scr" (use ${_appContext.brand}-list-scr)
42
+ - "score scr myscr" (use ${_appContext.brand}-scr-score)
43
+ - "scr info for churnRisk" (use ${_appContext.brand}-scr-describe)
44
+
45
+ ERRORS
46
+ Returns { scr: [] } if not found; { scr: [name, ...] } if found. Never hallucinate scr urls.
47
+ `;
48
+
49
+ let spec = {
50
+ name: 'find-scr',
51
+ description: description,
52
+ inputSchema: z.object({
53
+ name: z.string()
54
+ }),
55
+ handler: async (params) => {
56
+ if (params.name.endsWith('.scr')) {
57
+ params.name = params.name.slice(0, -4);
58
+ }
59
+ params.tool = 'find';
60
+ let r = await _findScr(params);
61
+ return r;
62
+ }
63
+ }
64
+ return spec;
65
+ }
66
+
67
+ export default findScr;
68
+
69
+