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

@prokosna/mpd3

v2.0.0

Published

Low level MPD (Music Player Daemon) client with Web Streams API

Readme

MPD Client for Node.js

Build Status

Connect to a Music Player Daemon (MPD) server, send commands, and receive events.

This library is a re-write version of the original mpd.js (mpd2) library, fully implemented in TypeScript and leveraging the Web Streams API. This design allows for efficient, non-blocking handling of MPD responses with multiple connections, even for large music libraries or playlists.

Installation

# from npm registry (recommended)
npm install @prokosna/mpd3

The package is also installable directly from GitHub for users that prefer pinning to a tag:

npm install github:prokosna/mpd.js#2.0.0

Basic Usage

import { Client, Parsers } from "@prokosna/mpd3";

async function main() {
  // Connect to MPD server (defaults to localhost:6600)
  const client = await Client.connect({
    host: "localhost",
    port: 6600,
  });

  try {
    console.log("Connected to MPD!");
    console.log();

    // Get current status - using sendCommand
    const status = await client.sendCommand("status");
    console.log("Status:", status);
    console.log();

    // Get current playlist info as a stream - using streamCommands
    // This is a raw stream of lines fetched from MPD.
    // OK and ACK are handled by stream's end and error events.
    const playlistInfoStream = await client.streamCommands(["playlistinfo"]);
    // Transform the stream into a list of objects
    const playlistInfoListStream = playlistInfoStream.pipeThrough(
      Parsers.transformToList({ delimiterKeys: "file" })
    );
    // Transform the list of objects into a typed list
    const playlistInfoTypedListStream = playlistInfoListStream.pipeThrough(
      Parsers.transformToTyped()
    );
    // Aggregate the list into an array
    const playlistInfo = await Parsers.aggregateToList(
      playlistInfoTypedListStream
    );
    console.log("Playlist Info (Count):", playlistInfo.length); // Result is an array of track objects
    console.log();

    // Other transforms are available in Parsers
    const listAllInfo = await client
      .streamCommand("listallinfo")
      .then((stream) =>
        stream
          .pipeThrough(
            Parsers.transformToListAndAccumulate({
              delimiterKeys: ["directory", "file"],
            })
          )
          .pipeThrough(Parsers.transformToTyped())
      )
      .then(Parsers.aggregateToList);
    console.log("List All Info (Count):", listAllInfo.length); // Result is an array of track objects
    console.log();

    // Get object from stream
    const stats = await client
      .streamCommand("stats")
      .then((stream) => stream.pipeThrough(Parsers.transformToObject()))
      .then(Parsers.takeFirstObject);
    console.log("Stats:", stats);
    console.log();

    // Listen for events
    client.on("system", (subsystem) => {
      console.log(`MPD subsystem changed: ${subsystem}`);
    });

    // Stop track if playlist is not empty
    if (playlistInfo.length > 0) {
      await client.sendCommand("play 0");
      console.log("Playback started.");
    } else {
      console.log("Playlist is empty, cannot start playback.");
    }
    console.log();

    // Keep the script running to listen for events
    console.log("Listening for MPD events... (Press Ctrl+C to exit)");
  } catch (error) {
    console.error("MPD Error:", error);
  } finally {
    process.on("SIGINT", async () => {
      console.log("\nDisconnecting...");
      await client.disconnect();
      console.log("Disconnected from MPD.");
      process.exit(0);
    });
  }
}

main().catch((err) => {
  console.error("Unhandled error in main:", err);
  process.exit(1);
});

API

Client.connect(config?: Config): Promise<Client>

Static Method

Establishes connection(s) to the MPD server and returns a connected Client instance. This is the primary way to create a client.

Options (Config type, extends net.NetConnectOpts):

  • host (string): MPD server hostname (default: localhost).
  • port (number): MPD server port (default: 6600).
  • password (string): Optional MPD password.
  • timeout (number): Connection timeout in milliseconds (default: 5000).
  • poolSize (number): Maximum number of connections in the pool (default: 3).
  • reconnectDelay (number): Delay in milliseconds between reconnection attempts (default: 5000).
  • maxRetries (number): Maximum number of retry attempts after a failed connection or a dropped event-monitoring connection. The initial connection attempt is not counted as a retry, so the total number of attempts on the initial path is 1 + maxRetries. Used for both initial connection and event monitoring reconnection (default: 3).

Reconnection Behavior:

The client implements automatic reconnection in two scenarios:

  1. Initial Connection: If the first attempt of Client.connect() fails, it will retry up to maxRetries more times with reconnectDelay between each attempt. With the default maxRetries: 3, this means up to 4 total attempts before rejecting.
  2. Event Monitoring: If the event monitoring connection drops (used for system events), the client automatically attempts to reconnect up to maxRetries times. System events will continue to be emitted after successful reconnection. A close event is only emitted after all reconnection attempts have been exhausted.

client.sendCommand(command: string | Command): Promise<string>

Sends a command to the MPD server.

  • command: The command string (e.g., 'status') or a Command object.

Returns: A Promise resolving to the full response string aggregated from the server, including the final OK line.

client.sendCommands(commandList: (string | Command)[]): Promise<string>

Sends multiple commands as a single command list to the MPD server.

  • commandList: An array of command strings or Command objects.

Returns: A Promise resolving to the full response string aggregated from the server for the entire command list.

client.streamCommand(command: string | Command): Promise<ReadableStream<ResponseLine>>

Sends a single command and returns the response as a ReadableStream.

  • command: The command string or Command object.

Returns: A Promise resolving to a ReadableStream where each chunk is a ResponseLine object ({ raw: string } containing one line of the MPD response, excluding the final OK). Useful for processing large responses line by line.

client.streamCommands(commandList: (string | Command)[]): Promise<ReadableStream<ResponseLine>>

Sends multiple commands as a command list and returns the response as a ReadableStream.

  • commandList: An array of command strings or Command objects.

Returns: A Promise resolving to a ReadableStream of ResponseLine objects for the entire command list response.

client.disconnect(): Promise<void>

Closes all connections to the MPD server, stops event monitoring, and cleans up resources.

client.PROTOCOL_VERSION: string (Getter)

Returns the MPD protocol version reported by the server during the initial connection.

Parsers

The following parser utilities are exported. They can be imported either as a Parsers namespace object (as shown in the examples above) or individually as named exports for better tree-shaking:

import { Parsers } from "@prokosna/mpd3";
// or
import { transformToList, aggregateToList } from "@prokosna/mpd3";

Available utilities:

  • transformToList
  • transformToListAndAccumulate
  • transformToObject
  • transformToTyped
  • aggregateToList
  • aggregateToString
  • takeFirstLineValue
  • takeFirstObject
  • takeFirstBinary

These utility functions are used by pipeThrough() or then() of Promise<ReadableStream>.

Events

The Client class extends Node's EventEmitter, so the standard client.on(...), client.off(...), and client.once(...) methods are available. Listening on a system/system-<subsystem> event lazily starts the dedicated MPD idle connection; the connection lives until client.disconnect() is called.

  • system (subsystem: string): Emitted when MPD reports a change in one of its subsystems (e.g., player, mixer, options, playlist). This event continues to be emitted after automatic reconnection.
  • system-<subsystem> (no payload): Per-subsystem variant, emitted alongside system. For example, client.on("system-player", () => { ... }) fires only when the player subsystem changes.
  • error (error: Error): Emitted when a connection or protocol error occurs within the connection pool or event monitoring.
  • close (error?: Error): Emitted when the disconnect() method is called, or when the event monitoring connection fails after exhausting all reconnection attempts. If an error is provided, the connection was closed due to that error.