Kembali ke Beranda
Programming

Membangun MCP dengan Java : Membuat Tools untuk AI Assistant

Tutorial membangun MCP Server menggunakan Java dan Spring Boot dari nol. Artikel membahas konsep MCP, peran MCP Client dan Server, transport STDIO/HTTP, pembuatan tool getTicket, integrasi service internal, pengujian, serta prinsip keamanan seperti RBAC, audit log, dan pembatasan data.

Model Context Protocol (MCP) adalah standar untuk menghubungkan AI assistant dengan sistem, data, dan fungsi yang kita miliki. Dengan MCP, AI tidak hanya menjawab berdasarkan pengetahuan model, tetapi dapat memanggil tool untuk mengambil data tiket, membuat laporan, mengecek status JIRA, mencari SOP, atau menjalankan proses bisnis tertentu.

Artikel ini membangun MCP Server sederhana menggunakan Java dan Spring Boot dari nol. Contoh yang dibuat adalah tool untuk mengambil data tiket berdasarkan nomor tiket. Konsep yang sama bisa dikembangkan untuk PLATO, PIA, sistem helpdesk, ERP, database internal, atau API perusahaan.

Apa Itu MCP?

Sederhananya, MCP adalah “bahasa penghubung” antara AI dan aplikasi.

Tanpa MCP, AI hanya menerima teks dari pengguna lalu menghasilkan teks kembali.

User → LLM → Jawaban teks

Dengan MCP, AI dapat menentukan kapan perlu memakai fungsi dari sistem lain.

User → LLM / AI Host → MCP Client → MCP Server → API / Database
                              ↑                    ↓
                              └──── hasil tool ────┘

Contoh percakapan:

User: Tolong cek status tiket CEISA-2026-00123.

AI tidak perlu menebak status tiket. AI dapat memanggil tool MCP seperti berikut:

get_ticket(ticket_number = "CEISA-2026-00123")

MCP Server kemudian mengambil data dari database atau API tiket, lalu mengembalikan hasil terstruktur ke AI. Setelah itu AI menyampaikan hasilnya dengan bahasa yang mudah dipahami pengguna.

Komponen Utama dalam MCP

Ada empat komponen yang perlu dipahami.

KomponenPeran
UserMemberikan instruksi atau pertanyaan
AI HostAplikasi yang menjalankan LLM dan mengelola percakapan
MCP ClientPenghubung dari AI Host ke MCP Server
MCP ServerAplikasi yang menyediakan tools, resources, atau prompts
ToolFungsi yang dapat dipanggil AI, misalnya get_ticket
ResourceData seperti file, dokumen, atau referensi yang dapat dibaca AI
PromptTemplate instruksi yang disediakan oleh server

Dalam artikel ini kita fokus pada tools, karena ini adalah bagian paling umum untuk integrasi aplikasi.

Kapan MCP Berguna?

MCP cocok ketika AI perlu berinteraksi dengan data atau proses yang tidak ada di dalam model.

Contohnya:

  • Mengambil detail tiket helpdesk.
  • Membaca status issue JIRA.
  • Mencari SOP berdasarkan kode.
  • Mengambil regulasi dari database RAG.
  • Membuat draft laporan.
  • Mengecek stok, harga, atau pesanan.
  • Membuat tiket baru setelah pengguna menyetujui.
  • Menjalankan analisis data operasional.

MCP bukan pengganti API. Justru MCP biasanya berada di atas API atau service internal yang sudah ada.

AI
 ↓
MCP Tool
 ↓
Service Java / REST API / Database / Elasticsearch / JIRA

Artinya, logika bisnis tetap sebaiknya berada pada service aplikasi. MCP berfungsi sebagai lapisan yang mendeskripsikan fungsi tersebut agar bisa dipahami dan dipanggil oleh AI.

Pilihan Transport: STDIO atau HTTP?

MCP dapat berjalan melalui beberapa cara komunikasi. Dua yang paling sering digunakan adalah STDIO dan HTTP.

