{
  "name": "ai.dxpert/uns-tools",
  "slug": "offline-mcp-0c847d39045aabddbd46386a",
  "type": "mcp",
  "category": "developer-tools",
  "example": false,
  "evidence_state": "offline_listing",
  "stamp": "Offline listing — machine-checked",
  "summary": "Acquired @dxpert/uns-tools@0.1.2; tarball sha256 f5ebd78dfb9768c17701adb2f8ed8a8f447ecf62dda7950ef09de4fccd6e68ae.",
  "outcome": "The server started offline in an isolated container (runtime/inspect.json).",
  "rule_results": [
    "It answered tools/list with 3 tools named [\"lint_sparkplug_topic\", \"check_uns_namespace\", \"run_readiness_diagnostic\"]."
  ],
  "task": "Does this exact package start offline and answer an MCP tools list?",
  "setup": "Acquisition lock records install_scripts_ignored=true; runtime command in argv.json.",
  "limitations": "Runtime isolation evidence: runtime/inspect.json. Scope: initialize and tools/list (mcp/report.json). Network-attempt tracing and credential tests are outside this scope. Later versions require a new run.",
  "source_url": "https://www.npmjs.com/package/@dxpert/uns-tools",
  "documentation_url": "https://www.npmjs.com/package/@dxpert/uns-tools",
  "tree_sha256": "b33c35e267ef6b3bb98bc5ef4ae30f1cfa44d7c52ce55ecfcc35caa393323d4e",
  "image_digest": "sha256:7393e97480d151dd97b8020ffd45a440f6fbe34b1128595c87b1df3e50d0ef2b",
  "file_sha256": {
    ".docker/buildx/.buildNodeID": "fc86f13f9cfd2d69609f25a983b7afde1d7dc1e40a328bfc1a678bba1082fe2e",
    ".docker/buildx/.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    ".docker/buildx/activity/default": "2e727cd659a5a21a40833474ce208f6e34fd01790bdd20c523e1502fe2e52bc5",
    ".docker/buildx/refs/default/default/enwg2ep9xlfe8x1uxz3c3ibjh": "1a454d3652664e9abeda38d022cc7513e5b5ee96deb0fc26e3c50478a9171064",
    ".dockerignore": "99a18f8ea8514c4bcd448371d1bc1b8b4d877d6606e7c5b3d2a9dd52b32aa8d0",
    "Containerfile": "d849cf10a7e9b70fecc5fcdc6333dd493aed8767d236893e675cfa4662520c54",
    "image.id": "81e9843fdf0f984b46e583e70eee1d4489ee5d72a0f63f32abe64e206695ab7b",
    "installed/node_modules/.package-lock.json": "7a7ef0ccdaabdd9fbcdd98b43820343f78e486bfd3ac2fc50601a36c728040be",
    "installed/node_modules/@dxpert/uns-tools/LICENSE": "f8c126575277cb7af98da3bf4dc9f393384591d5db45cd75800570316f06571b",
    "installed/node_modules/@dxpert/uns-tools/README.md": "4a4a4842f8718a1f0b65e54f7f8128df3a93e9dbe31dd2e2a77abccb2bb62186",
    "installed/node_modules/@dxpert/uns-tools/bin/uns-tools-mcp.js": "47af2252354cfb75af49cbc336bf3a680ba7b429bf40ffaed6aa4b8bc94792f2",
    "installed/node_modules/@dxpert/uns-tools/package.json": "fced387223ae1ec4ccc38a75d521b1cb228be2c4d941147bd0abb36b8a898c19",
    "installed/node_modules/@dxpert/uns-tools/src/server.js": "898fcd8299e476f23a68e27c3bf24d498f75f2077510d29002257d5759e1c0b3",
    "installed/node_modules/@dxpert/uns-tools/src/sparkplug-topic-lint.js": "123329c266d24263532b5a40ab7708befed545e74602b2c5401af02c45d2331d",
    "installed/node_modules/@dxpert/uns-tools/src/uns-naming-check.js": "c3eef6ef09285a4edf7734e7bb2da7d70d68de2471c8e297bdf1a81f4f6077d8",
    "installed/package-lock.json": "4645ec95c6119e13f728726c66b54c4f660768055637149b56510b8cd5a71c29",
    "installed/package.json": "d0c816ee3a7d7d0ef6c29c66e4d368b5b128915181511d5ae7d1fbee34ffe99d",
    "npmrc-global": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "npmrc-user": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "packs/dxpert-uns-tools-0.1.2.tgz": "f5ebd78dfb9768c17701adb2f8ed8a8f447ecf62dda7950ef09de4fccd6e68ae"
  },
  "lockfiles": [
    "installed/package-lock.json"
  ],
  "tools_list_hashes": [
    "4231e453d21fcef0d9459a1ddf8aafc4d1fc03dabcde6929640e0d1c385a021a"
  ],
  "utc_date": "2026-10-17T12:23:42.134840Z",
  "source_date": "2026-10-16",
  "discovered_date": "2026-10-16",
  "retested_date": "2026-10-17",
  "reviewed_date": "2026-10-17",
  "published_date": "2026-10-17",
  "modified_date": "2026-10-17",
  "reviewer": "machine pipeline",
  "harness_version": "toolwitness harness at commit 5a286f05b93bfbf27b15f403e41e3a1525edc32f",
  "claude_code_version": "Outside this listing scope.",
  "model_id": "Outside this listing scope.",
  "scanner_version": "none",
  "rulepack_version": "none",
  "agents": [],
  "disclaimer": "This record shows that this exact package version started offline in an isolated container and answered an MCP tools list (runtime/inspect.json, mcp/report.json). Scope: initialize and tools/list. It is not a security or quality verdict. Later versions are outside this record.",
  "commands": [
    "docker run -i --name toolwitness-999b5f1512cf4ebdaec856c2e4b721cd --pull=never --network none --read-only --cap-drop=all --security-opt=no-new-privileges --user=65532:65532 --memory=512m --memory-swap=512m --pids-limit=64 --cpus=1 --ulimit=nofile=256:256 --ulimit=fsize=16777216:16777216 --tmpfs=/tmp:rw,nosuid,nodev,noexec,size=64m,mode=1777 --env=HOME=/tmp --workdir=/tmp --entrypoint node sha256:7393e97480d151dd97b8020ffd45a440f6fbe34b1128595c87b1df3e50d0ef2b /installed/node_modules/@dxpert/uns-tools/bin/uns-tools-mcp.js"
  ],
  "prompt_list": [
    "Outside this listing scope."
  ],
  "history": [
    "2026-10-17T12:23:42.134840Z: offline initialize and tools/list"
  ],
  "application": {
    "name": "@dxpert/uns-tools",
    "softwareVersion": "0.1.2",
    "applicationCategory": "DeveloperApplication"
  },
  "artifacts": {
    "transcript": "stdin:\n{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"capabilities\":{},\"clientInfo\":{\"name\":\"toolwitness\",\"version\":\"s772-v0\"},\"protocolVersion\":\"2025-11-25\"}}\n{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}\n{\"id\":2,\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"params\":{}}\n\nstdout:\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{\"tools\":{}},\"serverInfo\":{\"name\":\"@dxpert/uns-tools\",\"version\":\"0.1.2\"}}}\n{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":{\"tools\":[{\"name\":\"lint_sparkplug_topic\",\"description\":\"Validate one or more MQTT topic strings against the Sparkplug B topic grammar (Sparkplug 3.0). Free, no API key, no account: the grammar runs locally inside this server and nothing is sent anywhere. Call this whenever a topic that is meant to be Sparkplug appears in a config, a broker trace, a code review, or a user question -- it is faster and far more reliable than reasoning about the grammar from memory. It checks the spBv1.0 namespace level, the eight message types (NBIRTH/NDEATH/DBIRTH/DDEATH/NDATA/DDATA/NCMD/DCMD) plus STATE, node-vs-device level count, the legacy Sparkplug 2.2 STATE form, publish-side MQTT wildcards, empty levels, and identifier characters that break downstream consumers. It returns ordered findings (fail / warn / pass / info) with the parsed topic parts, not a yes/no. It does NOT connect to a broker, decode payloads, or check whether the device actually exists.\",\"inputSchema\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"topics\":{\"description\":\"One topic string, or an array of topic strings. A single string containing newlines is also accepted and split per line.\",\"oneOf\":[{\"type\":\"string\"},{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"minItems\":1}]}},\"required\":[\"topics\"]}},{\"name\":\"check_uns_namespace\",\"description\":\"Check a set of Unified Namespace (UNS) topic paths for the convention problems that quietly rot a namespace: inconsistent hierarchy depth, mixed casing styles across segments, whitespace in segments, case-collisions between siblings that read as one node but are two, duplicate paths, empty levels, and stray MQTT wildcards. Free, no API key, no account: the checks run locally inside this server and nothing is sent anywhere. Call this when reviewing a proposed namespace, an ISA-95-style hierarchy, a broker topic dump, or a tag export -- before anyone builds on top of it, because renaming a namespace later is the expensive part. It returns a summary line plus per-issue findings (fail / warn / pass / info). It judges naming consistency only: it does NOT know your plant, does not validate Sparkplug grammar (use lint_sparkplug_topic for that), and does not design a namespace for you.\",\"inputSchema\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"topics\":{\"description\":\"The topic paths to check. An array of paths, or a single string with one path per line.\",\"oneOf\":[{\"type\":\"string\"},{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"minItems\":1}]}},\"required\":[\"topics\"]}},{\"name\":\"run_readiness_diagnostic\",\"description\":\"Run the public dxpert.ai industrial AI-readiness diagnostic: a 16-answer self-reported intake in, a scored report out (ten axes 0-5, a maturity stage, the foundation gaps blocking the stated AI ambition, and a confidence value). Free and requires no API key or account, but unlike the two validators this one DOES call the dxpert.ai API over the network, so it needs connectivity and is rate limited. Call this when someone asks how ready a plant or site is for AI/analytics, what is blocking them, or where to start -- and you can supply honest answers to the intake fields. Ask the user for the values you do not have rather than guessing them; the verdict is only as good as the intake. The response carries a \\\"scope\\\" field which this tool passes through verbatim: it is a preliminary self-reported screening, not an audit, and should be reported to the user as such.\",\"inputSchema\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"intake\":{\"type\":\"object\",\"description\":\"The 16-question readiness intake. All fields are required by the API; the enums below are the accepted values.\",\"properties\":{\"sector\":{\"enum\":[\"discrete_mfg\",\"automotive\",\"process\",\"pharma\",\"food_bev\",\"energy\",\"other\"]},\"site_count\":{\"type\":\"integer\",\"minimum\":1},\"data_off_floor\":{\"enum\":[\"manual\",\"scada_only\",\"opcua\",\"mqtt_sparkplug\",\"mixed\"]},\"common_model\":{\"enum\":[\"none\",\"per_system\",\"partial\",\"unified\"]},\"realtime_visibility\":{\"enum\":[\"none\",\"on_request\",\"partial\",\"single_pane\"]},\"historian_depth\":{\"enum\":[\"none\",\"local\",\"central_untrusted\",\"central_trusted\"]},\"edge_vs_poll\":{\"enum\":[\"poll\",\"mixed\",\"edge_push\"]},\"uns_state\":{\"enum\":[\"none\",\"point_to_point\",\"partial\",\"governed_uns\"]},\"data_ready_for_use_case\":{\"enum\":[\"no\",\"partial\",\"yes\"]},\"otit_security\":{\"enum\":[\"ad_hoc\",\"partial\",\"governed\"]},\"data_ownership\":{\"enum\":[\"tribal\",\"unclear\",\"owned_governed\"]},\"ai_ambition\":{\"type\":\"object\",\"description\":\"What they actually want AI to do, and how far they intend to take it.\",\"properties\":{\"text\":{\"type\":\"string\",\"maxLength\":500},\"target\":{\"enum\":[\"pilot\",\"scale\",\"autonomous\"]}},\"required\":[\"text\",\"target\"]},\"prior_attempts\":{\"type\":\"string\",\"maxLength\":1000},\"personal_stakes\":{\"type\":\"string\",\"maxLength\":500},\"who_they_trust\":{\"type\":\"string\",\"maxLength\":300},\"politically_useful\":{\"type\":\"string\",\"maxLength\":500}}}},\"required\":[\"intake\"]}}]}}\n",
    "sinkhole_log": "Scope: runtime isolation evidence in runtime/inspect.json.",
    "canary_log": "Outside this listing scope.",
    "scanner_output": "Outside this listing scope.",
    "normalized_text": "{\"calls\": [], \"exit_before_cleanup\": null, \"initialize\": {\"capabilities\": {\"tools\": {}}, \"protocolVersion\": \"2025-11-25\", \"serverInfo\": {\"name\": \"@dxpert/uns-tools\", \"version\": \"0.1.2\"}}, \"list_change_notifications\": 0, \"monotonic_seconds\": 0.20195368400891311, \"outcome\": \"listed tools offline\", \"started_utc\": \"2026-10-17T12:23:42.134840Z\", \"status\": \"completed\", \"tools\": [{\"description\": \"Validate one or more MQTT topic strings against the Sparkplug B topic grammar (Sparkplug 3.0). Free, no API key, no account: the grammar runs locally inside this server and nothing is sent anywhere. Call this whenever a topic that is meant to be Sparkplug appears in a config, a broker trace, a code review, or a user question -- it is faster and far more reliable than reasoning about the grammar from memory. It checks the spBv1.0 namespace level, the eight message types (NBIRTH/NDEATH/DBIRTH/DDEATH/NDATA/DDATA/NCMD/DCMD) plus STATE, node-vs-device level count, the legacy Sparkplug 2.2 STATE form, publish-side MQTT wildcards, empty levels, and identifier characters that break downstream consumers. It returns ordered findings (fail / warn / pass / info) with the parsed topic parts, not a yes/no. It does NOT connect to a broker, decode payloads, or check whether the device actually exists.\", \"inputSchema\": {\"additionalProperties\": false, \"properties\": {\"topics\": {\"description\": \"One topic string, or an array of topic strings. A single string containing newlines is also accepted and split per line.\", \"oneOf\": [{\"type\": \"string\"}, {\"items\": {\"type\": \"string\"}, \"minItems\": 1, \"type\": \"array\"}]}}, \"required\": [\"topics\"], \"type\": \"object\"}, \"name\": \"lint_sparkplug_topic\"}, {\"description\": \"Check a set of Unified Namespace (UNS) topic paths for the convention problems that quietly rot a namespace: inconsistent hierarchy depth, mixed casing styles across segments, whitespace in segments, case-collisions between siblings that read as one node but are two, duplicate paths, empty levels, and stray MQTT wildcards. Free, no API key, no account: the checks run locally inside this server and nothing is sent anywhere. Call this when reviewing a proposed namespace, an ISA-95-style hierarchy, a broker topic dump, or a tag export -- before anyone builds on top of it, because renaming a namespace later is the expensive part. It returns a summary line plus per-issue findings (fail / warn / pass / info). It judges naming consistency only: it does NOT know your plant, does not validate Sparkplug grammar (use lint_sparkplug_topic for that), and does not design a namespace for you.\", \"inputSchema\": {\"additionalProperties\": false, \"properties\": {\"topics\": {\"description\": \"The topic paths to check. An array of paths, or a single string with one path per line.\", \"oneOf\": [{\"type\": \"string\"}, {\"items\": {\"type\": \"string\"}, \"minItems\": 1, \"type\": \"array\"}]}}, \"required\": [\"topics\"], \"type\": \"object\"}, \"name\": \"check_uns_namespace\"}, {\"description\": \"Run the public dxpert.ai industrial AI-readiness diagnostic: a 16-answer self-reported intake in, a scored report out (ten axes 0-5, a maturity stage, the foundation gaps blocking the stated AI ambition, and a confidence value). Free and requires no API key or account, but unlike the two validators this one DOES call the dxpert.ai API over the network, so it needs connectivity and is rate limited. Call this when someone asks how ready a plant or site is for AI/analytics, what is blocking them, or where to start -- and you can supply honest answers to the intake fields. Ask the user for the values you do not have rather than guessing them; the verdict is only as good as the intake. The response carries a \\\"scope\\\" field which this tool passes through verbatim: it is a preliminary self-reported screening, not an audit, and should be reported to the user as such.\", \"inputSchema\": {\"additionalProperties\": false, \"properties\": {\"intake\": {\"description\": \"The 16-question readiness intake. All fields are required by the API; the enums below are the accepted values.\", \"properties\": {\"ai_ambition\": {\"description\": \"What they actually want AI to do, and how far they intend to take it.\", \"properties\": {\"target\": {\"enum\": [\"pilot\", \"scale\", \"autonomous\"]}, \"text\": {\"maxLength\": 500, \"type\": \"string\"}}, \"required\": [\"text\", \"target\"], \"type\": \"object\"}, \"common_model\": {\"enum\": [\"none\", \"per_system\", \"partial\", \"unified\"]}, \"data_off_floor\": {\"enum\": [\"manual\", \"scada_only\", \"opcua\", \"mqtt_sparkplug\", \"mixed\"]}, \"data_ownership\": {\"enum\": [\"tribal\", \"unclear\", \"owned_governed\"]}, \"data_ready_for_use_case\": {\"enum\": [\"no\", \"partial\", \"yes\"]}, \"edge_vs_poll\": {\"enum\": [\"poll\", \"mixed\", \"edge_push\"]}, \"historian_depth\": {\"enum\": [\"none\", \"local\", \"central_untrusted\", \"central_trusted\"]}, \"otit_security\": {\"enum\": [\"ad_hoc\", \"partial\", \"governed\"]}, \"personal_stakes\": {\"maxLength\": 500, \"type\": \"string\"}, \"politically_useful\": {\"maxLength\": 500, \"type\": \"string\"}, \"prior_attempts\": {\"maxLength\": 1000, \"type\": \"string\"}, \"realtime_visibility\": {\"enum\": [\"none\", \"on_request\", \"partial\", \"single_pane\"]}, \"sector\": {\"enum\": [\"discrete_mfg\", \"automotive\", \"process\", \"pharma\", \"food_bev\", \"energy\", \"other\"]}, \"site_count\": {\"minimum\": 1, \"type\": \"integer\"}, \"uns_state\": {\"enum\": [\"none\", \"point_to_point\", \"partial\", \"governed_uns\"]}, \"who_they_trust\": {\"maxLength\": 300, \"type\": \"string\"}}, \"type\": \"object\"}}, \"required\": [\"intake\"], \"type\": \"object\"}, \"name\": \"run_readiness_diagnostic\"}], \"tools_list_hashes\": [\"4231e453d21fcef0d9459a1ddf8aafc4d1fc03dabcde6929640e0d1c385a021a\"], \"wall_limit_seconds\": 45}"
  },
  "review_input": {
    "identity_artifact": "identity.json",
    "evidence_sha256": {
      "LOCK.json": "b23961413068e49bd530154d4241900999c5ed2db662140d1b8b3f7952d7932d",
      "argv.json": "8c8b8e1d2bb537eb0d3c842335c404bd48966a63b5b8571f9f7fd39464a5dc87",
      "complete.json": "63c70b344779060834e23be23546dd5a762c0ae30dbf20b870a5e08b9e3417f0",
      "component-record.json": "01fbe3446a71bd7a621fbdb2993ebd637037579f045275353fec95c1fddd4b7d",
      "fixture.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
      "harness/acquire.py": "67fe8484cb7028040f6b494de3702b02fcd544986a6bf738d14001b8ae2ae9cb",
      "harness/auto_witness.py": "b693353f11922463baf0884fe8680e083e2807e1ba7bb6026f6453db6aaf8b0a",
      "harness/mcp_driver.py": "b5996ec8e534b797c976dc83e44af0b52f64895fec5e72a4f9b32cb2f63cbbf7",
      "harness/record.py": "d34b444b8f6ccf5f79fae86dd02c2fc223f11e026cffa8090007ac5f9be85c82",
      "harness/runtime_proof.py": "b9f8d2405611de5894c6287631c30ade8e8e5013a547923fbd3034c76b0d2a71",
      "identity.json": "cdf02a580aefd98ed5bcea480d7890c4aee2361d4367f7aa74bc281e1032a003",
      "manifest.json": "5ca82efac5d96e95580ecc25c6475e037a58abbcdcd6b988ecf0ab77358db185",
      "mcp/report.json": "2da3a969c97b0a856952af0b50600cd4b965629fc3e98fa32e26c0fcc8058904",
      "mcp/stderr.bin": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "mcp/stdin.bin": "9ced9858b21f60691df654e649f586e91cfcaf60ed887c79c3df92f599166df6",
      "mcp/stdout.bin": "dba6da7ff4313d8b4f9d06f8296d9ccb4290efe57fdb8392ede65ffa17f943b1",
      "runtime/inspect.json": "337766d5456ec630174260e9ec279b65c87bb41673703b2c7654a93a1cf70698"
    },
    "claims": [
      {
        "id": "acquired",
        "field": "summary",
        "text": "Acquired @dxpert/uns-tools@0.1.2; tarball sha256 f5ebd78dfb9768c17701adb2f8ed8a8f447ecf62dda7950ef09de4fccd6e68ae.",
        "sources": [
          "LOCK.json"
        ]
      },
      {
        "id": "started",
        "field": "outcome",
        "text": "The server started offline in an isolated container (runtime/inspect.json).",
        "sources": [
          "runtime/inspect.json",
          "LOCK.json",
          "argv.json",
          "mcp/report.json",
          "mcp/stdout.bin"
        ]
      },
      {
        "id": "listed",
        "field": "rule_results.0",
        "text": "It answered tools/list with 3 tools named [\"lint_sparkplug_topic\", \"check_uns_namespace\", \"run_readiness_diagnostic\"].",
        "sources": [
          "mcp/report.json",
          "mcp/stdout.bin"
        ]
      }
    ]
  },
  "review": {
    "kind": "machine-checked",
    "date": "2026-10-17",
    "reviewed_sha256": "0c15063c7abf65604ab530f69301a7ea69cabe6b9d699eba8afb6a144cc4e086",
    "gates": "9c00286fca04a3130ccb92b2f899e5ce7aee5589a6c8f23d39834b47159bbdaf",
    "codex": "42b831fee800831b85bdc53bdd88a3cd35c282329573fef0d281f89fd1142511",
    "grok": "3cd22f669e6143b975d54caa0ac84341dd7dec4010203adf8905480cabfa66ea",
    "summary": "Deterministic gates passed; Codex confirmed all outcome claims; Grok reported no standing refutation."
  }
}
