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

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.
@@ -1,283 +0,0 @@
1
- ---
2
- name: sas-score-workflow
3
- description: >
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
- ---
10
-
11
- # SAS Score Workflow
12
-
13
- Orchestrates model validation, type-based routing, scoring invocation, and result presentation.
14
- Handles both MAS models and alternative scoring engines (jobs, jobdefs, SCR, SAS programs).
15
-
16
- ---
17
-
18
- ## Generic Scoring Syntax
19
-
20
- Users can invoke scoring with a unified syntax that automatically routes to the correct tool:
21
-
22
- ```
23
- score with model <name>.<type> [scenario =<key=value pairs>]
24
- score <name>.<type> [scenario =<key=value pairs>]
25
- ```
26
-
27
- **Type determines the routing:**
28
- - `.job` → route to `run-job` with scoring parameters
29
- - `.jobdef` → route to `run-jobdef` with scoring parameters
30
- - `.mas` → route to `model-score` (Model Analytical Service — default)
31
- - `.scr` → route to `scr-score` (SAS Container Runtime)
32
- - `.sas` → route to `run-sas-program` to run sas program in folder
33
-
34
- If no type is specified (bare model name), assume `.mas` (MAS model).
35
-
36
-
37
- ---
38
-
39
- ## Type-Based Routing
40
-
41
- Parse the model name to extract the type suffix and route accordingly:
42
-
43
- ### Type: `.mas` (Model Aggregation Service)
44
- - **Tool**: `model-score`
45
- - **Use for**: Standard MAS-deployed predictive models
46
- - **Example**: `score with model churn.mas scenario =age=45,income=60000`
47
- - **Invocation**: `model-score({ model: "churn", scenario: {...} })`
48
-
49
- ### Type: `.job` (SAS Viya Job)
50
- - **Tool**: `run-job`
51
- - **Use for**: Pre-built scoring jobs with parameters
52
- - **Example**: `score with model monthly_scorer.job scenario =month=10,year=2025`
53
- - **Invocation**: `run-job({ name: "monthly_scorer", scenario: {...} })`
54
-
55
- ### Type: `.jobdef` (SAS Viya Job Definition)
56
- - **Tool**: `run-jobdef`
57
- - **Use for**: Job definitions that perform scoring logic
58
- - **Example**: `score with model fraud_detector.jobdef using amount=500,merchant=online`
59
- - **Invocation**: `run-jobdef({ name: "fraud_detector", scenario: {...} })`
60
-
61
- ### Type: `.scr` (Score Code Runtime)
62
- - **Tool**: `scr-score`
63
- - **Use for**: Models deployed in SCR containers (REST endpoints)
64
- - **Example**: `score https://scr-host/models/loan.scr using age=45,credit=700`
65
- - **Invocation**: `scr-score({ url: "https://scr-host/models/loan", scenario: {...} })`
66
-
67
- ### Type: `.sas` (SAS Program / SQL)
68
- - **Tool**: `run-sas-program`
69
- - **Use for**: Custom SAS or SQL scoring code
70
- - **Example**: `score my_scoring_code.sas using x=1,y=2`
71
- - **Invocation**: `run-sas-program({ folder: "my_scoring_code", scenario: {...} })`
72
-
73
- ---
74
-
75
- ## Scenario Parsing
76
-
77
- The scenario parameter (comma-separated key=value pairs) is parsed into an object:
78
-
79
- ```
80
- scenario =age=45,income=60000,region=South
81
- ↓ parsed as:
82
- { age: "45", income: "60000", region: "South" }
83
- ```
84
-
85
- Accepted formats:
86
- - **String**: `age=45,income=60000`
87
- - **Object**: `{ age: 45, income: 60000 }`
88
- - **Array** (batch): `[ {age:45, income:60000}, {age:50, income:75000} ]`
89
-
90
- ---
91
-
92
- ## Step 1 — Check model familiarity before scoring
93
-
94
- Score immediately if:
95
- - The user names a specific model they've used before in this session, OR
96
- - The model name matches a previously confirmed model in the conversation
97
-
98
- Pause and suggest investigation if:
99
- - The model name is new, vague, or misspelled-looking (e.g. "the churn one", "that cancer model")
100
- - The user seems unsure of the required input variable names
101
-
102
- **Suggested message:**
103
- > "I don't recognize that model — want me to run `find-model` to confirm it exists,
104
- > or `model-info` to check its required inputs first?"
105
-
106
- ---
107
-
108
- ## Step 2 — Prepare the scenario data
109
-
110
- **For a single record** (one object):
111
- ```javascript
112
- scenario = { field1: value1, field2: value2, ... }
113
- ```
114
-
115
- **For batch scoring** (multiple records — the typical case):
116
- ```javascript
117
- scenario = [
118
- { field1: val1, field2: val2, ... },
119
- { field1: val3, field2: val4, ... },
120
- ...
121
- ]
122
- ```
123
-
124
- **Critical rules:**
125
- - Loop or call model-score **once per row**.
126
- - Field names in the scenario must match the model's expected input variable names **exactly**.
127
- - If table column names differ from model input names, **flag this to the user** and ask for confirmation before scoring.
128
- - Example: Table has `age_years`, but model expects `age` → ask user which column maps to which input.
129
- - Do not add units, labels, or extra metadata — raw field values only.
130
-
131
- ---
132
-
133
- ## Step 3 — Invoke the appropriate scoring tool
134
-
135
- Based on the type extracted from the model name, invoke the corresponding tool:
136
-
137
- **For `.mas` (default):**
138
- ```javascript
139
- model-score({
140
- model: "<modelname>",
141
- scenario: scenario, // object or array
142
- uflag: false // set true if you need field names prefixed with _
143
- })
144
- ```
145
-
146
- **For `.job`:**
147
- ```javascript
148
- run-job({
149
- name: "<jobname>",
150
- scenario: scenario
151
- })
152
- ```
153
-
154
- **For `.jobdef`:**
155
- ```javascript
156
- run-jobdef({
157
- name: "<jobdefname>",
158
- scenario: scenario
159
- })
160
- ```
161
-
162
- **For `.scr`:**
163
- ```javascript
164
- scr-score({
165
- url: "<scr_endpoint_url>",
166
- scenario: scenario
167
- })
168
- ```
169
-
170
- **For `.sas`:**
171
- ```javascript
172
- run-sas-program({
173
- src: "<sas_or_sql_code>",
174
- scenario: scenario
175
- })
176
- ```
177
-
178
- **Rules:**
179
- - Pass the full batch in one call; do not loop over rows
180
- - If scoring fails, return the structured error and suggest troubleshooting
181
- - For MAS models, include uflag parameter if underscore-prefixed output is needed
182
- - For jobs/jobdefs, scenario becomes parameter arguments
183
- - For SCR, include full URL endpoint
184
-
185
- ---
186
-
187
- ## Step 4 — Present the results
188
-
189
- Merge the scoring output back with the input records and present as a table where possible.
190
-
191
- **Always surface:**
192
- - The key prediction/score field(s) (e.g. `P_churn`, `score`, `prediction`, `P_risk`)
193
- - Any probability/confidence fields for classification models (e.g. `P_class0`, `P_class1`)
194
- - Selected input fields that drove the prediction, so the user can see context
195
-
196
- **Formatting:**
197
- - Present results in a table for clarity
198
- - If results exceed 10 rows, show the first 10 and ask: *"Want to see more results or export the full set?"*
199
- - Round numeric predictions to 2–4 decimal places for readability
200
-
201
- ---
202
-
203
- ## Common flows
204
-
205
- **Flow A — Score rows with MAS model**
206
- > "Score the first 10 customers in Public.customers with the churn model"
207
-
208
- 1. `read-table` → { table: "Public.customers", limit: 10 }
209
- 2. `model-score` → { model: "churn", scenario: [ ...10 row objects ] }
210
- 3. Present merged results with prediction + key inputs
211
-
212
- **Flow B — Score with a scoring job**
213
- > "Score December sales with the monthly_scorer job using month=12,year=2025"
214
-
215
- 1. `run-job` → { name: "monthly_scorer", scenario: { month: "12", year: "2025" } }
216
- 2. Capture job output and tables
217
- 3. Present results
218
-
219
- **Flow C — Score with a job definition**
220
- > "Run fraud detection jobdef on transaction amount=500, merchant=online"
221
-
222
- 1. `run-jobdef` → { name: "fraud_detection", scenario: { amount: "500", merchant: "online" } }
223
- 2. Capture log, listings, and tables
224
- 3. Present results
225
-
226
- **Flow D — Score with SCR endpoint**
227
- > "Score with the loan model at https://scr-host/models/loan using age=45, credit_score=700"
228
-
229
- 1. `scr-score` → { url: "https://scr-host/models/loan", scenario: { age: "45", credit_score: "700" } }
230
- 2. Capture prediction response
231
- 3. Present result
232
-
233
- **Flow E — Score results of an analytical query with MAS**
234
- > "Score high-value customers (spend > 5000) in mylib.sales with the fraud model"
235
-
236
- 1. `sas-query` → { table: "mylib.sales", sql: "SELECT * FROM mylib.sales WHERE spend > 5000" }
237
- 2. `model-score` → { model: "fraud", scenario: [ ...result rows ] }
238
- 3. Present merged results
239
-
240
- **Flow F — User supplies scenario data directly**
241
- > "Score age=45, income=60000, region=South with the churn model"
242
-
243
- 1. Skip read step
244
- 2. `model-score` → { model: "churn", scenario: { age: "45", income: "60000", region: "South" } }
245
- 3. Present result
246
-
247
- **Flow G — Model unfamiliar, need to confirm**
248
- > "Score Public.applicants with the creditRisk2 model"
249
-
250
- 1. Pause — "creditRisk2" is new
251
- 2. Suggest: `find-model` to confirm it exists, `model-info` to get input variables
252
- 3. Once confirmed → `read-table` + `model-score`
253
-
254
- **Flow H — Generic score syntax with type routing**
255
- > "score with model churn.mas scenario =age=45,income=60000"
256
- > "score fraud_detector.jobdef where scenario =amount=500"
257
- > "score monthly_report.job using month=10,year=2025"
258
-
259
- 1. Parse model name to extract type (.mas, .job, .jobdef, .scr, .sas)
260
- 2. Route to appropriate tool based on type
261
- 3. Parse scenario and invoke tool with parameters
262
- 4. Present results from routed tool
263
-
264
- ---
265
-
266
- ## Error handling
267
-
268
- | Problem | Action |
269
- |---|---|
270
- | Model not found | Suggest `find-model` to verify the model is deployed |
271
- | Input field name mismatch | Show the mismatch (table has X, model expects Y), ask user to confirm mapping |
272
- | Scoring error / invalid inputs | Return structured error, suggest `model-info` to check required inputs and data types |
273
- | Empty read result | Tell user, ask if they want to adjust the query/filter before scoring |
274
- | Missing input fields | Ask which table columns map to the required model inputs |
275
-
276
- ---
277
-
278
- ## Tips
279
-
280
- - **Batch is better:** Always pass the full set of records in one `model-score` call. Do not loop.
281
- - **Confirm mappings:** If column names don't match model inputs, ask before scoring.
282
- - **Show context:** Include key input columns in the result output so predictions make sense.
283
- - **Limit output:** For large result sets (>10 rows), ask before showing all.