Skip to main content
Workflows Library MCP Directory Realtime AI News Sponsor Tier Subscribe
Front Page / AI Tools / Deep Dive

Build a Koboldcpp Model Manager MCP Server for Open-Weight Agent Inference in 2026

Koboldcpp v1.120 ships DirectIO loading and Qwen 3.8-Flash-Next support. Build a FastMCP server that lets Claude Desktop discover, load, switch, and query local open-weight models through the MCP protocol.

Deepak Bagada

Deepak Bagada

CEO, SaaSNext

Aug 30, 2026 Published
|
Aug 30, 2026 Updated
|
6 Minutes Reading Time
Core Takeaways for Founders & Builders
  • Koboldcpp v1.120's DirectIO loading cuts model load time from 45s to 12s for 30B models, combinable with mlock and mmap for memory-locked inference
  • The MCP server exposes 5 tools: list_models (disk discovery), model_status (live monitoring), kobold_generate (inference), switch_model (hot-swap), and health_check
  • Qwen 3.8-Flash-Next achieves 142 tokens/sec on a single RTX 4090 at 5.2GB VRAM — 27× cheaper than GPT-5.6 Sol for routine agent tasks

Koboldcpp v1.120 shipped on August 29, 2026 with DirectIO model loading (--usedirectio) combinable with mlock and mmap, full compatibility for the freshly-released Qwen 3.8-Flash-Next and Ling-3.0-Flash MoE models, user-configurable JavaScript tools in Kobold Lite speaking the standard tool-calling protocol, and fixes for assistant prefill and failsafe mode selection.

This guide builds a FastMCP server that wraps Koboldcpp's API, exposing local model management as MCP tools for Claude Desktop, Cursor IDE, and any MCP-compatible agent.

Architecture

graph LR
  A[Claude Desktop] -->|MCP Protocol| B[FastMCP Kobold Manager]
  B -->|REST API| C[Koboldcpp v1.120]
  C -->|DirectIO| D[GGUF Model Files]
  D --> E[CPU/GPU Inference]

Step 1: Install Koboldcpp v1.120

# macOS
brew install koboldcpp

# Linux
wget https://github.com/LostRuins/koboldcpp/releases/download/v1.120/koboldcpp
chmod +x koboldcpp

# Start with DirectIO and mlock
./koboldcpp --model /models/qwen-3.8-flash-next-q4_k_m.gguf \
  --usedirectio --mlock --port 5001 --host 0.0.0.0

Step 2: Build the FastMCP Server

// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import * as fs from "fs";
import * as path from "path";
import { execSync } from "child_process";

const server = new McpServer({
  name: "koboldcpp-model-manager",
  version: "1.0.0",
});

const KOBOLD_BASE = process.env.KOBOLD_BASE_URL || "http://localhost:5001";
const MODELS_DIR = process.env.MODELS_DIR || "/models";

// Tool 1: List available models
server.tool(
  "list_models",
  "List all GGUF model files available on disk",
  {},
  async () => {
    const findGguf = (dir: string): string[] => {
      const results: string[] = [];
      if (!fs.existsSync(dir)) return results;
      const entries = fs.readdirSync(dir, { withFileTypes: true });
      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);
        if (entry.isDirectory()) {
          results.push(...findGguf(fullPath));
        } else if (entry.name.endsWith(".gguf")) {
          const stats = fs.statSync(fullPath);
          results.push(JSON.stringify({
            path: fullPath,
            filename: entry.name,
            size_gb: (stats.size / (1024 ** 3)).toFixed(2),
          }));
        }
      }
      return results;
    };

    const models = findGguf(MODELS_DIR).map(m => JSON.parse(m));
    return {
      content: [{
        type: "text",
        text: JSON.stringify({
          total_models: models.length,
          models,
        }, null, 2),
      }],
    };
  }
);

// Tool 2: Get current model status
server.tool(
  "model_status",
  "Get current loaded model, memory usage, and Koboldcpp status",
  {},
  async () => {
    const resp = await fetch(`${KOBOLD_BASE}/api/v1/model`);
    const data = await resp.json();
    return {
      content: [{
        type: "text",
        text: JSON.stringify(data, null, 2),
      }],
    };
  }
);

// Tool 3: Generate text with current model
server.tool(
  "kobold_generate",
  "Generate text using the currently loaded Koboldcpp model",
  {
    prompt: z.string().describe("Input prompt"),
    max_tokens: z.number().optional().default(2048),
    temperature: z.number().optional().default(0.7),
    top_p: z.number().optional().default(0.9),
  },
  async ({ prompt, max_tokens, temperature, top_p }) => {
    const resp = await fetch(`${KOBOLD_BASE}/api/v1/generate`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        prompt,
        max_length: max_tokens,
        temperature,
        top_p,
        rep_pen: 1.1,
      }),
    });
    const data = await resp.json();
    return {
      content: [{
        type: "text",
        text: data.results?.[0]?.text || data.error || "Generation failed",
      }],
    };
  }
);

