vme-mcp-server 0.1.4 → 0.1.6
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.
- package/README.md +1 -4
- package/dist/README.md +1 -1
- package/dist/lib/api-utils.js +251 -0
- package/dist/lib/intent-recognition.js +159 -0
- package/dist/lib/session.js +59 -0
- package/dist/lib/vm-parsing.js +82 -0
- package/dist/server.js +37 -918
- package/dist/server_old.js +933 -0
- package/dist/tools/create-vm.js +205 -0
- package/dist/tools/export-training-data.js +115 -0
- package/dist/tools/get-resources.js +40 -0
- package/dist/tools/index.js +41 -0
- package/dist/tools/parse-intent.js +52 -0
- package/dist/tools/provide-feedback.js +61 -0
- package/dist/types/interfaces.js +2 -0
- package/package.json +2 -2
@@ -0,0 +1,205 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.handleCreateVM = exports.createVMTool = void 0;
|
4
|
+
const vm_parsing_js_1 = require("../lib/vm-parsing.js");
|
5
|
+
const api_utils_js_1 = require("../lib/api-utils.js");
|
6
|
+
exports.createVMTool = {
|
7
|
+
name: "create_vm",
|
8
|
+
description: "Provision a new virtual machine",
|
9
|
+
inputSchema: {
|
10
|
+
type: "object",
|
11
|
+
properties: {
|
12
|
+
name: {
|
13
|
+
type: "string",
|
14
|
+
description: "Name for VM(s). Supports patterns like 'web01' or 'web01->web03' for multiple VMs"
|
15
|
+
},
|
16
|
+
group: {
|
17
|
+
type: "string",
|
18
|
+
description: "Group/site where VM will be created"
|
19
|
+
},
|
20
|
+
cloud: {
|
21
|
+
type: "string",
|
22
|
+
description: "Cloud/zone where VM will be provisioned (also accepts 'zone')"
|
23
|
+
},
|
24
|
+
zone: {
|
25
|
+
type: "string",
|
26
|
+
description: "Zone/cloud where VM will be provisioned (alias for 'cloud')"
|
27
|
+
},
|
28
|
+
template: {
|
29
|
+
type: "string",
|
30
|
+
description: "VM template or operating system"
|
31
|
+
},
|
32
|
+
size: {
|
33
|
+
type: "string",
|
34
|
+
description: "VM size (small, medium, 4GB, 8GB, etc.)"
|
35
|
+
},
|
36
|
+
distribution: {
|
37
|
+
type: "string",
|
38
|
+
description: "VM distribution strategy: 'auto' (default), 'spread' (across all nodes), or 'node1,node2,node3' (specific nodes)"
|
39
|
+
},
|
40
|
+
count: {
|
41
|
+
type: "number",
|
42
|
+
description: "Number of VMs to create (alternative to name patterns)"
|
43
|
+
}
|
44
|
+
},
|
45
|
+
required: ["name", "group", "template", "size"]
|
46
|
+
}
|
47
|
+
};
|
48
|
+
async function handleCreateVM(args) {
|
49
|
+
const { name, group, cloud, zone, template, size, distribution, count } = args;
|
50
|
+
// Allow both 'cloud' and 'zone' parameters interchangeably
|
51
|
+
const location = cloud || zone;
|
52
|
+
if (!location) {
|
53
|
+
return {
|
54
|
+
content: [
|
55
|
+
{
|
56
|
+
type: "text",
|
57
|
+
text: JSON.stringify({
|
58
|
+
error: {
|
59
|
+
code: "missing_location",
|
60
|
+
message: "Either 'cloud' or 'zone' parameter is required"
|
61
|
+
}
|
62
|
+
}, null, 2)
|
63
|
+
}
|
64
|
+
],
|
65
|
+
isError: true
|
66
|
+
};
|
67
|
+
}
|
68
|
+
// Parse VM names and determine distribution strategy
|
69
|
+
const vmNames = (0, vm_parsing_js_1.parseVMNames)(name, count);
|
70
|
+
const nodes = await (0, api_utils_js_1.getClusterNodes)();
|
71
|
+
// Calculate node assignments
|
72
|
+
const nodeAssignments = (0, vm_parsing_js_1.calculateNodeAssignments)(vmNames, nodes, distribution);
|
73
|
+
const resolved = await (0, api_utils_js_1.resolveInput)({ group, cloud: location, template, size });
|
74
|
+
const { groupId, cloudId, instanceTypeId, servicePlanId, imageId } = resolved;
|
75
|
+
if (!groupId || !cloudId || !instanceTypeId || !servicePlanId || !imageId) {
|
76
|
+
const errors = [];
|
77
|
+
if (!groupId)
|
78
|
+
errors.push(`Group '${group}' not found. Available: ${resolved.availableGroups.join(', ')}`);
|
79
|
+
if (!cloudId)
|
80
|
+
errors.push(`Zone/Cloud '${location}' not found. Available: ${resolved.availableZones.join(', ')}`);
|
81
|
+
if (!instanceTypeId)
|
82
|
+
errors.push(`Instance type could not be resolved`);
|
83
|
+
if (!servicePlanId)
|
84
|
+
errors.push(`Size '${size}' could not be resolved to service plan`);
|
85
|
+
if (!imageId)
|
86
|
+
errors.push(`Template '${template}' could not be resolved to OS image`);
|
87
|
+
return {
|
88
|
+
content: [
|
89
|
+
{
|
90
|
+
type: "text",
|
91
|
+
text: JSON.stringify({
|
92
|
+
error: {
|
93
|
+
code: "resolution_failed",
|
94
|
+
message: `Failed to resolve parameters:\n${errors.join('\n')}`
|
95
|
+
}
|
96
|
+
}, null, 2)
|
97
|
+
}
|
98
|
+
],
|
99
|
+
isError: true
|
100
|
+
};
|
101
|
+
}
|
102
|
+
// Create VMs sequentially
|
103
|
+
const results = [];
|
104
|
+
const errors = [];
|
105
|
+
for (const assignment of nodeAssignments) {
|
106
|
+
const vmConfig = {
|
107
|
+
resourcePoolId: 'pool-1',
|
108
|
+
poolProviderType: 'mvm',
|
109
|
+
imageId: imageId,
|
110
|
+
createUser: true
|
111
|
+
};
|
112
|
+
// Add kvmHostId only if explicitly specified
|
113
|
+
if (assignment.kvmHostId) {
|
114
|
+
vmConfig.kvmHostId = assignment.kvmHostId;
|
115
|
+
}
|
116
|
+
const payload = {
|
117
|
+
zoneId: cloudId,
|
118
|
+
instance: {
|
119
|
+
name: assignment.name,
|
120
|
+
cloud: 'tc-lab',
|
121
|
+
hostName: assignment.name,
|
122
|
+
type: 'mvm',
|
123
|
+
instanceType: {
|
124
|
+
code: 'mvm'
|
125
|
+
},
|
126
|
+
site: {
|
127
|
+
id: groupId
|
128
|
+
},
|
129
|
+
layout: {
|
130
|
+
id: 2, // Single HPE VM
|
131
|
+
code: 'mvm-1.0-single'
|
132
|
+
},
|
133
|
+
plan: {
|
134
|
+
id: servicePlanId
|
135
|
+
}
|
136
|
+
},
|
137
|
+
config: vmConfig,
|
138
|
+
volumes: [
|
139
|
+
{
|
140
|
+
id: -1,
|
141
|
+
rootVolume: true,
|
142
|
+
name: 'root',
|
143
|
+
size: 10,
|
144
|
+
storageType: 1,
|
145
|
+
datastoreId: 5
|
146
|
+
}
|
147
|
+
],
|
148
|
+
networkInterfaces: [
|
149
|
+
{
|
150
|
+
primaryInterface: true,
|
151
|
+
ipMode: 'dhcp',
|
152
|
+
network: {
|
153
|
+
id: 'network-2'
|
154
|
+
},
|
155
|
+
networkInterfaceTypeId: 10
|
156
|
+
}
|
157
|
+
],
|
158
|
+
layoutSize: 1
|
159
|
+
};
|
160
|
+
try {
|
161
|
+
const response = await api_utils_js_1.api.post("/instances", payload);
|
162
|
+
const vm = response.data?.instance;
|
163
|
+
const nodeInfo = assignment.kvmHostId ? ` on node ${assignment.kvmHostId}` : ' (auto-placed)';
|
164
|
+
results.push(`VM '${vm.name}' created (ID: ${vm.id})${nodeInfo}`);
|
165
|
+
}
|
166
|
+
catch (err) {
|
167
|
+
const nodeInfo = assignment.kvmHostId ? ` on node ${assignment.kvmHostId}` : '';
|
168
|
+
errors.push(`VM '${assignment.name}' failed${nodeInfo}: ${err.response?.data?.message || err.message}`);
|
169
|
+
}
|
170
|
+
}
|
171
|
+
// Prepare response
|
172
|
+
const summary = [];
|
173
|
+
if (results.length > 0) {
|
174
|
+
summary.push(`Successfully created ${results.length} VM(s):`);
|
175
|
+
summary.push(...results);
|
176
|
+
}
|
177
|
+
if (errors.length > 0) {
|
178
|
+
summary.push(`\nFailed to create ${errors.length} VM(s):`);
|
179
|
+
summary.push(...errors);
|
180
|
+
}
|
181
|
+
summary.push(`\nResolved parameters:`);
|
182
|
+
summary.push(`- Group: ${resolved.resolvedGroup}`);
|
183
|
+
summary.push(`- Zone/Cloud: ${resolved.resolvedCloud}`);
|
184
|
+
summary.push(`- Template: ${resolved.resolvedImage}`);
|
185
|
+
summary.push(`- Plan: ${resolved.resolvedPlan}`);
|
186
|
+
if (distribution === 'spread' || (vmNames.length > 1 && !distribution)) {
|
187
|
+
summary.push(`- Distribution: Spread across nodes ${nodes.join(', ')}`);
|
188
|
+
}
|
189
|
+
else if (nodeAssignments.some(a => a.kvmHostId)) {
|
190
|
+
summary.push(`- Distribution: Specific node placement`);
|
191
|
+
}
|
192
|
+
else {
|
193
|
+
summary.push(`- Distribution: Auto-placement`);
|
194
|
+
}
|
195
|
+
return {
|
196
|
+
content: [
|
197
|
+
{
|
198
|
+
type: "text",
|
199
|
+
text: summary.join('\n')
|
200
|
+
}
|
201
|
+
],
|
202
|
+
isError: errors.length > 0 && results.length === 0
|
203
|
+
};
|
204
|
+
}
|
205
|
+
exports.handleCreateVM = handleCreateVM;
|
@@ -0,0 +1,115 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.handleExportTrainingData = exports.exportTrainingDataTool = void 0;
|
4
|
+
const fs_1 = require("fs");
|
5
|
+
const path_1 = require("path");
|
6
|
+
exports.exportTrainingDataTool = {
|
7
|
+
name: "export_training_data",
|
8
|
+
description: "Export AI training data for model improvement (requires ENABLE_AI_TRAINING_DATA=true)",
|
9
|
+
inputSchema: {
|
10
|
+
type: "object",
|
11
|
+
properties: {
|
12
|
+
format: {
|
13
|
+
type: "string",
|
14
|
+
description: "Export format: 'jsonl' or 'csv'",
|
15
|
+
enum: ["jsonl", "csv"]
|
16
|
+
},
|
17
|
+
days: {
|
18
|
+
type: "number",
|
19
|
+
description: "Number of days of data to export (default: 7)"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
required: []
|
23
|
+
}
|
24
|
+
};
|
25
|
+
async function handleExportTrainingData(args) {
|
26
|
+
const AI_TRAINING_ENABLED = process.env.ENABLE_AI_TRAINING_DATA === 'true';
|
27
|
+
if (!AI_TRAINING_ENABLED) {
|
28
|
+
return {
|
29
|
+
content: [
|
30
|
+
{
|
31
|
+
type: "text",
|
32
|
+
text: JSON.stringify({
|
33
|
+
error: "Training data collection is disabled",
|
34
|
+
message: "Set ENABLE_AI_TRAINING_DATA=true in .env to enable data collection and export"
|
35
|
+
}, null, 2)
|
36
|
+
}
|
37
|
+
],
|
38
|
+
isError: true
|
39
|
+
};
|
40
|
+
}
|
41
|
+
const { format = "jsonl", days = 7 } = args;
|
42
|
+
try {
|
43
|
+
const logsDir = (0, path_1.join)(process.cwd(), 'ai-training-logs');
|
44
|
+
if (!(0, fs_1.existsSync)(logsDir)) {
|
45
|
+
return {
|
46
|
+
content: [
|
47
|
+
{
|
48
|
+
type: "text",
|
49
|
+
text: JSON.stringify({
|
50
|
+
message: "No training data found",
|
51
|
+
data_count: 0
|
52
|
+
}, null, 2)
|
53
|
+
}
|
54
|
+
],
|
55
|
+
isError: false
|
56
|
+
};
|
57
|
+
}
|
58
|
+
// Collect data from last N days
|
59
|
+
const cutoffDate = new Date(Date.now() - (days * 24 * 60 * 60 * 1000));
|
60
|
+
const allData = [];
|
61
|
+
// Read log files and aggregate data
|
62
|
+
const logFiles = (0, fs_1.readdirSync)(logsDir).filter((file) => file.startsWith('interactions-') && file.endsWith('.jsonl'));
|
63
|
+
for (const file of logFiles) {
|
64
|
+
const fileDate = new Date(file.replace('interactions-', '').replace('.jsonl', ''));
|
65
|
+
if (fileDate >= cutoffDate) {
|
66
|
+
const content = (0, fs_1.readFileSync)((0, path_1.join)(logsDir, file), 'utf-8');
|
67
|
+
const lines = content.trim().split('\n').filter(line => line.trim());
|
68
|
+
for (const line of lines) {
|
69
|
+
try {
|
70
|
+
allData.push(JSON.parse(line));
|
71
|
+
}
|
72
|
+
catch (e) {
|
73
|
+
// Skip malformed lines
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
return {
|
79
|
+
content: [
|
80
|
+
{
|
81
|
+
type: "text",
|
82
|
+
text: JSON.stringify({
|
83
|
+
message: `Exported ${allData.length} training data records from last ${days} days`,
|
84
|
+
format: format,
|
85
|
+
data_count: allData.length,
|
86
|
+
data: format === 'jsonl' ? allData : allData.map(item => ({
|
87
|
+
timestamp: item.timestamp,
|
88
|
+
tool: item.tool_name,
|
89
|
+
user_input: JSON.stringify(item.user_input),
|
90
|
+
parsed_output: JSON.stringify(item.parsed_output),
|
91
|
+
success: item.success_metrics?.operation_success,
|
92
|
+
confidence: item.success_metrics?.confidence_score
|
93
|
+
}))
|
94
|
+
}, null, 2)
|
95
|
+
}
|
96
|
+
],
|
97
|
+
isError: false
|
98
|
+
};
|
99
|
+
}
|
100
|
+
catch (error) {
|
101
|
+
return {
|
102
|
+
content: [
|
103
|
+
{
|
104
|
+
type: "text",
|
105
|
+
text: JSON.stringify({
|
106
|
+
error: "Failed to export training data",
|
107
|
+
message: error.message
|
108
|
+
}, null, 2)
|
109
|
+
}
|
110
|
+
],
|
111
|
+
isError: true
|
112
|
+
};
|
113
|
+
}
|
114
|
+
}
|
115
|
+
exports.handleExportTrainingData = handleExportTrainingData;
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.handleGetResources = exports.getResourcesTool = void 0;
|
4
|
+
const api_utils_js_1 = require("../lib/api-utils.js");
|
5
|
+
exports.getResourcesTool = {
|
6
|
+
name: "get_resources",
|
7
|
+
description: "Discover and explore available VME infrastructure resources with intelligent filtering",
|
8
|
+
inputSchema: {
|
9
|
+
type: "object",
|
10
|
+
properties: {
|
11
|
+
type: {
|
12
|
+
type: "string",
|
13
|
+
description: "Resource type filter: 'compute', 'network', 'storage', 'vm', or leave empty for all"
|
14
|
+
},
|
15
|
+
intent: {
|
16
|
+
type: "string",
|
17
|
+
description: "Intent-based filtering: 'create', 'provision', 'list', 'discover', or natural language description"
|
18
|
+
},
|
19
|
+
role: {
|
20
|
+
type: "string",
|
21
|
+
description: "User role for permission-aware filtering (future enhancement)"
|
22
|
+
}
|
23
|
+
},
|
24
|
+
required: []
|
25
|
+
}
|
26
|
+
};
|
27
|
+
async function handleGetResources(args) {
|
28
|
+
const { type, intent, role } = args;
|
29
|
+
const resources = await (0, api_utils_js_1.getResources)(type, intent, role);
|
30
|
+
return {
|
31
|
+
content: [
|
32
|
+
{
|
33
|
+
type: "text",
|
34
|
+
text: JSON.stringify(resources, null, 2)
|
35
|
+
}
|
36
|
+
],
|
37
|
+
isError: !!resources.error
|
38
|
+
};
|
39
|
+
}
|
40
|
+
exports.handleGetResources = handleGetResources;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.toolHandlers = exports.allTools = exports.handleProvideFeedback = exports.provideFeedbackTool = exports.handleExportTrainingData = exports.exportTrainingDataTool = exports.handleCreateVM = exports.createVMTool = exports.handleParseIntent = exports.parseIntentTool = exports.handleGetResources = exports.getResourcesTool = void 0;
|
4
|
+
// Import and re-export all tools and their handlers
|
5
|
+
const get_resources_js_1 = require("./get-resources.js");
|
6
|
+
const parse_intent_js_1 = require("./parse-intent.js");
|
7
|
+
const create_vm_js_1 = require("./create-vm.js");
|
8
|
+
const export_training_data_js_1 = require("./export-training-data.js");
|
9
|
+
const provide_feedback_js_1 = require("./provide-feedback.js");
|
10
|
+
// Re-export for external use
|
11
|
+
var get_resources_js_2 = require("./get-resources.js");
|
12
|
+
Object.defineProperty(exports, "getResourcesTool", { enumerable: true, get: function () { return get_resources_js_2.getResourcesTool; } });
|
13
|
+
Object.defineProperty(exports, "handleGetResources", { enumerable: true, get: function () { return get_resources_js_2.handleGetResources; } });
|
14
|
+
var parse_intent_js_2 = require("./parse-intent.js");
|
15
|
+
Object.defineProperty(exports, "parseIntentTool", { enumerable: true, get: function () { return parse_intent_js_2.parseIntentTool; } });
|
16
|
+
Object.defineProperty(exports, "handleParseIntent", { enumerable: true, get: function () { return parse_intent_js_2.handleParseIntent; } });
|
17
|
+
var create_vm_js_2 = require("./create-vm.js");
|
18
|
+
Object.defineProperty(exports, "createVMTool", { enumerable: true, get: function () { return create_vm_js_2.createVMTool; } });
|
19
|
+
Object.defineProperty(exports, "handleCreateVM", { enumerable: true, get: function () { return create_vm_js_2.handleCreateVM; } });
|
20
|
+
var export_training_data_js_2 = require("./export-training-data.js");
|
21
|
+
Object.defineProperty(exports, "exportTrainingDataTool", { enumerable: true, get: function () { return export_training_data_js_2.exportTrainingDataTool; } });
|
22
|
+
Object.defineProperty(exports, "handleExportTrainingData", { enumerable: true, get: function () { return export_training_data_js_2.handleExportTrainingData; } });
|
23
|
+
var provide_feedback_js_2 = require("./provide-feedback.js");
|
24
|
+
Object.defineProperty(exports, "provideFeedbackTool", { enumerable: true, get: function () { return provide_feedback_js_2.provideFeedbackTool; } });
|
25
|
+
Object.defineProperty(exports, "handleProvideFeedback", { enumerable: true, get: function () { return provide_feedback_js_2.handleProvideFeedback; } });
|
26
|
+
// Collect all tool definitions
|
27
|
+
exports.allTools = [
|
28
|
+
get_resources_js_1.getResourcesTool,
|
29
|
+
parse_intent_js_1.parseIntentTool,
|
30
|
+
create_vm_js_1.createVMTool,
|
31
|
+
export_training_data_js_1.exportTrainingDataTool,
|
32
|
+
provide_feedback_js_1.provideFeedbackTool
|
33
|
+
];
|
34
|
+
// Export tool handlers map for easy lookup
|
35
|
+
exports.toolHandlers = {
|
36
|
+
get_resources: get_resources_js_1.handleGetResources,
|
37
|
+
parse_vm_intent: parse_intent_js_1.handleParseIntent,
|
38
|
+
create_vm: create_vm_js_1.handleCreateVM,
|
39
|
+
export_training_data: export_training_data_js_1.handleExportTrainingData,
|
40
|
+
provide_feedback: provide_feedback_js_1.handleProvideFeedback
|
41
|
+
};
|
@@ -0,0 +1,52 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.handleParseIntent = exports.parseIntentTool = void 0;
|
4
|
+
const intent_recognition_js_1 = require("../lib/intent-recognition.js");
|
5
|
+
const session_js_1 = require("../lib/session.js");
|
6
|
+
exports.parseIntentTool = {
|
7
|
+
name: "parse_vm_intent",
|
8
|
+
description: "Parse natural language VM requests into structured parameters with confidence scoring",
|
9
|
+
inputSchema: {
|
10
|
+
type: "object",
|
11
|
+
properties: {
|
12
|
+
naturalLanguageInput: {
|
13
|
+
type: "string",
|
14
|
+
description: "Natural language description of VM provisioning request"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
required: ["naturalLanguageInput"]
|
18
|
+
}
|
19
|
+
};
|
20
|
+
async function handleParseIntent(args) {
|
21
|
+
const startTime = Date.now();
|
22
|
+
const { naturalLanguageInput } = args;
|
23
|
+
const sessionId = (0, session_js_1.generateSessionId)();
|
24
|
+
const parsedIntent = (0, intent_recognition_js_1.parseVMIntent)(naturalLanguageInput);
|
25
|
+
const parseTime = Date.now() - startTime;
|
26
|
+
// Log interaction for AI training (respects privacy settings)
|
27
|
+
(0, session_js_1.logInteraction)({
|
28
|
+
session_id: sessionId,
|
29
|
+
tool_name: 'parse_vm_intent',
|
30
|
+
user_input: { naturalLanguageInput },
|
31
|
+
parsed_output: parsedIntent,
|
32
|
+
success_metrics: {
|
33
|
+
operation_success: parsedIntent.action !== 'unknown',
|
34
|
+
confidence_score: parsedIntent.confidence,
|
35
|
+
entities_extracted: Object.keys(parsedIntent.entities).length
|
36
|
+
},
|
37
|
+
timing: {
|
38
|
+
parse_duration_ms: parseTime,
|
39
|
+
total_duration_ms: parseTime
|
40
|
+
}
|
41
|
+
});
|
42
|
+
return {
|
43
|
+
content: [
|
44
|
+
{
|
45
|
+
type: "text",
|
46
|
+
text: JSON.stringify(parsedIntent, null, 2)
|
47
|
+
}
|
48
|
+
],
|
49
|
+
isError: parsedIntent.action === 'unknown' && parsedIntent.confidence < 0.3
|
50
|
+
};
|
51
|
+
}
|
52
|
+
exports.handleParseIntent = handleParseIntent;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.handleProvideFeedback = exports.provideFeedbackTool = void 0;
|
4
|
+
const session_js_1 = require("../lib/session.js");
|
5
|
+
exports.provideFeedbackTool = {
|
6
|
+
name: "provide_feedback",
|
7
|
+
description: "Provide feedback on intent parsing accuracy to improve future predictions",
|
8
|
+
inputSchema: {
|
9
|
+
type: "object",
|
10
|
+
properties: {
|
11
|
+
original_input: {
|
12
|
+
type: "string",
|
13
|
+
description: "Original natural language input"
|
14
|
+
},
|
15
|
+
parsed_result: {
|
16
|
+
type: "object",
|
17
|
+
description: "The parsed result that was incorrect"
|
18
|
+
},
|
19
|
+
correct_interpretation: {
|
20
|
+
type: "object",
|
21
|
+
description: "What the correct interpretation should have been"
|
22
|
+
},
|
23
|
+
feedback_notes: {
|
24
|
+
type: "string",
|
25
|
+
description: "Additional notes about what went wrong"
|
26
|
+
}
|
27
|
+
},
|
28
|
+
required: ["original_input", "feedback_notes"]
|
29
|
+
}
|
30
|
+
};
|
31
|
+
async function handleProvideFeedback(args) {
|
32
|
+
const { original_input, parsed_result, correct_interpretation, feedback_notes } = args;
|
33
|
+
const sessionId = (0, session_js_1.generateSessionId)();
|
34
|
+
// Log feedback for future model improvements
|
35
|
+
(0, session_js_1.logInteraction)({
|
36
|
+
session_id: sessionId,
|
37
|
+
tool_name: 'provide_feedback',
|
38
|
+
user_input: { original_input, feedback_notes },
|
39
|
+
parsed_output: { parsed_result, correct_interpretation },
|
40
|
+
user_feedback: feedback_notes,
|
41
|
+
success_metrics: {
|
42
|
+
operation_success: false, // This indicates the original parsing was wrong
|
43
|
+
user_satisfaction: 0 // User had to provide feedback = dissatisfied
|
44
|
+
}
|
45
|
+
});
|
46
|
+
return {
|
47
|
+
content: [
|
48
|
+
{
|
49
|
+
type: "text",
|
50
|
+
text: JSON.stringify({
|
51
|
+
message: "Thank you for the feedback! This will help improve future intent recognition.",
|
52
|
+
feedback_recorded: true,
|
53
|
+
original_input: original_input,
|
54
|
+
feedback_notes: feedback_notes
|
55
|
+
}, null, 2)
|
56
|
+
}
|
57
|
+
],
|
58
|
+
isError: false
|
59
|
+
};
|
60
|
+
}
|
61
|
+
exports.handleProvideFeedback = handleProvideFeedback;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "vme-mcp-server",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.6",
|
4
4
|
"description": "VMware vCenter MCP Server - Natural language infrastructure management for Claude",
|
5
5
|
"main": "dist/server.js",
|
6
6
|
"bin": {
|
@@ -10,7 +10,7 @@
|
|
10
10
|
"build": "tsc",
|
11
11
|
"start": "node dist/server.js",
|
12
12
|
"dev": "tsx watch src/server.ts",
|
13
|
-
"prepublishOnly": "npm run build && cp README-NPM.md dist/README.md",
|
13
|
+
"prepublishOnly": "npm run build && echo '#!/usr/bin/env node' | cat - dist/server.js > temp && mv temp dist/server.js && chmod +x dist/server.js && cp README-NPM.md dist/README.md",
|
14
14
|
"test": "mocha tests/**/*.test.js",
|
15
15
|
"test:unit": "mocha tests/unit/*.test.js",
|
16
16
|
"test:integration": "mocha tests/integration/*.test.js",
|