Search internet radio stations, stream URLs, top stations, countries and genres (Radio Browser).
An open-source Model Context Protocol (MCP) server for internet radio. It lets Claude, Cursor, VS Code Copilot and other MCP clients search radio stations worldwide and get their direct stream URLs. It also lists top and trending stations, countries and genres.
The station data comes from Radio Browser, a community-maintained, public-domain directory with over 50,000 stations that have working streams. The server is built by 72FM, a free web radio player built on the same directory. Every result includes a listen_url that plays the station in the browser on 72FM, as well as the station's own stream_url.
Stations belong to their broadcasters. Neither 72FM nor this server owns, operates or curates them. Anyone can add or edit entries in the directory, so a stream can occasionally be offline.
@modelcontextprotocol/server (the official MCP TypeScript SDK, v2) and zod.Requires Node.js 20 or newer. The server runs straight from GitHub with npx, so there is nothing to install globally.
claude mcp add internet-radio -- npx -y github:AlonDrilich/internet-radio-mcp
Then run /mcp in a session to confirm that internet-radio is connected.
Open Settings → Developer → Edit Config. This opens claude_desktop_config.json: on macOS it is at ~/Library/Application Support/Claude/claude_desktop_config.json, and on Windows at %APPDATA%\Claude\claude_desktop_config.json. Add:
{
"mcpServers": {
"internet-radio": {
"command": "npx",
"args": ["-y", "github:AlonDrilich/internet-radio-mcp"]
}
}
}
Restart Claude Desktop.
Add the server to ~/.cursor/mcp.json to use it everywhere, or to .cursor/mcp.json to use it in one project:
{
"mcpServers": {
"internet-radio": {
"command": "npx",
"args": ["-y", "github:AlonDrilich/internet-radio-mcp"]
}
}
}
Add the server to .vscode/mcp.json, or run MCP: Add Server from the Command Palette:
{
"servers": {
"internet-radio": {
"type": "stdio",
"command": "npx",
"args": ["-y", "github:AlonDrilich/internet-radio-mcp"]
}
}
}
Any MCP client that can launch a stdio server can use the same command: npx -y github:AlonDrilich/internet-radio-mcp.
The first launch downloads the package from GitHub, which takes a few seconds. Later launches use the npx cache.
The same server is published as a container image, and is listed in the official MCP Registry as io.github.AlonDrilich/internet-radio-mcp:
docker run -i --rm ghcr.io/alondrilich/internet-radio-mcp:latest
In a client config, use "command": "docker" with "args": ["run", "-i", "--rm", "ghcr.io/alondrilich/internet-radio-mcp:latest"].
All tools are read-only and annotated with readOnlyHint: true and openWorldHint: true. Each result contains:
structuredContent that matches the tool's outputSchema.Broken streams (streams that failed the directory's last automated check) are excluded from searches.
| Tool | Arguments | Returns |
|---|---|---|
search_stations | name?, tag? (genre), countrycode? (ISO 3166-1 alpha-2, e.g. BR), language? (e.g. portuguese), order = votes | clickcount (default votes), limit 1–50 (default 10) | Matching stations |
get_station | id (Radio Browser stationuuid) | One station |
top_stations | by = votes | clicks | trending (default votes), countrycode?, tag?, limit 1–50 (default 10) | Most voted, most played, or trending stations |
list_countries | min_stations? (default 1), limit? | Country name, ISO code, station count and 72FM country page (https://72fm.com/radio/<iso2>) |
list_genres | limit 1–100 (default 30) | Top genre tags by station count. Placeholder and non-genre tags are filtered out (e.g. undefined, radio, fm, and country, region or language names). |
{
"id": "963fa65f-0601-11e8-ae97-52543be04c81",
"name": "Antena 1 São Paulo, SP (ZYD823 94,7 MHz FM) [aac]",
"country": "Brazil",
"countrycode": "BR",
"language": "portuguese",
"tags": ["adult contemporary", "jazz", "pop", "smooth jazz"],
"codec": "AAC+",
"bitrate": 96,
"homepage": "http://antena1.com.br/",
"stream_url": "http://antena1.newradio.it/stream?ext=.mp3",
"favicon": null,
"votes": 33238,
"lastcheckok": true,
"listen_url": "https://72fm.com/station/963fa65f-0601-11e8-ae97-52543be04c81"
}
stream_url is the directory's resolved stream URL, or the original URL when no resolved one exists.listen_url plays the station in the browser on 72FM.tags holds up to 8 tags.find_radio(request) finds stations for a mood, place, activity or genre, for example "calm jazz for a rainy evening" or "radio from Lisbon".
Station names, tags, languages, countries and URLs come from a public directory that anyone can edit, and the server hands them to an AI assistant. The server therefore treats every field as untrusted input:
stream_url, homepage, favicon) must be plain http or https written out in full, without credentials or backslashes, and are returned in their parsed canonical form; anything else (javascript:, data:, file:, https:host, a bare word) is dropped, and a station with no valid id or no playable stream is left out of the results.bitrate is converted when a station reports bits per second, and dropped when it is implausible; the directory's own bitrate sort is not offered because it ranks those entries first.This reduces the risk of indirect prompt injection; it cannot remove it. A station can still be called "Ignore previous instructions", and that text will be shown, as one capped line, like any other name. Treat results as untrusted when you build on them.
The server queries the Radio Browser mirrors in this order, with an 8-second timeout for each:
de1.api.radio-browser.infode2.api.radio-browser.infoall.api.radio-browser.infoIf all three fail, the tool returns a clear error (isError: true) and the server keeps running. Requests identify themselves with User-Agent: internet-radio-mcp/1.0 (+https://72fm.com).
You can change this behavior with two optional environment variables:
RADIO_BROWSER_MIRRORS: comma-separated base URLs to use instead of the defaults. Only https URLs without credentials are accepted (plain http only for localhost, 127.0.0.1 or [::1], for testing); anything else is ignored with a warning on stderr. Redirects are never followed.RADIO_BROWSER_TIMEOUT_MS: the timeout for each mirror, in milliseconds: a whole number from 100 to 60000 (default 8000).git clone https://github.com/AlonDrilich/internet-radio-mcp
cd internet-radio-mcp
npm install
npm run typecheck # tsc checkJs over the JSDoc-typed sources
npm run smoke # spawns the server over stdio and calls every tool against the live API
npx @modelcontextprotocol/inspector node src/index.js # interactive testing
The source is plain ES modules with JSDoc types (src/), so there is no build step. That is why npx github:… works without an npm publish.
MIT © Alon Drilich (72FM)
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
docker run -i --rm ghcr.io/alondrilich/internet-radio-mcp:1.0.2Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-alondrilich-internet-radio-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/alondrilich/internet-radio-mcp:1.0.2"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceghcr.io/alondrilich/internet-radio-mcp:1.0.2dockerInternet Radio works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.