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

@airi.live/mcp

v1.0.0

Published

MCP server for Airi — upload, transcode, DRM-encrypt and publish video from your AI assistant

Readme

@airi.live/mcp

Airi video infrastructure as MCP tools: upload a file, transcode it into a quality ladder, encrypt it with Widevine, PlayReady and FairPlay, and get back an embeddable player — from your AI assistant, in one conversation.

Runs locally over stdio. Your token never leaves your machine, and an upload's bytes go from disk straight to the bucket.

Add it

Get a token at airi.live/app/developers, then:

Claude Code

claude mcp add airi --env AIRI_KMS_TOKEN=kms_live_... -- npx -y @airi.live/mcp

Claude Desktop, Cursor, Windsurf, and anything else with a JSON config

{
  "mcpServers": {
    "airi": {
      "command": "npx",
      "args": ["-y", "@airi.live/mcp"],
      "env": { "AIRI_KMS_TOKEN": "kms_live_..." }
    }
  }
}

Node 20 or newer. Nothing to install — npx fetches it on first run.

Try it

Upload ~/Videos/keynote.mp4, encode it at 1080p and 720p with DRM, and give me an embed I can paste into our site.

The assistant will run roughly this:

airi_storage_upload   path=~/Videos/keynote.mp4        → file id
airi_encoding_quote   heights=[1080,720] duration=600  → $0.16
airi_encoding_start   package=hls+dash drm=true        → job id
airi_encoding_job     wait=true                        → completed
airi_player_create    name="Site player"               → player id
airi_player_embed     file=<id>                        → signed URL + <iframe>

The tools

| | | |---|---| | Storage | upload, list, get, sign_url, delete, usage | | Encoding | quote, renditions, start, job, list, cancel, packaging_job | | Players | create, list, update, delete, embed | | DRM keys | create, get, list, rotate, periods | | Policies | set, list, resolve, delete | | Usage | balance, licenses, stats | | Anything else | api_endpoints, api_call |

Thirty-two in all, prefixed airi_.

Three of them do more than one HTTP call, because the shape of the API is built for browsers and an assistant is not one. airi_storage_upload takes a path and returns a sealed file — declare, multipart upload, ETag collection and complete, all inside the tool. airi_encoding_job with wait: true blocks until the job finishes, so an encode is one step rather than a poll loop. airi_player_embed returns the <iframe> and player.js snippets alongside the resolved player.

The last two are an escape hatch. airi_api_endpoints reads the deployed API's own OpenAPI document — generated from the schemas that validate requests, so it is never stale — and airi_api_call runs whatever it finds. New endpoints are reachable the day they ship, without waiting for this package to catch up.

Two things it will not do

It will not hand your content keys to the model. key and iv are the AES secret that decrypts your video, and a tool result lands verbatim in the assistant's transcript — which is logged, replayed, and often sent to a third party. The key tools return the key id, the PSSH boxes and the licence URLs, and redact the rest. includeKeyMaterial: true returns it when you genuinely need to encrypt locally with shaka-packager. Encoding with drm: true never needs it.

It will not touch billing or your account. /v1/admin (credits balances, mints credentials), /v1/auth (issues session tokens) and /cas (the DRM provider's callback) are refused no matter what your token is allowed to do. What an agent may do and what a credential may do are different questions, and the answer to the first should not depend on how generously the second was minted. --allow-admin unlocks them if you decide otherwise.

Everything else is reachable, because it is the job. Deletes and encodes carry MCP's destructiveHint so your client can ask before running them, and the tool descriptions say plainly what cannot be undone: a contentId is permanent at the DRM provider, a deleted file has no undo, and cancelling an encode stops the billing rather than the encoder.

Scope it down

The token is the real boundary — this server cannot grant what your credential does not have. Mint one for the assistant rather than reusing your own, with only the scopes it needs:

| scope | | |---|---| | storage:read storage:write | files and signed URLs | | encoding:read encoding:write | transcoding and packaging | | player:read player:write | players and embeds | | keys:read keys:write | DRM keys, policies, balance and usage |

A read-only assistant is a credential with only the :read scopes. Revoke it from airi.live/app/developers and every tool stops working on the next call — Hyperdrive query caching is off for exactly this reason.

Options

Flags and environment variables both work; flags win. An env block is the better place for the token, since a flag shows up in the process list.

| flag | env | default | |---|---|---| | --token | AIRI_KMS_TOKEN | — (required) | | --namespace | AIRI_KMS_NAMESPACE | — | | --url | AIRI_KMS_URL | https://kms.airi.live | | --allow-admin | AIRI_MCP_ALLOW_ADMIN=true | off | | --timeout | AIRI_KMS_TIMEOUT_MS | 60000 | | | AIRI_DASHBOARD_URL | https://airi.live |

--namespace is only needed when your token is not already confined to one. Storage, encoding and players refuse to run without a concrete namespace: the object key is ${namespace}/${id}, so a wildcard would write to /uuid.

airi-mcp --help prints all of it.

Development

npm install
npm run dev          # run from source
npm run typecheck
npm run test:upload  # multipart correctness against a stub bucket
npm run smoke        # CLI, JSON-RPC handshake, tool registration, the admin guard
SMOKE_LIVE=true npm run smoke   # also calls read-only tools against the API

test/upload.ts is the one that matters. The multipart path is the only part of this server that can corrupt data rather than merely fail — an off-by-one in the offset arithmetic produces an object of exactly the right size whose bytes are wrong, and nothing downstream notices until a viewer sees a broken video. The live part size is 100 MB, so testing that boundary against the real service would mean pushing a gigabyte; the stub uses 64 KB parts and reassembles what the bucket received, including the ragged-last-part case.

Nothing may be written to stdout that is not a JSON-RPC message — stdout is the transport, and one stray console.log corrupts the stream in a way users see as "the MCP server failed to start" with no clue why. Diagnostics go to stderr.

Links

ISC