@sassoftware/sas-score-mcp-serverjs 0.4.1-21 → 0.4.1-24

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.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: SAS Viya Scoring Expert
3
+ description: Specialized SAS and Viya agent that classifies requests, selects the right SAS skill, and uses MCP tools safely for jobs, CAS data, libraries, models, scoring, and content workflows.
4
+ ---
5
+
6
+ # SAS Viya Scoring Expert
7
+
8
+ You are a SAS Viya expert agent.
9
+
10
+ Your job is to help users work with SAS and Viya resources through the SAS MCP server.
11
+ Treat requests as domain-specific SAS tasks, not generic coding tasks.
12
+
13
+ ## Default behavior
14
+ Before using MCP tools:
15
+ - Determine whether the request is about jobs, code, CAS data, libraries, models, scoring, content, or environment issues.
16
+ - If the request includes ambiguous terms such as model, score, scoring, read, query, job, code, table, content, asset, or resource, classify the request before acting.
17
+ - Prefer loading the most relevant SAS skill before using low-level tools.
18
+ - If confidence is low, ask one focused clarifying question.
19
+ - Prefer discovery and inspection before execution, publish, scoring, deploy, write, or destructive actions.
20
+
21
+ ## Skill-first policy
22
+ Use skills as the primary source of SAS workflow guidance.
23
+ Load one or more relevant SAS skills before using tools when the request is ambiguous, cross-domain, or execution-oriented.
24
+ Do not load unrelated skills.
25
+
26
+ ## Routing policy
27
+ When a request is ambiguous or could map to more than one SAS domain:
28
+ - Start with classification.
29
+ - Identify the most likely SAS asset or workflow type.
30
+ - Choose the best matching SAS skill.
31
+ - Only then select MCP tools.
32
+
33
+ ## Ambiguity policy
34
+ These terms are overloaded in SAS and Viya workflows and should not be interpreted casually:
35
+ - model
36
+ - score
37
+ - scoring
38
+ - read
39
+ - query
40
+ - job
41
+ - code
42
+ - table
43
+ - content
44
+ - asset
45
+ - resource
46
+
47
+ If the meaning is unclear, ask one targeted clarifying question or use discovery-oriented skills before any execution step.
48
+
49
+ ## Tool usage policy
50
+ - Prefer read-only discovery before execution.
51
+ - Confirm the target asset type before running jobs, scoring data, publishing models, or modifying content.
52
+ - If tool results contradict the initial interpretation, correct course explicitly and continue.
53
+ - Never invent asset names, identifiers, libraries, or model types.
54
+
55
+ ## Response style
56
+ Be concise, explicit, and domain-aware.
57
+ State which SAS concept or asset type you are acting on when ambiguity is possible.
58
+ Prefer short structured answers when guiding the user.
@@ -0,0 +1,146 @@
1
+ # SAS Agent instructions for this repository
2
+
3
+ ## Project overview
4
+ This repository builds and maintains a SAS-focused agent experience on top of an MCP server.
5
+ The MCP server exposes SAS and Viya capabilities such as jobs, code artifacts, CAS server resources, SAS server resources, MAS models, score/scoring assets, and related metadata.
6
+ Your job is to help users complete SAS-related tasks safely and accurately by selecting the right skill first, then using the right MCP tools.
7
+
8
+ ## Operating model
9
+ Treat this repository as a domain-specialized SAS agent, not as a generic coding project.
10
+ Prefer domain interpretation and skill-based guidance before directly invoking low-level tools.
11
+ When a request is ambiguous, resolve the ambiguity before taking action.
12
+
13
+ ## Request classification
14
+ Before using SAS MCP tools, classify the request into one of these categories:
15
+
16
+ - SAS job or flow execution
17
+ - SAS code or program analysis
18
+ - CAS data, caslibs, tables, or resources
19
+ - SAS data, librefs, tables, or resources
20
+ - MAS model, SAS job model, SAS jobdef model
21
+ - Score model / scoring artifact / scoring execution
22
+ - General SAS content or metadata discovery
23
+ - Authentication, connection, or environment issue
24
+
25
+ If the request could belong to multiple categories, ask one clarifying question unless lightweight discovery can resolve it safely.
26
+
27
+ ## Skill-first behavior
28
+ Before invoking MCP tools, decide whether one or more SAS skills should be used.
29
+ Prefer loading the most relevant SAS skill for the request category.
30
+ Use more than one skill only when the task clearly spans multiple domains, for example:
31
+ - CAS discovery + scoring
32
+ - model lookup + job execution
33
+ - content discovery + code analysis
34
+
35
+ Do not load unrelated skills.
36
+ Do not treat "model", "score", "job", "code", or "table" as interchangeable terms.
37
+
38
+ ## Tool usage policy
39
+ Use MCP tools only after you have identified the most likely domain.
40
+ Prefer read or discovery operations before write, execute, deploy, or destructive operations.
41
+ When a user asks to run, publish, deploy, or score something, confirm that you have identified the correct SAS asset type first.
42
+ If a tool response reveals that the original interpretation was wrong, correct course explicitly and continue.
43
+
44
+ ## Ambiguity handling
45
+ In this repository:
46
+
47
+ - "model" usually refers to MAS models, SAS job models, or SAS jobdef models, SCR models
48
+ - "score" or "scoring" usually refers to running a model on data, not measuring test coverage.
49
+ - "job" usually refers to a SAS job or flow, not a CI job.
50
+
51
+ When these terms appear without clear SAS context, ask a clarifying question or use the SAS request classifier skill before invoking tools.
52
+ The following terms are ambiguous and must be disambiguated from context or by asking a question:
53
+ - model
54
+ - score
55
+ - scoring
56
+ - job
57
+ - code
58
+ - table
59
+ - content
60
+ - resource
61
+
62
+ Examples:
63
+ - "find my model" may refer to a MAS model, model repository entry, or scoring asset
64
+ - "run scoring" may refer to a job, MAS, jobdef, SCR model
65
+ - "open the table" may refer to a CAS table or SAS dataset
66
+
67
+ ## Response style
68
+ Be concise, precise, and domain-aware.
69
+ Explain which SAS concept you are acting on when ambiguity is possible.
70
+ Do not pretend certainty when the asset type or environment is unclear.
71
+ Prefer structured answers with short steps when guiding the user.
72
+
73
+ ## Coding and implementation guidance
74
+ When editing code in this repository:
75
+ - Preserve existing MCP server patterns and naming conventions.
76
+ - Prefer small, composable modules over large prompt files.
77
+ - Keep tool descriptions short, specific, and distinct.
78
+ - Put durable domain workflows in skills, not in tool descriptions.
79
+ - Keep always-on instructions short; detailed procedures belong in skills.
80
+ - Prefer configuration and prompt assets that can be reused across Claude and Copilot.
81
+
82
+ ## Repository structure expectations
83
+ Expect to find:
84
+ - MCP server implementation code
85
+ - prompt or skill assets
86
+ - configuration for client integrations
87
+ - SAS/Viya-specific adapters or resource logic
88
+ - tests or examples for skill and tool behavior
89
+
90
+ When adding new artifacts:
91
+ - Put repo-wide guidance in `.github/copilot-instructions.md`
92
+ - Put targeted reusable workflows in `.github/skills/<skill-name>/SKILL.md`
93
+ - Keep supporting references, examples, and templates next to the skill that uses them
94
+
95
+ ## Safety and correctness
96
+ Never make up SAS assets, job names, model identifiers, or CAS resources.
97
+ If a requested action depends on environment-specific details, verify those details first.
98
+ Prefer inspection and discovery over assumption.
99
+
100
+ ---
101
+
102
+ # Available Skills
103
+
104
+ This repository provides specialized skills for SAS-focused workflows. Load the relevant skill for the user's request before using MCP tools.
105
+
106
+ ## sas-request-classifier
107
+ **Purpose:** Classify ambiguous SAS or Viya requests before using MCP tools.
108
+
109
+ **Use when:** Request mentions jobs, code, models, scoring, CAS tables, content, or resources and the correct SAS domain is not yet clear.
110
+
111
+ **Trigger phrases:** "find my model", "run scoring", "open the table", or any ambiguous request using domain terms.
112
+
113
+ ## sas-find-library-smart
114
+ **Purpose:** Find a SAS Viya library (libref or caslib) with intelligent server detection. Automatically checks CAS first, then SAS if not found.
115
+
116
+ **Use when:** User needs to verify a library exists, before accessing tables within it.
117
+
118
+ **Trigger phrases:** "find library", "does library exist", "check if library", "locate library", "is there a library named", "verify library".
119
+
120
+ ## sas-list-tables-smart
121
+ **Purpose:** List all tables in a SAS Viya library with intelligent server detection. When the server is not specified, automatically checks CAS first, then SAS if not found.
122
+
123
+ **Use when:** User wants to browse or explore available tables.
124
+
125
+ **Trigger phrases:** "list tables in", "show tables in", "what tables are in", "browse tables in", "tables in library", "enumerate tables".
126
+
127
+ ## sas-read-strategy
128
+ **Purpose:** Guide the user in choosing the right data retrieval tool: `sas-score-read-table` (for raw row access with filters) or `sas-score-sas-query` (for analytical queries, aggregations, joins).
129
+
130
+ **Use when:** User wants to fetch records from a SAS/CAS table.
131
+
132
+ **Trigger phrases:** "read records from", "get data where", "fetch rows from", "query the table", "give me the first N records", "aggregate by", "join tables".
133
+
134
+ ## sas-read-and-score
135
+ **Purpose:** Guide the full read → score workflow in SAS Viya: reading records from a table and then scoring them with a MAS model.
136
+
137
+ **Use when:** User wants to score records from a table, run a model against query results, predict outcomes for a set of rows, or any combination of fetching data and scoring it.
138
+
139
+ **Trigger phrases:** "score these records", "score results of my query", "run the model on this table", "predict for these customers", "fetch and score", "read and score", "score rows from", "run model on table data".
140
+
141
+ ## sas-score-workflow
142
+ **Purpose:** Mandatory routing logic for all scoring requests. Extracts model.type suffix and routes to the correct tool (run-job|run-jobdef|model-score|scr-score|run-program). Handles both MAS models and alternative scoring engines.
143
+
144
+ **Use when:** User requests scoring with a model name that may require routing to different execution engines.
145
+
146
+ **Trigger phrases:** "score with model X.job", "score X.jobdef scenario", "score with model X.mas", "score with model X.scr", any request with "score" + model name containing a dot (.) + type suffix.
@@ -78,23 +78,6 @@ ELSE
78
78
 
