@node-i3x/mcp 0.11.2 → 0.12.0
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/dist/cli.js +518 -220
- package/dist/cli.js.map +1 -1
- package/dist/in-process.d.ts +18 -0
- package/dist/in-process.js +280 -0
- package/dist/in-process.js.map +1 -0
- package/dist/index.d.ts +47 -114
- package/dist/index.js +514 -345
- package/dist/index.js.map +1 -1
- package/dist/rest-binding-DPjLoyyg.d.ts +133 -0
- package/package.json +16 -2
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/similarity.ts","../src/bindings/rest-binding.ts","../src/server.ts","../src/tools/connect.ts","../src/tools/discover-types.ts","../src/tools/explore-hierarchy.ts","../src/tools/inspect-asset.ts","../src/tools/monitor-events.ts","../src/tools/query-telemetry.ts","../src/cli.ts"],"sourcesContent":["/**\n * Computes a normalized similarity score between two strings (0.0 to 1.0)\n * using Levenshtein edit distance and substring matching.\n */\nexport function computeSimilarity(a: string, b: string): number {\n const s1 = a.toLowerCase().trim();\n const s2 = b.toLowerCase().trim();\n\n if (s1 === s2) return 1.0;\n if (!s1 || !s2) return 0.0;\n\n // Exact substring boost\n if (s1.includes(s2) || s2.includes(s1)) {\n const ratio = Math.min(s1.length, s2.length) / Math.max(s1.length, s2.length);\n return Math.max(0.7, ratio);\n }\n\n // Levenshtein distance calculation\n const m = s1.length;\n const n = s2.length;\n const dp: number[] = Array.from({ length: n + 1 }, (_, i) => i);\n\n for (let i = 1; i <= m; i++) {\n let prev = dp[0]!;\n dp[0] = i;\n for (let j = 1; j <= n; j++) {\n const temp = dp[j]!;\n const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;\n dp[j] = Math.min(dp[j]! + 1, dp[j - 1]! + 1, prev + cost);\n prev = temp;\n }\n }\n\n const distance = dp[n]!;\n const maxLen = Math.max(m, n);\n return Math.max(0, 1 - distance / maxLen);\n}\n\n/**\n * Ranks candidate strings by similarity against a target query,\n * returning the top N matches with score >= minScore.\n */\nexport function rankSuggestions(\n query: string,\n candidates: string[],\n topN = 5,\n minScore = 0.4,\n): string[] {\n return candidates\n .map((candidate) => ({\n candidate,\n score: computeSimilarity(query, candidate),\n }))\n .filter((item) => item.score >= minScore)\n .sort((a, b) => b.score - a.score)\n .slice(0, topN)\n .map((item) => item.candidate);\n}\n","import type {\n CurrentValueResult,\n HistoricalValueResult,\n Namespace,\n ObjectInstanceResponse,\n ObjectType,\n RelationshipType,\n ServerInfo,\n} from '@node-i3x/core';\nimport { rankSuggestions } from '../utils/similarity.js';\nimport type { I3XClientBinding } from './types.js';\n\nexport class RestClientBinding implements I3XClientBinding {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly requestTimeoutMs: number;\n\n constructor(baseUrl = 'http://localhost:3000', token?: string, timeoutMs = 15_000) {\n let cleanUrl = baseUrl.trim().replace(/\\/+$/, '');\n if (!cleanUrl.startsWith('http://') && !cleanUrl.startsWith('https://')) {\n cleanUrl = `http://${cleanUrl}`;\n }\n this.baseUrl = cleanUrl;\n this.requestTimeoutMs = timeoutMs;\n this.headers = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n if (token) {\n this.headers.Authorization = `Bearer ${token}`;\n }\n }\n\n private async request<T>(path: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const signal = options.signal || AbortSignal.timeout(this.requestTimeoutMs);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal,\n headers: {\n ...this.headers,\n ...(options.headers || {}),\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n const truncated =\n errorText.length > 300 ? `${errorText.slice(0, 300)}...` : errorText;\n throw new Error(`HTTP ${response.status} from ${path}: ${truncated}`);\n }\n\n return (await response.json()) as T;\n } catch (err) {\n if ((err as Error).name === 'TimeoutError') {\n throw new Error(\n `i3X Gateway request timed out after ${this.requestTimeoutMs}ms for ${path}`,\n );\n }\n throw err;\n }\n }\n\n async getInfo(): Promise<ServerInfo> {\n return this.request<ServerInfo>('/v1/info');\n }\n\n async getNamespaces(): Promise<Namespace[]> {\n const res = await this.request<{ namespaces: Namespace[] }>('/v1/namespaces');\n return res.namespaces || [];\n }\n\n async getObjectTypes(namespaceUri?: string): Promise<ObjectType[]> {\n const query = namespaceUri ? `?namespaceUri=${encodeURIComponent(namespaceUri)}` : '';\n const res = await this.request<{ objectTypes: ObjectType[] }>(\n `/v1/objecttypes${query}`,\n );\n return res.objectTypes || [];\n }\n\n async getRelationshipTypes(): Promise<RelationshipType[]> {\n const res = await this.request<{ relationshipTypes: RelationshipType[] }>(\n '/v1/relationshiptypes',\n );\n return res.relationshipTypes || [];\n }\n\n async getObjects(options?: {\n rootOnly?: boolean;\n typeElementId?: string;\n }): Promise<ObjectInstanceResponse[]> {\n const params = new URLSearchParams();\n if (options?.rootOnly) params.set('root', 'true');\n if (options?.typeElementId) params.set('typeElementId', options.typeElementId);\n\n const query = params.toString() ? `?${params.toString()}` : '';\n const res = await this.request<{ objects: ObjectInstanceResponse[] }>(\n `/v1/objects${query}`,\n );\n return res.objects || [];\n }\n\n async getObjectById(elementId: string): Promise<ObjectInstanceResponse | null> {\n try {\n const res = await this.request<{ objects: ObjectInstanceResponse[] }>(\n '/v1/objects/list',\n {\n method: 'POST',\n body: JSON.stringify({ elementIds: [elementId] }),\n },\n );\n if (res.objects && res.objects.length > 0) {\n return res.objects[0] ?? null;\n }\n return null;\n } catch {\n return null;\n }\n }\n\n async getRelatedObjects(\n elementId: string,\n relationshipType?: string,\n ): Promise<ObjectInstanceResponse[]> {\n try {\n const body: Record<string, unknown> = { elementId };\n if (relationshipType) body.relationshipType = relationshipType;\n\n const res = await this.request<{\n relatedObjects: Array<{ targetObject: ObjectInstanceResponse }>;\n }>('/v1/objects/related', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n return (res.relatedObjects || []).map((r) => r.targetObject);\n } catch {\n return [];\n }\n }\n\n async getObjectValues(\n elementIds: string[],\n maxDepth = 1,\n ): Promise<CurrentValueResult[]> {\n const res = await this.request<{ values: CurrentValueResult[] }>(\n '/v1/objects/value',\n {\n method: 'POST',\n body: JSON.stringify({ elementIds, maxDepth }),\n },\n );\n return res.values || [];\n }\n\n async getHistoricalValues(\n elementIds: string[],\n startTime: string,\n endTime: string,\n maxDepth = 1,\n ): Promise<HistoricalValueResult[]> {\n const res = await this.request<{ history: HistoricalValueResult[] }>(\n '/v1/objects/history',\n {\n method: 'POST',\n body: JSON.stringify({ elementIds, startTime, endTime, maxDepth }),\n },\n );\n return res.history || [];\n }\n\n async findSuggestions(unknownId: string): Promise<string[]> {\n try {\n const allObjects = await this.getObjects();\n const candidates = allObjects.map((o) => o.elementId);\n return rankSuggestions(unknownId, candidates, 5, 0.4);\n } catch {\n return [];\n }\n }\n}\n","import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { RestClientBinding } from './bindings/rest-binding.js';\nimport type { I3XClientBinding } from './bindings/types.js';\nimport { connectSchema, handleConnect } from './tools/connect.js';\nimport { discoverTypesSchema, handleDiscoverTypes } from './tools/discover-types.js';\nimport {\n exploreHierarchySchema,\n handleExploreHierarchy,\n} from './tools/explore-hierarchy.js';\nimport { handleInspectAsset, inspectAssetSchema } from './tools/inspect-asset.js';\nimport { handleMonitorEvents, monitorEventsSchema } from './tools/monitor-events.js';\nimport { handleQueryTelemetry, queryTelemetrySchema } from './tools/query-telemetry.js';\n\nexport class NodeI3xMcpServer {\n private readonly server: Server;\n private binding: I3XClientBinding;\n\n constructor(binding?: I3XClientBinding) {\n this.binding = binding || new RestClientBinding();\n\n this.server = new Server(\n {\n name: '@node-i3x/mcp',\n version: '0.10.0',\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n },\n },\n );\n\n this.setupHandlers();\n }\n\n public setBinding(binding: I3XClientBinding): void {\n this.binding = binding;\n }\n\n public getBinding(): I3XClientBinding {\n return this.binding;\n }\n\n private setupHandlers() {\n // List Available MCP Tools\n this.server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'i3x_connect',\n description:\n 'Connect or switch dynamically to a specific i3X server endpoint URL and optional Bearer token at runtime.',\n inputSchema: {\n type: 'object',\n properties: {\n serverUrl: {\n type: 'string',\n description:\n \"Target i3X Gateway REST endpoint URL (e.g. 'http://192.168.1.50:8000' or 'https://i3x-portal.sterfive.io/instance/SESSION_ID')\",\n },\n authToken: {\n type: 'string',\n description: 'Optional Bearer authentication token for secured endpoints',\n },\n verifyConnection: {\n type: 'boolean',\n description:\n 'Whether to verify connectivity by querying server /v1/info (default: true)',\n },\n },\n required: ['serverUrl'],\n },\n },\n {\n name: 'i3x_inspect_asset',\n description:\n 'Single-turn complete asset diagnostic. Returns identity, ObjectType schema, parent/child hierarchy, and live VQT telemetry in 1 call.',\n inputSchema: {\n type: 'object',\n properties: {\n elementId: {\n type: 'string',\n description:\n \"The elementId of the asset to inspect (e.g. 'Pump_101', 'Boiler_101')\",\n },\n includeValues: {\n type: 'boolean',\n description:\n 'Whether to include live VQT telemetry values (default: true)',\n },\n includeSchema: {\n type: 'boolean',\n description:\n 'Whether to include the ObjectType JSON Schema definition (default: true)',\n },\n },\n required: ['elementId'],\n },\n },\n {\n name: 'i3x_explore_plant_hierarchy',\n description:\n 'ISA-95 plant topology discovery. Traverses plant hierarchy from root assets down to child components up to maxDepth.',\n inputSchema: {\n type: 'object',\n properties: {\n rootElementId: {\n type: 'string',\n description:\n 'Optional specific root asset elementId. If omitted, explores all root assets.',\n },\n maxDepth: {\n type: 'number',\n description:\n 'Maximum depth to traverse child components (1 to 5, default: 2)',\n },\n },\n },\n },\n {\n name: 'i3x_query_telemetry',\n description:\n 'Live current VQT telemetry or historical time-series trend analysis with pre-computed statistical summaries (min, max, mean).',\n inputSchema: {\n type: 'object',\n properties: {\n elementIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"Array of asset elementIds to query (e.g. ['Pump_101', 'Boiler_101'])\",\n },\n mode: {\n type: 'string',\n enum: ['current', 'history'],\n description:\n \"Query mode: 'current' for live VQT, 'history' for time-series trend analysis\",\n },\n startTime: {\n type: 'string',\n description:\n \"ISO 8601 or relative duration (e.g. '-2h', '-30m') for history mode\",\n },\n endTime: {\n type: 'string',\n description: 'ISO 8601 end time (defaults to now) for history mode',\n },\n aggregateStats: {\n type: 'boolean',\n description:\n 'Whether to pre-compute min/max/mean statistical summaries (default: true)',\n },\n },\n required: ['elementIds'],\n },\n },\n {\n name: 'i3x_discover_types_and_schemas',\n description:\n 'Search registered i3X ObjectTypes, RelationshipTypes, and JSON Schema field validation requirements.',\n inputSchema: {\n type: 'object',\n properties: {\n typeElementId: {\n type: 'string',\n description:\n \"Optional specific ObjectType elementId (e.g. 'BoilerType'). If omitted, lists all types.\",\n },\n namespaceUri: {\n type: 'string',\n description:\n \"Optional namespaceUri filter (e.g. 'http://sterfive.com/UA/Demo/')\",\n },\n },\n },\n },\n {\n name: 'i3x_monitor_asset_events',\n description:\n 'Create an i3X subscription stream to monitor real-time VQT value changes or threshold alert conditions.',\n inputSchema: {\n type: 'object',\n properties: {\n elementIds: {\n type: 'array',\n items: { type: 'string' },\n description: 'Array of asset elementIds to monitor',\n },\n condition: {\n type: 'string',\n description:\n \"Optional alert condition filter (e.g. 'temperature > 85 || quality != Good')\",\n },\n },\n required: ['elementIds'],\n },\n },\n ],\n }));\n\n // Handle Tool Execution\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: rawArgs } = request.params;\n\n try {\n let result: unknown;\n\n switch (name) {\n case 'i3x_connect': {\n const parsed = connectSchema.parse(rawArgs);\n result = await handleConnect(parsed, (newBinding) => {\n this.binding = newBinding;\n });\n break;\n }\n case 'i3x_inspect_asset': {\n const parsed = inspectAssetSchema.parse(rawArgs);\n result = await handleInspectAsset(this.binding, parsed);\n break;\n }\n case 'i3x_explore_plant_hierarchy': {\n const parsed = exploreHierarchySchema.parse(rawArgs);\n result = await handleExploreHierarchy(this.binding, parsed);\n break;\n }\n case 'i3x_query_telemetry': {\n const parsed = queryTelemetrySchema.parse(rawArgs);\n result = await handleQueryTelemetry(this.binding, parsed);\n break;\n }\n case 'i3x_discover_types_and_schemas': {\n const parsed = discoverTypesSchema.parse(rawArgs);\n result = await handleDiscoverTypes(this.binding, parsed);\n break;\n }\n case 'i3x_monitor_asset_events': {\n const parsed = monitorEventsSchema.parse(rawArgs);\n result = await handleMonitorEvents(this.binding, parsed);\n break;\n }\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n error: (err as Error).message,\n tip: \"Check parameters or use 'i3x_explore_plant_hierarchy' to list available assets.\",\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n });\n\n // List Resources (i3x://info, i3x://namespaces)\n this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: [\n {\n uri: 'i3x://info',\n name: 'i3X Server Metadata',\n description: 'Server capabilities, spec version, and vendor information',\n mimeType: 'application/json',\n },\n {\n uri: 'i3x://namespaces',\n name: 'Registered Namespaces',\n description: 'List of registered OPC UA / i3X namespace URIs',\n mimeType: 'application/json',\n },\n ],\n }));\n\n // Read Resource\n this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const { uri } = request.params;\n\n if (uri === 'i3x://info') {\n const info = await this.binding.getInfo();\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(info, null, 2),\n },\n ],\n };\n }\n\n if (uri === 'i3x://namespaces') {\n const namespaces = await this.binding.getNamespaces();\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(namespaces, null, 2),\n },\n ],\n };\n }\n\n throw new Error(`Unknown resource URI: ${uri}`);\n });\n }\n\n async startStdio() {\n const transport = new StdioServerTransport();\n await this.server.connect(transport);\n }\n}\n","import { z } from 'zod';\nimport { RestClientBinding } from '../bindings/rest-binding.js';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const connectSchema = z.object({\n serverUrl: z\n .string()\n .describe(\n \"The base URL of the i3X Gateway (e.g. 'http://192.168.1.50:8000' or 'https://i3x-portal.sterfive.io/instance/SESSION_ID')\",\n ),\n authToken: z\n .string()\n .optional()\n .describe('Optional Bearer authentication token for secured endpoints'),\n verifyConnection: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to immediately verify connectivity by querying server /v1/info'),\n});\n\nexport async function handleConnect(\n args: z.infer<typeof connectSchema>,\n onBindingSwitch: (newBinding: I3XClientBinding) => void,\n) {\n const { serverUrl, authToken, verifyConnection } = args;\n\n const newBinding = new RestClientBinding(serverUrl, authToken);\n\n let serverInfo: unknown;\n if (verifyConnection) {\n try {\n serverInfo = await newBinding.getInfo();\n } catch (err) {\n return {\n status: 'connection_failed',\n serverUrl,\n error: (err as Error).message,\n tip: 'Please check that the server URL is reachable and the authentication token (if required) is valid.',\n };\n }\n }\n\n // Switch the active binding on the MCP server\n onBindingSwitch(newBinding);\n\n return {\n status: 'connected',\n serverUrl,\n authenticated: Boolean(authToken),\n serverInfo: serverInfo || 'Connection established without verification.',\n message: `Successfully connected to ${serverUrl}. All subsequent i3X tool calls will query this endpoint.`,\n };\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const discoverTypesSchema = z.object({\n typeElementId: z\n .string()\n .optional()\n .describe(\n \"Optional specific ObjectType elementId (e.g. 'BoilerType'). If omitted, lists all types.\",\n ),\n namespaceUri: z\n .string()\n .optional()\n .describe(\"Optional namespaceUri filter (e.g. 'http://sterfive.com/UA/Demo/')\"),\n});\n\nexport async function handleDiscoverTypes(\n binding: I3XClientBinding,\n args: z.infer<typeof discoverTypesSchema>,\n) {\n const { typeElementId, namespaceUri } = args;\n\n const [objectTypes, relationshipTypes, namespaces] = await Promise.all([\n binding.getObjectTypes(namespaceUri),\n binding.getRelationshipTypes(),\n binding.getNamespaces(),\n ]);\n\n if (typeElementId) {\n const matched = objectTypes.find((t) => t.elementId === typeElementId);\n if (!matched) {\n return {\n error: `ObjectType '${typeElementId}' not found.`,\n availableTypes: objectTypes.map((t) => t.elementId),\n };\n }\n return {\n objectType: matched,\n };\n }\n\n return {\n namespacesCount: namespaces.length,\n namespaces,\n objectTypesCount: objectTypes.length,\n objectTypes: objectTypes.map((t) => {\n const schemaObj =\n t.schema && typeof t.schema === 'object'\n ? (t.schema as Record<string, unknown>)\n : null;\n const required =\n schemaObj && Array.isArray(schemaObj.required)\n ? (schemaObj.required as string[])\n : [];\n\n return {\n elementId: t.elementId,\n displayName: t.displayName || t.elementId,\n namespaceUri: t.namespaceUri,\n requiredProperties: required,\n };\n }),\n relationshipTypesCount: relationshipTypes.length,\n relationshipTypes,\n };\n}\n","import { z } from 'zod';\nimport type { HierarchyNode, I3XClientBinding } from '../bindings/types.js';\n\nexport const exploreHierarchySchema = z.object({\n rootElementId: z\n .string()\n .optional()\n .describe(\n 'Optional specific root asset elementId. If omitted, explores all root assets.',\n ),\n maxDepth: z\n .number()\n .optional()\n .default(2)\n .describe('Maximum depth to traverse child components (1 to 5, default: 2)'),\n});\n\nexport async function handleExploreHierarchy(\n binding: I3XClientBinding,\n args: z.infer<typeof exploreHierarchySchema>,\n) {\n const maxDepth = Math.min(Math.max(args.maxDepth || 2, 1), 5);\n\n let roots: Array<{ elementId: string; displayName?: string; typeElementId?: string }>;\n\n if (args.rootElementId) {\n const root = await binding.getObjectById(args.rootElementId);\n if (!root) {\n const suggestions = await binding.findSuggestions(args.rootElementId);\n return {\n error: `Root asset '${args.rootElementId}' not found.`,\n suggestions,\n };\n }\n roots = [root];\n } else {\n roots = await binding.getObjects({ rootOnly: true });\n }\n\n async function buildNode(\n asset: { elementId: string; displayName?: string; typeElementId?: string },\n currentDepth: number,\n visited: Set<string>,\n ): Promise<HierarchyNode> {\n const node: HierarchyNode = {\n elementId: asset.elementId,\n displayName: asset.displayName || asset.elementId,\n typeElementId: asset.typeElementId,\n };\n\n visited.add(asset.elementId);\n\n if (currentDepth < maxDepth) {\n const children = await binding.getRelatedObjects(asset.elementId);\n const unvisitedChildren = children.filter((c) => !visited.has(c.elementId));\n\n if (unvisitedChildren.length > 0) {\n node.children = await Promise.all(\n unvisitedChildren.map((child) =>\n buildNode(child, currentDepth + 1, new Set(visited)),\n ),\n );\n }\n }\n\n return node;\n }\n\n const hierarchyTree = await Promise.all(\n roots.map((root) => buildNode(root, 1, new Set<string>())),\n );\n\n return {\n totalRoots: roots.length,\n traversalDepth: maxDepth,\n plantTopology: hierarchyTree,\n };\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const inspectAssetSchema = z.object({\n elementId: z\n .string()\n .describe(\"The elementId of the asset to inspect (e.g. 'Pump_101', 'Boiler_101')\"),\n includeValues: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to include live VQT (Value, Quality, Timestamp) telemetry values'),\n includeSchema: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to include the ObjectType JSON Schema definition'),\n});\n\nexport async function handleInspectAsset(\n binding: I3XClientBinding,\n args: z.infer<typeof inspectAssetSchema>,\n) {\n const { elementId, includeValues, includeSchema } = args;\n\n const asset = await binding.getObjectById(elementId);\n if (!asset) {\n const suggestions = await binding.findSuggestions(elementId);\n return {\n error: `Asset '${elementId}' not found in i3X address space.`,\n suggestions: suggestions.length > 0 ? suggestions : 'No close matches found.',\n tip: \"Use 'i3x_explore_plant_hierarchy' to list all root industrial assets.\",\n };\n }\n\n const result: Record<string, unknown> = {\n elementId: asset.elementId,\n displayName: asset.displayName || asset.elementId,\n description: asset.metadata?.description || undefined,\n typeElementId: asset.typeElementId,\n isRoot: !asset.parentId,\n };\n\n // Run sub-components, schema, and telemetry fetches concurrently for maximum speed & fault-tolerance\n const relatedPromise = binding.getRelatedObjects(elementId);\n const schemaPromise =\n includeSchema && asset.typeElementId\n ? binding.getObjectTypes()\n : Promise.resolve(null);\n const valuesPromise = includeValues\n ? binding.getObjectValues([elementId])\n : Promise.resolve(null);\n\n const [relatedResult, schemaResult, valuesResult] = await Promise.allSettled([\n relatedPromise,\n schemaPromise,\n valuesPromise,\n ]);\n\n // Sub-components\n if (\n relatedResult.status === 'fulfilled' &&\n Array.isArray(relatedResult.value) &&\n relatedResult.value.length > 0\n ) {\n result.subComponents = relatedResult.value.map((r) => ({\n elementId: r.elementId,\n displayName: r.displayName || r.elementId,\n typeElementId: r.typeElementId,\n }));\n }\n\n // Schema definition\n if (schemaResult.status === 'fulfilled' && Array.isArray(schemaResult.value)) {\n const targetType = schemaResult.value.find(\n (t) => t.elementId === asset.typeElementId,\n );\n if (targetType) {\n result.typeDefinition = {\n elementId: targetType.elementId,\n displayName: targetType.displayName,\n schema: targetType.schema,\n };\n }\n }\n\n // Current telemetry values\n if (\n valuesResult.status === 'fulfilled' &&\n Array.isArray(valuesResult.value) &&\n valuesResult.value.length > 0\n ) {\n result.currentValues = valuesResult.value[0];\n } else if (valuesResult.status === 'rejected') {\n result.currentValuesWarning = 'Telemetry data temporarily unavailable';\n }\n\n return result;\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const monitorEventsSchema = z.object({\n elementIds: z\n .array(z.string())\n .min(1)\n .describe(\"Array of asset elementIds to monitor (e.g. ['Boiler_101', 'Pump_101'])\"),\n condition: z\n .string()\n .optional()\n .describe(\n \"Optional monitoring alert condition filter (e.g. 'temperature > 85 || quality != Good')\",\n ),\n});\n\nexport async function handleMonitorEvents(\n binding: I3XClientBinding,\n args: z.infer<typeof monitorEventsSchema>,\n) {\n const { elementIds, condition } = args;\n\n // Snapshot current state first\n const currentValues = await binding.getObjectValues(elementIds);\n\n return {\n status: 'monitoring_active',\n monitoredAssets: elementIds,\n alertCondition: condition || 'All value or quality changes',\n initialSnapshot: currentValues,\n instructions:\n 'Subscription stream registered. The MCP server will emit notification events on matching VQT telemetry updates or threshold breaches.',\n };\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const queryTelemetrySchema = z.object({\n elementIds: z\n .array(z.string())\n .min(1)\n .describe(\"Array of asset elementIds to query (e.g. ['Pump_101', 'Boiler_101'])\"),\n mode: z\n .enum(['current', 'history'])\n .optional()\n .default('current')\n .describe(\n \"Query mode: 'current' for live VQT telemetry, 'history' for time-series trend analysis\",\n ),\n startTime: z\n .string()\n .optional()\n .describe(\n \"ISO 8601 start time or relative time string (e.g. '-2h', '-30m', '-1d') for history mode\",\n ),\n endTime: z\n .string()\n .optional()\n .describe('ISO 8601 end time (defaults to now) for history mode'),\n aggregateStats: z\n .boolean()\n .optional()\n .default(true)\n .describe(\n 'Whether to pre-compute min/max/mean statistical summaries for numeric sensor streams',\n ),\n});\n\nfunction parseStartTime(input?: string): string {\n if (!input) {\n const d = new Date();\n d.setHours(d.getHours() - 1);\n return d.toISOString();\n }\n\n const match = input.match(/^-(\\d+)([smhdw])$/i);\n if (match) {\n const amount = parseInt(match[1]!, 10);\n const unit = match[2]!.toLowerCase();\n const d = new Date();\n\n switch (unit) {\n case 's':\n d.setSeconds(d.getSeconds() - amount);\n break;\n case 'm':\n d.setMinutes(d.getMinutes() - amount);\n break;\n case 'h':\n d.setHours(d.getHours() - amount);\n break;\n case 'd':\n d.setDate(d.getDate() - amount);\n break;\n case 'w':\n d.setDate(d.getDate() - amount * 7);\n break;\n }\n return d.toISOString();\n }\n\n // Fallback to standard ISO Date parsing\n const parsed = new Date(input);\n if (Number.isNaN(parsed.getTime())) {\n const defaultDate = new Date();\n defaultDate.setHours(defaultDate.getHours() - 1);\n return defaultDate.toISOString();\n }\n\n return parsed.toISOString();\n}\n\nexport async function handleQueryTelemetry(\n binding: I3XClientBinding,\n args: z.infer<typeof queryTelemetrySchema>,\n) {\n const { elementIds, mode, aggregateStats } = args;\n\n if (mode === 'current') {\n const values = await binding.getObjectValues(elementIds);\n return {\n mode: 'current',\n telemetry: values,\n };\n }\n\n // History mode\n const startTime = parseStartTime(args.startTime);\n const endTimeDate = args.endTime ? new Date(args.endTime) : new Date();\n const endTime = Number.isNaN(endTimeDate.getTime())\n ? new Date().toISOString()\n : endTimeDate.toISOString();\n\n const history = await binding.getHistoricalValues(elementIds, startTime, endTime);\n\n if (!aggregateStats) {\n return {\n mode: 'history',\n timeRange: { startTime, endTime },\n history,\n };\n }\n\n // Calculate pre-computed statistical aggregates\n const reports = history.map((record, idx) => {\n const elementId = elementIds[idx] || `element_${idx}`;\n const report: Record<string, unknown> = {\n elementId,\n timeRange: { startTime, endTime },\n dataPoints: record.values || [],\n };\n\n const numericValues: number[] = [];\n let badQualityCount = 0;\n\n for (const v of record.values || []) {\n if (v.quality && String(v.quality).toUpperCase() !== 'GOOD') {\n badQualityCount++;\n }\n if (typeof v.value === 'number' && !Number.isNaN(v.value)) {\n numericValues.push(v.value);\n }\n }\n\n if (numericValues.length > 0) {\n const min = Math.min(...numericValues);\n const max = Math.max(...numericValues);\n const sum = numericValues.reduce((a, b) => a + b, 0);\n const mean = Math.round((sum / numericValues.length) * 100) / 100;\n\n report.statistics = {\n min,\n max,\n mean,\n count: numericValues.length,\n badQualityCount,\n };\n } else {\n report.statistics = {\n count: (record.values || []).length,\n badQualityCount,\n };\n }\n\n return report;\n });\n\n return {\n mode: 'history',\n timeRange: { startTime, endTime },\n telemetryReports: reports,\n };\n}\n","#!/usr/bin/env node\nimport { RestClientBinding } from './bindings/rest-binding.js';\nimport { NodeI3xMcpServer } from './server.js';\n\nconst args = process.argv.slice(2);\n\n// Check flags\nif (args.includes('--help') || args.includes('-h')) {\n console.error(`\nUsage: node-i3x-mcp [options]\n\nModel Context Protocol (MCP) server for industrial automation (i3X & OPC UA).\n\nOptions:\n --url <url> Target i3X Gateway REST URL (default: http://localhost:3000)\n --token <token> Optional Bearer authentication token\n --help, -h Show this help message\n --version, -v Show version number\n\nEnvironment Variables:\n I3X_SERVER_URL Target i3X Gateway REST URL (alias: I3X_BASE_URL)\n I3X_AUTH_TOKEN Optional Bearer authentication token\n`);\n process.exit(0);\n}\n\nif (args.includes('--version') || args.includes('-v')) {\n console.error('0.10.0');\n process.exit(0);\n}\n\nfunction getArgValue(flag: string): string | undefined {\n const idx = args.indexOf(flag);\n if (idx !== -1 && idx + 1 < args.length) {\n return args[idx + 1];\n }\n return undefined;\n}\n\nconst targetUrl =\n getArgValue('--url') ||\n process.env.I3X_SERVER_URL ||\n process.env.I3X_BASE_URL ||\n 'http://localhost:3000';\n\nconst authToken = getArgValue('--token') || process.env.I3X_AUTH_TOKEN;\n\nconst binding = new RestClientBinding(targetUrl, authToken);\nconst mcpServer = new NodeI3xMcpServer(binding);\n\n// Handle graceful termination\nprocess.on('SIGINT', () => process.exit(0));\nprocess.on('SIGTERM', () => process.exit(0));\n\nmcpServer.startStdio().catch((err) => {\n console.error('Fatal error starting @node-i3x/mcp server:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["args","authToken","z","binding","args","z","binding","args","z","binding","args","z","binding","args","z","binding","args","binding"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/utils/similarity.ts","../src/bindings/rest-binding.ts","../src/server.ts","../src/tools/connect.ts","../src/tools/discover-types.ts","../src/tools/explore-hierarchy.ts","../src/utils/relationships.ts","../src/tools/inspect-asset.ts","../src/tools/monitor-events.ts","../src/utils/element-ids.ts","../src/tools/query-telemetry.ts","../src/utils/output-limit.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from 'node:module';\nimport { RestClientBinding } from './bindings/rest-binding.js';\nimport { NodeI3xMcpServer } from './server.js';\n\nconst args = process.argv.slice(2);\n\n// Check flags\nif (args.includes('--help') || args.includes('-h')) {\n console.error(`\nUsage: node-i3x-mcp [options]\n\nModel Context Protocol (MCP) server for industrial automation (i3X & OPC UA).\n\nOptions:\n --url <url> Target i3X Gateway REST URL (default: http://localhost:3000)\n --token <token> Optional Bearer authentication token\n --help, -h Show this help message\n --version, -v Show version number\n\nEnvironment Variables:\n I3X_SERVER_URL Target i3X Gateway REST URL (alias: I3X_BASE_URL)\n I3X_AUTH_TOKEN Optional Bearer authentication token\n`);\n process.exit(0);\n}\n\nif (args.includes('--version') || args.includes('-v')) {\n const { version } = createRequire(import.meta.url)('../package.json') as {\n version: string;\n };\n console.log(version);\n process.exit(0);\n}\n\nfunction getArgValue(flag: string): string | undefined {\n const idx = args.indexOf(flag);\n if (idx !== -1 && idx + 1 < args.length) {\n return args[idx + 1];\n }\n return undefined;\n}\n\nconst targetUrl =\n getArgValue('--url') ||\n process.env.I3X_SERVER_URL ||\n process.env.I3X_BASE_URL ||\n 'http://localhost:3000';\n\nconst authToken = getArgValue('--token') || process.env.I3X_AUTH_TOKEN;\n\nconst binding = new RestClientBinding(targetUrl, authToken);\nconst mcpServer = new NodeI3xMcpServer(binding);\n\n// Handle graceful termination\nprocess.on('SIGINT', () => process.exit(0));\nprocess.on('SIGTERM', () => process.exit(0));\n\nmcpServer.startStdio().catch((err) => {\n console.error('Fatal error starting @node-i3x/mcp server:', err);\n process.exit(1);\n});\n","/**\n * Computes a normalized similarity score between two strings (0.0 to 1.0)\n * using Levenshtein edit distance and substring matching.\n */\nexport function computeSimilarity(a: string, b: string): number {\n const s1 = a.toLowerCase().trim();\n const s2 = b.toLowerCase().trim();\n\n if (s1 === s2) return 1.0;\n if (!s1 || !s2) return 0.0;\n\n // Exact substring boost\n if (s1.includes(s2) || s2.includes(s1)) {\n const ratio = Math.min(s1.length, s2.length) / Math.max(s1.length, s2.length);\n return Math.max(0.7, ratio);\n }\n\n // Levenshtein distance calculation\n const m = s1.length;\n const n = s2.length;\n const dp: number[] = Array.from({ length: n + 1 }, (_, i) => i);\n\n for (let i = 1; i <= m; i++) {\n let prev = dp[0]!;\n dp[0] = i;\n for (let j = 1; j <= n; j++) {\n const temp = dp[j]!;\n const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;\n dp[j] = Math.min(dp[j]! + 1, dp[j - 1]! + 1, prev + cost);\n prev = temp;\n }\n }\n\n const distance = dp[n]!;\n const maxLen = Math.max(m, n);\n return Math.max(0, 1 - distance / maxLen);\n}\n\n/**\n * Ranks candidate strings by similarity against a target query,\n * returning the top N matches with score >= minScore.\n */\nexport function rankSuggestions(\n query: string,\n candidates: string[],\n topN = 5,\n minScore = 0.4,\n): string[] {\n return candidates\n .map((candidate) => ({\n candidate,\n score: computeSimilarity(query, candidate),\n }))\n .filter((item) => item.score >= minScore)\n .sort((a, b) => b.score - a.score)\n .slice(0, topN)\n .map((item) => item.candidate);\n}\n\n/** Longer queries are not ids or names someone typed: no fuzzy matching (O(n·m) each). */\nexport const MAX_FUZZY_QUERY_LENGTH = 128;\n\n/**\n * computeSimilarity, or 0 without running Levenshtein when the length difference\n * alone keeps the score under `minScore` (distance >= |m - n|) and neither string\n * contains the other.\n */\nfunction boundedSimilarity(query: string, candidate: string, minScore: number): number {\n const q = query.toLowerCase().trim();\n const c = candidate.toLowerCase().trim();\n if (!q || !c) return 0;\n if (q.includes(c) || c.includes(q)) return computeSimilarity(q, c);\n const lengthBound = 1 - Math.abs(q.length - c.length) / Math.max(q.length, c.length);\n return lengthBound < minScore ? 0 : computeSimilarity(q, c);\n}\n\n/**\n * Ranks objects against a query by the better of their elementId and displayName\n * scores: elementIds are often opaque hashes, so names are what users type.\n */\nexport function rankObjectSuggestions(\n query: string,\n objects: ReadonlyArray<{ elementId: string; displayName?: string }>,\n topN = 5,\n minScore = 0.4,\n): Array<{ elementId: string; displayName?: string }> {\n if (query.trim().length > MAX_FUZZY_QUERY_LENGTH) return [];\n return objects\n .map(({ elementId, displayName }) => ({\n elementId,\n displayName,\n score: Math.max(\n boundedSimilarity(query, elementId, minScore),\n displayName ? boundedSimilarity(query, displayName, minScore) : 0,\n ),\n }))\n .filter((item) => item.score >= minScore)\n .sort((a, b) => b.score - a.score)\n .slice(0, topN)\n .map(({ elementId, displayName }) => ({ elementId, displayName }));\n}\n","import type {\n BulkResponse,\n BulkResultItem,\n CurrentValueResult,\n HistoricalValueResult,\n Namespace,\n ObjectInstanceResponse,\n ObjectType,\n RelatedObjectResult,\n RelationshipType,\n ServerInfo,\n SuccessResponse,\n} from '@node-i3x/core';\nimport { MAX_FUZZY_QUERY_LENGTH, rankObjectSuggestions } from '../utils/similarity.js';\nimport type { ElementResult, I3XClientBinding, Suggestion } from './types.js';\n\n/** How long the full object list used for suggestions is reused. */\nconst OBJECT_CACHE_TTL_MS = 60_000;\n\nexport class RestClientBinding implements I3XClientBinding {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly requestTimeoutMs: number;\n private readonly fetchImpl?: typeof fetch;\n private readonly token?: string;\n private objectCache?: { at: number; objects: Promise<ObjectInstanceResponse[]> };\n\n /**\n * @param fetchImpl - replaces the global fetch, e.g. to route requests into an\n * in-process server (see InProcessConnectorBinding).\n */\n constructor(\n baseUrl = 'http://localhost:3000',\n token?: string,\n timeoutMs = 15_000,\n fetchImpl?: typeof fetch,\n ) {\n let cleanUrl = baseUrl.trim().replace(/\\/+$/, '');\n if (!cleanUrl.startsWith('http://') && !cleanUrl.startsWith('https://')) {\n cleanUrl = `http://${cleanUrl}`;\n }\n // i3X base URLs are usually given with the /v1 suffix; every path below adds it.\n cleanUrl = cleanUrl.replace(/\\/v1$/i, '');\n this.baseUrl = cleanUrl;\n this.requestTimeoutMs = timeoutMs;\n this.fetchImpl = fetchImpl;\n this.token = token;\n this.headers = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n if (token) {\n this.headers.Authorization = `Bearer ${token}`;\n }\n }\n\n /** Normalized base URL, without a trailing /v1. */\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n get hasToken(): boolean {\n return Boolean(this.token);\n }\n\n /**\n * A binding to `baseUrl`. Without `token`, the current token is kept when the URL\n * is this binding's own (re-connecting must not silently drop the configured token).\n */\n connectTo(baseUrl: string, token?: string): RestClientBinding {\n // No fetchImpl: a connect targets the network, even from an in-process binding.\n const next = new RestClientBinding(baseUrl, token, this.requestTimeoutMs);\n if (token !== undefined || next.baseUrl !== this.baseUrl || !this.token) return next;\n return new RestClientBinding(baseUrl, this.token, this.requestTimeoutMs);\n }\n\n private async request<T>(path: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const signal = options.signal || AbortSignal.timeout(this.requestTimeoutMs);\n\n try {\n const response = await (this.fetchImpl ?? fetch)(url, {\n ...options,\n signal,\n headers: {\n ...this.headers,\n ...(options.headers || {}),\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n const truncated =\n errorText.length > 300 ? `${errorText.slice(0, 300)}...` : errorText;\n throw new Error(`HTTP ${response.status} from ${path}: ${truncated}`);\n }\n\n return (await response.json()) as T;\n } catch (err) {\n if ((err as Error).name === 'TimeoutError') {\n throw new Error(\n `i3X Gateway request timed out after ${this.requestTimeoutMs}ms for ${path}`,\n );\n }\n throw err;\n }\n }\n\n /** Unwrap a `{ success, result }` envelope; a `success: false` envelope becomes an error. */\n private async get<T>(path: string): Promise<T> {\n const res = await this.request<Partial<SuccessResponse<T>> & ErrorEnvelope>(path);\n if (res?.success !== true || !('result' in res)) {\n throw new Error(`i3X request ${path} failed: ${describeFailure(res)}`);\n }\n return res.result as T;\n }\n\n /**\n * POST a bulk request and return its `results` items, one per requested elementId.\n * `success` is false on the envelope as soon as one item failed, so items are\n * returned as they are; only a body without `results` is an error here.\n */\n private async postBulk<T>(path: string, body: unknown): Promise<BulkResultItem<T>[]> {\n const res = await this.request<Partial<BulkResponse<T>> & ErrorEnvelope>(path, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n if (!Array.isArray(res?.results)) {\n throw new Error(`i3X request ${path} failed: ${describeFailure(res)}`);\n }\n return res.results;\n }\n\n /** Bulk items as per-element results: a failed item keeps its elementId and error. */\n private async postBulkPerElement<T>(\n path: string,\n elementIds: string[],\n body: Record<string, unknown>,\n ): Promise<ElementResult<T>[]> {\n const items = await this.postBulk<T>(path, { elementIds, ...body });\n return items.map((item, idx) => {\n const elementId = item.elementId ?? elementIds[idx] ?? `element_${idx}`;\n if (!item.success) return { elementId, error: describeFailure(item) };\n // A success without a result would otherwise read as \"no data\" with no warning.\n if (item.result == null) return { elementId, error: 'Server returned no result' };\n return { elementId, result: item.result as T };\n });\n }\n\n /** The single item of a one-element bulk request. */\n private async postBulkOne<T>(\n path: string,\n body: { elementIds: [string] } & Record<string, unknown>,\n ): Promise<BulkResultItem<T>> {\n const [item] = await this.postBulk<T>(path, body);\n if (!item) throw new Error(`i3X request ${path} returned no result`);\n return item;\n }\n\n async getInfo(): Promise<ServerInfo> {\n return this.get<ServerInfo>('/v1/info');\n }\n\n async getNamespaces(): Promise<Namespace[]> {\n return this.get<Namespace[]>('/v1/namespaces');\n }\n\n async getObjectTypes(namespaceUri?: string): Promise<ObjectType[]> {\n const query = namespaceUri ? `?namespaceUri=${encodeURIComponent(namespaceUri)}` : '';\n return this.get<ObjectType[]>(`/v1/objecttypes${query}`);\n }\n\n async getRelationshipTypes(): Promise<RelationshipType[]> {\n return this.get<RelationshipType[]>('/v1/relationshiptypes');\n }\n\n async getObjects(options?: {\n rootOnly?: boolean;\n typeElementId?: string;\n }): Promise<ObjectInstanceResponse[]> {\n const params = new URLSearchParams();\n if (options?.rootOnly) params.set('root', 'true');\n if (options?.typeElementId) params.set('typeElementId', options.typeElementId);\n\n const query = params.toString() ? `?${params.toString()}` : '';\n return this.get<ObjectInstanceResponse[]>(`/v1/objects${query}`);\n }\n\n /** `null` only when the server reports the element as not found (404). */\n async getObjectById(elementId: string): Promise<ObjectInstanceResponse | null> {\n const path = '/v1/objects/list';\n const item = await this.postBulkOne<ObjectInstanceResponse>(path, {\n elementIds: [elementId],\n });\n if (item.success) return item.result ?? null;\n if (item.responseDetail?.status === 404) return null;\n throw new Error(\n `i3X request ${path} failed for '${elementId}': ${describeFailure(item)}`,\n );\n }\n\n async getRelatedObjects(\n elementId: string,\n relationshipType?: string,\n ): Promise<RelatedObjectResult[]> {\n const path = '/v1/objects/related';\n const body: { elementIds: [string] } & Record<string, unknown> = {\n elementIds: [elementId],\n };\n if (relationshipType) body.relationshipType = relationshipType;\n\n const item = await this.postBulkOne<RelatedObjectResult[]>(path, body);\n if (!item.success) {\n throw new Error(\n `i3X request ${path} failed for '${elementId}': ${describeFailure(item)}`,\n );\n }\n // Servers may ignore relationshipType, so filter here as well.\n return (item.result ?? []).filter(\n (r) => !relationshipType || r.sourceRelationship === relationshipType,\n );\n }\n\n async getRelatedObjectsBulk(\n elementIds: string[],\n ): Promise<ElementResult<RelatedObjectResult[]>[]> {\n return this.postBulkPerElement<RelatedObjectResult[]>(\n '/v1/objects/related',\n elementIds,\n {},\n );\n }\n\n async getObjectValues(\n elementIds: string[],\n maxDepth = 1,\n ): Promise<ElementResult<CurrentValueResult>[]> {\n return this.postBulkPerElement<CurrentValueResult>('/v1/objects/value', elementIds, {\n maxDepth,\n });\n }\n\n async getHistoricalValues(\n elementIds: string[],\n startTime: string,\n endTime: string,\n maxDepth = 1,\n ): Promise<ElementResult<HistoricalValueResult>[]> {\n return this.postBulkPerElement<HistoricalValueResult>(\n '/v1/objects/history',\n elementIds,\n { startTime, endTime, maxDepth },\n );\n }\n\n /** Closest objects by elementId or displayName; a failure to list objects propagates. */\n async findSuggestions(query: string): Promise<Suggestion[]> {\n if (query.trim().length > MAX_FUZZY_QUERY_LENGTH) return [];\n const now = Date.now();\n if (!this.objectCache || now - this.objectCache.at > OBJECT_CACHE_TTL_MS) {\n const objects = this.getObjects();\n this.objectCache = { at: now, objects };\n objects.catch(() => {\n if (this.objectCache?.objects === objects) this.objectCache = undefined;\n });\n }\n return rankObjectSuggestions(query, await this.objectCache.objects);\n }\n}\n\ninterface ErrorEnvelope {\n success?: boolean;\n responseDetail?: { title?: string; status?: number; detail?: string } | null;\n}\n\nfunction describeFailure(res: ErrorEnvelope | null | undefined): string {\n const d = res?.responseDetail;\n if (d) return [d.status, d.title, d.detail].filter(Boolean).join(' ');\n return `unexpected response ${JSON.stringify(res)?.slice(0, 200)}`;\n}\n","import { createRequire } from 'node:module';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { RestClientBinding } from './bindings/rest-binding.js';\nimport type { I3XClientBinding } from './bindings/types.js';\nimport { connectSchema, handleConnect } from './tools/connect.js';\nimport { discoverTypesSchema, handleDiscoverTypes } from './tools/discover-types.js';\nimport {\n exploreHierarchySchema,\n handleExploreHierarchy,\n} from './tools/explore-hierarchy.js';\nimport { handleInspectAsset, inspectAssetSchema } from './tools/inspect-asset.js';\nimport { handleMonitorEvents, monitorEventsSchema } from './tools/monitor-events.js';\nimport { handleQueryTelemetry, queryTelemetrySchema } from './tools/query-telemetry.js';\nimport { DEFAULT_MAX_RESULT_CHARS, serializeToolResult } from './utils/output-limit.js';\n\nconst { version } = createRequire(import.meta.url)('../package.json') as {\n version: string;\n};\n\nexport class NodeI3xMcpServer {\n private readonly server: Server;\n private binding: I3XClientBinding;\n\n private readonly maxResultChars: number;\n\n /**\n * @param options.maxResultChars - cap on a serialized tool result (default\n * I3X_MCP_MAX_RESULT_CHARS, else 100 000 characters).\n */\n constructor(binding?: I3XClientBinding, options: { maxResultChars?: number } = {}) {\n this.binding = binding || new RestClientBinding();\n this.maxResultChars =\n options.maxResultChars ??\n (Number(process.env.I3X_MCP_MAX_RESULT_CHARS) || DEFAULT_MAX_RESULT_CHARS);\n\n this.server = new Server(\n {\n name: '@node-i3x/mcp',\n version,\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n },\n },\n );\n\n this.setupHandlers();\n }\n\n public setBinding(binding: I3XClientBinding): void {\n this.binding = binding;\n }\n\n public getBinding(): I3XClientBinding {\n return this.binding;\n }\n\n private setupHandlers() {\n // List Available MCP Tools\n this.server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'i3x_connect',\n description:\n 'Connect or switch dynamically to a specific i3X server endpoint URL and optional Bearer token at runtime.',\n inputSchema: {\n type: 'object',\n properties: {\n serverUrl: {\n type: 'string',\n description:\n \"Target i3X Gateway REST endpoint URL (e.g. 'http://192.168.1.50:8000' or 'https://i3x-portal.sterfive.io/instance/SESSION_ID')\",\n },\n authToken: {\n type: 'string',\n description:\n 'Optional Bearer authentication token. Omit it to keep the current token when re-connecting to the same URL.',\n },\n verifyConnection: {\n type: 'boolean',\n description:\n 'Whether to verify connectivity and credentials before switching (default: true); a rejected token returns status auth_failed',\n },\n },\n required: ['serverUrl'],\n },\n },\n {\n name: 'i3x_inspect_asset',\n description:\n 'Single-turn complete asset diagnostic. Returns identity, ObjectType schema, parent/child hierarchy, and live VQT telemetry in 1 call.',\n inputSchema: {\n type: 'object',\n properties: {\n elementId: {\n type: 'string',\n description:\n \"The elementId of the asset to inspect (e.g. 'Pump_101', 'Boiler_101')\",\n },\n includeValues: {\n type: 'boolean',\n description:\n 'Whether to include live VQT telemetry values (default: true)',\n },\n includeSchema: {\n type: 'boolean',\n description:\n 'Whether to include the ObjectType JSON Schema definition (default: true)',\n },\n maxDepth: {\n type: 'number',\n description:\n 'Value read depth through components: 1 = the element only, 2 = with its components (default), 0 = unlimited',\n },\n },\n required: ['elementId'],\n },\n },\n {\n name: 'i3x_explore_plant_hierarchy',\n description:\n 'ISA-95 plant topology discovery. Traverses plant hierarchy from root assets down to child components up to maxDepth.',\n inputSchema: {\n type: 'object',\n properties: {\n rootElementId: {\n type: 'string',\n description:\n 'Optional specific root asset elementId. If omitted, explores all root assets.',\n },\n maxDepth: {\n type: 'number',\n description:\n 'Levels to show: 1 = roots only, 2 = roots and their children (default), 0 = unlimited (bounded by maxNodes)',\n },\n maxNodes: {\n type: 'number',\n description:\n 'Node budget for the whole tree (default 500, max 5000); the result is marked truncated when reached',\n },\n },\n },\n },\n {\n name: 'i3x_query_telemetry',\n description:\n 'Live current VQT telemetry or historical time-series trend analysis with pre-computed statistical summaries (min, max, mean).',\n inputSchema: {\n type: 'object',\n properties: {\n elementIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"Array of asset elementIds to query (e.g. ['Pump_101', 'Boiler_101']); duplicates are ignored, at most 100\",\n },\n mode: {\n type: 'string',\n enum: ['current', 'history'],\n description:\n \"Query mode: 'current' for live VQT, 'history' for time-series trend analysis\",\n },\n startTime: {\n type: 'string',\n description:\n \"ISO 8601 or relative duration (e.g. '-2h', '-30m') for history mode\",\n },\n endTime: {\n type: 'string',\n description:\n \"ISO 8601 or relative duration (e.g. '-10m') end time (defaults to now) for history mode\",\n },\n maxDepth: {\n type: 'number',\n description:\n 'Value read depth through components: 1 = the element only, 2 = with its components (default), 0 = unlimited',\n },\n aggregateStats: {\n type: 'boolean',\n description:\n 'Whether to pre-compute min/max/mean statistical summaries (default: true)',\n },\n },\n required: ['elementIds'],\n },\n },\n {\n name: 'i3x_discover_types_and_schemas',\n description:\n 'Search registered i3X ObjectTypes, RelationshipTypes, and JSON Schema field validation requirements.',\n inputSchema: {\n type: 'object',\n properties: {\n typeElementId: {\n type: 'string',\n description:\n \"Optional specific ObjectType elementId (e.g. 'BoilerType'). If omitted, lists all types.\",\n },\n namespaceUri: {\n type: 'string',\n description:\n \"Optional namespaceUri filter (e.g. 'http://sterfive.com/UA/Demo/')\",\n },\n },\n },\n },\n {\n name: 'i3x_monitor_asset_events',\n description:\n 'One-shot health check of assets: current VQT values plus an alert list of every series whose quality is not Good. Does not subscribe; call again to re-check.',\n inputSchema: {\n type: 'object',\n properties: {\n elementIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Array of asset elementIds to check; duplicates are ignored, at most 100',\n },\n maxDepth: {\n type: 'number',\n description:\n 'Value read depth through components: 1 = the element only, 2 = with its components (default), 0 = unlimited',\n },\n },\n required: ['elementIds'],\n },\n },\n ],\n }));\n\n // Handle Tool Execution\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: rawArgs } = request.params;\n\n try {\n let result: unknown;\n\n switch (name) {\n case 'i3x_connect': {\n const parsed = connectSchema.parse(rawArgs);\n result = await handleConnect(\n parsed,\n (newBinding) => {\n this.binding = newBinding;\n },\n this.binding,\n );\n break;\n }\n case 'i3x_inspect_asset': {\n const parsed = inspectAssetSchema.parse(rawArgs);\n result = await handleInspectAsset(this.binding, parsed);\n break;\n }\n case 'i3x_explore_plant_hierarchy': {\n const parsed = exploreHierarchySchema.parse(rawArgs);\n result = await handleExploreHierarchy(this.binding, parsed);\n break;\n }\n case 'i3x_query_telemetry': {\n const parsed = queryTelemetrySchema.parse(rawArgs);\n result = await handleQueryTelemetry(this.binding, parsed);\n break;\n }\n case 'i3x_discover_types_and_schemas': {\n const parsed = discoverTypesSchema.parse(rawArgs);\n result = await handleDiscoverTypes(this.binding, parsed);\n break;\n }\n case 'i3x_monitor_asset_events': {\n const parsed = monitorEventsSchema.parse(rawArgs);\n result = await handleMonitorEvents(this.binding, parsed);\n break;\n }\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: serializeToolResult(name, result, this.maxResultChars),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n error: (err as Error).message,\n tip: \"Check parameters or use 'i3x_explore_plant_hierarchy' to list available assets.\",\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n });\n\n // List Resources (i3x://info, i3x://namespaces)\n this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: [\n {\n uri: 'i3x://info',\n name: 'i3X Server Metadata',\n description: 'Server capabilities, spec version, and vendor information',\n mimeType: 'application/json',\n },\n {\n uri: 'i3x://namespaces',\n name: 'Registered Namespaces',\n description: 'List of registered OPC UA / i3X namespace URIs',\n mimeType: 'application/json',\n },\n ],\n }));\n\n // Read Resource\n this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const { uri } = request.params;\n\n if (uri === 'i3x://info') {\n const info = await this.binding.getInfo();\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(info, null, 2),\n },\n ],\n };\n }\n\n if (uri === 'i3x://namespaces') {\n const namespaces = await this.binding.getNamespaces();\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(namespaces, null, 2),\n },\n ],\n };\n }\n\n throw new Error(`Unknown resource URI: ${uri}`);\n });\n }\n\n async startStdio() {\n const transport = new StdioServerTransport();\n await this.server.connect(transport);\n }\n}\n","import { z } from 'zod';\nimport { RestClientBinding } from '../bindings/rest-binding.js';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const connectSchema = z.object({\n serverUrl: z\n .string()\n .describe(\n \"The base URL of the i3X Gateway (e.g. 'http://192.168.1.50:8000' or 'https://i3x-portal.sterfive.io/instance/SESSION_ID')\",\n ),\n authToken: z\n .string()\n .optional()\n .describe(\n 'Optional Bearer authentication token. Omitted when re-connecting to the current URL: the current token is kept.',\n ),\n verifyConnection: z\n .boolean()\n .optional()\n .default(true)\n .describe(\n 'Whether to verify connectivity and credentials before switching (reads /v1/info and /v1/namespaces)',\n ),\n});\n\nexport async function handleConnect(\n args: z.infer<typeof connectSchema>,\n onBindingSwitch: (newBinding: I3XClientBinding) => void,\n current?: I3XClientBinding,\n) {\n const { serverUrl, authToken, verifyConnection } = args;\n\n const newBinding =\n current instanceof RestClientBinding\n ? current.connectTo(serverUrl, authToken)\n : new RestClientBinding(serverUrl, authToken);\n const tokenKept = authToken === undefined && newBinding.hasToken;\n const url = newBinding.getBaseUrl();\n\n let serverInfo: unknown;\n if (verifyConnection) {\n try {\n serverInfo = await newBinding.getInfo();\n } catch (err) {\n return {\n status: 'connection_failed',\n serverUrl: url,\n error: (err as Error).message,\n tip: 'Please check that the server URL is reachable.',\n };\n }\n // /v1/info is public on secured servers, so it proves nothing about the token:\n // check credentials on an endpoint that requires them.\n try {\n await newBinding.getNamespaces();\n } catch (err) {\n const message = (err as Error).message;\n if (/^HTTP 40[13]\\b/.test(message)) {\n return {\n status: 'auth_failed',\n serverUrl: url,\n error: message,\n tip: 'The server rejected the credentials. Pass a valid authToken; the previous connection is still active.',\n };\n }\n return {\n status: 'connection_failed',\n serverUrl: url,\n error: message,\n tip: 'The server answered /v1/info but not /v1/namespaces; the previous connection is still active.',\n };\n }\n }\n\n // Switch the active binding on the MCP server\n onBindingSwitch(newBinding);\n\n return {\n status: 'connected',\n serverUrl: url,\n authenticated: newBinding.hasToken,\n ...(tokenKept\n ? { note: 'No authToken given: kept the token already in use for this URL.' }\n : {}),\n serverInfo: serverInfo || 'Connection established without verification.',\n message: `Successfully connected to ${url}. All subsequent i3X tool calls will query this endpoint.`,\n };\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\n\nexport const discoverTypesSchema = z.object({\n typeElementId: z\n .string()\n .optional()\n .describe(\n \"Optional specific ObjectType elementId (e.g. 'BoilerType'). If omitted, lists all types.\",\n ),\n namespaceUri: z\n .string()\n .optional()\n .describe(\"Optional namespaceUri filter (e.g. 'http://sterfive.com/UA/Demo/')\"),\n});\n\nexport async function handleDiscoverTypes(\n binding: I3XClientBinding,\n args: z.infer<typeof discoverTypesSchema>,\n) {\n const { typeElementId, namespaceUri } = args;\n\n const [objectTypes, relationshipTypes, namespaces] = await Promise.all([\n binding.getObjectTypes(namespaceUri),\n binding.getRelationshipTypes(),\n binding.getNamespaces(),\n ]);\n\n if (typeElementId) {\n const matched = objectTypes.find((t) => t.elementId === typeElementId);\n if (!matched) {\n return {\n error: `ObjectType '${typeElementId}' not found.`,\n availableTypes: objectTypes.map((t) => t.elementId),\n };\n }\n return {\n objectType: matched,\n };\n }\n\n return {\n namespacesCount: namespaces.length,\n namespaces,\n objectTypesCount: objectTypes.length,\n objectTypes: objectTypes.map((t) => {\n const schemaObj =\n t.schema && typeof t.schema === 'object'\n ? (t.schema as Record<string, unknown>)\n : null;\n const required =\n schemaObj && Array.isArray(schemaObj.required)\n ? (schemaObj.required as string[])\n : [];\n\n return {\n elementId: t.elementId,\n displayName: t.displayName || t.elementId,\n namespaceUri: t.namespaceUri,\n requiredProperties: required,\n };\n }),\n relationshipTypesCount: relationshipTypes.length,\n relationshipTypes,\n };\n}\n","import { z } from 'zod';\nimport type { HierarchyNode, I3XClientBinding } from '../bindings/types.js';\nimport { isParentRelationship } from '../utils/relationships.js';\n\n/** elementIds per /objects/related request: bounds body size and server work per call. */\nconst RELATED_BATCH_SIZE = 100;\n/** Concurrent /objects/related requests while expanding one level. */\nconst RELATED_CONCURRENCY = 4;\n\nexport const exploreHierarchySchema = z.object({\n rootElementId: z\n .string()\n .optional()\n .describe(\n 'Optional specific root asset elementId. If omitted, explores all root assets.',\n ),\n maxDepth: z\n .number()\n .int()\n .min(0)\n .optional()\n .default(2)\n .describe(\n 'Levels to show: 1 = roots only, 2 = roots and their children (default), 0 = unlimited (bounded by maxNodes)',\n ),\n maxNodes: z\n .number()\n .int()\n .min(1)\n .max(5000)\n .optional()\n .default(500)\n .describe(\n 'Node budget for the whole tree (default 500, max 5000); the tree is marked truncated when reached',\n ),\n});\n\ntype Asset = { elementId: string; displayName?: string; typeElementId?: string };\n\nexport async function handleExploreHierarchy(\n binding: I3XClientBinding,\n args: z.infer<typeof exploreHierarchySchema>,\n) {\n const maxDepth = args.maxDepth ?? 2;\n const maxNodes = args.maxNodes ?? 500;\n\n let roots: Asset[];\n if (args.rootElementId) {\n const root = await binding.getObjectById(args.rootElementId);\n if (!root) {\n const suggestions = await binding.findSuggestions(args.rootElementId);\n return {\n error: `Root asset '${args.rootElementId}' not found.`,\n suggestions,\n };\n }\n roots = [root];\n } else {\n roots = await binding.getObjects({ rootOnly: true });\n }\n\n const toNode = (asset: Asset): HierarchyNode => ({\n elementId: asset.elementId,\n displayName: asset.displayName || asset.elementId,\n typeElementId: asset.typeElementId,\n });\n\n // Breadth-first, one bulk /objects/related call per batch of a level, instead of\n // one call per node: per-node fan-out timed out on large address spaces.\n let nodeCount = 0;\n let truncated = false;\n const expanded = new Set<string>();\n const tree: HierarchyNode[] = [];\n for (const root of roots) {\n if (nodeCount >= maxNodes) {\n truncated = true;\n break;\n }\n tree.push(toNode(root));\n nodeCount++;\n }\n\n let level = tree;\n for (let depth = 1; level.length > 0 && (maxDepth === 0 || depth < maxDepth); depth++) {\n // Expand each element once; a shared component or a cycle shows up as `repeated`.\n const toExpand: HierarchyNode[] = [];\n for (const node of level) {\n if (expanded.has(node.elementId)) node.repeated = true;\n else {\n expanded.add(node.elementId);\n toExpand.push(node);\n }\n }\n\n const related = await readRelatedInBatches(\n binding,\n toExpand.map((n) => n.elementId),\n );\n\n const next: HierarchyNode[] = [];\n toExpand.forEach((node, idx) => {\n const entry = related[idx];\n if (entry?.error) {\n node.error = entry.error;\n return;\n }\n const children = (entry?.result ?? [])\n .filter((r) => !isParentRelationship(r.sourceRelationship))\n .map((r) => r.object);\n if (children.length === 0) return;\n if (nodeCount + children.length > maxNodes) {\n truncated = true;\n node.truncated = true;\n return;\n }\n node.children = children.map(toNode);\n nodeCount += children.length;\n next.push(...node.children);\n });\n level = next;\n }\n\n return {\n totalRoots: roots.length,\n traversalDepth: maxDepth === 0 ? 'unlimited' : maxDepth,\n nodeCount,\n ...(truncated\n ? {\n truncated: {\n maxNodes,\n hint: 'Node budget reached; nodes marked truncated were not expanded. Use rootElementId on one of them, a smaller maxDepth, or a larger maxNodes.',\n },\n }\n : {}),\n plantTopology: tree,\n };\n}\n\nasync function readRelatedInBatches(binding: I3XClientBinding, elementIds: string[]) {\n const batches: string[][] = [];\n for (let i = 0; i < elementIds.length; i += RELATED_BATCH_SIZE) {\n batches.push(elementIds.slice(i, i + RELATED_BATCH_SIZE));\n }\n const results: Awaited<ReturnType<I3XClientBinding['getRelatedObjectsBulk']>>[] =\n new Array(batches.length);\n let nextBatch = 0;\n const worker = async () => {\n while (nextBatch < batches.length) {\n const idx = nextBatch++;\n const batch = batches[idx]!;\n try {\n results[idx] = await binding.getRelatedObjectsBulk(batch);\n } catch (err) {\n // A failed request marks its own nodes only; the rest of the walk goes on.\n const error = err instanceof Error ? err.message : String(err);\n results[idx] = batch.map((elementId) => ({ elementId, error }));\n }\n }\n };\n await Promise.all(\n Array.from({ length: Math.min(RELATED_CONCURRENCY, batches.length) }, worker),\n );\n return results.flat();\n}\n","/**\n * Child-to-parent relationship names in `/objects/related` results: node-i3x's\n * IsComponentOf and the i3X spec's ComponentOf / HasParent. Everything else points\n * away from the source object.\n */\nconst PARENT_RELATIONSHIPS = new Set(['IsComponentOf', 'ComponentOf', 'HasParent']);\n\nexport function isParentRelationship(sourceRelationship: string): boolean {\n return PARENT_RELATIONSHIPS.has(sourceRelationship);\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\nimport { isParentRelationship } from '../utils/relationships.js';\n\nexport const inspectAssetSchema = z.object({\n elementId: z\n .string()\n .describe(\"The elementId of the asset to inspect (e.g. 'Pump_101', 'Boiler_101')\"),\n includeValues: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to include live VQT (Value, Quality, Timestamp) telemetry values'),\n includeSchema: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to include the ObjectType JSON Schema definition'),\n maxDepth: z\n .number()\n .int()\n .min(0)\n .optional()\n .default(2)\n .describe(\n 'Value read depth through components: 1 = the asset only (an Object usually has no value of its own), 2 = with its components (default), 0 = unlimited',\n ),\n});\n\nexport async function handleInspectAsset(\n binding: I3XClientBinding,\n args: z.infer<typeof inspectAssetSchema>,\n) {\n const { elementId, includeValues, includeSchema, maxDepth } = args;\n\n const asset = await binding.getObjectById(elementId);\n if (!asset) {\n const suggestions = await binding.findSuggestions(elementId);\n return {\n error: `Asset '${elementId}' not found in i3X address space.`,\n suggestions: suggestions.length > 0 ? suggestions : 'No close matches found.',\n tip: \"Use 'i3x_explore_plant_hierarchy' to list all root industrial assets.\",\n };\n }\n\n const result: Record<string, unknown> = {\n elementId: asset.elementId,\n displayName: asset.displayName || asset.elementId,\n description: asset.metadata?.description || undefined,\n typeElementId: asset.typeElementId,\n parentId: asset.parentId ?? null,\n isRoot: !asset.parentId,\n };\n const warnings: string[] = [];\n\n // Run sub-components, schema, and telemetry fetches concurrently for maximum speed & fault-tolerance\n const relatedPromise = binding.getRelatedObjects(elementId);\n const schemaPromise =\n includeSchema && asset.typeElementId\n ? binding.getObjectTypes()\n : Promise.resolve(null);\n const valuesPromise = includeValues\n ? binding.getObjectValues([elementId], maxDepth)\n : Promise.resolve(null);\n\n const [relatedResult, schemaResult, valuesResult] = await Promise.allSettled([\n relatedPromise,\n schemaPromise,\n valuesPromise,\n ]);\n\n // Sub-components: related objects also include the parent (a reverse relationship).\n if (relatedResult.status === 'fulfilled') {\n const subComponents = relatedResult.value.filter(\n (r) => !isParentRelationship(r.sourceRelationship),\n );\n if (subComponents.length > 0) {\n result.subComponents = subComponents.map((r) => ({\n elementId: r.object.elementId,\n displayName: r.object.displayName || r.object.elementId,\n typeElementId: r.object.typeElementId,\n relationship: r.sourceRelationship,\n }));\n }\n } else {\n warnings.push(`Sub-components unavailable: ${errorMessage(relatedResult.reason)}`);\n }\n\n // Schema definition\n if (schemaResult.status === 'fulfilled') {\n const targetType = schemaResult.value?.find(\n (t) => t.elementId === asset.typeElementId,\n );\n if (targetType) {\n result.typeDefinition = {\n elementId: targetType.elementId,\n displayName: targetType.displayName,\n schema: targetType.schema,\n };\n }\n } else {\n warnings.push(`Type schema unavailable: ${errorMessage(schemaResult.reason)}`);\n }\n\n // Current telemetry values\n if (valuesResult.status === 'fulfilled') {\n const entry = valuesResult.value?.[0];\n if (entry?.result) result.currentValues = entry.result;\n else if (entry?.error) warnings.push(`Telemetry unavailable: ${entry.error}`);\n } else {\n warnings.push(`Telemetry unavailable: ${errorMessage(valuesResult.reason)}`);\n }\n\n if (warnings.length > 0) result.warnings = warnings;\n return result;\n}\n\nfunction errorMessage(reason: unknown): string {\n return reason instanceof Error ? reason.message : String(reason);\n}\n","import { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\nimport { elementIdsSchema } from '../utils/element-ids.js';\n\n/** Alerts listed one by one; the summary still counts all of them. */\nconst MAX_LISTED_ALERTS = 50;\n\nexport const monitorEventsSchema = z.object({\n elementIds: elementIdsSchema(\n \"Array of asset elementIds to check (e.g. ['Boiler_101', 'Pump_101'])\",\n ),\n maxDepth: z\n .number()\n .int()\n .min(0)\n .optional()\n .default(2)\n .describe(\n 'Read depth through components: 1 = the element only, 2 = with its components (default), 0 = unlimited',\n ),\n});\n\n/**\n * One-shot health snapshot: current values plus every series whose quality is not Good.\n * It does not subscribe: MCP tool calls are request/response, so call it again to re-check.\n */\nexport async function handleMonitorEvents(\n binding: I3XClientBinding,\n args: z.infer<typeof monitorEventsSchema>,\n) {\n const { elementIds, maxDepth } = args;\n const snapshot = await binding.getObjectValues(elementIds, maxDepth);\n\n const alerts: Array<{ elementId: string; quality?: string; error?: string }> = [];\n for (const { elementId, result, error } of snapshot) {\n if (error) {\n alerts.push({ elementId, error });\n continue;\n }\n if (result && !isGood(result.quality)) {\n alerts.push({ elementId, quality: result.quality });\n }\n for (const [componentId, vqt] of Object.entries(result?.components ?? {})) {\n if (!isGood(vqt.quality))\n alerts.push({ elementId: componentId, quality: vqt.quality });\n }\n }\n\n const summary = {\n bad: alerts.filter((a) => a.quality && /^bad/i.test(a.quality)).length,\n uncertain: alerts.filter((a) => a.quality && /^uncertain/i.test(a.quality)).length,\n readErrors: alerts.filter((a) => a.error).length,\n };\n\n return {\n status: 'snapshot',\n checkedAt: new Date().toISOString(),\n summary,\n alerts: alerts.slice(0, MAX_LISTED_ALERTS),\n ...(alerts.length > MAX_LISTED_ALERTS\n ? { alertsOmitted: alerts.length - MAX_LISTED_ALERTS }\n : {}),\n snapshot,\n note: 'Point-in-time read; no subscription is created. Call again to re-check.',\n };\n}\n\nfunction isGood(quality: unknown): boolean {\n return String(quality).toLowerCase().startsWith('good');\n}\n","import { z } from 'zod';\n\n/** Distinct elementIds per call: bounds request size and the tool result. */\nexport const MAX_ELEMENT_IDS = 100;\n\n/** elementIds, deduplicated in order: repeated ids only multiply the output. */\nexport function elementIdsSchema(description: string) {\n return z\n .array(z.string())\n .min(1)\n .transform((ids) => [...new Set(ids)])\n .refine((ids) => ids.length <= MAX_ELEMENT_IDS, {\n message: `At most ${MAX_ELEMENT_IDS} distinct elementIds per call.`,\n })\n .describe(`${description}; duplicates are ignored, at most ${MAX_ELEMENT_IDS}`);\n}\n","import type { VQT } from '@node-i3x/core';\nimport { z } from 'zod';\nimport type { I3XClientBinding } from '../bindings/types.js';\nimport { elementIdsSchema } from '../utils/element-ids.js';\n\nexport const queryTelemetrySchema = z.object({\n elementIds: elementIdsSchema(\n \"Array of asset elementIds to query (e.g. ['Pump_101', 'Boiler_101'])\",\n ),\n mode: z\n .enum(['current', 'history'])\n .optional()\n .default('current')\n .describe(\n \"Query mode: 'current' for live VQT telemetry, 'history' for time-series trend analysis\",\n ),\n startTime: z\n .string()\n .optional()\n .describe(\n \"ISO 8601 start time or relative time string (e.g. '-2h', '-30m', '-1d') for history mode (default: -1h)\",\n ),\n endTime: z\n .string()\n .optional()\n .describe(\n \"ISO 8601 end time or relative time string (e.g. '-10m') for history mode (default: now)\",\n ),\n maxDepth: z\n .number()\n .int()\n .min(0)\n .optional()\n .default(2)\n .describe(\n 'Read depth through components: 1 = the element only, 2 = with its components (default), 0 = unlimited',\n ),\n aggregateStats: z\n .boolean()\n .optional()\n .default(true)\n .describe(\n 'Whether to pre-compute min/max/mean statistical summaries for numeric sensor streams',\n ),\n});\n\nconst RELATIVE_TIME = /^-(\\d+)([smhdw])$/i;\nconst UNIT_MS: Record<string, number> = {\n s: 1_000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\n/** ISO 8601 or relative ('-2h') time to ISO; an unparseable value is an error, not a default. */\nexport function parseTime(\n input: string | undefined,\n fallback: Date,\n name: string,\n): string {\n if (!input) return fallback.toISOString();\n\n const match = input.match(RELATIVE_TIME);\n if (match) {\n const amount = Number.parseInt(match[1]!, 10);\n return new Date(\n Date.now() - amount * UNIT_MS[match[2]!.toLowerCase()]!,\n ).toISOString();\n }\n\n const parsed = new Date(input);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(\n `Invalid ${name} '${input}': expected ISO 8601 (e.g. '2026-10-25T10:00:00Z') or a relative time (e.g. '-2h').`,\n );\n }\n return parsed.toISOString();\n}\n\nfunction describeDetail(d: { status?: number; title?: string; detail?: string }): string {\n return [d.status, d.title, d.detail].filter(Boolean).join(' ');\n}\n\n/** GoodNoData is a good status (no data in range), not a bad sample. */\nfunction isBadQuality(quality: unknown): boolean {\n return quality != null && !String(quality).toLowerCase().startsWith('good');\n}\n\nfunction seriesStatistics(values: readonly VQT[]) {\n const numericValues: number[] = [];\n let badQualityCount = 0;\n for (const v of values) {\n if (isBadQuality(v.quality)) badQualityCount++;\n if (typeof v.value === 'number' && !Number.isNaN(v.value))\n numericValues.push(v.value);\n }\n if (numericValues.length === 0) return { count: values.length, badQualityCount };\n\n const sum = numericValues.reduce((a, b) => a + b, 0);\n return {\n min: Math.min(...numericValues),\n max: Math.max(...numericValues),\n mean: Math.round((sum / numericValues.length) * 100) / 100,\n count: numericValues.length,\n badQualityCount,\n };\n}\n\nexport async function handleQueryTelemetry(\n binding: I3XClientBinding,\n args: z.infer<typeof queryTelemetrySchema>,\n) {\n const { elementIds, mode, aggregateStats, maxDepth } = args;\n\n if (mode === 'current') {\n const values = await binding.getObjectValues(elementIds, maxDepth);\n return {\n mode: 'current',\n telemetry: values,\n };\n }\n\n // History mode\n const now = new Date();\n const startTime = parseTime(\n args.startTime,\n new Date(now.getTime() - UNIT_MS.h!),\n 'startTime',\n );\n const endTime = parseTime(args.endTime, now, 'endTime');\n if (startTime > endTime) {\n throw new Error(`startTime ${startTime} is after endTime ${endTime}.`);\n }\n\n const history = await binding.getHistoricalValues(\n elementIds,\n startTime,\n endTime,\n maxDepth,\n );\n\n if (!aggregateStats) {\n return {\n mode: 'history',\n timeRange: { startTime, endTime },\n history,\n };\n }\n\n // Statistics per series: the element's own values and each component separately,\n // since mixing e.g. a temperature with a pressure is meaningless.\n const reports = history.map(({ elementId, result, error }) => {\n if (error || !result) return { elementId, error: error ?? 'No history returned' };\n\n const report: Record<string, unknown> = {\n elementId,\n dataPoints: result.values ?? [],\n statistics: seriesStatistics(result.values ?? []),\n };\n if (result.components) {\n const entries = Object.entries(result.components);\n report.components = Object.fromEntries(\n entries.map(([componentId, { values, responseDetail }]) => [\n componentId,\n // A failed component read is not an empty time range: report why.\n responseDetail\n ? { error: describeDetail(responseDetail) }\n : { dataPoints: values ?? [], statistics: seriesStatistics(values ?? []) },\n ]),\n );\n const failed = entries.filter(([, c]) => c.responseDetail);\n if (\n failed.length > 0 &&\n failed.length === entries.length &&\n !result.values?.length\n ) {\n report.note = `No component history could be read (${describeDetail(failed[0]![1].responseDetail!)}): the server keeps no history for this asset's variables.`;\n }\n }\n return report;\n });\n\n return {\n mode: 'history',\n timeRange: { startTime, endTime },\n telemetryReports: reports,\n };\n}\n","/** Default cap on a serialized tool result, in characters (I3X_MCP_MAX_RESULT_CHARS). */\nexport const DEFAULT_MAX_RESULT_CHARS = 100_000;\n\nconst NARROWING_HINTS: Record<string, string> = {\n i3x_explore_plant_hierarchy: 'pass rootElementId, or lower maxDepth or maxNodes',\n i3x_inspect_asset: 'lower maxDepth, or set includeSchema to false',\n i3x_query_telemetry: 'pass fewer elementIds, lower maxDepth, or shorten the time range',\n i3x_discover_types_and_schemas: 'pass typeElementId or namespaceUri',\n i3x_monitor_asset_events: 'pass fewer elementIds or lower maxDepth',\n};\n\n/**\n * Serialize a tool result, cutting it at `maxChars` with an explicit notice of what\n * was cut and how to narrow the query, instead of flooding the client's context.\n */\nexport function serializeToolResult(\n tool: string,\n result: unknown,\n maxChars: number,\n): string {\n const text = JSON.stringify(result, null, 2);\n if (text.length <= maxChars) return text;\n const hint = NARROWING_HINTS[tool] ?? 'narrow the query';\n return (\n `${text.slice(0, maxChars)}\\n\\n` +\n `[Result truncated: showing the first ${maxChars} of ${text.length} characters, ` +\n `so the JSON above is incomplete. To see everything, ${hint}.]`\n );\n}\n"],"mappings":"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","names":["createRequire","args","authToken","z","binding","args","z","z","binding","args","z","z","binding","args","z","z","z","binding","args","z","z","binding","args","binding","version","createRequire"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RestServerDeps } from '@node-i3x/rest-server';
|
|
2
|
+
import { RestClientBinding } from './index.js';
|
|
3
|
+
import '@node-i3x/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Binding to an i3X stack running in this process.
|
|
7
|
+
*
|
|
8
|
+
* Requests go through the real rest-server routes (Fastify `inject()`, no socket),
|
|
9
|
+
* so in-process answers are exactly what a remote node-i3x server would send:
|
|
10
|
+
* same parentId, roots, related objects, values and server info.
|
|
11
|
+
*/
|
|
12
|
+
declare class InProcessConnectorBinding extends RestClientBinding {
|
|
13
|
+
constructor(deps: RestServerDeps);
|
|
14
|
+
}
|
|
15
|
+
/** A fetch that answers from an in-process rest-server instead of the network. */
|
|
16
|
+
declare function injectFetch(deps: RestServerDeps): typeof fetch;
|
|
17
|
+
|
|
18
|
+
export { InProcessConnectorBinding, injectFetch };
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
// src/utils/similarity.ts
|
|
2
|
+
function computeSimilarity(a, b) {
|
|
3
|
+
const s1 = a.toLowerCase().trim();
|
|
4
|
+
const s2 = b.toLowerCase().trim();
|
|
5
|
+
if (s1 === s2) return 1;
|
|
6
|
+
if (!s1 || !s2) return 0;
|
|
7
|
+
if (s1.includes(s2) || s2.includes(s1)) {
|
|
8
|
+
const ratio = Math.min(s1.length, s2.length) / Math.max(s1.length, s2.length);
|
|
9
|
+
return Math.max(0.7, ratio);
|
|
10
|
+
}
|
|
11
|
+
const m = s1.length;
|
|
12
|
+
const n = s2.length;
|
|
13
|
+
const dp = Array.from({ length: n + 1 }, (_, i) => i);
|
|
14
|
+
for (let i = 1; i <= m; i++) {
|
|
15
|
+
let prev = dp[0];
|
|
16
|
+
dp[0] = i;
|
|
17
|
+
for (let j = 1; j <= n; j++) {
|
|
18
|
+
const temp = dp[j];
|
|
19
|
+
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
|
20
|
+
dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1, prev + cost);
|
|
21
|
+
prev = temp;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const distance = dp[n];
|
|
25
|
+
const maxLen = Math.max(m, n);
|
|
26
|
+
return Math.max(0, 1 - distance / maxLen);
|
|
27
|
+
}
|
|
28
|
+
var MAX_FUZZY_QUERY_LENGTH = 128;
|
|
29
|
+
function boundedSimilarity(query, candidate, minScore) {
|
|
30
|
+
const q = query.toLowerCase().trim();
|
|
31
|
+
const c = candidate.toLowerCase().trim();
|
|
32
|
+
if (!q || !c) return 0;
|
|
33
|
+
if (q.includes(c) || c.includes(q)) return computeSimilarity(q, c);
|
|
34
|
+
const lengthBound = 1 - Math.abs(q.length - c.length) / Math.max(q.length, c.length);
|
|
35
|
+
return lengthBound < minScore ? 0 : computeSimilarity(q, c);
|
|
36
|
+
}
|
|
37
|
+
function rankObjectSuggestions(query, objects, topN = 5, minScore = 0.4) {
|
|
38
|
+
if (query.trim().length > MAX_FUZZY_QUERY_LENGTH) return [];
|
|
39
|
+
return objects.map(({ elementId, displayName }) => ({
|
|
40
|
+
elementId,
|
|
41
|
+
displayName,
|
|
42
|
+
score: Math.max(
|
|
43
|
+
boundedSimilarity(query, elementId, minScore),
|
|
44
|
+
displayName ? boundedSimilarity(query, displayName, minScore) : 0
|
|
45
|
+
)
|
|
46
|
+
})).filter((item) => item.score >= minScore).sort((a, b) => b.score - a.score).slice(0, topN).map(({ elementId, displayName }) => ({ elementId, displayName }));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/bindings/rest-binding.ts
|
|
50
|
+
var OBJECT_CACHE_TTL_MS = 6e4;
|
|
51
|
+
var RestClientBinding = class _RestClientBinding {
|
|
52
|
+
baseUrl;
|
|
53
|
+
headers;
|
|
54
|
+
requestTimeoutMs;
|
|
55
|
+
fetchImpl;
|
|
56
|
+
token;
|
|
57
|
+
objectCache;
|
|
58
|
+
/**
|
|
59
|
+
* @param fetchImpl - replaces the global fetch, e.g. to route requests into an
|
|
60
|
+
* in-process server (see InProcessConnectorBinding).
|
|
61
|
+
*/
|
|
62
|
+
constructor(baseUrl = "http://localhost:3000", token, timeoutMs = 15e3, fetchImpl) {
|
|
63
|
+
let cleanUrl = baseUrl.trim().replace(/\/+$/, "");
|
|
64
|
+
if (!cleanUrl.startsWith("http://") && !cleanUrl.startsWith("https://")) {
|
|
65
|
+
cleanUrl = `http://${cleanUrl}`;
|
|
66
|
+
}
|
|
67
|
+
cleanUrl = cleanUrl.replace(/\/v1$/i, "");
|
|
68
|
+
this.baseUrl = cleanUrl;
|
|
69
|
+
this.requestTimeoutMs = timeoutMs;
|
|
70
|
+
this.fetchImpl = fetchImpl;
|
|
71
|
+
this.token = token;
|
|
72
|
+
this.headers = {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Accept: "application/json"
|
|
75
|
+
};
|
|
76
|
+
if (token) {
|
|
77
|
+
this.headers.Authorization = `Bearer ${token}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Normalized base URL, without a trailing /v1. */
|
|
81
|
+
getBaseUrl() {
|
|
82
|
+
return this.baseUrl;
|
|
83
|
+
}
|
|
84
|
+
get hasToken() {
|
|
85
|
+
return Boolean(this.token);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A binding to `baseUrl`. Without `token`, the current token is kept when the URL
|
|
89
|
+
* is this binding's own (re-connecting must not silently drop the configured token).
|
|
90
|
+
*/
|
|
91
|
+
connectTo(baseUrl, token) {
|
|
92
|
+
const next = new _RestClientBinding(baseUrl, token, this.requestTimeoutMs);
|
|
93
|
+
if (token !== void 0 || next.baseUrl !== this.baseUrl || !this.token) return next;
|
|
94
|
+
return new _RestClientBinding(baseUrl, this.token, this.requestTimeoutMs);
|
|
95
|
+
}
|
|
96
|
+
async request(path, options = {}) {
|
|
97
|
+
const url = `${this.baseUrl}${path}`;
|
|
98
|
+
const signal = options.signal || AbortSignal.timeout(this.requestTimeoutMs);
|
|
99
|
+
try {
|
|
100
|
+
const response = await (this.fetchImpl ?? fetch)(url, {
|
|
101
|
+
...options,
|
|
102
|
+
signal,
|
|
103
|
+
headers: {
|
|
104
|
+
...this.headers,
|
|
105
|
+
...options.headers || {}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
const errorText = await response.text();
|
|
110
|
+
const truncated = errorText.length > 300 ? `${errorText.slice(0, 300)}...` : errorText;
|
|
111
|
+
throw new Error(`HTTP ${response.status} from ${path}: ${truncated}`);
|
|
112
|
+
}
|
|
113
|
+
return await response.json();
|
|
114
|
+
} catch (err) {
|
|
115
|
+
if (err.name === "TimeoutError") {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`i3X Gateway request timed out after ${this.requestTimeoutMs}ms for ${path}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Unwrap a `{ success, result }` envelope; a `success: false` envelope becomes an error. */
|
|
124
|
+
async get(path) {
|
|
125
|
+
const res = await this.request(path);
|
|
126
|
+
if (res?.success !== true || !("result" in res)) {
|
|
127
|
+
throw new Error(`i3X request ${path} failed: ${describeFailure(res)}`);
|
|
128
|
+
}
|
|
129
|
+
return res.result;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* POST a bulk request and return its `results` items, one per requested elementId.
|
|
133
|
+
* `success` is false on the envelope as soon as one item failed, so items are
|
|
134
|
+
* returned as they are; only a body without `results` is an error here.
|
|
135
|
+
*/
|
|
136
|
+
async postBulk(path, body) {
|
|
137
|
+
const res = await this.request(path, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
body: JSON.stringify(body)
|
|
140
|
+
});
|
|
141
|
+
if (!Array.isArray(res?.results)) {
|
|
142
|
+
throw new Error(`i3X request ${path} failed: ${describeFailure(res)}`);
|
|
143
|
+
}
|
|
144
|
+
return res.results;
|
|
145
|
+
}
|
|
146
|
+
/** Bulk items as per-element results: a failed item keeps its elementId and error. */
|
|
147
|
+
async postBulkPerElement(path, elementIds, body) {
|
|
148
|
+
const items = await this.postBulk(path, { elementIds, ...body });
|
|
149
|
+
return items.map((item, idx) => {
|
|
150
|
+
const elementId = item.elementId ?? elementIds[idx] ?? `element_${idx}`;
|
|
151
|
+
if (!item.success) return { elementId, error: describeFailure(item) };
|
|
152
|
+
if (item.result == null) return { elementId, error: "Server returned no result" };
|
|
153
|
+
return { elementId, result: item.result };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/** The single item of a one-element bulk request. */
|
|
157
|
+
async postBulkOne(path, body) {
|
|
158
|
+
const [item] = await this.postBulk(path, body);
|
|
159
|
+
if (!item) throw new Error(`i3X request ${path} returned no result`);
|
|
160
|
+
return item;
|
|
161
|
+
}
|
|
162
|
+
async getInfo() {
|
|
163
|
+
return this.get("/v1/info");
|
|
164
|
+
}
|
|
165
|
+
async getNamespaces() {
|
|
166
|
+
return this.get("/v1/namespaces");
|
|
167
|
+
}
|
|
168
|
+
async getObjectTypes(namespaceUri) {
|
|
169
|
+
const query = namespaceUri ? `?namespaceUri=${encodeURIComponent(namespaceUri)}` : "";
|
|
170
|
+
return this.get(`/v1/objecttypes${query}`);
|
|
171
|
+
}
|
|
172
|
+
async getRelationshipTypes() {
|
|
173
|
+
return this.get("/v1/relationshiptypes");
|
|
174
|
+
}
|
|
175
|
+
async getObjects(options) {
|
|
176
|
+
const params = new URLSearchParams();
|
|
177
|
+
if (options?.rootOnly) params.set("root", "true");
|
|
178
|
+
if (options?.typeElementId) params.set("typeElementId", options.typeElementId);
|
|
179
|
+
const query = params.toString() ? `?${params.toString()}` : "";
|
|
180
|
+
return this.get(`/v1/objects${query}`);
|
|
181
|
+
}
|
|
182
|
+
/** `null` only when the server reports the element as not found (404). */
|
|
183
|
+
async getObjectById(elementId) {
|
|
184
|
+
const path = "/v1/objects/list";
|
|
185
|
+
const item = await this.postBulkOne(path, {
|
|
186
|
+
elementIds: [elementId]
|
|
187
|
+
});
|
|
188
|
+
if (item.success) return item.result ?? null;
|
|
189
|
+
if (item.responseDetail?.status === 404) return null;
|
|
190
|
+
throw new Error(
|
|
191
|
+
`i3X request ${path} failed for '${elementId}': ${describeFailure(item)}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
async getRelatedObjects(elementId, relationshipType) {
|
|
195
|
+
const path = "/v1/objects/related";
|
|
196
|
+
const body = {
|
|
197
|
+
elementIds: [elementId]
|
|
198
|
+
};
|
|
199
|
+
if (relationshipType) body.relationshipType = relationshipType;
|
|
200
|
+
const item = await this.postBulkOne(path, body);
|
|
201
|
+
if (!item.success) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
`i3X request ${path} failed for '${elementId}': ${describeFailure(item)}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
return (item.result ?? []).filter(
|
|
207
|
+
(r) => !relationshipType || r.sourceRelationship === relationshipType
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
async getRelatedObjectsBulk(elementIds) {
|
|
211
|
+
return this.postBulkPerElement(
|
|
212
|
+
"/v1/objects/related",
|
|
213
|
+
elementIds,
|
|
214
|
+
{}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
async getObjectValues(elementIds, maxDepth = 1) {
|
|
218
|
+
return this.postBulkPerElement("/v1/objects/value", elementIds, {
|
|
219
|
+
maxDepth
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async getHistoricalValues(elementIds, startTime, endTime, maxDepth = 1) {
|
|
223
|
+
return this.postBulkPerElement(
|
|
224
|
+
"/v1/objects/history",
|
|
225
|
+
elementIds,
|
|
226
|
+
{ startTime, endTime, maxDepth }
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
/** Closest objects by elementId or displayName; a failure to list objects propagates. */
|
|
230
|
+
async findSuggestions(query) {
|
|
231
|
+
if (query.trim().length > MAX_FUZZY_QUERY_LENGTH) return [];
|
|
232
|
+
const now = Date.now();
|
|
233
|
+
if (!this.objectCache || now - this.objectCache.at > OBJECT_CACHE_TTL_MS) {
|
|
234
|
+
const objects = this.getObjects();
|
|
235
|
+
this.objectCache = { at: now, objects };
|
|
236
|
+
objects.catch(() => {
|
|
237
|
+
if (this.objectCache?.objects === objects) this.objectCache = void 0;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return rankObjectSuggestions(query, await this.objectCache.objects);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
function describeFailure(res) {
|
|
244
|
+
const d = res?.responseDetail;
|
|
245
|
+
if (d) return [d.status, d.title, d.detail].filter(Boolean).join(" ");
|
|
246
|
+
return `unexpected response ${JSON.stringify(res)?.slice(0, 200)}`;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/bindings/connector-binding.ts
|
|
250
|
+
var InProcessConnectorBinding = class extends RestClientBinding {
|
|
251
|
+
constructor(deps) {
|
|
252
|
+
super("http://in-process", void 0, 15e3, injectFetch(deps));
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
function injectFetch(deps) {
|
|
256
|
+
let app;
|
|
257
|
+
return async (input, init) => {
|
|
258
|
+
app ??= import("@node-i3x/rest-server").then(
|
|
259
|
+
({ createApp }) => createApp({ ...deps, requireAuth: false }, { logger: false })
|
|
260
|
+
);
|
|
261
|
+
const url = new URL(String(input));
|
|
262
|
+
const res = await (await app).inject({
|
|
263
|
+
method: init?.method ?? "GET",
|
|
264
|
+
url: `${url.pathname}${url.search}`,
|
|
265
|
+
headers: init?.headers,
|
|
266
|
+
payload: typeof init?.body === "string" ? init.body : void 0
|
|
267
|
+
});
|
|
268
|
+
return new Response(res.body, {
|
|
269
|
+
status: res.statusCode,
|
|
270
|
+
headers: {
|
|
271
|
+
"content-type": String(res.headers["content-type"] ?? "application/json")
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
export {
|
|
277
|
+
InProcessConnectorBinding,
|
|
278
|
+
injectFetch
|
|
279
|
+
};
|
|
280
|
+
//# sourceMappingURL=in-process.js.map
|