@mcsherrylabs/pi-meerkat

Meerkat stdio MCP facade and registry tools, with a private pinned Evolver MCP child. Owns the announcement wire contract and preserves the existing Pi extension.

Packages

Package details

extensionskill

Install @mcsherrylabs/pi-meerkat from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@mcsherrylabs/pi-meerkat
Package
@mcsherrylabs/pi-meerkat
Version
0.7.0
Published
Nov 5, 2026
Downloads
977/mo · 311/wk
Author
alanmcsherry
License
Apache-2.0
Types
extension, skill
Size
197.4 KB
Dependencies
5 dependencies · 0 peers
Pi manifest JSON
{
  "skills": [
    "./skills"
  ],
  "extensions": [
    "./extensions"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@mcsherrylabs/pi-meerkat

Meerkat registry tools and a stdio MCP facade. One client registration exposes the seven Meerkat tools plus every tool dynamically discovered from the private @mcsherrylabs/evolver-mcp@0.15.0 child. The released upstream baseline is 65 tools, so healthy discovery currently returns 72. The count is a comparison baseline, not a routing allowlist.

Version 0.7.0 introduces this facade. Version 0.6.0 is the previous Pi/local-signing package and does not contain it. Use the explicit version below, not an unversioned npx command or an assumption about npm latest. Source/packed acceptance, publication, and verification of an installed published release are separate milestones.

Install from npm

Run this in the same environment where Claude Code (or another MCP client) runs. Node 22 is the verified runtime. Installation downloads the package and its exact released dependency; it does not provision or start a node:

npm install --prefix "$HOME/.local/share/meerkat-mcp/0.7.0" \
  --no-audit --no-fund @mcsherrylabs/pi-meerkat@0.7.0
export PATH="$HOME/.local/share/meerkat-mcp/0.7.0/node_modules/.bin:$PATH"

The installed facade resolves and launches its actual dependency's evolver-mcp bin (dist/cli.js). It does not use a sibling source checkout, global executable, or unversioned runtime download. Installation under the home directory persists across rig recreation.

Configure an existing node once

Setup records references, not key bytes. Select an existing node endpoint, separate content endpoint, identity, existing key file, registry read origin, explicit genesis/chain ID and node ID, registry channel, and TLS policy. This command does not provision a node, claim an identity, create/copy a key, initialize a registry database, or change a client registration automatically.

Set the following shell inputs to values you already operate. Do not copy a guessed identity, chain ID, key, or endpoint from a model or from registry content. MEERKAT_TLS_INSECURE=false keeps certificate verification enabled; an explicitly chosen private CA may be supplied with --ca-file /absolute/operator-ca.pem.

meerkat-mcp setup \
  --config "${MEERKAT_CONFIG:?Choose an absolute operator-owned config path}" \
  --node-url "${MEERKAT_NODE_URL:?Select the existing node origin}" \
  --content-url "${MEERKAT_CONTENT_URL:?Select its separate content origin}" \
  --identity "${MEERKAT_IDENTITY:?Select the existing signing identity}" \
  --key-path "${MEERKAT_KEY_PATH:?Select the existing absolute key reference}" \
  --key-type "${MEERKAT_KEY_TYPE:?Select ed25519 or bls}" \
  --tls-insecure "${MEERKAT_TLS_INSECURE:?Explicitly choose true or false}" \
  --meerkat-url "${MEERKAT_READ_URL:?Select the registry processor read origin}" \
  --chain-id "${MEERKAT_CHAIN_ID:?Supply the existing 64-hex chain ID}" \
  --node-id "${MEERKAT_NODE_ID:?Supply the existing inbox-binding node ID}" \
  --channel "${MEERKAT_CHANNEL:?Select the registry announcement channel}"

Create the config's parent directory beforehand. Setup exclusively creates an operator-owned mode-0600 file and refuses to overwrite an existing one. Treat that file and all parent paths as trusted launch configuration; do not let a project or another user replace them. Setup checks that the key reference exists but only the child reads signing-key bytes. Key bytes do not enter the setup output, facade, or registration.

Setup emits one JSON mcpServers entry, with the installed facade's absolute command and --config pointing to the saved file. Add that one Meerkat entry to your MCP client's configuration. No manual environment ceremony, separate Evolver registration, HTTP MCP service, Pi adapter, or separately managed child is required. Direct launch uses the same entrypoint:

meerkat-mcp --config "$MEERKAT_CONFIG"

Register in Claude Code

From the environment where Claude Code runs, register the installed facade with the same absolute config path used for setup:

claude mcp add --scope user --transport stdio meerkat -- \
  "$(command -v node)" \
  "$HOME/.local/share/meerkat-mcp/0.7.0/node_modules/@mcsherrylabs/pi-meerkat/dist/mcp-cli.js" \
  --config "$MEERKAT_CONFIG"

--scope user makes this operator registration available across your projects. Use --scope local instead to restrict the initial test to the current project. Start a fresh Claude Code session and run /mcp to inspect the connection and its tools. Do not register the private Evolver child separately. Begin with meerkat_summary, a small meerkat_services query, meerkat_inbox, and the upstream read-only evolver_chain_height; do not approve announcement/sign/submit calls until you deliberately choose to exercise a write.

The stdio connection uses stdout exclusively for MCP messages. Diagnostics go to stderr. The operator-selected node/content/trust/identity/key/channel inputs are captured at facade startup; model arguments and project configuration cannot select signing authority. Within one client, forwarded Evolver tools and meerkat_announce deliberately share the owned upstream session and signing history. Independent clients each get a distinct child/session/store. There are two server OS processes, privately owned by the single registration. Close the client connection or stop the facade to await its child and transport cleanup.

Degraded discovery and independent reads

Initialization and local reads do not require a signing key or a working upstream child. Without --config, registry read inputs retain MEERKAT_URL, EVOLVER_CHAIN_ID and APP_NODE_ID; these are the only inputs needed for bound inbox reads. With --config, the saved operator values bind those reads. REGISTRY_URL remains a refused obsolete name.

A bounded failed upstream discovery returns the seven local definitions with explicit upstream-unavailable/degraded metadata and a stderr diagnostic. All six read tools remain usable, including both inbox summary and paginated page routes. Announce and upstream-dependent calls refuse clearly. Failed refresh invalidates stale upstream routing; a later successful catalog discovery can restore healthy routing but never resumes or replays an interrupted write. There is no hidden-name workaround or eighth status tool.

Tools

Tool Purpose
meerkat_summary Start here: counts, kinds, keywords, misses, indexed channel and progress
meerkat_services Search announced services by keyword or free text
meerkat_service Read one service, including provenance
meerkat_detail Read the document already digest-verified by the registry
meerkat_rejections Learn why an ordered announcement was not indexed
meerkat_inbox Read the inbox summary, or a bounded page with round:index continuation
meerkat_announce Describe a channel you control, optionally with an open document

The original seven names, descriptions and input schemas are preserved against published 0.6.0. Upstream descriptions/schemas/results are forwarded unchanged. A newly discovered tool routes without an adapter. Colliding names and unknown/undiscovered calls refuse rather than shadowing. This is a tools facade, not a generic prompts/resources proxy. Supported cancellation is passed through; cancellation is not rollback. Supported upstream tool-list changes refresh the catalog.

Registry strings are untrusted data, never instructions or signing configuration. Read errors are not empty answers: not-found, unreachable, unavailable and truncated remain distinct. Inbox binding validates the configured chain and node; previews remain at most 256 decoded bytes per entry, with at most 50 entries and 12,800 preview bytes per page. Carry the returned next as after yourself; the facade does not advance a processor cursor.

Announcement semantics

The registry channel is trusted configuration, not a tool parameter. The facade uses the existing unsigned announcementBody encoder, with its field order, bounds, UTF-8 bytes and 4,096-byte body cap. Sequence is epoch seconds; lease expiry uses a read-only chain-round preflight in the same session, defaulting to 20,000 rounds, never wall-clock as chain height.

The owned sequence is:

  1. evolver_chain_height (read-only preflight).
  2. If nonempty detail text is supplied, await evolver_content_put with access=open; validate the real acknowledgement and original UTF-8 size/SHA-256 before embedding its reference.
  3. evolver_sign_channel_write for the configured channel and exact announcement bodyHex.
  4. Ordinary evolver_submit with only the original returned txId.

No DA conversion/collection, auto-claim, extra mutating setup, caller-selected identity/key/TTL, local signer, local key read or direct node submit is added. The document is published OPEN: anyone with its key may read it. Upload occurs before signing; a successful upload may remain stored after a later failure.

Only this owned orchestration decodes upstream's actual warning-suffixed JSON and submit prose; transparent forwarded results are never reworded. Protocol success or isError:false does not establish a committed announcement. Committed, fined, refused, unknown and local already-submitted remain distinct. A fined write can charge and deliver a body; committed is not registry acceptance—read the entry/rejections afterward.

Definitive local child/session loss before submit prevents that send. Once submit may have left the transport, a lost, timed-out or unreadable reply means UNKNOWN, retaining the original txId and reconciliation guidance. Read/reconcile that transaction; never automatically reconnect, resume, re-sign, retry or replay the write. Already-submitted says this call sent nothing, not that a previous attempt failed.

Existing Pi package and registry application

The retained Pi extension and useful channel-subscription / service-discovery skills are still shipped. The legacy extension's EVOLVER_URL, EVOLVER_IDENTITY, EVOLVER_KEY_PATH, EVOLVER_CONTENT_URL and two-file Pi config are not the MCP facade's authority interface. No additional Pi host adapter is required. The root registry application, database/schema, processor cursor and supported SDK Docker helper are unchanged. Root npm start starts the registry application and does not demonstrate facade acceptance.

The announcement wire contract remains in this package (src/contract.ts, export ./contract), so clients and the registry use one encoder rather than divergent copies. MCP runtime capability comes from the exact installed child; remaining SDK usage in the facade is unsigned encoding/types or the existing bound ProcessorClient inbox reads, not local signing.

Verification lanes

npm run check:pi                     # root: ordinary package tests, including K01–K07
npm run check:plan-two:client --workspace @mcsherrylabs/pi-meerkat

Run networked gates in a disposable isolated network namespace/container, with physical K_REGISTRY_TEST_TMP and temporary outputs outside the source tree. K uses a real downstream MCP client, built and freshly packed-installed facade, real released child, fixed fixture keys, HTTP boundary stand-ins, explicit counters/barriers, and awaited exact-owned cleanup. It makes no live model, faucet/devnet, production database or estate changes. PLAN_TWO_REPORT selects the acceptance report path; source CI retains this report and runs the normal package chain.

An npm pack is not publication. Publication needs an unused version, synchronized locks, an immutable pi-meerkat-vX.Y.Z tag at the accepted revision and successful exact-SHA required CI/publish jobs. Published-release verification additionally retrieves anonymous metadata and tarballs/integrity and exercises the installed published facade/dependency with independent clients in isolation. Served/downloaded instruction hashes and transcripts belong to that post-publication lane. Pending publication or delivery gates must not be represented as passes.