leshan-mcp-server
Version:
A standards-compliant MCP server for Leshan LwM2M, exposing Leshan as Model Context Protocol tools.
103 lines (90 loc) • 3.13 kB
JavaScript
import { post } from "../utils/leshanClient.js";
import { validateLwM2MPath } from "../utils/validation.js";
import logger from "../utils/loggerConfig.js";
/**
* Execute a resource on a LwM2M device
* @param {Object} params - Parameters
* @param {string} params.deviceId - Device endpoint
* @param {string} params.objectId - Object ID
* @param {string} params.instanceId - Instance ID
* @param {string} params.resourceId - Resource ID
* @param {any} params.arguments - Optional execution arguments
* @returns {Promise<Object>} MCP tool response
*/
export async function executeResource({ deviceId, objectId, instanceId, resourceId, arguments: execArgs }) {
const operationId = `execute-resource-${Date.now()}`;
try {
logger.info("Execute resource operation started", {
operationId,
deviceId,
path: `${objectId}/${instanceId}/${resourceId}`,
hasArguments: !!execArgs
});
// Validate path parameters
const validatedParams = validateLwM2MPath(deviceId, objectId, instanceId, resourceId);
const endpoint = `/clients/${encodeURIComponent(validatedParams.deviceId)}/${validatedParams.objectId}/${validatedParams.instanceId}/${validatedParams.resourceId}`;
const requestBody = execArgs ? { arguments: execArgs } : {};
logger.debug("Making execute request", {
operationId,
endpoint,
requestBody
});
const result = await post(endpoint, requestBody);
logger.info("Resource executed successfully", {
operationId,
deviceId: validatedParams.deviceId,
path: `${validatedParams.objectId}/${validatedParams.instanceId}/${validatedParams.resourceId}`
});
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
operation: "executeResource",
operationId,
timestamp: new Date().toISOString(),
device: {
endpoint: validatedParams.deviceId,
path: `${validatedParams.objectId}/${validatedParams.instanceId}/${validatedParams.resourceId}`
},
request: {
arguments: execArgs
},
result
}, null, 2)
}]
};
} catch (error) {
logger.error("Execute resource operation failed", {
operationId,
deviceId,
path: `${objectId}/${instanceId}/${resourceId}`,
arguments: execArgs,
error: error.message,
errorType: error.constructor.name
});
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
operation: "executeResource",
operationId,
timestamp: new Date().toISOString(),
error: {
message: error.message,
type: error.constructor.name,
...(error.statusCode && { statusCode: error.statusCode })
},
request: {
deviceId,
path: `${objectId}/${instanceId}/${resourceId}`,
arguments: execArgs
}
}, null, 2)
}],
isError: true
};
}
}
export default executeResource;