npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@isogonic/codeplane-server-inventory

v0.5.6

Published

Codeplane MCP server for SSH server inventory with encrypted secrets. Lets Codeplane agents answer 'audit all <group> servers' without manual credential input.

Readme

[!WARNING] This server exposes SSH and optional remote command execution to AI agents. Treat it like a privileged credential-aware tool: do not expose it over a network, and use SERVER_INVENTORY_ALLOW_EXEC=0 (the default) unless you explicitly need exec_on.

What It Is

An MCP server for Codeplane that stores:

  • A grouped, tagged inventory of SSH hosts — hostname, user, port, identity file, jump host, or just an ssh_alias that resolves via ~/.ssh/config.
  • An encrypted secrets store for passwords, sudo passwords, key passphrases, DB credentials, and API tokens — retrieved right before the call that needs them, never written to disk in plaintext.

Everything writable lives in your Codeplane data directory:

~/.config/server-inventory/
├── servers.json   inventory (no secrets, 0600)
├── secrets.enc    AES-256-GCM blob, master key in your macOS Keychain
└── audit.log      append-only JSON-lines, every mutation

Use the paths_report tool to get every file location, including resolved identity file paths and ssh aliases that don't resolve in your ~/.ssh/config.

Install

npm install -g @isogonic/codeplane-server-inventory

Or install locally in a project:

npm install @isogonic/codeplane-server-inventory

Add to Codeplane

This server runs as a local stdio MCP server. There is no separate CLI or network service.

Via Codeplane UI

  1. Open CodeplaneSettingsMCP Servers (or Connected Apps / Plugins, depending on your UI version).
  2. Click Add Server / Connect.
  3. Choose Local command (or Custom command).
  4. Fill in:
    • Name: server-inventory
    • Command: npx -y @isogonic/codeplane-server-inventory
    • Environment: add SERVER_INVENTORY_ALLOW_EXEC = 0
  5. Save / Connect. Codeplane will spawn the server on demand.

Via codeplane.jsonc

Add this to your codeplane.jsonc (or codeplane.json):

{
  "mcp": {
    "server-inventory": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@isogonic/codeplane-server-inventory"
      ],
      "environment": {
        "SERVER_INVENTORY_ALLOW_EXEC": "0"
      },
      "enabled": true,
      "timeout": 10000
    }
  }
}

If you installed globally:

{
  "mcp": {
    "server-inventory": {
      "type": "local",
      "command": ["server-inventory-mcp"],
      "environment": {
        "SERVER_INVENTORY_ALLOW_EXEC": "0"
      },
      "enabled": true,
      "timeout": 10000
    }
  }
}

Permissions

Allow or prompt for specific tools in codeplane.jsonc:

{
  "permission": {
    "tools": {
      "mcp__server-inventory__list_servers": "allow",
      "mcp__server-inventory__ssh_target_for": "allow",
      "mcp__server-inventory__get_secret": "ask",
      "mcp__server-inventory__exec_on": "deny"
    }
  }
}

MCP tool IDs are generated from the server name and tool name. Keep the server name (server-inventory) stable if you persist permission rules.

Core Features

  • Grouped + tagged inventory — organize servers by environment, role, team, or any tag.
  • Encrypted secrets store — AES-256-GCM with master key from macOS Keychain or scrypt-derived passphrase.
  • Agent-safe defaultsexec_on defaults to dry_run: true, duplicate names are rejected with a hint to use update_server, secrets are never echoed back to the user.
  • SSH reachability probingssh_check classifies outcomes: ok / auth_failed / dns_failure / refused / timeout / host_key_mismatch / unreachable / unknown.
  • Remote command executionexec_on runs commands across a name / group / tag. Opt-in only: refuses unless SERVER_INVENTORY_ALLOW_EXEC=1.
  • Audit trail — append-only JSON-lines log records every mutation and exec_on call (server + exit code only, never command body or output).

File Locations

| File | Default | Override | |------|---------|----------| | Inventory | ~/.config/server-inventory/servers.json | SERVER_INVENTORY_PATH | | Secrets | ~/.config/server-inventory/secrets.enc | SERVER_INVENTORY_SECRETS_PATH | | Audit log | ~/.config/server-inventory/audit.log | SERVER_INVENTORY_AUDIT_LOG | | Master key | macOS Keychain (security) on darwin; scrypt-derived from SERVER_INVENTORY_PASSPHRASE elsewhere | — | | exec_on gate | off by default | SERVER_INVENTORY_ALLOW_EXEC |

All files except ~/.ssh/config are created with mode 0600.

Tools