TransportCocok untukKarakteristik
STDIOTool lokal di laptop/server yang samaProses MCP dijalankan langsung oleh aplikasi AI
Streamable HTTPServer terpusat, multi-user, aplikasi enterpriseMCP diakses melalui endpoint HTTP
SSEImplementasi MCP HTTP generasi sebelumnyaMasih ditemui pada beberapa sistem lama

Untuk belajar dari nol, STDIO paling mudah dipahami. Namun untuk aplikasi seperti PLATO atau PIA yang dipakai banyak pengguna, HTTP biasanya lebih relevan karena MCP Server dapat dipasang sebagai service terpisah.

Catatan penting: pada MCP berbasis STDIO, jangan menulis log menggunakan System.out.println(). STDOUT dipakai untuk pertukaran pesan JSON-RPC MCP. Gunakan logger yang menulis ke STDERR atau file log.

Teknologi yang Digunakan

Contoh ini menggunakan:

  • Java 17 atau lebih baru
  • Spring Boot
  • Spring AI MCP Server
  • Maven
  • MCP Inspector atau MCP Client untuk pengujian

Struktur sederhana proyek:

mcp-ticket-server/
├── pom.xml
└── src/
    └── main/
        ├── java/
        │   └── id/nirantara/mcp/
        │       ├── McpTicketApplication.java
        │       ├── TicketTools.java
        │       ├── TicketService.java
        │       └── TicketResponse.java
        └── resources/
            └── application.yml

Membuat Project Spring Boot

Buat proyek Spring Boot melalui Spring Initializr atau siapkan struktur Maven secara manual.

Berikut contoh pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="
         http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>id.nirantara</groupId>
    <artifactId>mcp-ticket-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.0</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <spring-ai.version>1.1.0</spring-ai.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Versi dependency dapat berubah. Sebelum implementasi produksi, cek dokumentasi Spring AI dan MCP Java SDK untuk versi yang sesuai dengan Spring Boot yang digunakan.

Konfigurasi MCP Server

Buat file src/main/resources/application.yml.

spring:
  application:
    name: mcp-ticket-server

  ai:
    mcp:
      server:
        name: nirantara-ticket-server
        version: 1.0.0
        protocol: STREAMABLE

server:
  port: 8089

logging:
  level:
    id.nirantara.mcp: INFO

Dengan konfigurasi tersebut, aplikasi akan berjalan sebagai MCP Server melalui HTTP. Nantinya AI Host atau MCP Client dapat mengakses server ini melalui endpoint yang disediakan oleh starter MCP.

Membuat Main Application

Buat file McpTicketApplication.java.

package id.nirantara.mcp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class McpTicketApplication {

    public static void main(String[] args) {
        SpringApplication.run(McpTicketApplication.class, args);
    }
}

Membuat Model Respons Tiket

Buat file TicketResponse.java.

package id.nirantara.mcp;

public record TicketResponse(
        String ticketNumber,
        String title,
        String status,
        String application,
        String solution,
        String updatedAt
) {
}

Pada aplikasi nyata, objek ini dapat berasal dari database, API helpdesk, Elasticsearch, atau service internal lain.

Membuat Service untuk Mengambil Data

Buat file TicketService.java.

package id.nirantara.mcp;

import org.springframework.stereotype.Service;

@Service
public class TicketService {

    public TicketResponse findByTicketNumber(String ticketNumber) {

        // Contoh data sementara.
        // Ganti bagian ini dengan query database atau pemanggilan API internal.
        if ("CEISA-2026-00123".equalsIgnoreCase(ticketNumber)) {
            return new TicketResponse(
                    "CEISA-2026-00123",
                    "OTP tidak diterima oleh pengguna",
                    "Resolved",
                    "CEISA 4.0",
                    "Pastikan nomor telepon terdaftar aktif, lalu lakukan pengiriman OTP ulang.",
                    "2026-08-11 09:30"
            );
        }

        return null;
    }
}

Contoh integrasi dengan REST API internal:

public TicketResponse findByTicketNumber(String ticketNumber) {
    String url = "https://ticket-api.internal/api/tickets/" + ticketNumber;

    // Gunakan RestClient, WebClient, atau Feign Client.
    // Tambahkan timeout, autentikasi, dan penanganan error.
    return restClient.get()
            .uri(url)
            .retrieve()
            .body(TicketResponse.class);
}

Jangan menaruh credential API secara langsung di source code. Simpan token atau username/password pada environment variable, secret manager, atau konfigurasi terenkripsi.

Membuat MCP Tool

Bagian paling penting adalah mendefinisikan tool yang dapat ditemukan dan dipanggil oleh AI.

Buat file TicketTools.java.

package id.nirantara.mcp;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;

@Component
public class TicketTools {

    private final TicketService ticketService;

    public TicketTools(TicketService ticketService) {
        this.ticketService = ticketService;
    }

    @Tool(description = """
            Mengambil detail tiket berdasarkan nomor tiket.
            Gunakan tool ini apabila pengguna meminta status, detail,
            solusi, atau informasi tiket tertentu.
            """)
    public TicketResponse getTicket(
            @ToolParam(description = "Nomor tiket, contoh: CEISA-2026-00123")
            String ticketNumber
    ) {
        TicketResponse ticket = ticketService.findByTicketNumber(ticketNumber);

        if (ticket == null) {
            return new TicketResponse(
                    ticketNumber,
                    "Tiket tidak ditemukan",
                    "-",
                    "-",
                    "Periksa kembali nomor tiket yang diberikan.",
                    "-"
            );
        }

        return ticket;
    }
}

Anotasi @Tool membuat method tersebut didaftarkan sebagai kemampuan MCP. Deskripsi pada @Tool sangat penting karena AI memakai deskripsi ini untuk menentukan:

  1. kapan tool perlu dipanggil;
  2. data apa yang harus dikirim;
  3. hasil apa yang dapat diharapkan.

Nama method juga sebaiknya jelas. Gunakan kata kerja dan objek yang spesifik.

Contoh nama tool yang baik:

getTicket
searchTickets
getJiraIssue
createTicket
findSop
getTicketStatistics

Contoh nama yang kurang baik:

process
execute
doAction
getData
run

AI lebih mudah memilih tool jika nama dan deskripsinya menggambarkan fungsi bisnis secara langsung.

Mendaftarkan Tool ke MCP Server

Tambahkan konfigurasi berikut agar Spring Boot mengenali tool yang sudah dibuat.

package id.nirantara.mcp;

import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class McpToolConfiguration {

    @Bean
    public ToolCallbackProvider ticketToolsProvider(TicketTools ticketTools) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(ticketTools)
                .build();
    }
}

Saat aplikasi berjalan, MCP Client dapat melakukan proses discovery dan mengetahui bahwa server memiliki tool bernama getTicket.

Menjalankan Aplikasi

Jalankan aplikasi menggunakan Maven.

./mvnw spring-boot:run

Atau build menjadi JAR.

./mvnw clean package
java -jar target/mcp-ticket-server-0.0.1-SNAPSHOT.jar

Jika berhasil, MCP Server berjalan di port 8089.

Menguji dengan MCP Inspector

MCP Inspector membantu menguji server sebelum dihubungkan ke AI assistant. Dengan Inspector, kita dapat:

  • melihat daftar tools;
  • memeriksa schema parameter;
  • memanggil tool secara manual;
  • melihat respons dan error;
  • memastikan transport MCP sudah berjalan benar.

Contoh payload ketika memanggil getTicket:

{
  "ticketNumber": "CEISA-2026-00123"
}

Contoh hasil:

{
  "ticketNumber": "CEISA-2026-00123",
  "title": "OTP tidak diterima oleh pengguna",
  "status": "Resolved",
  "application": "CEISA 4.0",
  "solution": "Pastikan nomor telepon terdaftar aktif, lalu lakukan pengiriman OTP ulang.",
  "updatedAt": "2026-08-11 09:30"
}

