AizuDemy

Tutorial Build MCP Server Go: Automasi Linux Sysadmin Pakai AI Agent

Tutorial Build MCP Server Go: Automasi Linux Sysadmin Pakai AI Agent
๐ŸŽง
Dengarkan Artikel Ini
Suara AI Otomatis โ€ข 7 mnt baca baca
โšก TL;DR

Poin Kunci Artikel Ini:

  • [ ] Sudoers diisolasi hanya untuk perintah dan argumen yang terdaftar mutlak.
  • Namun, model AI membutuhkan protokol terstruktur untuk berinteraksi langsung dengan sistem operasi.
  • MCP adalah standar terbuka berbasis JSON-RPC 2.0 yang dikembangkan oleh Anthropic.
๐Ÿ“‹ Daftar Isi Materi Tutup โ–ด

Script Manual Lambat: AI Butuh Protokol Standar Akses OS

Eksekusi script Bash manual untuk mengelola infrastruktur Linux lambat, tidak terstruktur, dan rentan human error. Sysadmin sering membuat script ad-hoc tanpa standarisasi skema input-output, tanpa penanganan error yang konsisten, serta tanpa mekanisme rate-limiting atau pembatasan akses yang jelas. Ketika insiden terjadi di lingkungan produksi, mengeksekusi perintah satu per satu via SSH memperpanjang Mean Time to Resolution (MTTR).

AI Agent seperti Claude Desktop, Claude Code, atau LLM lokal (Ollama) memiliki kemampuan analisis log dan diagnostik sistem yang cepat. Namun, model AI membutuhkan protokol terstruktur untuk berinteraksi langsung dengan sistem operasi. Tanpa protokol standar, AI hanya bisa memberikan saran teks yang harus disalin-tempel secara manual oleh manusia.

Model Context Protocol (MCP) memecahkan masalah ini. MCP adalah standar terbuka berbasis JSON-RPC 2.0 yang dikembangkan oleh Anthropic. MCP mendefinisikan cara AI Agent (client) menemukan data (resources), mengeksekusi fungsi (tools), dan membaca instruksi konteks (prompts) dari server eksternal. Menggunakan Go (Golang) untuk membangun MCP Server memberikan tiga keuntungan utama: performa tinggi dengan pemakaian memori minimal, biner tunggal (single static binary) tanpa dependensi runtime eksternal seperti Node.js atau Python, serta model konkuensi murni bawaan language runtime.

Arsitektur & Protokol Transport MCP: Stdio vs HTTP/SSE

Spesifikasi MCP mendukung dua mekanisme transport utama untuk pertukaran pesan JSON-RPC 2.0:

  • Standard I/O (stdio): Client menjalankan proses biner MCP Server sebagai child process dan berkomunikasi melalui stream stdin dan stdout. Transport ini ideal untuk pengoperasian lokal atau di dalam kontainer terisolasi karena tidak membuka port jaringan eksternal.
  • HTTP dengan Server-Sent Events (SSE): Digunakan untuk arsitektur terdistribusi di mana MCP Server berjalan pada remote host dan diakses oleh client melalui koneksi HTTP terenkripsi (TLS).

Aturan kritis dalam transport stdio: seluruh output log aplikasi wajib diarahkan ke stderr. Jika biner mencetak teks biasa atau pesan debug ke stdout, format JSON-RPC akan terdistorsi (corrupted), menyebabkan client gagal melakukan parsing respons.

Build MCP Server Go: Ekspos Metric CPU, RAM, dan Systemd

Tahap berikut menjelaskan pembuatan MCP Server di Go menggunakan SDK resmi github.com/mark3labs/mcp-go untuk mengekspos metrics memori dan kontrol service systemd.

1. Inisialisasi Proyek Go

Eksekusi perintah berikut untuk membuat direktori proyek dan mengunduh dependensi SDK:

