Mirth Connect Explorer for Visual Studio Code
Browse and manage Mirth Connect 4.x servers from the VS Code sidebar: channel groups and channels with live deployment state, code template libraries, XML and JavaScript editing with save-back to the server, and opt-in channel control (deploy / start / stop) — without keeping the Mirth Administrator open.
Multiple servers are supported natively: each configured connection is its own root in the tree, so several Mirth instances can be watched side by side.
Requirements: VS Code ≥ 1.85 · Mirth Connect 4.x with HTTP Basic authentication · a user with at least Read permission on the API resources (full channel control additionally needs the corresponding write permissions).
Features
Browsing
One root per configured server in a dedicated activity-bar view. The server node shows the version and the write mode (· read-only, · writes on, · writes on · no confirm).
Channel tree organized by channel groups (GET /api/channelgroups, the 3.4+/4.x organization level):
● Production Mirth (v4.5.2)
Channels
Clinical Integrations
● ADT Inbound [started]
import HL7 MLLP Receiver
export To Lab System
● Lab Results Router [paused]
Legacy Interfaces
○ Legacy Archive [undeployed]
Ungrouped Channels
● Ops Monitor [started]
Code Template Libraries
Default Library
ƒ getCurrentDate [function]
𝐂 PersonUtils [class]
HL7 Utilities
ƒ buildAck
Channels not assigned to any group appear under Ungrouped Channels; if the groups endpoint is unavailable or empty, the list falls back to a flat view and an explanatory node says so.
Deployment state icons, merged from GET /api/channels/statuses:
- ● green — started
- ● yellow — paused
- ● red — stopped
- ● blue — deployed (not started)
- ○ grey — undeployed (in the channel list but has no status entry)
Code template libraries → templates hierarchy. Real Mirth libraries embed id-only template stubs (includeCodeTemplates=false is the server default); the extension joins them against GET /api/codeTemplates. Templates outside any library appear under Unassigned Templates.
Sections that come back empty show an explicit message node instead of silent whitespace.
Viewing and editing documents
- Click a channel or connector to open its channel definition as pretty-printed XML in a
mirth: virtual document (also right-click → Open XML).
- Click a code template to open its JavaScript, syntax-highlighted as JavaScript.
- Edit and Ctrl+S saves back to the server on connections with Allow writes enabled:
- channel XML →
PUT /api/channels/{id} — the exact document GET returns, so round-trips are lossless;
- template JavaScript → the client fetches the template JSON, patches only
properties.code, and PUTs the original wire shape back to PUT /api/codeTemplates/{id} — revision, contextSet, name and every other field are preserved untouched. Works for FUNCTION and CLASS templates.
- Save guards: saves whose
<id> element is missing or changed are refused client-side before any request (keep <id>, rename via <name> — Mirth rejects mismatched ids server-side with an opaque 400).
- After saving a channel the extension offers Redeploy now — the running deployment keeps the old revision until the channel is redeployed.
- On read-only connections the editor shows its read-only badge and blocks edits. Toggling the connection's Writes switch re-evaluates open documents in place — they flip between read-only and editable without a manual reopen.
Channel control (writes, opt-in per connection)
- A Writes switch per connection — read-only is the default. Read-only connections show no write actions at all and a permanent
· read-only badge.
- With Allow writes on, channel nodes offer Deploy / Redeploy / Undeploy and Start / Resume / Pause / Stop (right-click → the writes section). These are the same endpoints the Mirth Administrator uses, each carrying
?returnErrors=true so asynchronous server-side failures surface as HTTP errors instead of a silent 200. Redeploy sends _deploy — the API documents it as "Deploys (or redeploys) a single channel"; there is no _redeploy endpoint. After the action the tree refreshes so the state icons reflect the result.
- Write confirmations are a separate per-connection switch. By default every action opens a modal naming the channel, the server and the concrete effect. On trusted dev servers the dialogs can be turned off (Configure Connection → Write confirmations); such servers are visibly marked (
· writes on · no confirm badge, "run immediately" in the tooltip), and the after-save Redeploy now offer skips its second dialog too.
- The gate is enforced twice: the UI only offers the actions on writable connections, and the REST client refuses any write on a read-only connection before a single byte leaves the process. Production instances stay protected even if another code path tries.
Diagnostics
- Request log — every request is logged to the Mirth Explorer output channel (
Mirth: Show Output Log) with method, path, byte size and the applied TLS state (tlsMode=…, certs=allowed|verified, sni=sent|suppressed).
- Copy Connection Diagnostics (server right-click) — a per-endpoint report on the clipboard: HTTP status, content type, size, JSON shape and a raw response sample for every read endpoint, plus the VS Code proxy-layer state. The fastest way to diagnose a server that connects but shows an empty tree.
- Run TLS Diagnostics (server right-click) — probes the server port with a matrix of handshake configurations (TCP reachability, plain-HTTP detection, TLS 1.3/1.2, classic ECDH groups, legacy ciphers, no-RSA-PSS, no-SNI) and reports which one the server accepts, including the peer certificate (a corporate issuer exposes an SSL-inspection middlebox). When a probe succeeds it offers to apply the matching TLS compatibility mode — or, for the no-SNI probe, to suppress SNI (combined with allow self-signed when the server then presents Mirth's default self-signed certificate). When every probe is rejected, the report embeds ready-to-run
curl.exe (Windows schannel) and openssl s_client cross-check commands that decide whether the block is client-side or server/network-side.
- Resilient error handling — connection failures, bad credentials (401/403), wrong API base paths (404), TLS problems and timeouts surface as a tree error node with a human-readable message; certificate errors open Configure Connection directly when clicked.
Installation
The shipped mirth-explorer-1.0.0.vsix already contains the compiled bundle, manifest and docs — end users install it directly, with no npm install, no compile step and no Node.js required:
- VS Code UI: Extensions view (
Ctrl+Shift+X) → ⋯ menu → Install from VSIX… → pick the .vsix file.
- Command line:
code --install-extension mirth-explorer-1.0.0.vsix
- VS Code forks (VSCodium, Cursor, …): the same Install from VSIX… action in their extensions view.
To build the .vsix yourself, run npm install && npm run package (adjust publisher in package.json first if you plan to publish).
Connecting to a server
Run Mirth: Add Connection (palette, + button on the view, or the welcome-screen button) and enter:
Display name — e.g. Production Mirth.
Base URL — e.g. https://localhost:8443/api. A trailing /api is added automatically if missing; http:// or https:// is assumed (https:// when omitted).
Username / password — the password is stored in VS Code secret storage (OS keychain), never in settings.json.
Certificate handling — choose Allow self-signed certificates for servers without a trusted CA certificate.
TLS compatibility — leave Default TLS for normal servers. If the handshake fails (SSL alert number 47 / EPROTO), retry with:
- Classic ECDH groups only — first choice for alert 47: modern VS Code/Electron clients offer post-quantum key groups (e.g.
X25519MLKEM768) that some Java servers and TLS appliances reject;
- TLS 1.2 + classic ECDH groups — caps the protocol at 1.2 and restricts key groups (the thorough fix);
- Disable TLS 1.3 — caps the handshake at TLS 1.2 (keeps modern groups);
- Legacy TLS — also allows outdated protocols/ciphers (last resort).
If none of the modes work, run Mirth: Run TLS Diagnostics (right-click the server): it probes the port with the full handshake matrix, reports which configuration the server accepts, detects plain-HTTP ports misconfigured as https://, and offers to apply the working mode automatically.
Writes — read-only first (recommended); Allow writes exposes deploy/undeploy and channel control plus editable documents.
Write confirmations (only asked when writes are enabled) — Confirm every write (default) shows a modal before each channel state operation; Run writes immediately skips those dialogs for trusted dev servers.
The connection is probed with GET /api/server/version before it is saved, so typos fail fast. Everything except the password can be changed later via Mirth: Configure Connection (server right-click): TLS compatibility, certificate handling, SNI suppression, base URL (changing it keeps the TLS/certificate/SNI settings), writes and write confirmations. Change passwords with Update Password; Remove Connection also deletes the stored secret.
Per-connection settings reference
| Setting |
Values (default first) |
Stored as |
| TLS compatibility |
default · classic-groups · tls12 · tls12-classic · legacy |
tlsMode |
| Certificate verification |
verify certificates · allow self-signed |
allowSelfSigned |
| SNI |
sent · suppressed (connects to the resolved IP, Host header unchanged) |
suppressSni |
| Writes |
read-only · allow writes |
allowWrites |
| Write confirmations |
modal before each write · run immediately |
confirmWrites |
| Base URL |
editable in place |
url |
Connections live in user settings under mirthExplorer.connections, so they are reviewable and hand-editable; passwords never are.
What the extension calls
| Endpoint |
Used for |
GET /api/server/version |
Version shown on the server node; connection probe (produces text/plain) |
GET /api/channels |
Channel list incl. source/destination connectors |
GET /api/channels/statuses |
Deployment state per channel |
GET /api/channels/{channelId} |
Channel XML (Accept: application/xml) |
GET /api/channelgroups |
Channel groups (all-lowercase path, as declared by Mirth) with their channel references |
GET /api/codeTemplateLibraries |
Code template libraries (embeds id-only template stubs; ?includeCodeTemplates=true adds the full templates) |
GET /api/codeTemplates / GET /api/codeTemplates/{id} |
Flat template list (script under properties.code) and per-template fallback |
PUT /api/channels/{channelId} |
Save an edited channel XML (writes-enabled connections only) |
PUT /api/codeTemplates/{templateId} |
Save an edited code template (fetch-patch-PUT of properties.code; writes-enabled connections only) |
POST /api/channels/{channelId}/_deploy / _undeploy / _start / _stop / _pause / _resume |
Channel lifecycle writes (writes-enabled connections only), each with ?returnErrors=true so asynchronous server-side failures surface as HTTP errors. Redeploy sends _deploy — the API documents it as "Deploys (or redeploys) a single channel"; there is no _redeploy endpoint |
Authentication is HTTP Basic on every request, and every request carries an X-Requested-With: XMLHttpRequest header — Mirth 4.5+ servers with CSRF protection enabled (the default) answer HTTP 400 to API calls without it. JSON list responses use Mirth's real Jettison shape ({"list": {"channel": [...]}}, single items collapsed to objects) and are unwrapped automatically; servers that answer XML to JSON requests are handled by a minimal XML fallback parser. If your Mirth instance has Basic authentication disabled (custom security/SSO setups), requests will fail with HTTP 401 — token-based login like the NextGen Administrator uses is on the roadmap.
Troubleshooting
| Symptom |
Likely cause / fix |
Authentication failed (HTTP 401) |
Wrong username/password, or Basic auth disabled on the server. Verify credentials in the Administrator; use Update Password after changing them. HTTP 403 usually means the user lacks Read permissions for the resource. |
Not found (HTTP 404) for … |
Wrong base URL or a resource the server doesn't expose — the message names the exact path and the API base in use. Point the connection at the Mirth HTTPS endpoint (usually port 8443); the extension appends /api itself. |
HTTP 400 — "All requests must have 'X-Requested-With' header" |
The server enforces CSRF protection (Mirth 4.5+ default). Current builds always send the header — if you see this, an old build is installed; update the extension. |
TLS handshake failed (EPROTO, SSL alert number 47) |
The server rejected the TLS handshake. Try the connection's TLS compatibility modes in this order: Classic ECDH groups only (fixes rejections of the post-quantum key groups modern Electron clients advertise), TLS 1.2 + classic ECDH groups, Disable TLS 1.3, Legacy TLS. If none work, run Mirth: Run TLS Diagnostics on the server node — it pinpoints which handshake (if any) the server accepts, detects plain-HTTP ports addressed as https://, and shows the peer certificate. |
TLS handshake failed and Windows curl.exe also fails (SEC_E_ILLEGAL_MESSAGE) |
The block is server/network-side, not client-side: Windows' native TLS stack (schannel) is rejected at the same stage — before certificate validation even starts, so --insecure cannot help. Work through the TLS report's checklist: confirm the port is really Mirth's HTTPS listener (default 8443), probe the plain-HTTP variant, and ask the network team whether an SSL-inspecting appliance / load balancer / WAF (JA3 fingerprint filtering) fronts this port or the listener requires a client certificate. The TLS diagnostics report embeds the exact commands. |
| Every SNI-bearing handshake fails, but the no-SNI probe succeeds |
An SNI-routing/filtering front-end (load balancer, WAF, SSL appliance) does not accept the server_name this connection sends. Use the offered "Suppress SNI" option (stored as suppressSni: requests connect to the resolved IP with no server_name extension, Host: header unchanged) — or have the network team allow this SNI name on the front-end. When the server presents Mirth's default self-signed certificate (subject=mirth-connect), the offer combines "Suppress SNI + allow self-signed", because suppressing SNI makes that certificate appear and it would otherwise fail verification on the next connect. Both settings are changeable any time via Mirth: Configure Connection. |
TLS certificate error (DEPTH_ZERO_SELF_SIGNED_CERT, UNABLE_TO_VERIFY_LEAF_SIGNATURE, ERR_TLS_CERT_ALTNAME_INVALID, …) |
The handshake succeeds; certificate verification fails. Enable Allow self-signed certificates — click the tree error node or Mirth: Configure Connection → Certificate verification — then refresh. Suppressing SNI / using an IP URL surfaces the server's default self-signed certificate, so the two settings often go together. The request log shows the applied state (certs=allowed / certs=verified) on every line. If the log already shows certs=allowed and verification still fails, VS Code's proxy layer is verifying on its own behalf: set Settings → Http: Proxy Support → off (or add the host to Http: No Proxy) and reload — the extension host routes non-loopback requests through its proxy resolver otherwise, which re-applies Http: Proxy Strict SSL and can discard the per-connection TLS settings (request-level TLS options survive that swap; the loopback bypass is why 127.0.0.1 works while remote hosts fail). To trust the certificate properly, install the issuing CA into the OS trust store. |
| Connects but the tree shows no channels / templates |
Empty sections show an explicit message node — click it (or right-click the server → Copy Connection Diagnostics) for a per-endpoint report with HTTP status, content type and a raw response sample. The report header includes the VS Code proxy layer state (http.proxySupport / http.proxy / http.proxyStrictSSL / http.noProxy) — when a proxy fronts the connection, the proxy decides certificate verification and the SNI the server sees. Open Mirth: Show Output Log (View → Output → Mirth Explorer) for the full request log. |
| Channels load but are not divided into groups |
The extension queries /api/channelgroups (all lowercase — Jersey paths are case-sensitive). When the endpoint fails, a message node explains the flat fallback; check that the server's API is reachable and the user has Read permission on groups. |
Connection refused / timeout |
Server not running, wrong host/port, or a firewall between VS Code and the server. |
Channels show as undeployed |
The channel has never been deployed, or GET /api/channels/statuses returned no entry for it — the status icons are best-effort decoration; the channel list itself still loads. |
Cannot edit in read-only editor on a mirth: document |
The connection's Writes switch is off — that is the safety gate, working as intended. Enable it via Mirth: Configure Connection → Writes → Allow writes; open documents re-evaluate automatically after the toggle. If the switch is already on and the editor is still read-only, reopen the editor once so the permission is re-evaluated. |
Saving a channel fails with … <id> … does not match the opened channel |
The <id> element in the XML was changed or removed. Restore the original <id> and save again — Mirth rejects mismatched ids server-side. Rename a channel via its <name> element instead. |
Security notes
- Passwords are stored via
vscode.SecretStorage (encrypted at rest by the OS); connection metadata (name/URL/username and the flags above) lives in user settings.
- Connections start read-only; writes (saving edits, deploy/undeploy, channel control) happen only after enabling the per-connection Writes switch, and each action is additionally guarded by the per-connection Write confirmations switch (on by default). The editor reflects the gate (
FilePermission.Readonly), and the REST client refuses write requests itself as a second line of defense.
- On HTTPS with self-signed certificates, only enable Allow self-signed certificates on networks you trust — disabling TLS verification exposes credentials to man-in-the-middle attacks. HTTP (non-TLS) connections transmit credentials in cleartext; prefer HTTPS for anything non-local.
- Saving documents sends their full content back to the server; channel state operations change the running deployment. Keep both switched off for production connections you only want to inspect.
| |