79
79
  ---
80
80
 
81
- ## Table Reference Format
82
-
83
- When users follow up to find or work with tables, they may provide a reference in dot notation (e.g., "find table cars in Public" or "maps.india").
84
-
85
- **Always parse table references as: `lib.table`**
86
- - First part (before dot) = **library name** → `lib` parameter
87
- - Second part (after dot) = **table name** → `name` or `table` parameter
88
-
89
- **Examples:**
90
- - "maps.india" → `lib: "maps"`, `name: "india"`
91
- - "Public.customers" → `lib: "Public"`, `name: "customers"`
92
- - "sashelp.cars" → `lib: "sashelp"`, `name: "cars"`
93
-
94
- This rule ensures consistent parsing when users reference tables in subsequent operations after finding a library.
95
-
96
- ---
97
-
98
81
  ## Common patterns
99
82
 
100
83
  **Pattern 1 — Find library, server unspecified**
@@ -15,39 +15,20 @@ of the data operation. Determines which server contains the data and which retri
15
15
 
16
16
  ## Determine the server location
17
17
 
18
- Before retrieving data, locate the table and determine which server contains it:
18
+ Before retrieving data, verify the library and determine which server(s) contain the table:
19
19
 
20
- **Smart table lookup with server detection**
20
+ **Step 1: Verify library existence**
21
+ - Use `sas-find-library-smart` skill to check the library in CAS first, then SAS if needed
22
+ - This establishes the correct server and uppercase convention for SAS libraries
23
+ - Informs the user which server contains the library
21
24
 
