OpenRouterMcp 0.0.2
dotnet tool install --global OpenRouterMcp --version 0.0.2
dotnet new tool-manifest
dotnet tool install --local OpenRouterMcp --version 0.0.2
#tool dotnet:?package=OpenRouterMcp&version=0.0.2
nuke :add-package OpenRouterMcp --version 0.0.2
π¨ dotnet-openrouter
A .NET 10 global tool and MCP server for AI-powered image and audio generation via OpenRouter
π Overview
dotnet-openrouter is a dual-mode .NET global tool that brings OpenRouter's media generation capabilities to your terminal and AI assistant workflow. It operates in two modes:
- CLI mode β generate images and audio directly from the command line with a simple, intuitive interface
- MCP server mode β expose generation capabilities as Model Context Protocol tools so AI assistants like Claude can call them autonomously
Both modes share the same service layer, so behaviour is identical whether you drive it from the shell or from an AI assistant.
OpenRouter provides a unified API endpoint (/api/v1/chat/completions) that routes to best-in-class models for each modality β Gemini for images, GPT-4o for audio β without requiring separate API accounts for each provider.
β¨ Features
- πΌοΈ Image generation β create images from text prompts with configurable aspect ratios and resolutions (up to 4K)
- π Audio generation β synthesise speech and audio from text with six voice options and multiple output formats
- π€ MCP server β expose all capabilities as MCP tools for seamless AI assistant integration
- π Simple authentication β store your OpenRouter API key once with a single command
- π Flexible output β control output directory, filename, format, and dimensions
- π Resilient HTTP β automatic retry with exponential back-off for transient API errors
- π¦ Zero-dependency install β single
dotnet tool installcommand, no runtime dependencies - π οΈ Scriptable β
--robotflag outputs JSON for shell scripting and automation - π Model-agnostic β specify any OpenRouter-compatible model by ID
β‘ Quick Start
# 1. Install the tool
dotnet tool install -g OpenRouterMcp
# 2. Save your OpenRouter API key
dotnet-openrouter auth --key sk-or-v1-...
# 3. Generate your first image
dotnet-openrouter image -d "A golden sunset over a mountain lake"
π¦ Installation
Prerequisites
- .NET 10 SDK or later
- An OpenRouter account with API access
Install the Global Tool
dotnet tool install -g OpenRouterMcp
To update to the latest version:
dotnet tool update -g OpenRouterMcp
To uninstall:
dotnet tool uninstall -g OpenRouterMcp
Authenticate
Get your API key from openrouter.ai/keys, then save it:
dotnet-openrouter auth --key sk-or-v1-YOUR_API_KEY_HERE
The key is stored in ~/.openrouter-mcp/config.json with restricted file permissions (chmod 600 on Unix).
π Usage
CLI Mode
Image Generation
Generate an image from a text description:
dotnet-openrouter image -d "A cat wearing a top hat, watercolour style"
All options:
dotnet-openrouter image \
--description "A futuristic city skyline at night" \
--model "google/gemini-2.5-flash-image-preview" \
--aspect-ratio "16:9" \
--size "2K" \
--output "./images" \
--filename "city-skyline.png"
| Option | Alias | Required | Default | Description |
|---|---|---|---|---|
--description |
-d |
Yes | β | Text prompt for image generation |
--model |
-m |
No | google/gemini-2.5-flash-image-preview |
OpenRouter model ID |
--output |
-o |
No | ./ |
Output directory |
--filename |
-f |
No | generated-{timestamp}.png |
Output filename |
--aspect-ratio |
-a |
No | 1:1 |
Aspect ratio (1:1, 16:9, 4:3, 2:3, 3:2) |
--size |
-s |
No | 1K |
Image resolution (0.5K, 1K, 2K, 4K) |
--robot |
-r |
No | false |
Output JSON for scripting |
Example output:
Image saved to ./generated-20260313-143022.png (1920x1080, 2.3 MB)
With --robot:
{
"path": "./generated-20260313-143022.png",
"width": 1920,
"height": 1080,
"bytes": 2411724
}
Audio Generation
Generate audio from a text description:
dotnet-openrouter audio -d "Welcome to our podcast. Today we explore the future of AI."
All options:
dotnet-openrouter audio \
--description "Say hello in a warm, friendly tone" \
--model "openai/gpt-4o-audio-preview" \
--voice shimmer \
--format wav \
--output "./audio" \
--filename "greeting.wav"
| Option | Alias | Required | Default | Description |
|---|---|---|---|---|
--description |
-d |
Yes | β | Text prompt or content to speak |
--model |
-m |
No | openai/gpt-4o-audio-preview |
OpenRouter model ID |
--output |
-o |
No | ./ |
Output directory |
--filename |
-f |
No | generated-{timestamp}.mp3 |
Output filename |
--voice |
-v |
No | alloy |
Voice character (see below) |
--format |
β | No | mp3 |
Audio format (wav, mp3, flac, opus, pcm16) |
--robot |
-r |
No | false |
Output JSON for scripting |
Available voices:
| Voice | Character |
|---|---|
alloy |
Neutral, balanced |
echo |
Deep, resonant |
fable |
Warm, narrative |
onyx |
Authoritative |
nova |
Energetic, bright |
shimmer |
Soft, expressive |
Example output:
Audio saved to ./generated-20260313-143055.wav (4.2s, 1.1 MB)
Authentication Management
Store your API key:
dotnet-openrouter auth --key sk-or-v1-abc123...
Output:
API key saved to ~/.openrouter-mcp/config.json
MCP Server Mode
Start the MCP server on stdio transport (used by AI assistants):
dotnet-openrouter mcp
All logging is written to stderr; stdout carries only the JSON-RPC protocol stream, so MCP hosts can safely parse it.
Claude Desktop Configuration
Add the server to your Claude Desktop configuration file.
macOS β ~/Library/Application Support/Claude/claude_desktop_config.json
Windows β %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"openrouter": {
"command": "dotnet-openrouter",
"args": ["mcp"],
"env": {
"OPENROUTER_API_KEY": "sk-or-v1-YOUR_KEY_HERE"
}
}
}
}
Alternatively, if you have authenticated via dotnet-openrouter auth, you can omit the env block β the tool reads the key from ~/.openrouter-mcp/config.json automatically.
VS Code / GitHub Copilot Configuration
Add to your VS Code settings.json or workspace .vscode/mcp.json:
{
"mcp": {
"servers": {
"openrouter": {
"command": "dotnet-openrouter",
"args": ["mcp"],
"env": {
"OPENROUTER_API_KEY": "sk-or-v1-YOUR_KEY_HERE"
}
}
}
}
}
Once configured, ask your AI assistant to generate images or audio naturally:
"Generate a landscape image of a misty forest at dawn in a 16:9 format and save it to my Downloads folder."
"Create a short audio clip of a friendly welcome message using the shimmer voice."
See docs/MCP-CONFIGURATION.md for a complete setup guide covering all MCP clients.
ποΈ Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β OpenRouter MCP Server β
β β
β ββββββββββββββββ βββββββββββββββββββ β
β β CLI Mode β β MCP Mode β β
β β β β β β
β β β’ auth β β β’ stdio server β β
β β β’ image β β β’ tool calls β β
β β β’ audio β β β’ JSON-RPC β β
β ββββββββ¬ββββββββ ββββββββββ¬βββββββββ β
β β β β
β ββββββββββββ¬ββββββββββββββββ β
β β β
β ββββββββββββΌβββββββββββ β
β β Shared Services β β
β β β β
β β β’ ConfigService β β
β β β’ OpenRouterServiceβ β
β ββββββββββββ¬βββββββββββ β
β β β
β ββββββββββββΌβββββββββββ β
β β OpenRouter API v1 β β
β β (chat/completions) β β
β βββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
The CLI commands and MCP tools are thin wrappers over a shared service layer. Both paths call identical service methods, so behaviour is consistent regardless of how the tool is invoked. The OpenRouterService handles all HTTP communication, retry logic, and response parsing; ConfigService manages API key storage and configuration.
π Authentication & Security
API Key Storage
The API key is stored at ~/.openrouter-mcp/config.json:
{
"apiKey": "sk-or-v1-..."
}
On Unix/macOS the config directory and file are created with chmod 700 and chmod 600 respectively, preventing other users from reading the key.
Environment Variable
As an alternative to file-based storage, set the OPENROUTER_API_KEY environment variable. This takes precedence over the config file, making it suitable for CI/CD pipelines:
export OPENROUTER_API_KEY=sk-or-v1-...
dotnet-openrouter image -d "A test image"
Best Practices
- Do not commit
~/.openrouter-mcp/config.jsonto version control - In production or CI environments, prefer
OPENROUTER_API_KEYover file storage - Rotate your OpenRouter API key if it is ever exposed
- OpenRouter API keys are scoped per account β create a dedicated key for each tool or deployment
ποΈ Available Models
OpenRouter aggregates models from multiple providers. Browse the full catalogue at openrouter.ai/models.
Filter by modality:
- Image models β openrouter.ai/models?output_modalities=image
- Audio models β openrouter.ai/models?output_modalities=audio
Notable Image Models
| Model ID | Provider | Notes |
|---|---|---|
google/gemini-2.5-flash-image-preview |
Default β fast, high quality | |
google/gemini-2.0-flash-exp:image |
Experimental variant |
Notable Audio Models
| Model ID | Provider | Notes |
|---|---|---|
openai/gpt-4o-audio-preview |
OpenAI | Default β six voices, multiple formats |
openai/gpt-4o-mini-audio-preview |
OpenAI | Faster, lower cost |
π οΈ MCP Tools Reference
These tools are exposed when running in MCP server mode (dotnet-openrouter mcp).
GenerateImage
Generate an image from a text description and save it to disk.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
description |
string |
Yes | β | Text prompt describing the image to generate |
model |
string |
No | google/gemini-2.5-flash-image-preview |
OpenRouter model ID |
aspectRatio |
string |
No | 1:1 |
Aspect ratio (1:1, 16:9, 4:3, 2:3, 3:2) |
imageSize |
string |
No | 1K |
Output resolution (0.5K, 1K, 2K, 4K) |
outputPath |
string |
No | ./ |
Directory or full path for the saved file |
Example tool call (JSON-RPC):
{
"tool": "GenerateImage",
"arguments": {
"description": "A serene Japanese garden in spring, cherry blossoms falling",
"model": "google/gemini-2.5-flash-image-preview",
"aspectRatio": "16:9",
"imageSize": "2K",
"outputPath": "/Users/alice/Pictures"
}
}
GenerateAudio
Generate audio from a text description and save it to disk.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
description |
string |
Yes | β | Text prompt or content to synthesise |
model |
string |
No | openai/gpt-4o-audio-preview |
OpenRouter model ID |
voice |
string |
No | alloy |
Voice character (alloy, echo, fable, onyx, nova, shimmer) |
format |
string |
No | mp3 |
Output format (wav, mp3, flac, opus, pcm16) |
outputPath |
string |
No | ./ |
Directory or full path for the saved file |
Example tool call (JSON-RPC):
{
"tool": "GenerateAudio",
"arguments": {
"description": "Narrate a short introduction: Welcome to the OpenRouter podcast.",
"model": "openai/gpt-4o-audio-preview",
"voice": "shimmer",
"format": "wav",
"outputPath": "/Users/alice/Audio"
}
}
π» Development
Clone and Build
git clone https://github.com/brendankowitz/dotnet-openrouter.git
cd dotnet-openrouter
# Build
dotnet build
# Run tests
dotnet test
# Pack NuGet package
dotnet pack src/OpenRouterMcp/OpenRouterMcp.csproj --configuration Release --output ./packages
Install from Local Package
dotnet tool install -g OpenRouterMcp --add-source ./packages
Run Without Installing
dotnet run --project src/OpenRouterMcp -- image -d "A test image"
dotnet run --project src/OpenRouterMcp -- mcp
Project Structure
dotnet-openrouter/
βββ src/
β βββ OpenRouterMcp/
β βββ Commands/ # CLI command implementations
β β βββ AuthCommand.cs
β β βββ ImageCommand.cs
β β βββ AudioCommand.cs
β β βββ McpCommand.cs
β βββ Services/ # Business logic layer
β β βββ IConfigService.cs
β β βββ ConfigService.cs
β β βββ IOpenRouterService.cs
β β βββ OpenRouterService.cs
β βββ Models/ # Data structures
β β βββ OpenRouterRequest.cs
β β βββ OpenRouterResponse.cs
β β βββ ImageConfig.cs
β β βββ ImageResult.cs
β β βββ AudioConfig.cs
β β βββ AudioResult.cs
β βββ Mcp/ # MCP server and tools
β β βββ OpenRouterMcpServer.cs
β β βββ Tools/
β β βββ GenerateImageTool.cs
β β βββ GenerateAudioTool.cs
β βββ Program.cs # Entry point and DI setup
β βββ OpenRouterMcp.csproj
βββ docs/
β βββ MCP-CONFIGURATION.md # MCP setup guide
β βββ features/ # Feature investigations
βββ .github/
β βββ workflows/
β βββ build.yml # Reusable build template
β βββ ci.yml # CI/CD pipeline
β βββ pr.yml # PR validation
βββ .mcp/
β βββ server.json # MCP server metadata
βββ packages/ # NuGet output (gitignored)
βββ OpenRouterMcp.slnx
βββ build.ps1
βββ build.sh
βββ GitVersion.yml
βββ LICENSE
βββ README.md
Key Dependencies
| Package | Version | Purpose |
|---|---|---|
System.CommandLine |
2.0.0-beta4 | CLI framework |
ModelContextProtocol |
0.8.0-preview.1 | MCP server support |
Microsoft.Extensions.Hosting |
9.0.0 | Dependency injection and hosting |
Microsoft.Extensions.Http |
9.0.0 | HttpClientFactory |
Microsoft.Extensions.Http.Resilience |
9.0.0 | Retry policies |
GitVersion.MsBuild |
6.0.5 | Semantic versioning |
π€ Contributing
Contributions are welcome. Please follow these steps:
- Fork the repository at github.com/brendankowitz/dotnet-openrouter
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes, ensuring all existing tests pass
- Add tests for new functionality
- Submit a pull request with a clear description of the change
For significant changes, please open an issue first to discuss the approach.
π License
This project is licensed under the MIT License. See LICENSE for details.
π Related Projects
- dotnet-gmail-mcp β the sibling project that inspired this architecture; provides Gmail integration as a .NET global tool and MCP server
- OpenRouter β the unified API gateway this tool connects to
- Model Context Protocol β the open standard for AI assistant tool integration
- ModelContextProtocol .NET SDK β the SDK used to implement the MCP server
<p align="center"> Built with .NET 10 Β· Powered by <a href="https://openrouter.ai">OpenRouter</a> Β· MCP Enabled </p>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.2 | 96 | 3/16/2026 |