@sassoftware/sas-score-mcp-serverjs 0.0.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 (96) hide show
  1. package/.babelrc +6 -0
  2. package/.env +13 -0
  3. package/.env.http +29 -0
  4. package/CHANGES.md +2 -0
  5. package/CONTRIBUTING.md +14 -0
  6. package/ContributorAgreement.txt +56 -0
  7. package/LICENSE +205 -0
  8. package/LICENSES.json +105 -0
  9. package/QUICK_REFERENCE.md +378 -0
  10. package/README.md +267 -0
  11. package/SECURITY.md +31 -0
  12. package/SUPPORT.md +3 -0
  13. package/TOOL_DESCRIPTION_TEMPLATE.md +157 -0
  14. package/TOOL_UPDATES_SUMMARY.md +208 -0
  15. package/cli.js +214 -0
  16. package/labs/.subclass.json +13 -0
  17. package/labs/README.md +4 -0
  18. package/mcpConfigurations/README.md +3 -0
  19. package/mcpConfigurations/http.json +8 -0
  20. package/mcpConfigurations/stdio.json +20 -0
  21. package/mcpConfigurations/stdiodev.json +20 -0
  22. package/mcpserver.png +0 -0
  23. package/openApi.json +106 -0
  24. package/openApi.yaml +84 -0
  25. package/package.json +72 -0
  26. package/sas-mcp-tools-reference.md +600 -0
  27. package/sasCode/sas-sql-query.sas +33 -0
  28. package/sasCode/sas_sql_tool.json +237 -0
  29. package/scripts/getViyaca.sh +8 -0
  30. package/src/core.js +19 -0
  31. package/src/coreSSE.js +14 -0
  32. package/src/corehttp.js +335 -0
  33. package/src/createHttpTransport.js +26 -0
  34. package/src/createMcpServer.js +76 -0
  35. package/src/db/scrModels.js +23 -0
  36. package/src/toolSet/devaScore.js +69 -0
  37. package/src/toolSet/findJob.js +90 -0
  38. package/src/toolSet/findJobdef.js +95 -0
  39. package/src/toolSet/findLibrary.js +100 -0
  40. package/src/toolSet/findModel.js +83 -0
  41. package/src/toolSet/findTable.js +94 -0
  42. package/src/toolSet/getEnv.js +72 -0
  43. package/src/toolSet/listJobdefs.js +96 -0
  44. package/src/toolSet/listJobs.js +110 -0
  45. package/src/toolSet/listLibraries.js +90 -0
  46. package/src/toolSet/listModels.js +83 -0
  47. package/src/toolSet/listTables.js +95 -0
  48. package/src/toolSet/makeTools.js +75 -0
  49. package/src/toolSet/mcp server .png +0 -0
  50. package/src/toolSet/modelInfo.js +87 -0
  51. package/src/toolSet/modelScore.js +131 -0
  52. package/src/toolSet/readTable.js +104 -0
  53. package/src/toolSet/runCasProgram.js +118 -0
  54. package/src/toolSet/runJob.js +81 -0
  55. package/src/toolSet/runJobdef.js +85 -0
  56. package/src/toolSet/runMacro.js +82 -0
  57. package/src/toolSet/runProgram.js +145 -0
  58. package/src/toolSet/sasQuery.js +126 -0
  59. package/src/toolSet/sasQueryTemplate.js +148 -0
  60. package/src/toolSet/sasQueryTemplate2.js +140 -0
  61. package/src/toolSet/scrInfo.js +55 -0
  62. package/src/toolSet/scrScore.js +71 -0
  63. package/src/toolSet/searchAssets.js +52 -0
  64. package/src/toolSet/setContext.js +98 -0
  65. package/src/toolSet/superstat.js +60 -0
  66. package/src/toolSet/tableInfo.js +102 -0
  67. package/src/toolhelpers/_catalogSearch.js +87 -0
  68. package/src/toolhelpers/_getEnv.js +10 -0
  69. package/src/toolhelpers/_itemsData.js +28 -0
  70. package/src/toolhelpers/_jobSubmit.js +78 -0
  71. package/src/toolhelpers/_listJobdefs.js +59 -0
  72. package/src/toolhelpers/_listJobs.js +63 -0
  73. package/src/toolhelpers/_listLibrary.js +56 -0
  74. package/src/toolhelpers/_listModels.js +41 -0
  75. package/src/toolhelpers/_listTables.js +52 -0
  76. package/src/toolhelpers/_masDescribe.js +27 -0
  77. package/src/toolhelpers/_masScoring.js +64 -0
  78. package/src/toolhelpers/_readTable.js +69 -0
  79. package/src/toolhelpers/_scrInfo.js +32 -0
  80. package/src/toolhelpers/_scrScore.js +49 -0
  81. package/src/toolhelpers/_submitCasl.js +34 -0
  82. package/src/toolhelpers/_submitCode.js +96 -0
  83. package/src/toolhelpers/_submitMacro.js +24 -0
  84. package/src/toolhelpers/_tableColumns.js +61 -0
  85. package/src/toolhelpers/_tableInfo.js +72 -0
  86. package/src/toolhelpers/deleteSession.js +13 -0
  87. package/src/toolhelpers/getLogonPayload.js +100 -0
  88. package/src/toolhelpers/getOpts.js +43 -0
  89. package/src/toolhelpers/getOptsViya.js +38 -0
  90. package/src/toolhelpers/getStoreOpts.js +18 -0
  91. package/src/toolhelpers/getToken.js +40 -0
  92. package/src/toolhelpers/refreshToken.js +48 -0
  93. package/test/README.md +63 -0
  94. package/test/listLibraries.test.js +245 -0
  95. package/tool-developer-guide.md +80 -0
  96. package/types.js +25 -0
