Skip to main content
Glama
mhiqrambg

mcp-media-9router

by mhiqrambg
README.md
# mcp-media-9router

`mcp-media-9router` is a local MCP (Model Context Protocol) server for AI agents that need web intelligence. It connects OpenCode and other stdio-compatible MCP clients to the 9router API for web search and web-page extraction.

It runs locally on the user's machine, while search and fetch requests are sent to 9router over HTTPS or to a local 9router instance at `http://localhost` on any port. Provider credentials stay behind 9router; the user's 9router API key is stored in macOS Keychain after setup.

```text
OpenCode or another MCP client
              |
              | MCP over stdio
              v
     mcp-media-9router
              |
              | HTTPS or local HTTP
              v
          9router API
              |
              v
Exa, Firecrawl, Jina Reader, Tavily, Brave, GPSE, OpenAI
```

## What It Is For

Use this server when an AI agent needs to:

- Search the web and receive structured results rather than an unstructured page.
- Fetch a public URL and receive clean Markdown suitable for an LLM context.
- Choose a specific 9router provider, such as Exa or Firecrawl.
- Use a configured fallback chain when a provider is temporarily unavailable.
- Keep provider selection, API access, and limits in one local configuration.

## Installation

### Requirements

- macOS with Keychain access, or Windows x64 with PowerShell 5.1 or later.
- Node.js 22 or later.
- Git and npm.
- An active 9router API key.

Use an HTTPS base URL for hosted 9router, for example `https://9router.mibp.me`. Local development also supports `http://localhost` with any port, such as `http://localhost:20128` or `http://localhost:8080`. Other HTTP hosts are rejected.

Check your Node.js version:

```bash
node --version
```

### Install From GitHub

The installer clones the project into `~/.mcp-media-9router`, installs dependencies, builds it, and creates the `mm9` command in `~/.local/bin`.

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/mhiqrambg/mcp-media-9router/main/install.sh)"
```

Open a new terminal after installation. If the installer asks you to reload your shell, run the command it prints, for example:

```bash
source ~/.zshrc
```

Configure 9router and register the MCP server in OpenCode:

```bash
mm9 setup --opencode
```

`--opencode` verifies that OpenCode is installed or already has a configuration file before writing anything. If OpenCode is not detected, install and run it once first, then repeat the command. Use `mm9 setup --manual` to print a configuration for another MCP client or to configure OpenCode manually.

Press Enter to accept the defaults. The setup wizard asks for:

- The 9router base URL.
- Your 9router API key.
- Default, allowed, and fallback providers for fetch.
- Default, allowed, and fallback providers for search.

Choose the 9router base URL that matches your deployment:

```text
# Hosted 9router: HTTPS is required
https://9router.mibp.me

