UNPKG

leshan-mcp-server

Version:

A standards-compliant MCP server for Leshan LwM2M, exposing Leshan as Model Context Protocol tools.

96 lines (84 loc) 3 kB
import { get } from "../utils/leshanClient.js"; import { validateLwM2MPath } from "../utils/validation.js"; import logger from "../utils/loggerConfig.js"; /** * Read a resource value from 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 * @returns {Promise<Object>} MCP tool response */ export async function readResource({ deviceId, objectId, instanceId, resourceId }) { const operationId = `read-resource-${Date.now()}`; try { logger.info("Read resource operation started", { operationId, deviceId, path: `${objectId}/${instanceId}/${resourceId}` }); // Validate and sanitize input parameters const validatedParams = validateLwM2MPath(deviceId, objectId, instanceId, resourceId); const endpoint = `/clients/${encodeURIComponent(validatedParams.deviceId)}/${validatedParams.objectId}/${validatedParams.instanceId}/${validatedParams.resourceId}`; logger.debug("Making read request", { operationId, endpoint }); const result = await get(endpoint); logger.info("Resource read successfully", { operationId, deviceId: validatedParams.deviceId, path: `${validatedParams.objectId}/${validatedParams.instanceId}/${validatedParams.resourceId}`, valueType: typeof result, hasValue: result !== null && result !== undefined }); return { content: [{ type: "text", text: JSON.stringify({ success: true, operation: "readResource", operationId, timestamp: new Date().toISOString(), device: { endpoint: validatedParams.deviceId, path: `${validatedParams.objectId}/${validatedParams.instanceId}/${validatedParams.resourceId}` }, result: { value: result, type: typeof result, isEmpty: result === null || result === undefined || result === "" } }, null, 2) }] }; } catch (error) { logger.error("Read resource operation failed", { operationId, deviceId, path: `${objectId}/${instanceId}/${resourceId}`, error: error.message, errorType: error.constructor.name }); return { content: [{ type: "text", text: JSON.stringify({ success: false, operation: "readResource", operationId, timestamp: new Date().toISOString(), error: { message: error.message, type: error.constructor.name, ...(error.statusCode && { statusCode: error.statusCode }) }, request: { deviceId, path: `${objectId}/${instanceId}/${resourceId}` } }, null, 2) }], isError: true }; } } export default readResource;