mkdir mcp-linux-server && cd mcp-linux-server
go mod init mcp-linux-server
go get github.com/mark3labs/mcp-go

2. Implementasi Kode Server Go

Buat file main.go dan masukkan kode berikut. Kode ini mendaftarkan dua tool: get_memory_usage untuk membaca statistik RAM dan check_service_status untuk mengecek status service Linux.

package main

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"time"

	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
)

func main() {
	s := server.NewMCPServer("linux-sysadmin-mcp", "1.0.0")

	// Tool 1: Cek RAM
	memTool := mcp.NewTool("get_memory_usage",
		mcp.WithDescription("Mengambil statistik penggunaan RAM sistem Linux menggunakan perintah free"),
	)
	s.AddTool(memTool, handleMemoryUsage)

	// Tool 2: Cek Service Systemd
	serviceTool := mcp.NewTool("check_service_status",
		mcp.WithDescription("Memeriksa status operasional service systemd"),
		mcp.WithString("service_name", mcp.Required(), mcp.Description("Nama service target (contoh: nginx, docker, sshd)")),
	)
	s.AddTool(serviceTool, handleServiceStatus)

	// Jalankan server menggunakan transport Stdio
	if err := server.ServeStdio(s); err != nil {
		fmt.Fprintf(os.Stderr, "[ERROR] MCP Server crash: %v\
", err)
		os.Exit(1)
	}
}

func handleMemoryUsage(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	logAudit("get_memory_usage", "N/A", "system")
	
	out, err := exec.CommandContext(ctx, "free", "-h").Output()
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("Gagal membaca statistik RAM: %v", err)), nil
	}
	return mcp.NewToolResultText(string(out)), nil
}

func handleServiceStatus(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	service, ok := request.Params.Arguments["service_name"].(string)
	if !ok || strings.TrimSpace(service) == "" {
		return mcp.NewToolResultError("Argument service_name wajib diisi dan harus berupa string"), nil
	}

	// Validasi Strict: cegah command injection
	matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", service)
	if !matched {
		return mcp.NewToolResultError("Format nama service tidak valid! Hanya karakter alfanumerik, dash, dan underscore diperbolehkan."), nil
	}

	logAudit("check_service_status", service, "system")

	out, err := exec.CommandContext(ctx, "systemctl", "is-active", service).Output()
	status := strings.TrimSpace(string(out))
	if err != nil && status == "" {
		status = "unknown/inactive"
	}

	return mcp.NewToolResultText(fmt.Sprintf("Service '%s' status: %s", service, status)), nil
}

func logAudit(action string, input string, user string) {
	f, err := os.OpenFile("/var/log/mcp-audit.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		fmt.Fprintf(os.Stderr, "[WARN] Gagal menulis audit log: %v\
", err)
		return
	}
	defer f.Close()
	entry := fmt.Sprintf("[%s] USER=%s ACTION=%s INPUT=%s\
", time.Now().Format(time.RFC3339), user, action, input)
	f.WriteString(entry)
}

Integrasi Claude Desktop & Ollama Framework

Setelah kode dikompilasi, biner MCP Server dihubungkan ke client AI (Claude Desktop atau LLM Agent lokal).

  1. Kompilasi source code Go menjadi file biner biner executable:
    go build -ldflags="-s -w" -o /usr/local/bin/mcp-linux-server main.go
  2. Buka file konfigurasi client JSON:
    • Linux: ~/.config/Claude/claude_desktop_config.json
    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  3. Tambahkan entri server ke dalam bagian mcpServers:
    {
      "mcpServers": {
        "linux_admin": {
          "command": "/usr/local/bin/mcp-linux-server"
        }
      }
    }
  4. Restart Claude Desktop. AI Agent akan mendeteksi tool get_memory_usage dan check_service_status secara otomatis saat sesi percakapan dimulai.

Vulnerability Vectors & Mitigasi Security: Mencegah RCE