Menghubungkan MCP dengan LLM

Penting untuk dipahami: MCP Server bukan LLM dan tidak melakukan klasifikasi bahasa secara otomatis.

Alurnya biasanya seperti ini:

1. User bertanya:
   "Cek status CEISA-2026-00123"

2. AI Host membaca pertanyaan.

3. LLM melihat daftar tools dari MCP Server.

4. LLM memilih:
   getTicket(ticketNumber = "CEISA-2026-00123")

5. MCP Client memanggil MCP Server.

6. MCP Server mengambil data dari sistem tiket.

7. Hasil dikembalikan ke LLM.

8. LLM membuat jawaban natural untuk user.

Misalnya hasil akhir yang ditampilkan AI:

Tiket CEISA-2026-00123 saat ini berstatus Resolved. Kendalanya adalah OTP tidak diterima pengguna. Solusi yang dicatat adalah memastikan nomor telepon terdaftar aktif, lalu melakukan pengiriman OTP ulang.

Jadi, LLM berperan sebagai pengambil keputusan dan penyusun jawaban. MCP Server berperan sebagai penyedia kemampuan serta akses yang terkontrol ke sistem internal.

Contoh Tool untuk Sistem Ticketing

Dalam sistem seperti PLATO atau PIA, MCP dapat menyediakan beberapa tool berikut.

@Tool(description = "Mencari tiket berdasarkan kata kunci kendala.")
public List<TicketResponse> searchTickets(String keyword) {
    return ticketService.search(keyword);
}

@Tool(description = "Mengambil statistik tiket berdasarkan rentang waktu dan aplikasi.")
public TicketStatisticResponse getTicketStatistics(
        String application,
        String startDate,
        String endDate
) {
    return ticketService.getStatistics(application, startDate, endDate);
}

@Tool(description = "Membuat tiket baru setelah data pengguna lengkap dan valid.")
public CreateTicketResponse createTicket(
        String title,
        String description,
        String application,
        String reporter
) {
    return ticketService.createTicket(title, description, application, reporter);
}

Untuk tool yang mengubah data seperti createTicket, updateTicket, atau closeTicket, tambahkan validasi dan mekanisme persetujuan pengguna. Jangan membiarkan AI membuat perubahan penting tanpa kontrol.

Prinsip Keamanan MCP untuk Aplikasi Internal

MCP memudahkan AI memanggil fungsi aplikasi. Karena itu, desain keamanan harus direncanakan dari awal.

1. Bedakan Tool Baca dan Tool Ubah Data

Tool baca biasanya lebih aman.

getTicket
searchSop
getJiraIssue
getTicketStatistics

Tool yang mengubah data perlu perlindungan lebih ketat.

createTicket
updateTicket
assignTicket
closeTicket
deleteDocument

Untuk operasi perubahan data, gunakan konfirmasi pengguna, audit log, RBAC, dan validasi parameter.

2. Jangan Memberi Akses Database Langsung ke LLM

Arsitektur yang kurang aman:

LLM → Database produksi

Arsitektur yang lebih aman:

LLM → MCP Tool → Service Layer → Database

Dengan service layer, kita dapat membatasi query, memvalidasi input, menyaring data sensitif, dan mencatat aktivitas.

3. Terapkan Role-Based Access Control

Tool yang tersedia sebaiknya menyesuaikan role pengguna.

Contoh:

RoleAkses
HelpdeskMembaca dan membuat tiket
SupervisorMembaca statistik dan melakukan assignment
AdminMengubah master data
AuditorMembaca data serta audit log

Jangan hanya mengandalkan prompt seperti “jangan tampilkan data rahasia”. Pemeriksaan hak akses harus dilakukan di backend Java.

4. Batasi Data yang Dikembalikan

Jangan selalu mengembalikan seluruh data tiket, terutama bila terdapat nomor telepon, email, NIK, token, credential, atau catatan internal sensitif.

Gunakan DTO khusus untuk AI.