@@ -0,0 +1,157 @@
1
+ # Tool Description Template
2
+
3
+ This template standardizes how all tool descriptions should be written in the MCP Server project. Every tool should follow this structure.
4
+
5
+ ## Template Format
6
+
7
+ ```javascript
8
+ function toolName(_appContext) {
9
+ let description = `
10
+ ## toolName — brief one-line description
11
+
12
+ LLM Invocation Guidance (When to use)
13
+ Use THIS tool when:
14
+ - User request example 1
15
+ - User request example 2
16
+ - User request example 3
17
+
18
+ Do NOT use this tool for:
19
+ - When to use tool X instead
20
+ - When to use tool Y instead
21
+ - Common misconceptions
22
+
23
+ Purpose
24
+ Clear explanation of what this tool does and why someone would use it. Can be 1-3 sentences.
25
+
26
+ Parameters
27
+ [If tool has no required parameters, state "This tool requires no parameters."]
28
+ - paramName (type, default value): Description of what this parameter does and any constraints.
29
+ - anotherParam (type): Required parameter. Description of what it does.
30
+
31
+ Response Contract
32
+ Describe the format and structure of the response. Include:
33
+ - The top-level structure (object, array, etc.)
34
+ - Key fields in the response
35
+ - Possible error conditions
36
+ - Example response structure
37
+
38
+ Disambiguation & Clarification
39
+ - If user says "X" but might mean "Y" → clarify with: "Did you mean...?"
40
+ - If parameter is ambiguous → explain how to handle missing/unclear values
41
+ - List common confusion points with other similar tools
42
+
43
+ Examples (→ mapped params)
44
+ Real-world examples showing user input and how parameters map:
45
+ - "user request example 1" → { param1: "value", param2: 10 }
46
+ - "user request example 2" → { param1: "value" }
47
+
48
+ Negative Examples (should NOT call toolName)
49
+ - "user request that should use tool X" (use toolX instead)
50
+ - "another incorrect usage" (use toolY instead)
51
+
52
+ Related Tools
53
+ Link to other tools in the workflow:
54
+ - First step: listSomething or findSomething
55
+ - Get details: infoTool or detailTool
56
+ - Take action: actionTool or executeTool
57
+ `;
58
+
59
+ let spec = {
60
+ name: 'toolName',
61
+ description: description,
62
+ schema: {
63
+ 'paramName': z.string(),
64
+ 'anotherParam': z.number().default(10)
65
+ },
66
+ required: ['paramName'],
67
+ handler: async (params) => {
68
+ let r = await _helperFunction(params);
69
+ return r;
70
+ }
71
+ }
72
+
73
+ return spec;
74
+ }
75
+
76
+ export default toolName;
77
+ ```
78
+
79
+ ## Section Guidelines
80
+
81
+ ### LLM Invocation Guidance
82
+ - List 3-5 specific user request patterns that would trigger this tool
83
+ - Use quotes for actual user phrases: `"find model X"`, `"list models"`
84
+ - List 2-4 common misconceptions or tools to use instead
85
+ - Be explicit: "Use THIS tool when..." and "Do NOT use this tool for..."
86
+
87
+ ### Purpose
88
+ - 1-3 sentences maximum
89
+ - Explain the business value, not just the mechanics
90
+ - Can reference other tools if relevant
91
+
92
+ ### Parameters
93
+ - **Format**: `paramName (type, default): description`
94
+ - Include all parameters (required and optional)
95
+ - Specify defaults clearly
96
+ - Add constraints if applicable: `(1-100)`, `(required)`, `(optional)`, `(read-only)`
97
+ - Be specific about what values are valid
98
+
99
+ ### Response Contract
100
+ - Describe JSON structure the LLM will receive
101
+ - Include key field names and their types
102
+ - Mention empty/null cases
103
+ - If applicable, show example response
104
+
105
+ ### Disambiguation & Clarification
106
+ - Format as bullet points with possible user input and clarification
107
+ - Include exact clarification question to ask (in quotes)
108
+ - Mention edge cases
109
+
110
+ ### Examples
111
+ - Format as: `"user phrase" → { param: "value" }`
112
+ - Show 3-5 real-world examples
113
+ - Include examples with different parameter combinations
114
+ - Must demonstrate parameter mapping clearly
115
+
116
+ ### Negative Examples
117
+ - Format as: `"incorrect user request" (use toolX instead)`
118
+ - Show 2-3 common mistakes
119
+ - Always specify which tool to use instead
120
+
121
+ ### Related Tools
122
+ - Show workflow chains: listThing → findThing → infoThing → actionThing
123
+ - Mention which tools come before/after in typical usage
124
+
125
+ ## Tone & Style Guidelines
126
+
127
+ 1. **Be specific**: Use actual examples and parameter values, not abstractions
128
+ 2. **Be explicit**: Say "Use THIS tool when" not "Can be used when"
129
+ 3. **Be practical**: Focus on when/how LLMs should invoke the tool
130
+ 4. **Be complete**: Include all parameters and all guidance sections
131
+ 5. **Be concise**: Keep descriptions focused and avoid redundancy
132
+
133
+ ## Validation Checklist
134
+
135
+ Before marking a tool as conforming to the template:
136
+
137
+ - [ ] Has "LLM Invocation Guidance" section with "Use THIS" and "Do NOT"
138
+ - [ ] Has "Purpose" section explaining what the tool does
139
+ - [ ] Has "Parameters" section documenting all params with types and defaults
140
+ - [ ] Has "Response Contract" describing the response format
141
+ - [ ] Has "Disambiguation & Clarification" section
142
+ - [ ] Has "Examples" section with 3+ real-world examples showing param mapping
143
+ - [ ] Has "Negative Examples" section with 2+ examples of what NOT to do
144
+ - [ ] Has "Related Tools" section showing workflow context (if applicable)
145
+ - [ ] Uses markdown formatting properly (## headers, - bullets, `code`)
146
+ - [ ] Consistent formatting across all sections
147
+
148
+ ## Tools Updated to Template
149
+
150
+ - [x] listModels.js - ✅ Already conforms
151
+ - [x] findModel.js - 🔧 Needs cleanup (remove redundancy)
152
+ - [ ] deval.js - 🔧 Needs major expansion
153
+ - [ ] devaScore.js - 🔧 Needs expansion
154
+ - [ ] setContext.js - 🔧 Needs expansion
155
+ - [ ] modelInfo.js - 🔧 Needs expansion
156
+ - [ ] readTable.js - ✅ Mostly conforms (minor tweaks)
157
+ - [ ] ... (other tools)
@@ -0,0 +1,208 @@
1
+ # Tool Description Standardization - Update Summary
2
+
3
+ ## Overview
4
+ All tool descriptions have been standardized to follow a consistent template format. This ensures:
5
+ - Clear, explicit "when to use" guidance for LLMs
6
+ - Consistent structure across all tools
7
+ - Comprehensive parameter and response documentation
8
+ - Real-world examples with parameter mappings
9
+ - Negative examples showing what NOT to do
10
+ - Related tools showing workflow context
11
+
12
+ ## Template Reference
13
+ See `TOOL_DESCRIPTION_TEMPLATE.md` for the complete template specification and validation checklist.
14
+
15
+ ## Tools Updated
16
+
17
+ ### ✅ Tools Fully Conforming to Template
18
+
19
+ #### Major Updates (5 tools)
20
+
21
+ 1. **findModel.js** - Cleaned up and standardized
22
+ - ✂️ Removed redundant JSON metadata object
23
+ - ✂️ Removed confusing/error lines (41-47) that listed find lib/table/job incorrectly
24
+ - ✅ Now has all required template sections
25
+ - ✅ Clear LLM invocation guidance
26
+
27
+ 2. **deval.js** - Expanded from 2 lines to comprehensive format
28
+ - ➕ Added "LLM Invocation Guidance" section with 4 use cases
29
+ - ➕ Added "Do NOT use this tool for" section (4 items)
30
+ - ➕ Added clear "Purpose" statement
31
+ - ➕ Added "Parameters" documentation
32
+ - ➕ Added "Response Contract" describing return format
33
+ - ➕ Added "Disambiguation & Clarification" section
34
+ - ➕ Added 3 real-world "Examples" with parameter mappings
35
+ - ➕ Added "Negative Examples" section
36
+ - ➕ Added "Related Tools" section
37
+
38
+ 3. **setContext.js** - Expanded with comprehensive guidance
39
+ - ➕ Added "LLM Invocation Guidance" section with 4 use cases
40
+ - ➕ Added "Do NOT use" section
41
+ - ➕ Added detailed "Purpose" explaining session context switching
42
+ - ➕ Enhanced "Parameters" with real server examples
43
+ - ➕ Added "Response Contract" with detailed structure
44
+ - ➕ Added "Disambiguation & Clarification" for edge cases
45
+ - ➕ Added 4 real-world "Examples" with parameter mappings
46
+ - ➕ Added "Negative Examples" section
47
+ - ➕ Added "Related Tools" section
48
+
49
+ 4. **devaScore.js** - Reformatted with template structure
50
+ - 🔄 Restructured from instruction-heavy to template format
51
+ - ➕ Added "LLM Invocation Guidance" section
52
+ - ➕ Added "Do NOT use" section
53
+ - ➕ Added clear parameter documentation
54
+ - ➕ Added "Response Contract" section
55
+ - ➕ Added "Examples" and "Negative Examples" sections
56
+ - ➕ Added "Notes" section explaining left-to-right fold
57
+
58
+ 5. **modelInfo.js** - Expanded with comprehensive structure
59
+ - ➕ Added "LLM Invocation Guidance" with 4 use cases
60
+ - ➕ Added "Do NOT use" section
61
+ - ➕ Enhanced "Purpose" statement
62
+ - ➕ Added detailed "Response Contract" describing metadata fields
63
+ - ➕ Added "Disambiguation & Clarification" section
64
+ - ➕ Added 4 real-world "Examples" with parameter mappings
65
+ - ➕ Added "Negative Examples" section
66
+ - ➕ Added "Related Tools" showing workflow chain
67
+
68
+ #### Moderate Updates (1 tool)
69
+
70
+ 6. **readTable.js** - Enhanced to fully conform to template
71
+ - 🔄 Restructured sections for template consistency
72
+ - ➕ Enhanced "LLM Invocation Guidance" with 5 specific use cases
73
+ - ➕ Improved "Do NOT use" section with explanation
74
+ - ➕ Clarified "Parameters" format and added constraints
75
+ - 🔄 Renamed "Output" to "Response Contract" per template
76
+ - ➕ Added "Pagination & Filtering" section with examples
77
+ - ➕ Enhanced "Examples" with 5 detailed parameter mappings
78
+ - ➕ Added comprehensive "Related Tools" section
79
+
80
+ #### Already Conforming (1 tool)
81
+
82
+ 7. **listModels.js** - ✅ Already fully compliant
83
+ - Already had comprehensive template format
84
+ - No changes needed
85
+
86
+ ## Template Sections Included in All Updated Tools
87
+
88
+ ### 1. LLM Invocation Guidance (When to use)
89
+ Explicit "Use THIS tool when" bullet points with real user phrases. Typically 3-5 examples.
90
+
91
+ ### 2. Do NOT use this tool for
92
+ Clear list of what NOT to do and which tools to use instead. Prevents misuse.
93
+
94
+ ### 3. Purpose
95
+ 1-3 sentence explanation of what the tool does and why.
96
+
97
+ ### 4. Parameters
98
+ - Name, type, default value, and description for each parameter
99
+ - Constraints and valid value ranges where applicable
100
+ - Required vs optional clearly indicated
101
+
102
+ ### 5. Response Contract
103
+ - JSON structure of the response
104
+ - Key fields and their types
105
+ - Edge cases (empty, null, errors)
106
+ - Example response format
107
+
108
+ ### 6. Disambiguation & Clarification
109
+ - How to handle missing parameters
110
+ - How to clarify ambiguous requests
111
+ - Exact clarification questions to ask
112
+
113
+ ### 7. Examples (→ mapped params)
114
+ - Real-world user phrases
115
+ - Parameter mappings shown
116
+ - Includes various parameter combinations
117
+ - Format: `"user input" → { param: value }`
118
+
119
+ ### 8. Negative Examples (should NOT call toolName)
120
+ - Common mistakes showing what NOT to do
121
+ - Specifies which tool to use instead
122
+ - Format: `"bad request" (use toolX instead)`
123
+
124
+ ### 9. Related Tools
125
+ - Workflow chains showing which tools work together
126
+ - Dependencies and typical call sequences
127
+ - Links to prerequisite/follow-up tools
128
+
129
+ ## Statistics
130
+
131
+ | Metric | Count |
132
+ |--------|-------|
133
+ | Tools with major updates | 5 |
134
+ | Tools with moderate updates | 1 |
135
+ | Tools already conforming | 1 |
136
+ | Total tools standardized | 7 |
137
+ | Template file created | 1 |
138
+
139
+ ## Key Improvements
140
+
141
+ ### Consistency
142
+ - All tools now follow the same structure
143
+ - Uniform formatting and section ordering
144
+ - Consistent tone and style
145
+
146
+ ### Clarity
147
+ - Explicit "when to use" guidance for LLMs
148
+ - Clear parameter documentation with types and defaults
149
+ - Real-world examples instead of abstractions
150
+
151
+ ### Completeness
152
+ - All tools include negative examples
153
+ - All tools explain related tools/workflows
154
+ - All tools have response contracts
155
+
156
+ ### Usability
157
+ - LLMs can understand tool purpose immediately
158
+ - Clear disambiguation guidance for edge cases
159
+ - Parameter mappings prevent incorrect invocations
160
+
161
+ ## Files Modified
162
+
163
+ 1. `src/toolSet/findModel.js` - Cleaned up redundancy
164
+ 2. `src/toolSet/deval.js` - Expanded description (2 → 47 lines)
165
+ 3. `src/toolSet/setContext.js` - Expanded description (9 → 60 lines)
166
+ 4. `src/toolSet/devaScore.js` - Reformatted (12 → 54 lines)
167
+ 5. `src/toolSet/modelInfo.js` - Expanded description (12 → 69 lines)
168
+ 6. `src/toolSet/readTable.js` - Enhanced description (56 → 80 lines)
169
+
170
+ ## Files Created
171
+
172
+ 1. `TOOL_DESCRIPTION_TEMPLATE.md` - Master template specification
173
+ 2. `TOOL_UPDATES_SUMMARY.md` - This file
174
+
175
+ ## Next Steps (Optional)
176
+
177
+ Consider updating remaining tools in the toolSet directory to match this template:
178
+ - `listTables.js` - Already fairly complete, minor tweaks possible
179
+ - `listLibraries.js`
180
+ - `listJobs.js`
181
+ - `findJob.js`
182
+ - `findLibrary.js`
183
+ - `findTable.js`
184
+ - `job.js`
185
+ - `jobdef.js`
186
+ - `tableInfo.js`
187
+ - `program.js`
188
+ - `sasQuery.js`
189
+ - `modelScore.js`
190
+ - `scrInfo.js`
191
+ - `scrScore.js`
192
+ - And any others...
193
+
194
+ ## Validation Checklist
195
+
196
+ To verify a tool conforms to the template, check:
197
+
198
+ - [ ] Has "LLM Invocation Guidance" section with "Use THIS tool when" list
199
+ - [ ] Has "Do NOT use this tool for" section with specific alternatives
200
+ - [ ] Has "Purpose" section explaining what the tool does
201
+ - [ ] Has "Parameters" section with type, default, and description for each param
202
+ - [ ] Has "Response Contract" describing the return format
203
+ - [ ] Has "Disambiguation & Clarification" section for edge cases
204
+ - [ ] Has "Examples (→ mapped params)" section with 3+ real-world examples
205
+ - [ ] Has "Negative Examples (should NOT call...)" section with what NOT to do
206
+ - [ ] Has "Related Tools" section showing workflow context
207
+ - [ ] Uses proper markdown formatting (## headers, - bullets, `code`)
208
+ - [ ] Consistent formatting and tone throughout
package/cli.js ADDED
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ // Main entry point for MCP server
8
+
9
+
10
+ import coreSSE from './src/coreSSE.js';
11
+ import corehttp from './src/corehttp.js';
12
+ import createMcpServer from './src/createMcpServer.js';
13
+ import { config } from 'dotenv';
14
+ // import dotenvExpand from 'dotenv-expand';
15
+ import fs from 'fs';
16
+ import { randomUUID } from 'node:crypto';
17
+
18
+ import refreshToken from './src/toolHelpers/refreshToken.js';
19
+ import getOptsViya from './src/toolHelpers/getOptsViya.js';
20
+
21
+ import { fileURLToPath } from 'url';
22
+ import { dirname } from 'path';
23
+
24
+ import NodeCache from 'node-cache';
25
+
26
+ const __dirname = dirname(fileURLToPath(import.meta.url));
27
+
28
+ let pkg = fs.readFileSync(__dirname + '/package.json', 'utf8');
29
+
30
+ /********************************* */
31
+ const BRAND = 'sas-score'
32
+ /********************************* */
33
+ let pkgJson = JSON.parse(pkg);
34
+ let version = pkgJson.version;
35
+ let mcpType = process.env.MCPTYPE || 'http';
36
+ console.error(
37
+ `\nStarting MCP ServerJS - Version: ${pkgJson.version} - ${new Date().toISOString()}\n
38
+ brand: ${process.env.BRAND || BRAND}\n
39
+ mcpType: ${mcpType}\n
40
+ viyaServer: ${process.env.VIYA_SERVER}\n`
41
+ );
42
+ // session sessionCache
43
+ // For more robust caching consider products like Redis
44
+ // and storage provided by cloud providers
45
+
46
+ debugger;
47
+ let sessionCache = new NodeCache({ stdTTL: 0, checkperiod: 2 * 60, useClones: false });
48
+
49
+ //
50
+ // Load environment variables from .env file if present
51
+ // swithching to:
52
+ // stdio: set the env in the mcp config
53
+ // http: use dotenv-cli to load env before starting the mcp server
54
+
55
+
56
+ // need to tell core what transport to use(http or stdio)
57
+
58
+ // subclasses for sasQuery tool (special use case)
59
+ // to be replaced by the planned adding external tool definition capability
60
+
61
+ let subclassJson = [];
62
+ if (process.env.SUBCLASS != null) {
63
+ console.error(`Using subclass: ${process.env.SUBCLASS}`);
64
+ let subclass = process.env.SUBCLASS;
65
+ if (fs.existsSync(subclass)) {
66
+ console.error(`Loading subclass information from ${subclass}...`);
67
+ let s = fs.readFileSync(subclass, 'utf8');
68
+ subclassJson = JSON.parse(s);
69
+ console.error(`Loaded subclass: ${JSON.stringify(subclassJson, null, 2)}`);
70
+ }
71
+ }
72
+ // setup base appEnv
73
+ // for stdio this is the _appContext
74
+ // for http each session a copy of this as appEnvTemplate is created in corehttp
75
+ const appEnvBase = {
76
+ version: version,
77
+ mcpType: mcpType,
78
+ brand: (process.env.BRAND == null) ? BRAND : process.env.BRAND,
79
+ HTTPS:
80
+ process.env.HTTPS != null && process.env.HTTPS.toUpperCase() === 'TRUE'
81
+ ? true
82
+ : false,
83
+ SAS_CLI_PROFILE: process.env.SAS_CLI_PROFILE || 'Default',
84
+ SAS_CLI_CONFIG: process.env.SAS_CLI_CONFIG || process.env.HOME, // default to user home directory
85
+ SSLCERT: process.env.SSLCERT || null,
86
+ VIYACERT: process.env.VIYACERT || null,
87
+
88
+ AUTHFLOW: process.env.AUTHFLOW || 'sascli',
89
+ VIYA_SERVER: process.env.VIYA_SERVER,
90
+ PORT: process.env.PORT || 8080,
91
+ USERNAME: process.env.USERNAME || null,
92
+ PASSWORD: process.env.PASSWORD || null,
93
+ CLIENTIDPW: process.env.CLIENTIDPW || null,
94
+ CLIENTSECRET: process.env.CLIENTSECRETPW || null,
95
+ TOKEN: process.env.TOKEN || null,
96
+ REFRESH_TOKEN: process.env.REFRESH_TOKEN || null,
97
+ TOKENFILE: process.env.TOKENFILE || null,
98
+ TLS_CREATE: process.env.TLS_CREATE || null,
99
+ SUBCLASS: process.env.SUBCLASS || null,
100
+ subclassJson: subclassJson,
101
+ // future use for controlling tool list using env variable
102
+ toolsets:
103
+ process.env.TOOLSETS != null
104
+ ? process.env.TOOLSETS.split(',')
105
+ : ['default'],
106
+ // user defined tools
107
+ //runtime variables
108
+ tokenRefresh: process.env.TOKENREFRESH === 'FALSE' ? false : true,
109
+ tls: null,
110
+ refreshToken: null,
111
+ transports: {},
112
+ mcpServer: null,
113
+ viyaSessions: {},
114
+ store: null,
115
+ casServer: null,
116
+ casSessionId: null,
117
+ computeSessionId: null,
118
+ logonPayload: null,
119
+ bearerToken: null,
120
+ tlsOpts: null,
121
+ contexts: {
122
+ store: null, /* for restaf users */
123
+ storeConfig: {},
124
+ casSession: null, /* restaf cas session object */
125
+ computeSession: null, /* restaf compute session object */
126
+ viyaCert: null, /* ssl/tsl certificates to connect to viya */
127
+ logonPayload: null, /* viya logon payload to connect to viya */
128
+ casServerId: null,
129
+ computeSessonId: null,
130
+ sas: (process.env.COMPUTECONTEXT == null) ? 'SAS Job Execution compute context' : process.env.COMPUTECONTEXT,
131
+ cas: (process.env.CASSERVER == null) ? 'cas-shared-default' : process.env.CASSERVER,
132
+ ext: {} /* for additional extensions that a developer may want to add */
133
+ }
134
+ };
135
+
136
+ // setup TLS options for viya calls
137
+
138
+ console.error('[Note]Viya SSL dir set to: ' + appEnvBase.VIYACERT);
139
+ await getOptsViya(appEnvBase); /* appEnvBase.contexts.viyaCert is set here */
140
+ appEnvBase.contexts.storeConfig = {
141
+ casProxy: true,
142
+ options: { ns: null, proxyServer: null, httpOptions: appEnvBase.contexts.viyaCert }
143
+ };
144
+
145
+ if (appEnvBase.TOKENFILE != null) {
146
+ try {
147
+ console.error(`[Note]Loading token from file: ${appEnvBase.TOKENFILE}...`);
148
+ appEnvBase.TOKEN = fs.readFileSync(appEnvBase.TOKENFILE, { encoding: 'utf8' });
149
+ appEnvBase.AUTHFLOW = 'token';
150
+ appEnvBase.appContexts.logonPayload = {
151
+ host: appEnvBase.VIYA_SERVER,
152
+ authType: 'server',
153
+ token: appEnvBase.TOKEN,
154
+ tokenType: 'Bearer'
155
+
156
+ }
157
+ } catch (err) {
158
+ console.error(`[Error] Failed to read token file: ${err}`);
159
+ }
160
+ }
161
+
162
+ // handle refresh token flow
163
+ // use this for testing only.
164
+ if (appEnvBase.REFRESH_TOKEN != null) {
165
+ appEnvBase.refreshToken = appEnvBase.REFRESH_TOKEN;
166
+ appEnvBase.AUTHFLOW = 'refresh';
167
+ let t = await refreshToken(appEnvBase, { token: appEnvBase.REFRESH_TOKEN, host: appEnvBase.VIYA_SERVER });
168
+ appEnvBase.contexts.logonPayload = {
169
+ host: appEnvBase.VIYA_SERVER,
170
+ authType: 'server',
171
+ token: t,
172
+ tokenType: 'Bearer'
173
+ }
174
+ }
175
+
176
+ // if authflow is cli, postpone getting logonPayload until needed
177
+
178
+ /*
179
+ if(appEnvBase.AUTHFLOW ==='sascli') {
180
+ let logonPayload = await getLogonPayload(appEnvBase);
181
+ appEnvBase.logonPayload = logonPayload;
182
+ }
183
+ */
184
+
185
+ // setup mcpServer (both http and stdio use this)
186
+ // this is singleton - best practices recommend this
187
+
188
+ let mcpServer = await createMcpServer(sessionCache, appEnvBase);
189
+
190
+ sessionCache.set('appEnvBase', appEnvBase);
191
+ let appEnvTemplate = Object.assign({}, appEnvBase);
192
+
193
+ sessionCache.set('appEnvTemplate', appEnvTemplate);
194
+
195
+ let transports = {};
196
+ sessionCache.set('transports', transports);
197
+
198
+ // set this for stdio transport use
199
+ // dummy sessionId for use in the tools
200
+ if (mcpType === 'stdio') {
201
+ let sessionId = randomUUID();
202
+ sessionCache.set('currentId', sessionId);
203
+ sessionCache.set(sessionId, appEnvBase);
204
+ console.error('[Note] Setting up stdio transport with sessionId:', sessionId);
205
+ console.error('[Note] Used in setting up tools and some persistence(not all).');
206
+ await coreSSE(mcpServer);
207
+
208
+ } else {
209
+ console.error('[Note] Starting HTTP MCP server...');
210
+ await corehttp(mcpServer, sessionCache, appEnvBase);
211
+ console.error('[Note] MCP HTTP server started on port ' + appEnvBase.PORT);
212
+ }
213
+
214
+
@@ -0,0 +1,13 @@
1
+ [
2
+
3
+ {
4
+ "name": "query-customer-usage",
5
+ "template": "sasQueryTemplate",
6
+ "table": "Public.gidb_current",
7
+ "selectColumns": "opsys, offering, product, rate, quantity, quantype, currency",
8
+ "columns": null,
9
+ "job": "run_sql_query",
10
+ "server": "cas"
11
+ }
12
+
13
+ ]
package/labs/README.md ADDED
@@ -0,0 +1,4 @@
1
+ # Lab
2
+
3
+ This folder has files that are for some future work.
4
+ Not used by the current mcp server
@@ -0,0 +1,3 @@
1
+ # Configurations
2
+
3
+ Typical mvp configuration files
@@ -0,0 +1,8 @@
1
+ {
2
+ "servers": {
3
+ "sasmcp": {
4
+ "type": "http",
5
+ "url": "http://localhost:8080/mcp"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "servers": {
3
+ "sasmcp": {
4
+ "type": "stdio",
5
+ "command": "npx",
6
+ "args": [
7
+ "@sassoftware/sas-score-mcp-serverjs"
8
+ ],
9
+ "env": {
10
+ "MCPTYPE": "stdio",
11
+ "AUTHFLOW": "sascli",
12
+ "SAS_CLI_PROFILE": "cis",
13
+ "SAS_CLI_CONFIG": "c:\\Users\\kumar",
14
+ "SSLCERT": "c:\\Users\\kumar\\.tls",
15
+ "COMPUTECONTEXT": "SAS Job Execution compute context",
16
+ "CAS_SERVER": "cas-shared-default"
17
+ }
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "servers": {
3
+ "sasmcp": {
4
+ "type": "stdio",
5
+ "command": "node",
6
+ "args": [
7
+ "c:\\dev\\gitlab\\mcp-serverjs\\cli.js"
8
+ ],
9
+ "env": {
10
+ "MCPTYPE": "stdio",
11
+ "AUTHFLOW": "sascli",
12
+ "SAS_CLI_PROFILE": "cis",
13
+ "SAS_CLI_CONFIG": "c:\\Users\\kumar",
14
+ "SSLCERT": "c:\\Users\\kumar\\.tls",
15
+ "COMPUTECONTEXT": "SAS Job Execution compute context",
16
+ "CAS_SERVER": "cas-shared-default"
17
+ }
18
+ }
19
+ }
20
+ }
package/mcpserver.png ADDED
Binary file