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

@iflow-mcp/xd-ventures-ovh-ikvm-mcp

v0.1.0

Published

MCP server for bare metal server iKVM/IPMI console access — screenshot capture for LLM-based debugging

Readme

ovh-ikvm-mcp

CI Docker License

MCP server that gives LLMs visual access to bare metal server consoles via iKVM/IPMI. Capture screenshots of remote server screens for AI-powered debugging of bare metal deployments.

Overview

This MCP (Model Context Protocol) server exposes bare metal server iKVM consoles as tools that LLMs can use. An LLM can list available servers and request screenshots of their console output — useful for debugging boot issues, kernel panics, network misconfigurations, and other problems visible on the server screen.

How it works

LLM ──MCP──► ikvm-mcp server ──OVH API──► get viewer URL
                    │
                    ├──KVM WebSocket──► extract JPEG frame ──► PNG screenshot (AMI/ASRockRack BMC)
                    └──VNC/RFB over WebSocket──► capture framebuffer ──► PNG screenshot (standard VNC)
  1. The MCP server authenticates with the cloud provider API (OVH)
  2. Requests an iKVM/IPMI HTML5 console session
  3. Establishes a BMC session (extracts session cookie and CSRF token from the viewer page)
  4. Connects to the KVM WebSocket, receives JPEG video frames
  5. Extracts the first complete JPEG frame and converts it to PNG
  6. Returns the image to the LLM via MCP

Supported providers

| Provider | Status | |----------|--------| | OVH | Supported |

MCP Tools

list_servers

List all available bare metal servers with iKVM/IPMI access.

Parameters: none

Returns: JSON array of server objects:

[
  {
    "id": "ns1234567.ip-1-2-3.eu",
    "name": "ns1234567.ip-1-2-3.eu",
    "provider": "ovh",
    "datacenter": "sbg3",
    "ip": "1.2.3.4"
  }
]

get_screenshot

Capture a screenshot of a server's iKVM/IPMI console screen. Returns a PNG image optimized for LLM vision (2x upscale + brightness boost). Set raw=true to get the original unprocessed image.

Parameters:

| Name | Type | Default | Description | |------|------|---------|-------------| | serverId | string | (required) | Server identifier (e.g., ns1234567.ip-1-2-3.eu) | | raw | boolean | false | Return the raw screenshot without LLM optimization |

Returns: PNG image content block (base64-encoded)

Setup

Prerequisites

  • Bun >= 1.0
  • OVH API credentials (Application Key, Application Secret, Consumer Key)

OVH API credentials

  1. Create an application at https://eu.api.ovh.com/createApp/ (or your region's equivalent: ca.api.ovh.com, api.us.ovhcloud.com)
  2. Note the Application Key and Application Secret
  3. Request a consumer key with the required permissions:
curl -X POST https://eu.api.ovh.com/1.0/auth/credential \
  -H "X-Ovh-Application: YOUR_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accessRules": [
      { "method": "GET", "path": "/dedicated/server" },
      { "method": "GET", "path": "/dedicated/server/*" },
      { "method": "POST", "path": "/dedicated/server/*/features/ipmi/access" },
      { "method": "GET", "path": "/dedicated/server/*/features/ipmi/access" },
      { "method": "GET", "path": "/dedicated/server/*/task/*" }
    ]
  }'
  1. The response includes a consumerKey and a validationUrl — open the URL in your browser to authorize the key

Installation

git clone https://github.com/xd-ventures/ovh-ikvm-mcp.git
cd ovh-ikvm-mcp
bun install

Configuration

Set the required environment variables:

export OVH_ENDPOINT="eu"                    # API region: eu, ca, or us
export OVH_APPLICATION_KEY="your-app-key"
export OVH_APPLICATION_SECRET="your-app-secret"
export OVH_CONSUMER_KEY="your-consumer-key"

Running

bun start

The server starts on http://localhost:3001/mcp by default.

Docker

A pre-built image is published to GitHub Container Registry on every push to main.

docker run --rm \
  -e OVH_ENDPOINT=eu \
  -e OVH_APPLICATION_KEY=your-app-key \
  -e OVH_APPLICATION_SECRET=your-app-secret \
  -e OVH_CONSUMER_KEY=your-consumer-key \
  -p 3001:3001 \
  ghcr.io/xd-ventures/ovh-ikvm-mcp:latest

The container runs as a non-root user and includes a health check on /health.

You can also build the image locally:

docker build -t ovh-ikvm-mcp .
docker run --rm -e OVH_ENDPOINT=eu -e OVH_APPLICATION_KEY=... -e OVH_APPLICATION_SECRET=... -e OVH_CONSUMER_KEY=... -p 3001:3001 ovh-ikvm-mcp

Using with AI Coding Agents

The server uses Streamable HTTP transport (not stdio), so all agents connect to it over HTTP. Start the server first, then configure your agent to point at it.

1. Start the server:

cd ovh-ikvm-mcp
export OVH_ENDPOINT="eu"
export OVH_APPLICATION_KEY="your-app-key"
export OVH_APPLICATION_SECRET="your-app-secret"
export OVH_CONSUMER_KEY="your-consumer-key"
bun start

You should see: ikvm-mcp server listening on http://localhost:3001/mcp

2. Configure your agent (pick one):


Claude Code

