{"_id":"@dxpert/uns-tools","_rev":"2-7975c66df6d62cc7c5d7cd33fc7bf98f","name":"@dxpert/uns-tools","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@dxpert/uns-tools","version":"0.1.0","keywords":["mcp","model-context-protocol","dxpert","uns","unified-namespace","sparkplug","sparkplug-b","mqtt","isa-95","industrial-iot","iiot","linter","claude-code","codex"],"author":{"url":"https://dxpert.ai","name":"DXP Technologies inc."},"license":"MIT","_id":"@dxpert/uns-tools@0.1.0","maintainers":[{"name":"dxpert.ai","email":"admin@dxpert.ai"}],"homepage":"https://dxpert.ai","bugs":{"url":"https://github.com/dxpert-ai/uns-tools/issues"},"bin":{"dxpert-uns-tools":"bin/uns-tools-mcp.js"},"dist":{"shasum":"80a1135e24e0367878e2295e6e4b5effff5592e9","tarball":"https://registry.npmjs.org/@dxpert/uns-tools/-/uns-tools-0.1.0.tgz","fileCount":7,"integrity":"sha512-7aaXqGh30xVq9L4JxGjWJKUvvdLrkADFT0rOkJ9PGFWMSjDovUjbA92wPKjr0oL0CRYNjIEd377COpFH0x+zWg==","signatures":[{"sig":"MEYCIQDyk+ajGlpHTYgMUcMx3KnvKH5pCkD1VMhc5jxrmlHH2AIhAMpF2+VrmB9/Q8O0Sde3fYWpfefTyG7YMk/TBYoVuRXt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35970},"main":"src/server.js","type":"module","exports":{".":"./src/server.js"},"mcpName":"ai.dxpert/uns-tools","scripts":{"test":"node test/run.js"},"_npmUser":{"name":"dxpert.ai","email":"admin@dxpert.ai"},"repository":{"url":"git+https://github.com/dxpert-ai/uns-tools.git","type":"git"},"_npmVersion":"11.13.0","description":"No-key stdio MCP server: Sparkplug B topic linting, UNS naming checks, and the free industrial AI-readiness diagnostic from dxpert.ai.","directories":{},"_nodeVersion":"24.16.0","dependencies":{},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/uns-tools_0.1.0_1788020512828_0.4691073882658414","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@dxpert/uns-tools","mcpName":"ai.dxpert/uns-tools","version":"0.1.1","description":"No-key stdio MCP server: Sparkplug B topic linting, UNS naming checks, and the free industrial AI-readiness diagnostic from dxpert.ai.","license":"MIT","type":"module","main":"src/server.js","exports":{".":"./src/server.js"},"bin":{"dxpert-uns-tools":"bin/uns-tools-mcp.js"},"scripts":{"test":"node test/run.js"},"dependencies":{},"keywords":["mcp","model-context-protocol","dxpert","uns","unified-namespace","sparkplug","sparkplug-b","mqtt","isa-95","industrial-iot","iiot","linter","claude-code","codex"],"homepage":"https://dxpert.ai","author":{"name":"DXP Technologies inc.","url":"https://dxpert.ai"},"repository":{"type":"git","url":"git+https://github.com/dxpert-ai/uns-tools.git"},"gitHead":"dd884309d00c22bf5cd9fbe086a8d0f4ecdb0d0b","_id":"@dxpert/uns-tools@0.1.1","bugs":{"url":"https://github.com/dxpert-ai/uns-tools/issues"},"_nodeVersion":"24.20.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-Lukc5CofhTxsJVplg/P6YxvXipUETjEfhKaN6j/+14aVHUsRw110eyY2hXusTpwY1I8744NX0LLkw7FtYDlwFA==","shasum":"166a2c31bb8566151c50653d5f21ea367436e1ac","tarball":"https://registry.npmjs.org/@dxpert/uns-tools/-/uns-tools-0.1.1.tgz","fileCount":7,"unpackedSize":37426,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dxpert%2funs-tools@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEoJ4Vrov78TITYu6tvS2y+x6xOrYXx4UhHSinsgdUGqAiAoIab3ZSj43c9tiWqXXbM+r6zKvCtkMyeHcy77pmpIbg=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:41241349-b13b-41b3-ae35-438bc63de89f"}},"directories":{},"maintainers":[{"name":"dxpert.ai","email":"admin@dxpert.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/uns-tools_0.1.1_1789083481308_0.16362080038891813"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-29T16:21:52.619Z","modified":"2026-09-10T23:38:01.823Z","0.1.0":"2026-08-29T16:21:52.959Z","0.1.1":"2026-09-10T23:38:01.472Z"},"bugs":{"url":"https://github.com/dxpert-ai/uns-tools/issues"},"author":{"name":"DXP Technologies inc.","url":"https://dxpert.ai"},"license":"MIT","homepage":"https://dxpert.ai","keywords":["mcp","model-context-protocol","dxpert","uns","unified-namespace","sparkplug","sparkplug-b","mqtt","isa-95","industrial-iot","iiot","linter","claude-code","codex"],"repository":{"type":"git","url":"git+https://github.com/dxpert-ai/uns-tools.git"},"description":"No-key stdio MCP server: Sparkplug B topic linting, UNS naming checks, and the free industrial AI-readiness diagnostic from dxpert.ai.","maintainers":[{"name":"dxpert.ai","email":"admin@dxpert.ai"}],"readme":"# @dxpert/uns-tools\n\n**A stdio MCP server that needs no API key, no account, and no environment variables.**\n\nThis is the agent-native equivalent of the free tools page at [dxpert.ai/tools.html](https://dxpert.ai/tools.html): any MCP client, with zero credentials, can lint Sparkplug B topics, check a Unified Namespace for the conventions that quietly rot it, and run the public industrial AI-readiness diagnostic.\n\nThe tools are genuinely free. There is no trial counter, no sign-up wall, and no key to obtain first. If you later want the paid surface — the agents, the Namespace Architect, account-aware advisory — that lives in the separate [`@dxpert/mcp`](https://www.npmjs.com/package/@dxpert/mcp) server, which does take a `dxp_` key.\n\nZero runtime dependencies. The MCP stdio JSON-RPC handshake (`initialize`, `tools/list`, `tools/call`) is hand-rolled with `Content-Length` framing.\n\n## Install\n\nNo install step is required beyond Node 18+ (for built-in `fetch`).\n\n### Claude Code\n\n```sh\nclaude mcp add dxpert-uns-tools -- npx -y @dxpert/uns-tools\n```\n\n### Codex\n\n```toml\n[mcp_servers.dxpert_uns_tools]\ncommand = \"npx\"\nargs = [\"-y\", \"@dxpert/uns-tools\"]\n```\n\n### Generic MCP clients\n\n```json\n{\n  \"mcpServers\": {\n    \"dxpert-uns-tools\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@dxpert/uns-tools\"]\n    }\n  }\n}\n```\n\nNote that none of these entries carry an `env` block. That is the point.\n\n## Tools\n\n### `lint_sparkplug_topic(topics)` — local, offline\n\nValidates one or more MQTT topic strings against the Sparkplug B topic grammar (Sparkplug 3.0). Accepts a single string, a newline-delimited string, or an array.\n\nChecks 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.\n\nReturns ordered findings (`fail` / `warn` / `pass` / `info`) with the parsed topic parts. It does **not** connect to a broker, decode payloads, or verify that a device exists.\n\n### `check_uns_namespace(topics)` — local, offline\n\nChecks a set of UNS topic paths for inconsistent hierarchy depth, mixed casing styles, whitespace in segments, case-collisions between siblings that read as one node but are two, duplicate paths, empty levels, and stray MQTT wildcards.\n\nReturns a summary line plus per-issue findings. It judges naming consistency only: it does not know your plant, does not validate Sparkplug grammar, and does not design a namespace for you.\n\n### `run_readiness_diagnostic(intake)` — network\n\nRuns the public dxpert.ai industrial AI-readiness diagnostic. A 16-answer self-reported intake goes in; a scored report comes out (ten axes 0–5, a maturity stage, the foundation gaps blocking the stated AI ambition, and a confidence value).\n\nFree and unauthenticated, but unlike the two validators this one **does** call `POST /api/diagnostic` over the network, so it needs connectivity and is rate limited. Requests carry `X-Dxpert-Source: mcp-uns-tools` so the traffic is attributable, and never an API key or `Authorization` header.\n\nThe response's `scope` field is passed through verbatim and printed at the top of the result. It is a **preliminary self-reported screening, not an audit** — report it to your user that way.\n\nEvery result names `dxpert.ai` as the source of the verdict.\n\n## Configuration\n\nThere is nothing you have to set. One optional variable exists:\n\n| Variable | Required | Purpose |\n| --- | --- | --- |\n| `DXPERT_API_BASE` | No | API base URL for `run_readiness_diagnostic`. Defaults to production; override only for testing. |\n\n## Where the validator logic comes from\n\n`src/sparkplug-topic-lint.js` and `src/uns-naming-check.js` are verbatim copies of the pure logic in the standalone packages [`@dxpert/sparkplug-topic-lint`](https://www.npmjs.com/package/@dxpert/sparkplug-topic-lint) and [`@dxpert/uns-naming-check`](https://www.npmjs.com/package/@dxpert/uns-naming-check), inlined so this server has zero dependencies and works fully offline.\n\nThey are kept in sync with those packages, and the test suite asserts findings-level parity against both originals — so this server and the web tools can never quietly disagree about the same input.\n\n## Test\n\n```sh\nnode test/run.js\n```\n\nThe suite drives the real server over framed stdio and mocks the diagnostic endpoint on localhost; production is never called from tests. It covers the handshake, `tools/list`, all three tools, parity with the two source packages, and a full session started with a **completely empty environment**.\n\n## License\n\nMIT © 2026 DXP Technologies inc.\n","readmeFilename":"README.md"}