Repository navigation
Development
How this project is built and how to contribute. The authoritative rules are in AGENTS.md and CONTRIBUTING.md; this page is the overview.
git clone https://github.com/Reid-n0rc/uni-t-uts-mcp.git
cd uni-t-uts-mcp
npm ci
npm run build # tsc -> build/
npm run typecheck # type-checks src and tests
npm test # vitest (no hardware needed)
npm run inspector # try the server in the MCP InspectorRequires Node.js 22+. Tests never need an analyzer: they use a mocked connection or an in-process fake SCPI server (tests/fakeScpiServer.ts) plus captured instrument fixtures (tests/fixtures/).
- Issues first. Every piece of work is a GitHub issue (goal, tests to write first, acceptance criteria, size). The roadmap issue lists them all. Keep each task small enough for one sitting.
-
Issue, then branch, then PR. Work on a branch named
issue-<n>-<slug>, and open one PR withCloses #<n>. No PR without an issue, and nothing goes tomainexcept through a PR. - Test-driven. Write failing tests first and commit them, then implement until green, then refactor.
- Small, reviewable commits. One logical change each, each building and passing, so the history can be audited.
- CI. Build, typecheck and tests run on Node 22 and 24 on Linux, macOS and Windows, plus the install and Docker smoke jobs, a check that the wiki pages build, and CodeQL. All checks must be green with zero open code-scanning alerts before merging.
- Signed commits are encouraged but not required.
- Documentation is part of done. A PR that adds or changes a tool, a hardware finding, a workflow rule or the layout updates the matching docs in the same PR.
-
No secrets, serial numbers or real IP addresses in the repo, issues or PRs. Use placeholders such as
192.168.1.100. - No tags, releases or version bumps unless the maintainer asks.
The wiki is generated from the repository and published automatically, so never edit it in the GitHub wiki editor (edits are overwritten on the next sync). Where each page lives:
| Wiki page | Source of truth |
|---|---|
| Tools |
docs/tools-reference.md (generated) |
| Instrument Behavior |
docs/verified-hardware.md (generated) |
| Home |
docs/wiki/Home.md template, with the version from package.json and the tool table from docs/tools-reference.md (generated) |
| Roadmap |
docs/wiki/Roadmap.md template plus the open and closed issues (generated) |
| Getting Started, Architecture, Safety and Security, Troubleshooting, Manual Testing, Development, the sidebar and footer |
docs/wiki/*.md (hand-written, reviewed in pull requests) |
node scripts/sync-wiki.mjs --check builds the pages and verifies that every internal link and anchor resolves, that links to repository files point at files that exist, that every page is in the sidebar, and that no serial numbers, real IP addresses or personal email addresses are present; CI runs it on every pull request. After a change to main that touches docs/, the README, the changelog or package.json (and when an issue changes), the wiki-sync.yml workflow builds the pages and pushes an ordinary commit to the wiki repository with the default GITHUB_TOKEN; nothing is pushed when nothing changed. node scripts/sync-wiki.mjs --out <dir> builds the pages locally (the Roadmap lists issues only when GH_TOKEN or GITHUB_TOKEN is set). The project site's tool list is generated from the same docs/tools-reference.md by npm run site.
- Open an issue; branch
issue-<n>-<slug>. - Write the tests first: integration tests with a mocked connection in
tests/integration/, including failure modes. - Implement it in
src/tools/<group>.ts(exportregister<Group>Tools(server)) and register it insrc/server.ts.- Read-only tools get
readOnlyHint: true. - Setters validate, use
applyCommands, read back and warn about adjusted values. - Getters use the strict parsers in
src/instrument.ts. - Handlers never throw; return
errorResult(...).
- Read-only tools get
- Add the tool to the
CONTRACTtable intests/toolContract.ts(and canned replies for any new query toQUERY_REPLIES), and to the expected names intests/unit/server.test.ts. - Document it: a
### \tool_name`section indocs/tools-reference.md(a test fails if it is missing), hardware findings indocs/verified-hardware.md, SCPI details indocs/programming-guide.md`, and the README tool table. - Verify it on real hardware if you can (below) and record the result.
SCPI syntax comes from the UNI-T programming manuals (links in docs/references.md). Do not guess commands; cite the manual section in a code comment when a command is non-obvious.
Hardware checks are manual and recorded in docs/verified-hardware.md (model, firmware, what was observed). Rules of the road:
- Write down every setting before you change it and restore it afterwards; finish with a clean
:SYSTem:ERRor?. - Respect the instrument's quirks: one query at a time; an unsupported query stalls it for about 2 s and queues a late
-113; the instrument ignores commands during a single sweep on the raw socket (see Instrument Behavior). - Never send resets, network-setting changes, lock commands or file writes while probing.
- Probe scripts live in
scripts/and read the host fromUTS_IP; they redact serial numbers from their output. - If you have a different model or firmware, please say which in your PR.
When several people or agents work at once, each should use its own git worktree (not just a branch in the shared checkout), and only one should drive the real instrument at a time.
See Architecture for the source layout, and the repository's tests/ folder for unit tests, mocked integration tests, the fake SCPI server and the fixtures captured from the real instrument.
Releases are made by tag-triggered GitHub Actions: a GitHub release with the npm tarball, a Docker image on GitHub Container Registry the package is also published to the npm registry (with provenance). v1.1.0 is released and on npm. Tags and releases are a maintainer decision; see docs/releasing.md.
MIT licensed. Verified on a UNI-T UTS3036B (firmware V1.04.0040); other models are untested. This wiki is generated from the repository's docs/ folder, which is authoritative: change it there, not here.