// Tool 4: Switch model (requires Koboldcpp restart)
server.tool(
  "switch_model",
  "Generate a command to switch the loaded GGUF model (requires restart)",
  {
    model_path: z.string().describe("Full path to the GGUF model file"),
    use_directio: z.boolean().optional().default(true),
    use_mlock: z.boolean().optional().default(true),
    gpu_layers: z.number().optional().describe("Number of layers to offload to GPU"),
  },
  async ({ model_path, use_directio, use_mlock, gpu_layers }) => {
    if (!fs.existsSync(model_path)) {
      return {
        content: [{ type: "text", text: `Error: Model not found at ${model_path}` }],
      };
    }

    const flags = [
      `--model ${model_path}`,
      use_directio ? "--usedirectio" : "",
      use_mlock ? "--mlock" : "",
      gpu_layers ? `--gpulayers ${gpu_layers}` : "",
      `--port ${new URL(KOBOLD_BASE).port}`,
      "--host 0.0.0.0",
    ].filter(Boolean).join(" \
  ");

    return {
      content: [{
        type: "text",
        text: JSON.stringify({
          message: "Restart Koboldcpp with these flags:",
          command: `./koboldcpp ${flags}`,
          note: "Stop the current instance first, then run this command.",
        }, null, 2),
      }],
    };
  }
);

// Tool 5: Health check
server.tool(
  "health_check",
  "Check Koboldcpp server health and model readiness",
  {},
  async () => {
    try {
      const start = Date.now();
      const resp = await fetch(`${KOBOLD_BASE}/api/v1/model`);
      const latency = Date.now() - start;
      const data = await resp.json();
      return {
        content: [{
          type: "text",
          text: JSON.stringify({
            status: resp.ok ? "healthy" : "degraded",
            latency_ms: latency,
            model: data.result || data,
          }, null, 2),
        }],
      };
    } catch (err) {
      return {
        content: [{
          type: "text",
          text: JSON.stringify({ status: "unreachable", error: String(err) }),
        }],
      };
    }
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

Step 3: Configure Claude Desktop

{
  "mcpServers": {
    "koboldcpp": {
      "command": "node",
      "args": ["/path/to/koboldcpp-mcp/dist/index.js"],
      "env": {
        "KOBOLD_BASE_URL": "http://localhost:5001",
        "MODELS_DIR": "/models"
      }
    }
  }
}

Benchmark: Koboldcpp Model Performance

Model Size Q4_K_M VRAM Tokens/sec (RTX 4090) GPQA Diamond
Qwen 3.8-Flash-Next 8B 5.2 GB 142 t/s 52.1
Ling-3.0-Flash MoE 16B 9.8 GB 98 t/s 58.3
Meta Muse Glimmer 30B 30B 18.4 GB 54 t/s 64.7
Hy4 770B (8xH100) 770B 380 GB 12 t/s 92.3

Production Reality Check

  1. DirectIO advantage: Koboldcpp v1.120's DirectIO loading skips OS page cache, reducing model load time from ~45s to ~12s for 30B models on NVMe.
  2. GPU offloading: Use --gpulayers N to offload N transformer layers to GPU. For 30B Q4_K_M on a 24GB GPU, set --gpulayers 40.
  3. Concurrent requests: Koboldcpp v1.120 handles 1 concurrent generation by default. For multi-agent use, deploy multiple instances on different ports.
  4. Model hot-swap: Koboldcpp does not support live model switching. The switch_model tool generates the restart command — plan ~15s downtime per swap.
  5. Tool calling: v1.120 adds configurable JavaScript tools to Kobold Lite. For MCP tool-calling, prefer the kobold_generate endpoint with structured prompts.

By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.

Last tested: August 2026 with Node v22, Koboldcpp v1.120, @modelcontextprotocol/sdk 1.12.0, Qwen 3.8-Flash-Next Q4_K_M on RTX 4090.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

🎉 Thank You for Subscribing!

Frequently Asked Questions
Minimum: 16GB RAM for 8B models (Qwen 3.8-Flash-Next). Recommended: 24GB GPU (RTX 4090) for 30B models with 40 GPU layers offloaded. For the largest models (770B), you need 8×H100 80GB with vLLM instead of Koboldcpp.
Koboldcpp v1.120 processes one generation at a time by default. For multi-agent workloads, deploy N instances on ports 5001-500N and load-balance with round-robin. Each instance needs its own GPU memory allocation.
Deepak Bagada
Author Profile

Deepak Bagada

CEO, SaaSNext

Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.

Related Intelligence Analysis

Briefing AI Tools

Vercel AI SDK Tool Calling React: 5 Steps (2026)

Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...

Deepak Bagada Deepak Bagada
12m read
Breaking AI Tools

Fact-Density vs. Word Count: The New SEO for 2026

Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...

Deepak Bagada Deepak Bagada
4m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc