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

parliament-mcp

v0.2.0-rc.1

Published

Multi-agent plan-debate room served over MCP — chat agents from any vendor (Claude Code, Codex, Cursor, ...) join a shared room, debate a plan through distinct lenses, and a Speaker moderates and produces a verdict.

Readme

parliament-mcp

A multi-agent plan-debate room served over MCP. Chat agents from any vendor — Claude Code, Codex, Cursor, anything that speaks MCP — join a shared room from their own chat windows, debate a plan through distinct adversarial lenses, and a Speaker moderates and produces a verdict with a consolidated review.

Because each panelist is just a chat window, model and effort are per-window choices — all on your existing subscriptions, no API keys.

Scope (v0.2): local, single machine, single user. All windows in one debate must run the same parliament-mcp version.

Install

npm install && npm run build          # (from source; npm package pending)

# 1) Register the MCP server in each client
claude mcp add --scope user parliament -- node "$PWD/dist/index.js"
codex mcp add parliament -- node "$PWD/dist/index.js"

# 2) Install the slash commands (/start-debate, /enter-debate, /exit-debate, /stop-debate)
node dist/index.js install-commands

Connectivity check — in any chat window, ask the agent to call the parliament list_debates tool. On a fresh install the expected response is an empty list []: that means working, no debates yet. An error means the MCP registration is wrong.

Avoid approval prompts (recommended — a debate stalls behind any prompt you're not watching):

  • Claude Code — add to ~/.claude/settings.json:
    { "permissions": { "allow": ["mcp__parliament"] } }
  • Codex — approvals follow your approval_policy in ~/.codex/config.toml; never (or approving the server once) covers it.

Pin the version once published ([email protected], not @latest) — mixed versions across windows are detected and refused, but pinning avoids hitting that mid-debate.

After upgrading parliament-mcp, reconnect every open session. MCP servers load their code once, at session start: an already-open chat window keeps running the OLD version until its server reconnects (/mcp → parliament → reconnect in Claude Code; restart the session in Codex). Rooms record which version created them (schemaVersion is the compatibility counter — bumped for format or coordination-semantics changes) and every join stamps the joining server's version; skew produces a loud warning naming the seat.

The happy path

Speaker (the chat that has the plan): create_debatewait_for_event loop → produce_verdict. Panelist (each other window): join_debatepost_openingwait_for_mic loop → post_turn.

That's the whole conceptual model. In practice you type:

  1. /start-debate in the chat where you planned something — optionally ​/start-debate panel: opus, codex:xhigh to auto-launch the panelist terminals (macOS only; otherwise it prints join commands to paste). The agent digests the plan, writes the briefing, creates the room, and hands out per-seat join commands.
  2. Each panelist window: /enter-debate <debate-id> <seat-id> <seat-token>keep these commands; they are also the recovery path.
  3. Blind openings are filed (sealed until all are in), the floor opens, seats debate by point id, pass when done. Talk to the Speaker anytime — your scope changes broadcast as amendments.
  4. The Speaker rules on points, then delivers the verdict. Everything lands in ~/.parliament/debates/<id>/: briefing.md, per-turn transcripts, amendments.log, verdict.json, consolidated-review.md.

Recovery shelf (for humans)

Chat windows die: turn limits, closed terminals, context compaction. The debate survives all of it — state lives on disk, not in any window.

| Symptom | Fix | | --- | --- | | A panelist window died / is confused / lost context | Re-paste its original join command (any window). Re-join is idempotent and returns full state. Claude windows launched by /start-debate panel: also get a claude --resume <uuid> command that reopens the original session with context intact. | | Mic stuck on a dead seat | The Speaker's poll surfaces a stalled warning naming the seat. Speaker: grant_mic to another seat, or drop_seat the dead one (its points survive; it can rejoin later). | | A seat never joined and assembly is stuck | Speaker: open_floor (starts with the ≥2 seats that filed; absentees are dropped, can rejoin). | | Want a quick look without blocking | get_turn_board / get_ledger (non-blocking reads). | | A panelist window is filling up / degrading | There is no reliable way for an agent (or this server) to detect context exhaustion — don't wait for one. The seat can post a wrap-up turn (its points stay open), leave, and a fresh window re-pastes the same join command: the debate loses nothing but the agent's unexpressed private reasoning. | | Everything is on fire | /stop-debate — halts immediately, state preserved on disk. |

Design invariant (tested): the human plus the Speaker window alone can always advance or end a debate — without hand-editing files, and without the Speaker ever speaking for an absent panelist.

Live viewer

Watch a debate like a live stream:

parliament-mcp view <debate-id>     # prints a random loopback URL

One read-only page, updating live over SSE: turns as they land, current mic holder, ledger statuses, stall warnings, the verdict. No controls, no writes — it is strictly a reader of room.json (reconnects resume without gaps or duplicates). parliament-mcp history lists concluded debates from the history records written at verdict time.

Viewer trust note (read before running it): the debate files are protected by file permissions (0600 — your OS user only). The viewer changes that boundary while it runs: loopback restricts by host, not by user, so on a shared machine any local account or process that can reach 127.0.0.1 on the printed port can read the entire debate, briefing included. Stop the viewer when you stop watching.

Honest telemetry

The turn board reports per-seat server_payload_bytes / est_payload_tokens: exact bytes of event-bearing tool results this server serialized to that seat (est tokens = bytes/4). It is Parliament traffic only — not billing tokens, not the agent's context usage, and it has no denominator: never read it as "% of context". Seat identity and session ids carry per-field provenance (launcher_requested / agent_observed_corroborated / agent_observed_uncorroborated / self_reported_unverified) and the tiers are never merged. A recorded session id is a correlation key into your local transcript store — treat debate/history files as referencing potentially sensitive local transcripts; redact ids before pasting into shared channels or bug reports.

Trust model — read this

Parliament has no authentication. Its trust boundary is your OS user account: any process running as you — including unrelated background agents — can read and modify every debate, briefing, and verdict under ~/.parliament (created 0700/0600, which keeps other users out, nothing more). Seat credentials prevent accidents (a confused window posting into the wrong seat), not attacks. Blind-opening sealing is advisory: a panelist agent with shell access could read the files early; nothing running as the same user can be stopped from doing so. Do not put secrets or credentials in a briefing.

Tools

Happy path — panelist: join_debate, post_opening, wait_for_mic, post_turn · speaker: create_debate, wait_for_event, produce_verdict Speaker moderationpost_amendment, update_point_status, extend_debate (advisory log) Recovery shelfgrant_mic, drop_seat, open_floor, get_turn_board, get_ledger, leave_debate, stop_debate Discoverylist_debates, get_briefing

Dev

npm run smoke   # e2e: 3 clients/3 processes — full lifecycle + recovery matrix
                # (credentials, idempotent re-join, stall detection, drop_seat,
                #  forced floor-open, ruling protection, schemaVersion guard, file modes)

Known-untested (tracked from the v0.2 design debate): the context-growth/compaction endurance hypothesis — whether hours of idle polling degrades panelist quality in real chat harnesses. Run a long live debate before trusting the default poll timeout.