Register via the CLI:

claude mcp add ikvm --transport http http://localhost:3001/mcp

Or add to your project's .mcp.json so teammates get it automatically:

{
  "mcpServers": {
    "ikvm": {
      "type": "http",
      "url": "http://localhost:3001/mcp"
    }
  }
}

Verify it's connected:

claude mcp list

Make sure the OVH environment variables are set in the terminal where you run bun start.


Claude Desktop

Add to your Claude Desktop MCP config:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "ikvm": {
      "url": "http://localhost:3001/mcp"
    }
  }
}

After saving, restart Claude Desktop. The hammer icon in the input box confirms the MCP tools are loaded.


Cursor

Add to .cursor/mcp.json in your project root (or ~/.cursor/mcp.json for global):

{
  "mcpServers": {
    "ikvm": {
      "url": "http://localhost:3001/mcp"
    }
  }
}

After saving, open Cursor Settings > MCP and verify the ikvm server shows a green indicator.


Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "ikvm": {
      "serverUrl": "http://localhost:3001/mcp"
    }
  }
}

Example Prompts

Once connected, you can use these prompts with any agent:

List servers and take a screenshot:

List my bare metal servers using the ikvm MCP, then take a screenshot
of the first server's console. Describe what you see on the screen.

Debug a server that won't boot:

My server ns1234567.ip-1-2-3.eu is stuck during boot. Take a screenshot
of its console and diagnose the issue. If you see a kernel panic or
GRUB error, suggest how to fix it.

Monitor server state:

Take a screenshot of ns1234567.ip-1-2-3.eu console. Is the server
at a login prompt, showing an error, or still booting? If it's at
a login prompt, the OS reinstall was successful.

Compare raw vs optimized output:

Take two screenshots of ns1234567.ip-1-2-3.eu — one default (optimized)
and one with raw=true. Compare the readability.

Development

# Install dependencies
bun install

# Run tests
bun test

# Run with watch mode
bun run dev

# Type check
bun run typecheck

# Lint
bun run lint

# Lint and auto-fix
bun run lint:fix

# Format
bun run format

Testing

Tests use Bun's built-in test runner with:

  • Mock BMC server — simulates ASRockRack/AMI BMC with session auth and JPEG frame WebSocket
  • Test VNC server — minimal RFB server serving a known image for VNC client tests
  • Mock OVH API — simulates OVH REST API endpoints with auth validation
  • In-memory MCP transport — tests MCP tool invocation without HTTP overhead

Run the full verification suite:

bun run typecheck && bun run lint && bun test

Architecture

src/
├── index.ts              # Entry point — Bun HTTP server with MCP transport
├── kvm/
│   ├── types.ts          # KVM/BMC session types
│   ├── bmc-session.ts    # BMC session establishment (cookie + CSRF extraction)
│   ├── screenshot.ts     # KVM screenshot: IVTP WebSocket → AST2500 decode → PNG
│   ├── optimize.ts       # LLM vision optimization (2x upscale + brightness boost)
│   └── decoder-fetcher.ts # Runtime fetcher for AST2500 decoder from BMC
├── vnc/
│   ├── rfb-client.ts     # VNC/RFB protocol client over WebSocket
│   ├── encodings.ts      # RFB framebuffer encoding decoders (Raw, CopyRect)
│   ├── types.ts          # RFB protocol types and constants
│   └── screenshot.ts     # High-level: connect → capture → PNG encode
├── providers/
│   ├── types.ts          # Provider interface (listServers, getScreenshot)
│   └── ovh/
│       ├── api.ts        # OVH API client with request signing
│       ├── provider.ts   # OVH provider implementation
│       └── types.ts      # OVH-specific types
└── mcp/
    └── server.ts         # MCP server setup + tool definitions

Provider interface

Adding a new provider means implementing the Provider interface:

interface Provider {
  name: string;
  listServers(): Promise<Server[]>;
  getScreenshot(serverId: string): Promise<Buffer>;
}

AMI KVM client

OVH servers use ASRockRack/AMI BMC firmware with a proprietary WebSocket KVM protocol at wss://<host>/kvm. The KVM client:

  1. Fetches the viewer redirect page and extracts the QSESSIONID cookie and garc CSRF token
  2. Connects to the KVM WebSocket endpoint
  3. Scans incoming binary messages for JPEG SOI (0xFFD8) / EOI (0xFFD9) markers
  4. Extracts the first complete JPEG frame and converts it to PNG

VNC/RFB client

The VNC client connects directly to the WebSocket endpoint exposed by iKVM viewers that use standard VNC, performing the RFB protocol handshake (version negotiation, security, framebuffer request) without needing a headless browser.

Supported RFB features:

  • Protocol versions: 3.3, 3.7, 3.8
  • Security: None, VNC Authentication (DES challenge-response)
  • Encodings: Raw, CopyRect

Acknowledgments

This project connects to BMC firmware by American Megatrends Inc. (AMI). The AST2500 video decoder is fetched at runtime from the BMC's web interface and is not distributed with this project. See NOTICE for details.

Contributing

See CONTRIBUTING.md for development setup, workflow, and guidelines.

This project follows the Contributor Covenant 3.0 code of conduct.

To report security vulnerabilities, see SECURITY.md.

License

Apache 2.0 — see LICENSE.