@etm-professional-control/winccoa-mcp-server
Version:
MCP Server for WinCC OA with field-specific configurations
140 lines • 4.34 kB
JavaScript
/**
* Utility helper functions for MCP tool responses and datapoint operations
*/
/**
* Create content array for MCP responses, filtering internal types if needed
* @param arr - Array of type names
* @param withInternals - Whether to include internal types (starting with _)
* @returns Content array for MCP response
*/
export function mkTypesContent(arr, withInternals) {
const ret = [];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (item !== undefined) {
if (!item.startsWith('_')) {
ret.push({ type: "text", text: item });
}
else if (withInternals) {
ret.push({ type: "text", text: item });
}
}
}
return ret;
}
/**
* Recursively add description and unit information to datapoint children
* @param children - Array of child datapoint elements
* @param parentPath - Parent datapoint path
* @param winccoa - WinCC OA manager instance
*/
export function addDescriptionAndUnitsToChildren(children, parentPath, winccoa) {
children.forEach(child => {
const currentPath = `${parentPath}.${child.name}`;
if (Array.isArray(child.children) && child.children.length > 0) {
addDescriptionAndUnitsToChildren(child.children, currentPath, winccoa);
}
else {
// Only get unit and description for leaf elements (no children)
try {
child.unit = winccoa.dpGetUnit(currentPath);
child.description = winccoa.dpGetDescription(currentPath);
}
catch (error) {
// Silently ignore errors for individual elements
}
}
});
}
/**
* Create standardized error response for MCP tools
* @param message - Error message
* @param codeOrDetails - Error code (string) or details object (optional)
* @returns MCP error response
*/
export function createErrorResponse(message, codeOrDetails) {
const response = {
error: true,
message
};
if (typeof codeOrDetails === 'string') {
response.code = codeOrDetails;
}
else if (typeof codeOrDetails === 'object' && codeOrDetails !== null) {
Object.assign(response, codeOrDetails);
}
return {
content: [{
type: "text",
text: JSON.stringify(response)
}]
};
}
/**
* Create standardized success response for MCP tools
* @param result - Result data
* @param message - Optional success message
* @returns MCP success response
*/
export function createSuccessResponse(result, message) {
const response = {
success: true,
data: result
};
if (message) {
response.message = message;
}
return {
content: [{
type: "text",
text: JSON.stringify(response)
}]
};
}
/**
* Validate datapoint name format
* @param dpName - Datapoint name to validate
* @returns True if valid
*/
export function isValidDatapointName(dpName) {
if (!dpName || typeof dpName !== 'string') {
return false;
}
// Basic validation: should not be empty, no special chars that break WinCC OA
return dpName.length > 0 && !dpName.includes('..') && !dpName.startsWith('.');
}
/**
* Validate datapoint element for dpGet operations
* Rejects asterisk (*) wildcard to prevent large responses
* @param dpe - Datapoint element name to validate
* @returns True if valid for dpGet
*/
export function isValidDatapointElementForGet(dpe) {
if (!dpe || typeof dpe !== 'string') {
return false;
}
// Reject asterisk wildcard (causes response too large)
if (dpe.includes('*')) {
return false;
}
// Basic validation
return dpe.length > 0 && !dpe.includes('..') && !dpe.startsWith('.');
}
/**
* Validate array of datapoint elements for dpGet operations
* @param dpes - Array of datapoint element names
* @returns Validation result with invalid entries if any
*/
export function validateDatapointElementsForGet(dpes) {
const invalid = [];
for (const dpe of dpes) {
if (!isValidDatapointElementForGet(dpe)) {
invalid.push(dpe);
}
}
return {
valid: invalid.length === 0,
invalid
};
}
//# sourceMappingURL=helpers.js.map