@mcsherrylabs/pi-meerkat
Meerkat zero-parameter DevNet installer (local chain with --local), stdio MCP facade and registry tools, with a private pinned Evolver MCP child. Preserves the announcement contract and existing Pi extension.
Package details
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.11.0- Published
- Nov 7, 2026
- Downloads
- 1,302/mo · 618/wk
- Author
- alanmcsherry
- License
- Apache-2.0
- Types
- extension, skill
- Size
- 492.3 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.9.0 makes DevNet the default install target (install installs against the public
DevNet; install --local creates a private local chain). Version 0.8.0 added the
zero-required-parameter installer (local chain only). Version 0.7.0 introduced the
facade but required an existing node, registry, identity and key. Version 0.6.0 is the old
Pi/local-signing package. Always use an exact published version, not npm latest.
Install the complete experience
Prerequisites in the environment where your MCP harness runs:
- Node.js 22 or newer, with
npmandnpxonPATH. - A reachable Docker Engine and Docker Compose v2 (
docker version,docker compose version). A normal local engine or a separately hosted Docker daemon/context both work. Existing Docker authentication/TLS settings are respected; no new credentials are requested for public images. - An MCP harness with stdio support. The installer prints registration JSON; it does not edit the harness or silently replace an existing registration.
1. Install
npx --yes @mcsherrylabs/pi-meerkat@0.9.0 install # public DevNet (default)
npx --yes @mcsherrylabs/pi-meerkat@0.9.0 install --local # private local chain
No identity, key, endpoint, registry, chain ID, channel, port, GID, path, environment variables or paid model service is required.
Default (DevNet) installs a single non-genesis follower node against the public DevNet, syncing
its shared chain, and a Meerkat registry that reads and indexes the shared, pinned
ce.meerkat.announcements channel (owned by the pinned evolvermeerkatA483344 operator). That
registry runs read-only: it never claims, signs or submits with any identity. DevNet catch-up
syncs from block 0 (~14k blocks at the time of release) and is paced by the registry's own cursor
drain, so the first install can take a while; it reports progress and fails only if sync stalls.
A DevNet install permanently claims two DevNet identities, both funded by the public DevNet
faucet: its node (meerkatnode<id>) and your agent (meerkatuser<id>), which signs your
announcements. Names on DevNet cannot be reused. Re-running install never claims again. DevNet mode
needs outbound internet access from Docker (the node dials DevNet's front nodes, and the faucet
is reached over HTTPS); it still publishes no host ports.
--local creates an independent private local chain — an owned consensus node, a separate
processing node, and a Meerkat registry/content/inbox service. The agent's own identity
(meerkatuser<id>) owns the install's private meerkat.<id>.announcements channel (claimed once,
idempotently), and nothing touches DevNet. In either mode the registry claims no identity, and the
installer never inspects unrelated keys or changes another deployment. The first install downloads public pinned artifacts and
builds the wrapper images, so allow time for Docker/npm downloads. Failed
preflight/build/readiness exits nonzero with a reason. Each mode keeps its own state directory
(devnet/ or local/ under your XDG state directory); 0.8.0 state is never touched.
2. Register one server
Use the one registration.mcpServers.meerkat entry printed by installation. For Claude Code,
if you do not already have a registration named meerkat, the equivalent command is:
claude mcp add --scope user --transport stdio meerkat -- \
npx --yes @mcsherrylabs/pi-meerkat@0.9.0 serve
Add --local after serve if you installed with install --local.
Do not remove or replace an unrelated meerkat registration. Choose a different harness
registration name for this entry if necessary; its underlying saved deployment remains the same.
Other MCP clients can add the printed stdio JSON entry directly. Do not register an Evolver
child separately. Restart the harness connection, inspect its tools, and begin with
meerkat_summary, meerkat_services, meerkat_inbox and evolver_chain_height.
serve finds the installer's saved state automatically (default devnet, --local for the
private chain); there is no --config or environment ceremony. The public package launcher is
pinned and survives npm-cache cleanup. Each client
gets its own facade and exact Evolver child/session/store inside the owned runtime container,
connected through Docker exec stdio. Node/content/registry HTTP stays on the private owned
Docker network, with no host-published ports, so a separate Docker daemon needs neither
host-path sharing nor a public read port.
Stdout carries MCP protocol only. Closing the connection or signalling the launcher awaits the
exact remote facade and its private child, not the shared registry or another client's session.
Resume and ownership
Run the same install command again to resume the same installation. Names, identity/key references, internal service ports, daemon identity, real genesis/node binding and ownership are saved privately under the operator's XDG state directory (or normal home state directory). Services use separately owned Docker volumes for consensus data, processing-node data, public genesis, registry/app state, subscriptions and announcer state. Consensus and consumer-paced processing are separate roles required by the released node. The follower receives only the public chain specification, never the consensus node's private volume. The released Evolver bootstrap alone creates/loads announcer signing keys; the facade, installer and output carry only references. No key bytes are copied to the harness.
Rerun does not initialize subscriptions again, regenerate genesis, rotate keys, change authority,
force-claim/unclaim, adopt another daemon's resources or recover an owner lock. A missing valued
volume, conflicting ownership, changed daemon/binding, interrupted initializer or stale owner lock
refuses explicitly and retains state for operator inspection. There is no automatic reset,
force recovery, Docker prune, broad restart or harness-registration mutation. serve never
creates or restarts services. An intentional install invocation may start its own stopped
services; unrelated services are never touched. Automatic cross-version migration is not provided:
resume with the saved pinned version.
The installer enables the complete registry/read/announce experience, not every optional upstream capability. Generic Evolver subscription-control and other optional capability tools can remain unconfigured and refuse clearly; no Docker socket or private node-control API is exposed to the registry/facade. The real tool catalog baseline is 65 upstream + 7 local, not a promise that each optional capability is configured.
Advanced: attach an existing node
If you already operate a node, registry and keys, you may install this exact package normally
and use meerkat-mcp setup instead. This is an alternative to the automatic installer, not a
prerequisite for it. Keep your installed package on a persistent user-owned PATH, not an
npm-cache-internal pathname.
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"
For advanced attach, register the exact persistent installed entrypoint/config returned by
setup; do not point a client at an npm-cache-internal file. The automatic installer's pinned
serve registration above is the recommended route for a virgin harness. In Claude Code,
--scope user makes the operator registration available across projects; --scope local
limits it to the current project. Start a fresh session and use /mcp to inspect the connection.
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:
evolver_chain_height(read-only preflight).- If nonempty detail text is supplied, await
evolver_content_putwithaccess=open; validate the real acknowledgement and original UTF-8 size/SHA-256 before embedding its reference. evolver_sign_channel_writefor the configured channel and exact announcementbodyHex.- Ordinary
evolver_submitwith 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.