22
- Use `sas-score-find-table` with intelligent server detection:
23
-
24
- 1. **First attempt**: Check CAS server (`server: "cas"`)
25
- - If table exists return table and server to caller
26
- - If table not foundproceed to step 2
27
-
28
- 2. **Second attempt**: Check SAS server (`server: "sas"`)
29
- - If table exists → return table and server to caller
30
- - If table not found in either server → inform user and suggest verifying the library and table names
31
-
32
- **Possible outcomes:**
33
- - Table found in CAS → use `server: "cas"` for subsequent read operations
34
- - Table found in SAS → use `server: "sas"` for subsequent read operations
35
- - Table not found in either server → inform user: *"The table 'lib.table' was not found in CAS or SAS. Please verify the library and table names."*
36
-
37
- ---
38
-
39
- ## Table Reference Format
40
-
41
- When a user provides a table reference in dot notation (e.g., "read maps.india" or "find table cars.Public"):
42
-
43
- **Always parse as: `lib.table`**
44
- - First part (before dot) = **library name** → `lib` parameter
45
- - Second part (after dot) = **table name** → `name` or `table` parameter
46
-
47
- **Examples:**
48
- - "maps.india" → `lib: "maps"`, `name: "india"`
49
- - "Public.customers" → `lib: "Public"`, `name: "customers"`
50
- - "sashelp.cars" → `lib: "sashelp"`, `name: "cars"`
25
+ **Step 2: Locate the specific table**
26
+ - Use `sas-score-find-table` to check if the table exists in the library
27
+ - Possible outcomes:
28
+ - If table exists **only in CAS** set `server: "cas"`
29
+ - If table exists **only in SAS** set `server: "sas"`
30
+ - If table exists **in both** → ask the user: *"The table exists in both CAS and SAS. Which server would you prefer to query from?"*
31
+ - If table exists **in neither** inform user and suggest verifying the table name
51
32
 
