@agntn/lyrics0.1.1
Unified song lyrics provider library for AI agents
Built for omp
The author tagged this package omp-extension.
Reports 0
No reports yet.
Readme
@agntn/lyrics
π΅ Six lyrics providers. Ask for a song, get its words, timestamps and source when available.
Why?
Genius knows plenty about a song, but its API won't give you the lyrics. Other sites have the words, each with its own catalogue and quirks. Apparently remembering the chorus was the easy part. This package puts six providers behind one TypeScript API and CLI.
β¨ Features
- π Find the track first. Search by artist and title, then use a provider's track ID for a more specific lookup.
- π Start without credentials. LRCLIB, lyrics.ovh, Tekstowo and AZLyrics need no key.
- πͺ Try the next catalogue. Lyrics lookups can skip missing tracks, auth failures, paywalls, unsupported operations and parse errors. Rate limits and transport failures still stop the call.
- β±οΈ Follow the timestamps. LRCLIB supplies LRC. Parse it or find the current line locally.
- π Read a translation. Tekstowo exposes community translations alongside the original text, when available.
- π€ Bring your agent. MCP, Pi, OMP and Vercel AI SDK tools sit alongside the CLI and library.
- π Keep the source attached. Results can include source URLs and attribution. Keep them when displaying the text.
π¦ Install
Requires Node.js 24 or newer.
pnpm add @agntn/lyrics
The package is not published to npm yet. Registry install commands here are for use after publication. For now, use the checkout instructions under Development.
π First call
Start by checking which providers are available:
npx @agntn/lyrics providers
Output from the local build, with both credential variables unset:
Registered providers (6):
lrclib: search, lyrics, synced
lyricsovh: lyrics
genius: search, lyrics [needs GENIUS_ACCESS_TOKEN]
tekstowo: search, lyrics, translation
azlyrics: lyrics
musixmatch: search, lyrics [needs MUSIXMATCH_API_KEY]
βΉ Use --provider <name> to select one, --provider all to compare every provider, or leave it out to walk providers until one has the song
No key needed for this check. After installation, use pnpm exec lyrics for the commands below.
Commands
| Command | What you get | Example |
|---|---|---|
get |
One track's lyrics | pnpm exec lyrics get "Radiohead" "Creep" |
search |
Matching tracks | pnpm exec lyrics search "radiohead creep" -n 5 |
synced |
LRC, or the line at a given second | pnpm exec lyrics synced "Radiohead" "Creep" --at 45 |
providers |
Provider capabilities and credential requirements | pnpm exec lyrics providers |
mcp |
MCP server over stdio | pnpm exec lyrics mcp |
Want a translation? Try pnpm exec lyrics get "Kult" "Arahja" -p tekstowo --translation. Use get --help, search --help or synced --help for each command's options.
π§ Library
import { formatLyrics, lyricsWithFallback } from "@agntn/lyrics";
const { lyrics, skipped } = await lyricsWithFallback({
artist: "Radiohead",
track: "Creep",
duration: 239,
});
console.log(formatLyrics(lyrics));
console.log(skipped);
You get the song and a record of providers passed over. formatLyrics() prints the source and attribution when provided. Need a particular catalogue? Use create("lrclib").lyrics(query) instead. For comparisons, searchAll() and lyricsAll() return each provider's result or error.
Already have LRC? No request needed. These lines are invented:
import { lineAt, parseLrc } from "@agntn/lyrics";
const lines = parseLrc("[00:10.00] The kettle joins the band\n[00:20.50] Nobody hired the spoon");
console.log(lineAt(lines, 21));
{ time: 20.5, text: 'Nobody hired the spoon' }
See the result types, exports and LRC helpers for the rest.
πΊοΈ Providers
| Provider | Credentials | Search | Lyrics | LRC | Translation |
|---|---|---|---|---|---|
lrclib |
None | β | β | β | |
lyricsovh |
None | β | |||
genius |
GENIUS_ACCESS_TOKEN for search or track IDs |
β | β | ||
tekstowo |
None | β | β | β | |
azlyrics |
None | β | |||
musixmatch |
MUSIXMATCH_API_KEY |
β | β |
get tries providers in registration order. search selects the first usable search provider. Pass -p all to either command for comparison, or name one provider to avoid fallback. Adding a key doesn't promote that provider. See the provider implementations.
Genius can fetch lyrics without a token using an artist/title URL, but spelling differences can make that miss. Musixmatch's free plan returns an excerpt marked partial: true.
π€ Agents
Install the extension for your harness:
pi install @agntn/lyrics
omp install @agntn/lyrics
For an MCP client that accepts mcpServers configuration:
{
"mcpServers": {
"lyrics": {
"command": "npx",
"args": ["-y", "@agntn/lyrics", "mcp"]
}
}
}
MCP and both extensions expose lyrics_get, lyrics_search, lyrics_line_at and lyrics_providers. The line lookup works locally on supplied LRC. Using Vercel AI SDK instead? Install the ai peer dependency and import tools from @agntn/lyrics/ai. See the tool exports and MCP server.
π« Copyright still applies
Fetching lyrics doesn't license them to you. Keep the source URL and attribution with any text you display. Quote only the shortest excerpt your task needs.
Genius, Tekstowo and AZLyrics read HTML. Their terms restrict automated access, and layout changes can cause ParseError. Musixmatch uses a licensed API, subject to its plan and terms. Choosing acceptable sources is your responsibility as the operator.
π§© Adding a provider
Have another catalogue? Extend Provider, declare its capabilities and call register(). The lyrics.ovh implementation is a small example. Search is optional, lyrics retrieval isn't.
π οΈ Development
From a checkout:
pnpm install
pnpm build
node dist/cli.mjs providers
pnpm test # Provider tests use mocked requests
pnpm typecheck # Core and extension types, including a build
pnpm lint # Lint and formatting checks
pnpm fmt # Apply lint fixes and formatting
Tests use invented lyrics, not fragments of real songs. Please keep it that way.
π Thanks
Claude for Open Source and Codex for Open Source help make this package possible. More time for the code, fewer tabs to juggle.
π License
MIT. The package's code, not the songs.