add_connection advertised an empty `{ properties: {} }` while the server
validated strictly, so clients could not see field types or the required
`type` literal and sent port/verifyTls as strings.
Cause: the connection schema was wrapped in `.superRefine`, producing a
ZodEffects with no `.shape`. The MCP SDK's normalizeObjectSchema returns
undefined for it and falls back to EMPTY_OBJECT_JSON_SCHEMA. update_connection
passed a raw shape, so it serialized fine - hence the asymmetry.
Split the schema: a strict z.object (connectionObjectSchema) is advertised as
the wire schema, and the refined connectionConfigSchema is passed as a new
optional parseSchema applied in the handler. Strict unknown-key rejection and
the apiKey-or-user+password check are both preserved. fullSchema is now typed
as a ZodObject so a ZodEffects can no longer be passed by mistake.
Build from repo root so @dbmole/core resolves; tsup bundles core into
dist while undici/MCP SDK/zod/ssh2 ship as pruned node_modules.
Mark ssh2 external in tsup: it is pulled in transitively by the bundled
core and ships an optional native crypto addon (pure-JS fallback). Inlining
would force esbuild to resolve a .node binary that need not exist on the
target; node-gyp also cannot reliably build it on alpine. Externalizing lets
ssh2 resolve from node_modules at runtime.
npm nests undici under packages/esmole-mcp/node_modules, so the runtime
stage copies both the root and the per-package node_modules.