Memberikan akses eksekusi sistem ke AI Agent tanpa batas keamanan adalah celah bahaya. LLM dapat mengalami prompt injection dari teks eksternal yang dianalisis, mengarahkan Agent mengeksekusi instruksi destruktif.

1. Hindari Shell Execution Evaluator

Jangan pernah menjalankan perintah via shell evaluator seperti exec.Command("sh", "-c", input) atau exec.Command("bash", "-c", input). Pendekatan ini memungkinkan penyerang menyisipkan karakter metacharacter shell seperti ;, |, atau && untuk mengeksekusi perintah tambahan (Arbitrary Command Execution).

Gunakan format pemisahan argumen eksplisit pada exec.CommandContext(ctx, "binary", "arg1", "arg2").

2. Sanitasi Input Berbasis Sanitization/Regex Whitelist

Setiap input parameter dari AI Client wajib difilter dengan ekspresi reguler ketat sebelum diproses oleh sistem operasi. Hanya karakter aman yang diizinkan masuk ke proses:

matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", inputParam)
if !matched {
    return errors.New("Input ditolak: terdeteksi karakter ilegal")
}

3. Whitelisting Service Target

Untuk membatasi cakupan aksinya, buat daftarkan izin (allowlist) perintah atau service yang boleh diakses oleh MCP Server:

var allowedServices = map[string]bool{
	"nginx":  true,
	"docker": true,
	"sshd":   true,
}

if !allowedServices[serviceName] {
	return mcp.NewToolResultError("Akses ditolak: service tidak terdaftar dalam allowlist security policy"), nil
}

Prinsip Least Privilege & Implementasi Audit Logging

Menjalankan proses MCP Server menggunakan akun root melanggar prinsip dasar keamanan sistem. Jika terjadi exploit pada biner server, penyerang mendapatkan kendali penuh atas sistem operasi.

1. Konfigurasi User Sistem Tanpa Shell

Buat akun user dedicated berhak akses rendah khusus untuk menjalankan service MCP:

sudo useradd -r -s /sbin/nologin mcp-agent

2. Konfigurasi Sudoers Terbatas

Jika server memerlukan perintah berhak akses tinggi (seperti merestart service), berikan izin spesifik pada file /etc/sudoers.d/mcp-agent tanpa akses password:

mcp-agent ALL=(ALL) NOPASSWD: /usr/bin/systemctl status nginx, /usr/bin/systemctl restart nginx

3. Centralized Audit Log

Setiap eksekusi tool wajib dicatat ke file log yang terproteksi (/var/log/mcp-audit.log). Format log harus mencakup timestamp ISO-8601, nama tool, parameter yang dikirim, serta status keberhasilan eksekusi. Data ini krusial untuk analisis forensik keamanan digital.

Checklist Keamanan Produksi

  • [ ] Biner MCP Server tidak dijalankan oleh user root.
  • [ ] Seluruh parameter string difilter menggunakan regex ^[a-zA-Z0-9_-]+$.
  • [ ] Pemanggilan sistem menggunakan exec.CommandContext dengan argumen terpisah (tanpa sh -c).
  • [ ] Sudoers diisolasi hanya untuk perintah dan argumen yang terdaftar mutlak.
  • [ ] File log audit di-set dengan hak akses terbatas (chmod 0600).
  • [ ] Proses dipasang di dalam ekosistem terisolasi seperti Docker/Podman container atau systemd isolation jail (ProtectSystem=strict).

Kesimpulan

Mengintegrasikan AI Agent ke infrastruktur Linux dengan MCP Server Go memberikan efisiensi tinggi tanpa mengorbankan keamanan. Protokol terstandar JSON-RPC 2.0, validasi input yang ketat, serta penerapan principle of least privilege memastikan server tetap aman dari risiko Remote Code Execution (RCE). Bangun MCP Tool modular Anda sekarang untuk mengotomatisasi pekerjaan sysadmin secara presisi dan aman.

๐Ÿ“– Artikel Terkait