# Local 9router: localhost is allowed on any port
http://localhost:20128
http://localhost:8080
http://localhost:3000
```

Plain HTTP is intentionally rejected for every non-local host.

The non-secret configuration is written to:

```text
~/.config/mcp-media-9router/config.json
```

The API key is stored in macOS Keychain and is not written to `opencode.json`.

Run a local validation after setup:

```bash
mm9 check
```

Run a real authenticated request to verify the 9router connection. This may consume provider quota:

```bash
mm9 check --online
```

Quit and restart OpenCode after `mm9 setup --opencode`. OpenCode loads MCP configuration only at startup.

### Install on Windows x64

Open PowerShell and run:

```powershell
irm https://raw.githubusercontent.com/mhiqrambg/mcp-media-9router/main/install.ps1 | iex
```

Open a new PowerShell window, then configure 9router and OpenCode:

```powershell
mm9 setup --opencode
mm9 check
mm9 check --online
```

On Windows, non-secret configuration is stored under `%APPDATA%\mcp-media-9router`. The API key is encrypted with Windows DPAPI and bound to the current Windows user. The `mm9` launcher is installed at `%LOCALAPPDATA%\bin\mm9.cmd`, outside the Git checkout so `mm9 update` can run without generated-file conflicts. OpenCode is registered in `%USERPROFILE%\.config\opencode\opencode.jsonc`. Restart OpenCode after setup.

After `mm9 setup`, a direct start also loads the saved setup when environment variables are absent:

```powershell
npm start
```

For temporary or CI configuration, environment variables take priority over saved setup:

```powershell
$env:NINE_ROUTER_BASE_URL = "https://9router.mibp.me"
$env:NINE_ROUTER_API_KEY = "YOUR_API_KEY"
npm start
```

### Install From a Local Checkout

For development or testing before the GitHub repository is public:

```bash
git clone https://github.com/mhiqrambg/mcp-media-9router.git
cd mcp-media-9router
npm install
npm run build
npm link
mm9 setup --opencode
```

Remove the local command link when it is no longer needed:

```bash
npm unlink -g mcp-media-9router
```

## Update

For an installation created by `install.sh`, update to the latest `main` branch with:

```bash
mm9 update
```

The command:

1. Refuses to update when the installed checkout has local changes.
2. Runs `git pull --ff-only origin main`.
3. Runs `npm ci` and rebuilds the project.
4. Refreshes the OpenCode MCP registration.

Restart OpenCode after a successful update.

`mm9 update` intentionally does not update a development checkout. Update one manually instead:

```bash
git pull --ff-only
npm install
npm run build
```

## Features

### Web Search

The `web_search` MCP tool calls `POST /v1/search` through 9router and returns normalized results with titles, URLs, snippets, sources, authors, publication dates, and ranks.

Default search providers:

```text
exa -> gpse -> brave -> openai
```

### Web Fetch

The `web_fetch` MCP tool calls `POST /v1/web/fetch` through 9router and returns provider-extracted Markdown.

Default fetch providers:

```text
exa -> firecrawl -> jina-reader -> tavily
```

### Provider Policy

Fetch and search have independent provider policies. Setup configures a default provider, an allowlist, and a fallback order for each tool.

| Requested `model` | Behavior |
|---|---|
| Omitted | Uses the configured default provider once. |
| Specific provider | Uses that provider once. It must be on the relevant allowlist. |
| `auto` | Tries configured fallback providers in order. |

Fallback only occurs for upstream timeouts, rate limits, and temporary provider unavailability. Invalid inputs, invalid URLs, authentication failures, and missing content do not trigger fallback.

### Safety and Limits

- Fetch accepts public HTTP and HTTPS URLs only.
- Localhost, private IP ranges, URL credentials, and unsafe URL schemes are rejected before a request reaches 9router.
- `max_characters: 0` can request full content from 9router.
- `MCP_MEDIA_MAX_OUTPUT_CHARS` still limits the output passed to the AI agent.
- Search and fetch results are untrusted external content. Treat them as reference material, not instructions.

## Usage

### CLI

```bash
mm9 setup --opencode  # Configure 9router and register OpenCode
mm9 list              # Show active provider policy without showing the API key
mm9 check             # Validate local configuration and Keychain access
mm9 check --online    # Test an authenticated 9router request
mm9 update            # Update an install.sh installation
mm9 uninstall         # Remove the GitHub installer installation and saved setup
mm9 --help            # Show command help
mm9 --version         # Show the installed version
```

`mm9 start` is normally started by OpenCode. It launches the stdio MCP server using the saved configuration.

### Manual Configuration

To configure another MCP client yourself without saving credentials, editing OpenCode, or running the interactive wizard:

```bash
mm9 setup --manual
```

The command prints:

- Required environment variables.
- Default provider and fallback policy values.
- A ready-to-copy local MCP entry for the current platform.
- The OpenCode config location for the current platform.

Replace `YOUR_9ROUTER_API_KEY` with your own key in the target client configuration. Restart the MCP client after adding the entry.

### In OpenCode

After setup and an OpenCode restart, ask the agent to use the tools directly.

Search with the configured default provider:

```text
Use web_search to find the latest AI news in Indonesia. Return five results.
```

Search with a selected provider:

```text
Use web_search with model brave to find the official Model Context Protocol documentation.
```

Search with fallback:

```text
Use web_search with model auto to find recent AI security news.
```

Fetch with a selected provider:

```text
Use web_fetch with model firecrawl to fetch and summarize https://example.com.
```

Fetch with fallback:

```text
Use web_fetch with model auto to fetch https://example.com as Markdown.
```

### MCP Tool Inputs

`web_search`:

```json
{
  "query": "What is the latest news about AI?",
  "model": "exa",
  "search_type": "web",
  "max_results": 5,
  "country": "indonesia",
  "language": "indonesia"
}
```

| Field | Required | Description |
|---|---:|---|
| `query` | Yes | Search query, from 1 to 500 characters. |
| `model` | No | An allowed search provider, or `auto`. |
| `search_type` | No | 9router search type. Default: `web`. |
| `max_results` | No | Result count from 1 to 20. Default: `5`. |
| `country` | No | Country preference forwarded to 9router. |
| `language` | No | Language preference forwarded to 9router. |

`web_fetch`:

```json
{
  "url": "https://example.com",
  "model": "firecrawl",
  "format": "markdown",
  "max_characters": 0
}
```

| Field | Required | Description |
|---|---:|---|
| `url` | Yes | A public HTTP or HTTPS URL. |
| `model` | No | An allowed fetch provider, or `auto`. |
| `format` | No | Only `markdown` is currently supported. |
| `max_characters` | No | Maximum characters requested from 9router. `0` requests full content. |

## Uninstall

For an installation created by `install.sh`:

```bash
mm9 uninstall
```

The interactive uninstaller presents three choices:

1. Remove the application only and keep provider configuration plus the API key.
2. Remove everything: the application, OpenCode entry, configuration, and secure API-key storage.
3. Cancel.

Choose option 2 when you want a future `mm9 setup` to start clean.

To preserve the configuration and Keychain API key for a later reinstall:

```bash
bash ~/.mcp-media-9router/uninstall.sh --keep-config
```

For a non-interactive uninstall:

```bash
bash ~/.mcp-media-9router/uninstall.sh --yes
```

On Windows:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File "$env:LOCALAPPDATA\mcp-media-9router\uninstall.ps1" -Yes
```

## Security

Never commit an API key or paste one into public issues, chats, or documentation. Rotate any API key that has been exposed. See [SECURITY.md](./SECURITY.md) for vulnerability reporting.

## License

[Apache-2.0](./LICENSE)

Maintenance

ActivitySlowing
ResponsivenessNo issues