52
33
  ---
53
34
 
@@ -74,31 +55,21 @@ Ask yourself: does the user already have the data in hand?
74
55
 
75
56
  **How:**
76
57
  ```
77
- sas-score-find-table({
78
- lib: "libraryname",
79
- table: "tablename",
80
- server: "cas" // start with CAS
81
- })
82
- // if not found, repeat with server: "sas"
83
-
84
58
  sas-score-read-table({
85
59
  table: "tablename",
86
60
  lib: "libraryname",
87
- server: "cas" or "sas", // REQUIRED: determined from sas-score-find-table check
88
- start: 1, // REQUIRED: 1-based row offset (default: 1)
89
- limit: N, // REQUIRED: max rows to retrieve (default: 10, max: 1000)
61
+ server: "cas" or "sas", // determined from sas-score-find-table check
62
+ limit: N, // default 10, adjust based on user request
90
63
  where: "..." // optional SQL WHERE clause
91
64
  })
92
65
  ```
93
66
 
94
67
  **Rules:**
95
- - Always determine the server first using `sas-score-find-table` with smart detection (CAS → SAS)
96
- - **ALWAYS set `server` parameter** never omit it; use the result from `sas-score-find-table` to determine "cas" or "sas"
97
- - **ALWAYS set `start` parameter** — use 1 for the first call, or the offset for pagination
98
- - **ALWAYS set `limit` parameter** — keep batch size ≤ 50 rows unless the user explicitly requests more; cap at 1000
68
+ - Always determine the server first using `sas-score-find-table`
69
+ - Keep batch size 50 rows unless the user explicitly requests more
99
70
  - If table name is missing, ask: *"Which table should I read from? (format: lib.tablename)"*
100
71
  - If library is missing, ask: *"Which library contains the table?"*
101
- - If table exists in both servers, prefer CAS (already determined by smart detection)
72
+ - If table exists in both servers, ask user which to use
102
73
  - Return raw column values; do not transform or aggregate
103
74
 
104
75
  ---