public record SafeTicketResponse(
        String ticketNumber,
        String title,
        String status,
        String application,
        String solution
) {
}

5. Catat Audit Log

Setiap pemanggilan tool perlu dicatat.

waktu
user_id
role
tool_name
parameter
status
durasi
hasil ringkas

Audit log membantu investigasi ketika ada akses tidak wajar atau hasil AI perlu ditelusuri kembali.

Kesalahan yang Sering Terjadi

Menganggap MCP adalah Pengganti API

MCP bukan pengganti REST API, database, atau service bisnis. MCP adalah lapisan integrasi agar AI dapat menggunakan kemampuan sistem secara standar.

Membuat Tool Terlalu Umum

Tool seperti executeQuery(sql) sangat berisiko karena memberi AI kemampuan terlalu luas.

Lebih baik buat tool spesifik:

getTicket(ticketNumber)
getOpenTickets(application)
getTicketStatistics(startDate, endDate)

Deskripsi Tool Tidak Jelas

Deskripsi yang buruk membuat AI salah memilih tool atau salah mengisi parameter.

Kurang jelas:

@Tool(description = "Mengambil data")

Lebih jelas:

@Tool(description = """
        Mengambil detail tiket berdasarkan nomor tiket.
        Gunakan hanya jika pengguna menyebutkan nomor tiket.
        Jangan gunakan untuk pencarian berdasarkan kata kunci.
        """)

Terlalu Banyak Log ke STDOUT

Untuk transport STDIO, output sembarangan ke console dapat merusak komunikasi JSON-RPC. Gunakan logging framework seperti SLF4J dan pastikan output log diarahkan ke STDERR atau file.

Pengembangan Berikutnya

Setelah tool pertama berhasil, MCP Server dapat dikembangkan bertahap.

  1. Menghubungkan TicketService ke database atau API sebenarnya.
  2. Menambahkan autentikasi antar-service.
  3. Menambahkan RBAC berdasarkan pengguna AI.
  4. Menambahkan audit log.
  5. Membuat tool pencarian SOP dan regulasi.
  6. Menambahkan tool statistik tiket.
  7. Menghubungkan ke JIRA.
  8. Menambahkan cache untuk query yang sering digunakan.
  9. Menambahkan monitoring latency dan error rate.
  10. Memisahkan tool berdasarkan domain: Ticket, SOP, Regulation, JIRA, dan Reporting.

Untuk PIA, pola MCP dapat digunakan seperti berikut:

PIA / LLM
 ├── MCP Ticket Server
 ├── MCP SOP Server
 ├── MCP Regulation Server
 ├── MCP JIRA Server
 └── MCP Reporting Server

Dengan pemisahan ini, tiap domain memiliki akses, validasi, dan audit log sendiri. Sistem menjadi lebih mudah dirawat dibandingkan satu aplikasi AI yang langsung terhubung ke seluruh database dan API.

Penutup

MCP membuat AI dapat berinteraksi dengan sistem nyata secara lebih terstruktur. Pada Java, pendekatan yang praktis adalah memakai Spring Boot sebagai fondasi aplikasi, lalu mendaftarkan method bisnis sebagai MCP tools.

Mulailah dari satu tool yang aman dan spesifik, misalnya getTicket. Setelah alur discovery, pemanggilan tool, dan respons berjalan stabil, barulah tambahkan tool lain seperti pencarian SOP, statistik tiket, integrasi JIRA, atau pembuatan tiket.

Kunci implementasi MCP yang baik bukan hanya membuat AI bisa memanggil fungsi, tetapi memastikan fungsi tersebut memiliki batas akses yang jelas, validasi kuat, audit log, dan data respons yang aman.

Referensi

mcpmodel context protocoljavaspring bootspring aiai agentllmartificial intelligencebackend developmentapi integrationticketing systemplatopianirantara
Nirantara Logo

Published by Nirantara

Nirantara is an Indonesian Enterprise AI company specializing in Enterprise AI, RAG, Intelligent Search, and AI Automation. Article written by jsturana.

Learn more about Nirantara