Skip to content

v4.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 11 Aug 17:30
· 6 commits to main since this release
d90fe2a

Optional multi-portal mode: a single server can serve many customer portals,
selecting the active one at runtime, instead of running one server (and pasting one
token) per portal. With LM_MULTI_PORTAL=true the server no longer binds to a fixed
portal + token at startup — it loads a credential vault and switches portals on
demand, so the full tool set is registered once rather than per portal. Core LM tools
273 -> 277 (full surface 306). Single-portal behavior is unchanged.

Added

  • list_portals -- list the portals in the vault (name, host, auth type, writable).
    Returns metadata only; never a token.
  • use_portal -- make a portal active for subsequent tool calls (builds and caches a
    LogicMonitor client per portal on demand).
  • current_portal -- show the active portal.
  • reload_portals -- re-read the vault so portals added/removed since startup take
    effect without a client restart (keeps the active portal if it still exists).
  • New portals grouping in search_tools and the tool-categories resource (not an
    LM_MCP_CATEGORIES token; portal tools are exempt from category filtering in
    multi-portal mode).

Behavior and safety

  • Credentials load from an age-encrypted vault (LM_VAULT_FILE + LM_AGE_KEY) or a
    plaintext JSON file (LM_PORTALS_FILE, testing only) instead of the environment.
  • Read-only by default per portal: a write requires both LM_ENABLE_WRITE_OPERATIONS=true
    and "writable": true on that portal's vault record (error code PORTAL_READ_ONLY).
  • Data tools return a clear "No portal selected" message until use_portal is called.
  • Single-portal mode is preserved: without LM_MULTI_PORTAL, a fixed LM_PORTAL is
    still required (fail-fast retained), and behavior matches previous releases.

Config

  • portal is now optional (multi-portal selects at runtime); added multi_portal,
    vault_file, age_key, and portals_file. Authentication validation is skipped in
    multi-portal mode; base_url guards a missing portal.

Fixed (multi-portal hardening)

  • Multi-portal mode is stdio-only: config construction rejects it with the HTTP
    transport, whose process-global client would leak the active portal across
    concurrent callers (this also removes the unreachable-healthy healthz state).
  • Portal tools are hidden and rejected outside multi-portal mode; a vault in the
    environment can no longer repoint a single-portal server or bypass the per-portal
    write gate.
  • Multi-portal config fails fast at startup when no vault source is configured;
    vault paths expand ~; the encrypted vault takes precedence over
    LM_PORTALS_FILE with a warning when both are set.
  • age failures surface stderr, a missing age binary gets a clear error, and
    decryption has a 30s timeout.
  • Vault record hostnames are normalized like LM_PORTAL (scheme stripped,
    validated); one invalid record warns instead of breaking the vault.
  • reload_portals is atomic (a failed reload leaves the old registry, active
    portal, and client intact) and closes replaced clients instead of leaking
    connection pools; shutdown clears the global client reference.
  • LM_MCP_CATEGORIES no longer filters out the portal tools in multi-portal mode
    (the documented Cursor recipe previously made the mode unusable).
  • search_tools, get_reference, and get_workflow work before a portal is
    selected.
  • Terraform tools return a clear unsupported error in multi-portal mode instead of
    running with no credentials.
  • portal_url deep links use the active portal instead of emitting
    https://None/...; ingest_url guards a missing portal.
  • The write gate reports "No portal selected" before claiming a portal is
    read-only; portal switches are recorded in session history and the write audit
    log, and audit lines carry the active portal name.
  • Deploy scripts and MULTIPORTAL.md: lm-mcp-add.sh creates the age identity on
    first run (the referenced vault setup now exists), the launcher honors
    LM_PORTALS_FILE and falls back to the published package when no clone is
    present, hardcoded personal paths are gone, and the manual re-encrypt snippet
    can no longer truncate the vault via an unset variable.