Releases: hurtener/dockyard
v1.7.3
Fixed
- Template scaffolds no longer pin
v0.0.0.dockyard new --template analytics-widgets/--template approval-flowspreviously hardcoded
require github.com/hurtener/dockyard v0.0.0in the generatedgo.mod, so a
project scaffolded with a published CLI failedgo mod tidywith
unknown revision v0.0.0unless--dockyard-path(and itsreplace
directive) was supplied. The templatego.mod.tmplnow resolves the Dockyard
version through a__DOCKYARD_VERSION__token — the same release-version pin
the blank scaffold already applied — so ago install …@latestCLI pins the
real release version and resolves the published module flag-free
(D-186). - The distributed inspector now actually works. Every distributed
dockyard
binary — bothgo install …@latestand the cross-compiled GitHub Release
downloads — previously shipped a non-functional inspector:dockyard dev/
dockyard inspectserved a placeholder page ("The inspector frontend has not
been built yet") because the embedded Svelte SPA bundle was gitignored and
neither distribution channel ran the localmake inspector-bundlestep. The
bundle (internal/inspector/dist/) is now committed, so the embedded inspector
is the real SPA on every channel; a CI freshness gate
(make inspector-bundle-check) keeps the committed bundle in lock-step with
web/inspectorsource (D-187).
Documentation
- Template walkthroughs now spell out the web setup before the dev loop. The
getting-started and template-walkthrough pages make explicit that a template
ships a Svelte UI requiring(cd web && npm install)and a one-time
dockyard buildbeforedockyard dev— without them the dev loop fails with
vite: command not foundandopen web/dist/index.html: file does not exist. The pages also document thatdockyard devauto-attaches the inspector
(and the standalonedockyard inspectalternative), and lead the scaffold
commands with the flag-free published-CLI form.
Commits
Fixed
- preflight: serialize the web/docs smoke gates under parallel execution (D-188)
- inspector: make inspector-bundle-check structural, not a byte-diff (D-187)
- scaffold,inspector: repair the published-CLI path; parallelize preflight
v1.7.2
Changed
- Published-docs refresh. The docs site (
docs/site/) no longer reads as
v1.0.0: install commands use@latest, the home "Released" callout is
version-agnostic, and "V1" era phrasing is removed. The Svelte App sketches in
the getting-started and UI-resources guides were rewritten to the real
dockyard-bridgeAPI (createBridge()→bridge.onToolResult(r => r.structuredContent)→bridge.connect()) — the previous sketches showed a
top-level API that no longer exists — and now composedockyard-ui's
PageState. The inspector guide notes it validates the App handshake and sizes
the preview; the approval-flows guide flags inline elicitation as
Dockyard-host-only.
Fixed
dockyard new --helpno longer lists a non-existentinspectortemplate
(onlyanalytics-widgetsandapproval-flowsship). The auto-generated CLI
reference is regenerated accordingly.
v1.7.1
Fixed
- The
approval-flowstemplate now passesdockyard build. (D-184) A
contract with a free-shapemap[string]anyfield whose Go doc comment contains
an example object literal (e.g.{"subscribers": 1247}) was wrongly reported as
a schema↔TypeScript drift, blocking the build. The generated code was correct;
the drift cross-check's line-oriented TypeScript parser mistook the example's
closing}(on a JSDoc comment line) for the interface's closing brace and
truncated the field list. The parser now skips comment content. Surfaced because
the template smoke only rango build, neverdockyard validate— it now runs
dockyard validateso this class of drift is gated. - Both templates' READMEs gain a step-by-step build-and-run Quickstart
(dockyard new→go run/dockyard dev→dockyard build→
dockyard install).
Commits
Fixed
- codegen: drift cross-check skips JSDoc comment braces; templates buildable + README quickstart (D-184)
v1.7.0
Changed
dockyard-bridge'sui/wire layer is now pinned to the vendored official
@modelcontextprotocol/ext-appsschema. (D-182) The bridge previously
hand-transcribed the MCP Apps wire dialect, which drifted silently (the cause
of the 1.6.1 handshake bugs). The schema is vendored into the repo by upstream
SHA, and a wire-conformance test now.parse()s the bridge's outbound wire
against it — a drift is a failing build, not a blank App in a host. The shipped
App bundle stays Zod-free and consumers need no schema dependency (the schema
is referenced only by the bridge's test layer).HostContextgains schema-accurate fields (additive).containerDimensions
now models flexible sizing (maxWidth/maxHeight) alongside fixed
width/height;stylesgainscss.fonts;toolInfo,platform, and
deviceCapabilitiesmatch the schema.
Fixed
dockyard-bridgeadvertisesappCapabilities.availableDisplayModes, not
displayModes. (D-182, item A) The host's parse silently stripped the
non-schemadisplayModeskey, so it never learned which display modes an App
supported and fullscreen/pip degradation never worked. The publicdisplayModes
bridge option is unchanged.dockyard-bridgehandlesui/resource-teardownas a request, not a
notification. (D-182, item B) A spec host sends teardown as a request and
waits for the View's response before tearing the iframe down; the bridge now
responds, then closes. Adds the app-initiatedui/notifications/request-teardown
(BridgeShell.requestTeardown()).dockyard-bridgeapplies host fonts. (D-182, item D) Host-provided
styles.css.fontsCSS is injected into the View document so the host's fonts
load.ui/messageandui/update-model-contextnow send schema-conformant
content. (D-182 — checkpoint audit) Both sent a bare-stringcontent(and
ui/messageallowed a non-userrole); the schema requirescontent: ContentBlock[](androle: "user"), so a spec host would have rejected them.
sendMessagenow wraps a string into a text block;UpdateModelContextParams.content
isContentBlock[]. The conformance test now.parse()s every View→host
request (open-link, message, request-display-mode, update-model-context), not
just the handshake.- The local inspector consumes the View's
size-changedandrequest-teardown.
(D-182, item 4 — checkpoint audit) It sizes the preview iframe to the App's
reported content height (mirroring a real host) and remounts on a teardown
request, instead of silently dropping both. - Conformance coverage extended to the full wire (D-182 — second audit pass).
The conformance layer now also guards the bridge's inbound reads (a
schema-validtool-input/tool-result/tool-cancelled/host-context-changed
reaches the App subscriber with every field intact), the inspector's
outbound host→View wire (the reference host'sui/initializeresult,
request-display-moderesult, and notifications.parse()clean), and the
server-emitted_meta.ui+ capability shapes. Inbound notification types
(arguments,width/height) are now optional to match the schema.
Packaging
dockyard-bridge/specexposes the vendored ext-apps schema (used by the
inspector and the bridge's own conformance tests). Itszod+
@modelcontextprotocol/sdkimports are provided by the consumer (devDependencies
of bothdockyard-bridgeandweb/inspector); they are intentionally not
declared as peer dependencies — an optional peer makes a bundler stub it and
breaks the production build. The package's.entry imports no zod, so App
authors importing only.install nothing extra.- The local inspector is a faithful, validating spec host. (D-182, item 4) It
no longer sends a host→Viewui/notifications/initialized; it marks itself ready
when the View sendsinitialized, readsavailableDisplayModes, and now
validates the View'sui/initializeagainst the vendored schema, rejecting a
non-spec shape with a JSON-RPC error. This removes the leniency that let the
1.6.1 View bugs pass locally — the inspector now catches them. The schema is
shared via a new opt-indockyard-bridge/specsubpath (the package's.entry
stays Zod-free for App consumers).
Notes
- Dockyard's Tasks×Apps
ui/notifications (task-progress,
elicitation-response) are now explicitly fenced as Dockyard extensions
outside the MCP Apps schema; they function only against a Dockyard-aware host
(the inspector, or Harbor). (D-183)
Commits
Added
- inspector: validate inbound ui/initialize against the vendored schema (D-182, item 4)
- bridge: teardown-as-request, fence Dockyard exts, faithful inspector host (D-182/D-183)
- bridge: vendor ext-apps schema + wire-conformance test + items A/C/D (D-182)
Fixed
- inspector: resolve dockyard-bridge/spec zod from the inspector root (fixes make build in CI)
- bridge,inspector: checkpoint-audit fixes for v1.7 wave A (§17)
v1.6.1
Fixed
-
dockyard-bridgeui/initializenow uses the MCP Appsui/dialect — a
spec-compliant host no longer rejects the View handshake. (D-179) The View's
ui/initializerequest sent base-MCP{capabilities:{appCapabilities}, clientInfo}; the MCP Apps host (@modelcontextprotocol/ext-apps) validates the
request against a strict schema requiring top-level{appInfo, appCapabilities, protocolVersion}(appInfoREQUIRED). The mismatch made the host return a
JSON-RPC error for the first handshake message, soconnect()rejected,ready
never became true, and an otherwise-correct App rendered blank with no visible
error. The bridge now sends theui/dialect shape. (Hosts only spoke this
dialect; the local inspector accepted the base-MCP shape, which is why this
passed locally.) The publicclientInfobridge option is unchanged. -
dockyard-bridgeSENDSui/notifications/initializedrather than awaiting it.
(D-180) The handshake waited to receiveui/notifications/initialized
before resolvingready. Per the JSON-RPC/MCP lifecycle (and the ext-apps
reference View) the View is the initiator and sendsinitializedafter the
ui/initializeresult, then is ready. A spec-compliant host never sends a
View→host message, so the old code deadlocked. An inboundinitializedfrom a
non-spec host is now ignored. -
dockyard-bridgereports View content size to the host via
ui/notifications/size-changed. (D-181) The bridge only ever received
size-changed(host→View); it never measured or reported its own content
height. A spec-compliant host sizes the App iframe from the View's report;
without it the iframe collapses to ~0px and the App looks blank even after it
paints. The bridge now runs aResizeObserverand emits a de-duplicated
size-changedon ready and on every change, torn down inclose().
Commits
Fixed
- bridge: speak the MCP Apps ui/ dialect so a spec host renders the App
v1.6.0
Changed
-
_meta.ui.domainis now a host-supplied verbatim value; server-side
auto-derivation is retired. (Behaviour change — minor.) The MCP Apps spec
makesdomainhost-dependent — the host mints the dedicated iframe origin
and documents its format; a server copies it verbatim or leaves it empty.
App.Domainis emitted onresources/readbyte-for-byte; Dockyard no
longer synthesises Claude's{hash}.claudemcpcontent.comsubdomain (which a
local connector rejects). What changes for you: a project that set
HostProfile: "claude"+Domainpreviously got a derived
claudemcpcontent.comorigin and now gets itsDomainverbatim — setDomain
to the exact origin your host documents for a verified remote deployment, or
leave it empty for the host's default per-conversation origin.App.HostProfile
andApp.ServerURLare deprecated (retained, ignored for derivation); the
pluggable host-profile seam stays for a future host-blessed transform. The
default scaffold and templates set noDomain, so they are unaffected. (D-176) -
A stdio-only server that sets a
Domainnow warns at startup. A dedicated
origin is honoured only on a remote connector; a local (stdio) connector
ignores it.ServeStdiologs a loudslog.Warnnaming the App;
HTTPHandlerdoes not. (D-176) -
The product templates scaffold the html-style
ui://<server>/<app>/index.htmlresource URI. This matches the reference MCP
Apps SDK convention. The framework treats theui://URI as an opaque string,
so this is a convention + docs change only — an existing project's
ui://<server>/<app>URI keeps working. (D-178)
Added
- A server-level opt-in to additionally emit the deprecated flat tool-UI
_metakey.server.Options{EmitLegacyToolUIMeta: true}makes every
UI-bearing tool registered through theruntime/toolbuilder carry the
deprecated flat key alongside the canonical nested_meta.ui.resourceUri, for
a host that still reads the flat form. The default (off) is unchanged
RFC-compliant nested-only output; the 2026-01-26 spec marks the flat form
deprecated, so Dockyard never emits it by default. (D-177)
Commits
Added
- apps: v1.6 wave A — MCP Apps spec-alignment (verbatim domain, opt-in flat key, html-style URI)
v1.5.0
Changed
-
The frontend packages are renamed to unscoped names:
@dockyard/bridge→
dockyard-bridge,@dockyard/ui→dockyard-ui. They publish under an
unscoped personal-account name (the@dockyardorg scope was unownable and
blocked the v1.4.0 npm publish). An App's imports change accordingly
(import { createBridge } from 'dockyard-bridge'); the templates and the
attach-a-ui-resourceskill are updated to match. Nothing was ever published
under@dockyard, so there is no deprecation to manage. The internal
inspector frontend keeps its@dockyard/inspectorworkspace name (it is never
published). (D-174) -
Builder.UIgained an optional visibility variadic —
.UI(appName, tool.VisibilityApp)sets_meta.ui.visibilityfor a UI-only
action tool; omitting it keeps the spec default (model + app). New
tool.VisibilityModel/tool.VisibilityAppconsts. Behaviour change: a
.UI("name")that references no registered App now returns a typed error at
Register(previously a silent no-op) — register the App (apps.Register)
before the tool. A correctly-ordered project is unaffected. (D-173)
Fixed
- A framework-wide wiring audit (the same class as the
_meta.uibug) fixed
three declared-but-unwired seams:require_spec_complianceis now enforced. The quality flag was
declared, scaffoldedtrue, and documented "enforced bydockyard validate", but no consumer read it — the spec-compliance check ran
unconditionally, so toggling the flag did nothing. It now gates the check
(opt-out), consistent with the otherquality.*gates. All shipped
manifests set ittrue, so no real project changes behaviour. (D-175)@dockyard/bridge'sui/resource-teardownnow tears the View down.
The notification was documented as triggeringBridgeShell.close()but was
never dispatched — a production host sending it would leak the bridge's
listeners/transport and leavereadystucktrue. It now callsclose().- The bridge retains the negotiated
protocolVersion+hostInfofrom
theui/initializeresult (exposed asbridge.protocolVersion/
bridge.hostInfo);protocol.tspromised retention but both were
discarded.
tool.New[...].UI(appName).Register(srv)now emits the tool→App link.
The builder previously dropped it silently — the registered tool carried no
_meta.ui.resourceUri(RFC §7.1), so a host that renders MCP Apps showed the
text fallback instead of the App. The builder now resolves the App's name to
itsui://URI (via a newserver.AppLinkseam recorded byapps.Register)
and emits_meta.uiatRegister. Theanalytics-widgetstemplate is fixed
automatically (no template change). (D-173)
Commits
Fixed
- wiring: framework-wide audit — enforce require_spec_compliance, wire bridge teardown + handshake retention (v1.5 wave A)
- tool: wire the tool→App _meta.ui link in the builder (v1.5 wave A item 1)
v1.4.0
Added
@dockyard/bridgeand@dockyard/uiare published to npm. A
scaffolded UI project'sweb/now resolves them from npm with no
--dockyard-pathand no local Dockyard checkout —dockyard new --template analytics-widgetsthencd web && npm installjust works. The
packages setpublishConfig.access: "public", track the repo version, and
publish from a gated, idempotent tag-push job (verified bynpm pack+ a
scaffold-install build first).--dockyard-pathreverts to a pure
build-from-source convenience (D-172).- Bridge View-side task-progress channel.
@dockyard/bridgeexposes a
typedbridge.onTaskProgress((p) => …)subscription so an MCP App's card
can render a live progress value (e.g. "62%") for a long-running task,
fed by a newui/notifications/task-progresshost→View notification
(RFC §8.4). The Dockyard runtime emits eachTaskHandle.Progress/
TaskHandle.Statuscall as anobs/v1task.progressprogress-phase
event; the inspector forwards those to the App preview, so the channel is
demoable throughdockyard inspect. A host that does not forward progress
degrades cleanly — the subscriber simply never fires (D-171).
Changed
obs/v1task.progresspayload gained an optionalfractionfield
(the task's completion fraction in [0, 1] at a mid-flight progress point).
This is an additive change to theobs/v1contract — existing
consumers that do not read it are unaffected, the schema version stays
dockyard.obs/v1, and the golden tests pin the new shape (D-171).
Commits
Added
- release: publish @dockyard/bridge + @dockyard/ui to npm (v1.3 wave B item 4)
- bridge: View-side task-progress channel (v1.3 wave B item 5)
v1.3.0
Added
dockyard new --here— scaffold into an existing non-empty directory
(e.g. one you alreadygit init-ed). Existing files are left untouched;
a scaffold output that would overwrite a file is refused, never silently
overwritten.
Changed
- The
require_fixturesandrequire_contract_testsquality gates are
now enforced bydockyard validate(previously declared but inert).
require_fixturesis UI-scoped — each tool with aui:app must ship
inspector fixtures (fixtures/<tool>/*.json); a non-UI tool needs none.
require_contract_testsrequires the project to carry at least one
*_test.go. Behaviour change: a project that turned a gate on but
does not satisfy it (a UI tool with no fixtures, or a project with no
test) now failsdockyard validatewhere it previously passed. A freshly
scaffolded project — blank or template — stays green. dockyard newpins the CLI's version into the scaffoldedgo.mod
(instead of thev0.0.0placeholder) when the CLI knows its release
version, so a project that drops the localreplacedirective resolves
the published module without a hand edit. Released binaries and
go install …@vX.Y.Znow also report their real version.
Fixed
dockyard new's "directory not empty" error now names the entries it
found (so a hidden.git/or.gitignoreis visible as the cause) and
points at--here.
Commits
Added
- v1.3-wave-A: enforce quality gates, pin go.mod version, dockyard new --here
Fixed
- ui: widen inspector rail + wrap long table cells
v1.2.0
Added
dockyard new --no-postgen— opt out of the new post-scaffold steps
(for hermetic / air-gapped / CI runs, or to run them yourself).
Changed
dockyard newnow runsgo mod tidy+dockyard generatefor you
at scaffold time, so a fresh project — blank or--template—
reaches a greendockyard validateon the first try with no manual
command. The steps are best-effort: a failure (e.g. no module-proxy
reach) prints a warning and the manual fallback rather than failing the
scaffold. Opt out with--no-postgen.- Release notes now carry an auto-generated commit supplement. A
GitHub Release body is the hand-authoredCHANGELOG.mdsection
followed by a Conventional-Commits-derived list of what landed
(feat→ Added,fix→ Fixed, the rest → Changed;docs/chore/
test/ci/build/styledropped). The hand-authored prose stays the
canonical narrative; the supplement is appended on a tag push only.
Commits
Added
- cli,changelogx: v1.2 wave A — scaffold autogen + changelog supplement
Fixed
- skills: avoid line-leading "+" that markdownlint reads as a bullet