| Tool | What it does | |------|---------------| | inventory_info | Where the inventory + secrets + audit log live; counts. | | paths_report | Detailed report of every file location, including resolved identity files (with chmod warnings) and ssh aliases (with whether ~/.ssh/config defines them). | | validate_inventory | Sanity-check every server: identity files exist, ssh aliases resolve, every entry is reachable. | | list_servers | Filter by group / tag / environment / role / free-text search. | | get_server | Full record + ssh command + which secret keys are available. | | list_groups | Every distinct group with member names. | | list_tags | Every distinct tag with usage counts. | | ssh_target_for | Resolve a name OR group OR tag to ssh commands. | | add_server / update_server / remove_server | CRUD. remove_server cascades to delete secrets; update_server with rename_to migrates them. | | secrets_info | Backend + master-key provider + secrets file path. | | set_secret | Encrypt + store one value. Accepts expires_at (ISO) or expires_in (30d, 12h, 2w); preserves created_at across updates. Returns metadata, never the value. | | get_secret | Decrypt + return one value. Call this right before the command that needs it. | | list_secrets | Keys for one server with metadata (created_at, updated_at, optional expires_at, expired). Values are never returned. | | list_all_secrets | Every server's keys with metadata + an expired_count. | | delete_secret | Remove one key. | | audit_tail | Last N entries from the audit log. | | ssh_check | Probe reachability per host with structured outcomes. Bounded parallelism, ConnectTimeout, hard kill timer. | | exec_on | Run a non-interactive command across name / group / tag. Opt-in: refuses unless SERVER_INVENTORY_ALLOW_EXEC=1. Defaults to dry_run: true — first call returns reachability + the plan; pass dry_run: false to actually run. Output truncated; audit log records server + exit code only. |

Example: audit all logicplanes servers

A realistic agent flow once the inventory is populated:

user → agent → Codeplane → MCP

agent: list_groups
       ← { groups: [{ name: "logicplanes", count: 4, members: [...] }, ...] }

agent: ssh_target_for { group: "logicplanes" }
       ← { count: 4, targets: [
             { name: "lp-web-1",   command: "ssh [email protected]", ... },
             { name: "lp-db-1",    command: "ssh lp-db-1",         ... },
             { name: "lp-app-1",   command: "ssh -J ops@bastion [email protected]" },
             ...
         ] }

for each target:
  agent: get_server { name }
         ← { ..., secrets: { keys: ["sudo_password"], hint: "..." } }

  agent: get_secret { server, key: "sudo_password" }
         ← { value: "..." }       # used immediately, not persisted

  agent (via its own ssh tool): ssh ... 'echo "$sudo_pw" | sudo -S lynis audit system --quick'

  agent: collects findings

The agent never had to ask you which servers count, what credentials to use, or where the keys live. paths_report would have told it everything in one call if it ever needed to debug.

Security Model

What this server is good for:

  • Personal / small-team inventory that lives on your laptop or a single workstation. The encrypted secrets file is unreadable without the master key, which never leaves your keychain (or env var).
  • Replacing "credentials pasted into chat" with "credentials retrieved from an encrypted local store the moment the agent needs them".
  • An audit trail of what was changed and when.

What it is not:

  • A team password manager. There's no sharing, no rotation policy. Per-key expires_at is a reminder mechanism (surfaced through list_secrets and validate_inventory); it does NOT delete or rotate the value. Use 1Password / Bitwarden / Vault for actual team credential management.
  • An access-control system. Anything that can talk to this MCP server can read all the secrets. Don't expose it over the network.
  • Tamper-proof. The audit log is on disk and can be deleted. If you need cryptographically verifiable history, ship the audit log to a WORM store.

Development

git clone https://github.com/isogonic/codeplane-server-inventory.git
cd codeplane-server-inventory
npm install
npm run build     # compile TypeScript -> dist/
npm run test:unit # node --test on the unit suites
npm run smoke     # spawn the built MCP server, exercise every tool
npm test          # build + unit + smoke chained
npm run dev       # run src/index.ts directly via tsx (no build)

Set SERVER_INVENTORY_TRACE=1 for stderr breadcrumbs from the lock / load / save paths when debugging.

Cross-Platform Support

Works on:

  • macOS (uses Keychain for master key by default)
  • Linux (uses env-passphrase fallback)
  • Windows (uses env-passphrase fallback; file permissions are ignored by the OS)

All files use Node.js built-ins (path, fs, os, crypto) and are tested on ubuntu-latest and macos-latest with Node 20 and 22.

Repository Layout

src/
  index.ts        MCP server entry point (stdio)
  inventory.ts    inventory store + SSH resolution
  secrets.ts      encrypted secrets store
  audit.ts        append-only audit log
  schema.ts       Zod validation
  paths.ts        paths_report helper
  ssh.ts          ssh_check / exec_on implementation
tests/            Node test suites
scripts/          smoke test
dist/             compiled output

License

MIT — see LICENSE.