@@ -112,13 +83,6 @@ sas-score-read-table({
112
83
 
113
84
  **How:**
114
85
  ```
115
- sas-score-find-table({
116
- lib: "libraryname",
117
- table: "tablename",
118
- server: "cas" // start with CAS
119
- })
120
- // if not found, repeat with server: "sas"
121
-
122
86
  sas-query({
123
87
  table: "lib.tablename",
124
88
  query: "user's natural language question",
@@ -127,8 +91,8 @@ sas-query({
127
91
  ```
128
92
 
129
93
  **Rules:**
130
- - Check which server contains the table using `sas-score-find-table` with smart detection (CAS → SAS) first
131
- - If table exists in CAS, query from CAS; if only in SAS, query from SAS
94
+ - Check which server(s) contain the table using `sas-score-find-table` first
95
+ - If table exists in both CAS and SAS, ask user which to query from
132
96
  - Parse the user's natural language question into a PROC SQL SELECT statement
133
97
  - Ensure SELECT statement is valid SQL syntax
134
98
  - Do not add trailing semicolons to the SQL string
@@ -142,12 +106,12 @@ sas-query({
142
106
  **Pattern A — Raw row retrieval**
143
107
  > "Show me the first 5 rows from Public.customers"
144
108
 
145
- → `sas-score-read-table({ table: "customers", lib: "Public", server: "cas", start: 1, limit: 5 })`
109
+ → `sas-score-read-table({ table: "customers", lib: "Public", limit: 5 })`
146
110
 
147
111
  **Pattern B — Filtered retrieval**
148
112
  > "Get all high-value orders (amount > 5000) from mylib.orders"
149
113
 
150
- → `sas-score-read-table({ table: "orders", lib: "mylib", server: "sas", start: 1, limit: 50, where: "amount > 5000" })`
114
+ → `sas-score-read-table({ table: "orders", lib: "mylib", where: "amount > 5000" })`
151
115
 
152
116
  **Pattern C — Aggregation**
153
117
  > "What is the average price by make in Public.cars?"
@@ -165,12 +129,11 @@ sas-query({
165
129
 
166
130
  | Problem | Action |
167
131
  |---|---|
168
- | Table not found in CAS | Try SAS server using `sas-score-find-table` with `server: "sas"` |
169
- | Table not found in either server | Inform user: *"The table 'lib.table' was not found in CAS or SAS. Please verify the library and table names."* |
170
- | Table exists only in CAS | Use `server: "cas"` automatically for read operations |
171
- | Table exists only in SAS | Use `server: "sas"` automatically for read operations |
172
- | Table name missing entirely | Ask: *"Which table should I read from? (format: lib.tablename)"* |
173
- | Library name missing | Ask: *"Which library contains the table?"* |
132
+ | Library not found | Use `sas-find-library-smart` skill to verify the library exists |
133
+ | Table not found in either server | Inform user and suggest checking the table name |
134
+ | Table exists in both CAS and SAS | Ask: *"The table exists in both servers. Which would you prefer: CAS or SAS?"* |
135
+ | Table exists only in one server | Use that server automatically in your request |
136
+ | Table name missing entirely | Ask: *"Which table should I read from?"* |
174
137
  | Ambiguous intent (raw vs aggregate) | Ask: *"Do you want individual rows or a summary by some field?"* |
175
138
  | Empty result | Inform user, ask to adjust filter or query |
176
139
 
@@ -178,7 +141,7 @@ sas-query({
178
141
 
179
142
  ## Integration with other skills
180
143
 
181
- - **Before this skill**: Use `sas-score-find-table` to verify the table exists and determine the server location
144
+ - **Before this skill**: Use `sas-find-library-smart` to verify and locate the library
182
145
  - **After this skill**: Use `sas-read-and-score` to score the retrieved data
183
146
 
184
147
  ---
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: sas-request-classifier
3
+ description: Classify ambiguous SAS or Viya requests before using MCP tools. Use when prompts mention jobs, code, models, scoring, CAS tables, content, or resources and the correct SAS domain is not yet clear.
4
+ ---
5
+
6
+ # SAS Request Classifier
7
+
8
+ Use this skill to determine what kind of SAS object, workflow, or environment the user is referring to before selecting tools.
9
+
10
+ ## When to use
11
+ Use this skill when the request contains ambiguous domain terms such as:
12
+ - model
13
+ - score
14
+ - scoring
15
+ - read
16
+ - query
17
+ - job
18
+ - jobdef
19
+ - code
20
+ - table
21
+ - content
22
+ - asset
23
+ - resource
24
+
25
+ Use this skill before any execution-oriented tool call if there is a chance the request is referring to the wrong SAS domain.
26
+
27
+ ## Goal
28
+ Map the user request to the most likely SAS domain and hand off to the correct downstream skill or tool path.
29
+
30
+ ## Classification targets
31
+ Classify the request into one or more of these categories:
32
+ - Reading or querying tables → Route to **sas-read-strategy**
33
+ - CAS resource, caslib, or table discovery → Route to **sas-find-library-smart** or **sas-list-tables-smart**
34
+ - SAS data, libref, or table discovery → Route to **sas-find-library-smart** or **sas-list-tables-smart**
35
+ - Score model or scoring artifact → Route to **sas-score-workflow**
36
+ - Read data and score together → Route to **sas-read-and-score**
37
+ - SAS job or flow execution
38
+ - SAS code or program analysis
39
+ - General content or metadata lookup
40
+ - Environment, auth, or connectivity issue
41
+
42
+ ## Procedure
43
+ 1. Read the request and identify ambiguous nouns and verbs.
44
+ 2. Infer whether the request is asking to discover, inspect, execute, deploy, score, compare, or troubleshoot.
45
+ 3. Decide the most likely SAS domain and matching skill.
46
+ 4. If confidence is low, ask one focused clarifying question.
47
+ 5. If confidence is high, load and use the relevant skill:
48
+ - **sas-find-library-smart** — Find CAS or SAS libraries
49
+ - **sas-list-tables-smart** — Browse tables in a library
50
+ - **sas-read-strategy** — Choose read-table vs. sas-query for data retrieval
51
+ - **sas-read-and-score** — Combine data reading with model scoring
52
+ - **sas-score-workflow** — Route scoring requests to correct execution engine
53
+ 6. Only after classification and skill guidance, use MCP tools.
54
+
55
+ ## Disambiguation hints
56
+ - "Run" often implies job execution, but may also mean scoring or model invocation. Check for "score" or "model" context.
57
+ - "Model" may refer to MAS models, SAS jobs, jobdefs, or SCR models. Look for context or type suffix (e.g., `.job`, `.mas`, `.scr`).
58
+ - "Score" may refer to model scoring or job execution. Look for model name or context.
59
+ - "Table" usually suggests CAS, but confirm library name and server context.
60
+ - "Find", "list", "browse" — starts as discovery. Route to sas-find-library-smart or sas-list-tables-smart.
61
+ - "Read", "query", "fetch" — data retrieval. Route to sas-read-strategy.
62
+ - "Predict", "score records", "run model on data" — combined workflow. Route to sas-read-and-score or sas-score-workflow.
63
+
64
+ ## Output
65
+ When you finish classification, state:
66
+ - the inferred SAS domain
67
+ - the confidence level
68
+ - the relevant skill(s) to load
69
+ - any remaining ambiguity or clarifying questions needed
@@ -1,11 +1,11 @@
1
- ---
1
+ gi ---
2
2
  name: sas-score-workflow
3
3
  description: >
4
- MANDATORY routing logic for all scoring requests. Extract model.type suffix, route to correct tool
5
- (run-job|run-jobdef|model-score|scr-score|run-program). Complete routing decision BEFORE invoking
6
- any tool. Handles both MAS models and alternative scoring engines (jobs, jobdefs, SCR, SAS programs).
7
- Trigger phrases: "score with model X.job", "score X.jobdef scenario", "score with model X.mas",
8
- "score with model X.scr", any request with "score" + model name containing a dot (.) + type suffix.
4
+ Guide the full model scoring workflow: validate model familiarity, route to appropriate scoring tool
5
+ based on model type, invoke scoring with scenario data, and present merged results. Use this skill
6
+ when the user wants to run predictions on data (already fetched or user-supplied). Supports generic
7
+ syntax: "score with model <name>.<type> scenario =<params>" where type is job|jobdef|mas|scr|sas.
8
+ Trigger phrases: "score these records", "predict using model", "run model on", "score with model X.mas".
9
9
  ---
10
10
 
11
11
  # SAS Score Workflow
@@ -35,91 +35,6 @@ If no type is specified (bare model name), assume `.mas` (MAS model).
35
35
 
36
36
  ---
37
37
 
38
- ## ⚠️ MANDATORY: ROUTING DECISION (DO THIS FIRST)
39
-
40
- **CRITICAL: This decision must be completed BEFORE invoking ANY scoring tool.**
41
-
42
- When a user requests scoring with a model name (e.g., `score a=10,b=20 with model simplejob.job`):
43
-
44
- ### Step 1: Extract the Type Suffix
45
- Check if the model name contains a dot:
46
- - **YES** (e.g., `simplejob.job`) → Split on the last dot to extract type: `job`
47
- - **NO** (e.g., `churn`) → Assume type is `.mas` (default MAS model)
48
-
49
- ### Step 2: Validate the Type
50
- Confirm the extracted type is one of: `job`, `jobdef`, `mas`, `scr`, `sas`
51
- - **VALID** → Proceed to Step 3
52
- - **INVALID** (e.g., `.xyz`) → Assume `.mas` and treat entire input as model name
53
-
54
- ### Step 3: Strip the Type Suffix
55
- Remove the `.type` from the model name:
56
- - `simplejob.job` → base name: `simplejob`
57
- - `churn.mas` → base name: `churn`
58
- - `fraud_detector.jobdef` → base name: `fraud_detector`
59
-
60
- ### Step 4: Route to the Correct Tool
61
- Invoke the tool that matches the type:
62
- - **`.job`** → `sas-score-run-job`
63
- - **`.jobdef`** → `sas-score-run-jobdef`
64
- - **`.mas`** → `sas-score-model-score`
65
- - **`.scr`** → `sas-score-scr-score`
66
- - **`.sas`** → `sas-score-run-sas-program`
67
-
68
- ### Step 5: Invoke with Correct Parameters
69
- Pass the base name (without type) to the routed tool.
70
-
71
- ---
72
-
73
- ## Routing Decision Tree
74
-
75
- ```
76
- User request: "score a=10,b=20 with model simplejob.job"
77
-
78
- [Extract model reference] → "simplejob.job"
79
-
80
- [Split on last dot] → base="simplejob", type="job"
81
-
82
- [Validate type] → "job" ∈ [job, jobdef, mas, scr, sas]? YES
83
-
84
- [Route by type]
85
- └─ type="job" → call sas-score-run-job()
86
-
87
- [Invoke tool] → sas-score-run-job({ name: "simplejob", scenario: {a: "10", b: "20"} })
88
-
89
- [Return results]
90
- ```
91
-
92
- ---
93
-
94
- ## ❌ Anti-Patterns (DO NOT DO THIS)
95
-
96
- These mistakes cause incorrect routing:
97
-
98
- | Request | Wrong Tool Called | Why It's Wrong | Correct Tool |
99
- |---------|-------------------|----------------|---------------|
100
- | `score simplejob.job scenario =a=10,b=20` | `deva-score` | `.job` suffix ignored; generic scorer used | `sas-score-run-job` |
101
- | `score churn.mas where age=45` | `run-job` | Type mismatch; treated as job instead of MAS | `sas-score-model-score` |
102
- | `score fraud.jobdef using amount=500` | `model-score` | Wrong tool for jobdef type | `sas-score-run-jobdef` |
103
- | `score model.scr with scenario` | `run-jobdef` | SCR endpoint ignored | `sas-score-scr-score` |
104
- | `score code.sas using x=1` | `model-score` | SAS program treated as MAS model | `sas-score-run-sas-program` |
105
-
106
- ---
107
-
108
- ## ✅ Checkpoint Verification
109
-
110
- Before invoking ANY tool, verify all checkpoints:
111
-
112
- - [ ] **Did I extract the type correctly?** (Check: is it one of the 5 types: `job`, `jobdef`, `mas`, `scr`, `sas`?)
113
- - [ ] **Did I strip the type suffix from the model name?** (Pass base name only: `simplejob`, not `simplejob.job`)
114
- - [ ] **Does the routing match the type?** (e.g., `.job` → `run-job`, `.mas` → `model-score`)
115
- - [ ] **Am I using the correct parameter name?** (e.g., `name:` for jobs/jobdefs, `model:` for MAS, `url:` for SCR)
116
- - [ ] **Is the scenario parsed correctly?** (e.g., `{ a: "10", b: "20" }` from `a=10,b=20`)
117
- - [ ] **Have I considered if this is the default MAS case?** (If no type, assume `.mas` and use `model-score`)
118
-
119
- ⚠️ **All checkboxes must be ✓ before invoking the tool.**
120
-
121
- ---
122
-
123
38
  ## Type-Based Routing
124
39
 
125
40
  ### Parse and Strip Model Type
@@ -381,8 +296,6 @@ Merge the scoring output back with the input records and present as a table wher
381
296
  | Scoring error / invalid inputs | Return structured error, suggest `model-info` to check required inputs and data types |
382
297
  | Empty read result | Tell user, ask if they want to adjust the query/filter before scoring |
383
298
  | Missing input fields | Ask which table columns map to the required model inputs |
384
- | **Type routing error (wrong tool called)** | **Check: did I complete the MANDATORY routing decision? Did I extract the type correctly? Did I route to the right tool based on type?** |
385
- | **Type suffix not recognized** | **Assume `.mas` (default MAS model) and treat entire input as model name** |
386
299
 
387
300
  ---
388
301
 
package/cli.js CHANGED
@@ -23,6 +23,7 @@ import readCerts from './src/toolHelpers/readCerts.js';
23
23
  import { fileURLToPath } from 'url';
24
24
  import { dirname, join } from 'path';
25
25
  import os from 'os';
26
+ import setupSkills from './src/setupSkills.js';
26
27
  import { parseArgs } from "node:util";
27
28
 
28
29
  import NodeCache from 'node-cache';
@@ -213,11 +214,21 @@ if (args.values.version) {
213
214
  // the -client indicates the current mcp client
214
215
  console.error(`[Note] MCP client set to: ${process.env.CLIENT}`);
215
216
 
217
+
216
218
  let client = process.env.CLIENT;
219
+ if (client !== 'none') {
220
+ console.error(`[Note] Setting up skills for client: ${client}...`);
221
+ setupSkills(client);
222
+ } else {
223
+ console.error(`[Note] No client specified, skipping skill setup...`);
224
+ }
225
+
226
+
227
+ /*
217
228
  if (client !== 'none') {
218
229
  let destdir = '.' + client;
219
230
  let skillsDest = join(os.homedir(), destdir,'skills');
220
- const skillsSrc = join(__dirname, 'skills');
231
+ const skillsSrc = join(__dirname, '.github');
221
232
  if (!fs.existsSync(skillsSrc)) {
222
233
  console.error('No skills directory found in this package.');
223
234
  process.exit(1);
@@ -244,6 +255,7 @@ if (client !== 'none') {
244
255
 
245
256
  }
246
257
  }
258
+ */
247
259
 
248
260
 
249
261
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sassoftware/sas-score-mcp-serverjs",
3
- "version": "0.4.1-21",
3
+ "version": "0.4.1-24",
4
4
  "description": "A mcp server for SAS Viya",
5
5
  "author": "Deva Kumar <deva.kumar@sas.com>",
6
6
  "license": "Apache-2.0",
@@ -42,9 +42,8 @@
42
42
  "cli.js",
43
43
  "openApi.json",
44
44
  "openApi.yaml",
45
- "skills",
46
45
  "scripts",
47
- ".claude"
46
+ ".skills"
48
47
  ],
49
48
  "dependencies": {
50
49
  "@modelcontextprotocol/sdk": "^1.29.0",