MCP serverini ishlab chiqish bo‘yicha qaydlar

MCP serverini ishlab chiqish bo‘yicha qaydlar

Kirish

AI chatbot funksionalligini qo‘shish loyihasi boshlangach, menga “LLMga tizim ma’lumotlarini so‘rash imkonini berish” qismi topshirildi. LLM foydalanuvchilarning savollariga javob berishi uchun oxir-oqibat tizimimizda saqlanayotgan real vaqt ma’lumotlarini ko‘rishi kerak, ularni qanday ulashni aniqlash esa mening vazifam edi.

Men MCP (Model Context Protocol) konsepsiyasi bilan allaqachon tanish edim. Yangiliklar va hujjatlarda unga LLMga “vositalar”ni ulab, tashqi tizimlar bilan o‘zaro ishlash imkonini beradigan standart protokol sifatida duch kelganman va yaqinda bir nechta AI xizmatlari undan foydalana boshlaganini ham bilardim. Ammo bu men uni “bilardim” degani edi — “qurib ko‘rganman” degani emas. Konsepsiyani tushuntira olish bilan Spring Boot loyihasini amalda MCP serveri sifatida sozlab, uni ishlaydigan holatga keltirish o‘rtasida kutilganidan ancha katta farq bor edi.

Ushbu maqola ana shu farqni bartaraf etish jarayonida nimalarni o‘rganganimni, shuningdek, bu jarayonda Spring AI aslida qancha ishni siz uchun bajarishini bayon qiladi.

1. Muammo — Konsepsiyani bilish, ammo nimadan boshlashni bilmaslik

1-1. Ushbu loyihada hal qilishim kerak bo‘lgan muammo

Jamoamizning AI chatbot arxitekturasi quyidagicha tashkil etilgan edi.

UI → AI 서버 → LLM
        ↓ (MCP)
     MCP 서버
        ↓
MSA로 각각의 데이터를 수집하고 있는 서비스들

Foydalanuvchi “Hozirda ma’lumot yig‘mayotgan qurilmalar bormi?” deb so‘raganida, AI serveri LLM yordamida “bu savolga javob berish uchun serverlar ro‘yxatini so‘rash vositasi kerak”ligini aniqlaydi va ushbu vosita chaqiruvini men yaratgan MCP serveriga MCP orqali uzatadi. MCP serveri so‘rovni serverlarni boshqarish xizmatiga yuboriladigan haqiqiy REST API chaqiruviga aylantiradi, uni bajaradi, natijani LLM oson tushunadigan formatga keltiradi va qaytaradi.

Men uchun mas’uliyat aynan shu MCP serveri edi. Boshqacha aytganda, bu “mavjud ichki tizimning funksionalligini, AIfoydalana oladigan foydalanish uchun qulay shaklda yangi ochib beradigan serverni”boshidan qurish vazifasi edi.

1-2. Nimalarni ishlab chiqish kerak edi

MCP spetsifikatsiyasini o‘qiganda, u initialize, tools/list va tools/call kabi JSON-RPC xabarlari almashinadigan protokol ekanini tushunish oson. Biroq ishlab chiqishni amalda boshlaganimdan so‘ng, ko‘plab aniq savollar paydo bo‘ldi.

  • Bu protokolni to‘g‘ridan-to‘g‘ri Spring Boot controlleri sifatida amalga oshirishim kerakmidi? Agar JSON-RPC marshrutlashini, sessiyalarni boshqarishni (Mcp-Session-Id) va Streamable HTTP transportini barchasini qo‘lda yozishim kerak bo‘lsa, bu asosiy maqsadni unutib, mayda tafsilotlarga berilib ketish bilan barobar bo‘lardi.
  • Kodda “Tool” qanday ifodalanishi kerak? Bitta metod shunchaki bitta vositami yoki alohida interfeysni amalga oshirishim kerakmi?
  • Vositaga kiritiladigan va undan chiqariladigan ma’lumotlar spetsifikatsiyasini (JSON Schema) kim yaratadi? MCP clienti (LLM tomonida) vositani chaqirishdan oldin u qanday parametrlarni qabul qilishini bilishi kerak. Agar har safar sxemani qo‘lda yozishim kerak bo‘lsa, hatto bitta vositani qo‘shish ham juda katta hajmdagi andozaviy kod paydo bo‘lishiga olib keladigandek tuyuldi.
  • Xizmatimizda allaqachon bir nechta backend xizmati, jumladan, serverlarni boshqarish va qurilmalarni boshqarish xizmatlari mavjud bo‘lib, ularning har birida o‘z REST API konvensiyalari va client kutubxonasi bor. Ularni MCP vositalari sifatida o‘raganimizda, keyinchalik boshqa jamoa a’zolari qo‘shimcha xizmatlarni qo‘shganda chalkashib ketmasligi uchun ushbu loyihani qanday tuzishim kerak?

Qisqasi, muammo “MCP nima ekanida” emas edi. “Tuzilmani qanday tashkil etishekotizimni ichida ushbu va tuzilmani qanday tartibga solish va uni qanday yozish Spring Boot’da”ana shu haqiqiy muammo edi.

2. Yechim — Spring AI’ning MCP serverini qo‘llab-quvvatlashi

Men bu muammoni Spring ekotizimidagi framework — Spring AI (Spring’ning rasmiy AI integratsiya loyihasi) yordamida hal qilishga qaror qildim. Spring AI MCP serverlarini amalga oshirish uchun starter taqdim etadi va ikkita asosiy ishni siz uchun bajaradi.

  • Protokol darajasidagi qayta ishlash: Framework initialize, tools/list va tools/call kabi MCP protokoli xabarlarini marshrutlash, shuningdek, sessiyalarni boshqarish bilan shug‘ullanadi.
  • Annotatsiya asoslangan vosita va h.k.qayd: Dasturchilar oddiy metodga “bu vosita” degan annotatsiya qo‘shishlari kifoya, framework esa qolgan barcha ishlarni (sxema yaratish, ro‘yxatdan o‘tkazish va chaqiruvni ulash) avtomatik bajaradi.

Buni tanlash sababi aniq edi.

  • mavjud texnologiyalar steki bilan tabiiy integratsiya: Backendimiz to‘liq Spring Boot + Gradle asosida qurilgan, har bir xizmat uchun mijoz kutubxonalari ham Spring ekotizimida ishlaydi. Agar MCP serveri ham xuddi shu stekdan foydalansa, jamoa a’zolari hech qanday o‘rganish bosqichisiz uni darhol tushunishlari mumkin.
  • annotatsiya asoslangan vosita qo‘shish xarajat past: Agar yangi vositani qo‘shish “bitta metod yozish + bir nechta annotatsiya qo‘shish” bilan yakunlansa, boshqa jamoa a’zolari kelajakda boshqa domenlar uchun vositalar qo‘shishda xuddi shu usulni shunchaki takrorlashlari mumkin.
  • protokol amalga oshirish tafsilotlari erkinlik: Mijoz (LLM tomonidagi MCP mijozi) bilan to‘g‘ri muloqot qilish uchun JSON-RPC xabar formati, sessiyalarni boshqarish va xatolik javobi formati kabi jihatlar spetsifikatsiyaga muvofiq aniq amalga oshirilishi kerak. Framework ushbu quyi darajadagi tafsilotlarni bizning nomimizdan boshqargani hal qiluvchi omil bo‘ldi.

Natijada, build.gradle faylidagi bitta bog‘liqlik va application.yml faylidagi bir necha qator konfiguratsiya ushbu loyihaning MCP serveri uchun zarur bo‘lgan butun skeletni tashkil etdi.

spring:
  ai:
    mcp:
      server:
        name: my-mcp-server
        protocol: STREAMABLE
        type: SYNC
        annotation-scanner:
          enabled: true

3. Amalga oshirish misollari — Spring AI aslida siz uchun nimalarni boshqaradi

Shu yerdan boshlab kod yozish davomida “Ha, frameworkdan nima uchun foydalanishimiz endi tushunarli,” deb o‘ylaganim jihatlarni tartibladim.

3-1. MCP Inspector yordamida bevosita tekshirish

Protokol nazariy jihatdan avtomatik boshqarilsa ham, xotirjam bo‘lish uchun uni o‘z ko‘zingiz bilan ko‘rishingiz kerak. Bu bosqichda foydalanishingiz mumkin bo‘lgan vosita — MCP Inspector. Bu Anthropic tomonidan rasman tarqatiladigan, MCP serverlarini sinash va nosozliklarni tuzatish uchun mo‘ljallangan veb-asosli vosita bo‘lib, uni alohida o‘rnatishsiz quyidagi yagona qator yordamida darhol ishga tushirish mumkin.

npx @modelcontextprotocol/inspector

Yuqoridagi kod bilan ishga tushirilganda, ishlab chiqilayotgan vositani veb-interfeys orqali sinash va tekshirish mumkin. Serverlar ekranida Serverlar qo‘shish tugmasini bosing va Oqimlashuvchi HTTP transport turini tanlang, so‘ng ulanish uchun ishlab chiqilayotgan serverning MCP endpoint manzilini (masalan, http://localhost:8088/mcp) kiriting. Ulangandan so‘ng annotatsiyalar yordamida ro‘yxatdan o‘tkazgan vositalarim ro‘yxati nomlari, tavsiflari va kirish sxemalari bilan birga Vositalar yorlig‘ida aynan o‘z holicha paydo bo‘ladi; vositani tanlab, uning parametrlarini to‘ldirishingiz va uni bevosita chaqirishingiz mumkin.

Ushbu ekranda bevosita bosib ko‘rish orqali bu protokol darajasida aynan sodir bo‘ladigan jarayon ekanini tasdiqlay oldim.

  1. initialize so‘rovi yuborilganda, server sessiya yaratadi va javob sarlavhasida Mcp-Session-Id ni qaytaradi.
  2. Keyingi so‘rovlarni sarlavhada ushbu sessiya identifikatori bilan yuborish mumkin va
  3. tools/list chaqirilganda, annotatsiyalar yordamida ro‘yxatdan o‘tkazgan vositalarim ro‘yxati ularning nomlari, tavsiflari va kirish sxemalari bilan birga avtomatik qaytariladi.
  4. Haqiqiy vosita tools/call yordamida chaqirilganda, men yozgan Java metodi bajariladi va uning qaytarilgan qiymati avtomatik ravishda MCP javob formatiga (content, isError va hokazo) o‘raladi.

Men yozgan kodda ushbu protokolni boshqarish mantiqining birorta ham qatori yo‘q. Agar bu qismni o‘zim amalga oshirganimda, loyihaning dastlabki bir necha haftasini faqat “MCP spetsifikatsiyasini qayta amalga oshirish”ga sarflagan bo‘lardim, deb o‘ylayman.

Sinov paytida meni chalg‘itgan yana bir jihat bo‘ldi. Massiv (List) turidagi parametrni qabul qiladigan vositani chaqirganda, Inspector kiritish maydoniga shunchaki bitta qiymat kiritdim va natijada “integer topildi, massiv kutilgan edi” degan sxema tekshiruvi xatosi yuz berdi. Serverning o‘zi qaytargan sxema to‘g‘ri ravishda massiv edi, ammo kiritish maydoniga uni ["qiymat1", "qiymat2"] kabi JSON massivi ko‘rinishida kiritish kerakligini bilmasdim. Buni faqat hujjatlardan o‘rganish qiyin; bu tafsilotni vositalarni birma-bir o‘zim chaqirib ko‘rish orqali kashf qildim.

3-2. @McpTool / @McpToolParam — Bitta metod bitta vositaga aylanadigan tuzilma

Biz amalda yaratgan vositalardan birini soddalashtirsak, u quyidagicha ko‘rinadi.

@McpTool(
        name = "findServers",
        description = "서버 목록을 조회합니다. "
                + "이름 부분 문자열로 필터링할 수 있습니다.",
        annotations = @McpTool.McpAnnotations(
                title = "서버 목록 조회",
                readOnlyHint = true,
                destructiveHint = false,
                idempotentHint = true,
                openWorldHint = false
        )
)
public List<GatewaySummary> findGateways(
        @McpToolParam(description = "서버 이름 필터용 문자열", required = false)
        String nameFilter
) {
    // 내부적으로는 서버 관리 서비스의 기존 API 클라이언트를 그대로 호출
}

Ushbu kod ishga tushganda, framework quyidagilarni avtomatik boshqaradi.

  • Metod imzosini (String nameFilter) tahlil qilib, JSON Schema (\"type\": \"string\") ni avtomatik yaratadi
  • Tavsif LLM uchun “ushbu vositadan qachon foydalanish kerak”ligini aniqlashga asos bo‘lib xizmat qiladi. Boshqacha aytganda, ushbu tavsifning qanchalik aniq yozilgani LLM vositani samarali tanlay olishi va undan foydalana olishiga bevosita ta’sir qiladi.
  • McpAnnotations dagi readOnlyHint, destructiveHint, idempotentHint va openWorldHint — MCP spetsifikatsiyasida “ushbu vosita tizimga qanday ta’sir ko‘rsatishi” haqida belgilangan metama’lumotlardir. Bizning barcha vositalarimiz faqat o‘qish uchun mo‘ljallanganligi sababli, ularni readOnlyHint=true va destructiveHint=false tarzida standartlashtirdik. Ushbu ko‘rsatmalar mijoz tomonidan “ushbu vositani qayta-qayta xavfsiz chaqirish mumkinmi”ligini aniqlash uchun ishlatiladi.
  • Qaytariladigan tur ham JSON formatida seriyalashtiriladi va hech qanday alohida konversiya kodisiz javobga qo‘shiladi.

Boshqacha aytganda, men amalda yozgan kod“mavjud API mijozidan foydalanib chaqirish natijalarni va tartibga solish odatdagi Java metodini”—shu bilan tugadi. MCP ga xos qismlar atigi bir nechta annotatsiyadan iborat edi; qolgan barcha ishlar Spring dasturchilari allaqachon yaxshi biladigan yondashuv asosida bajarildi.

3-3. Bir nechta backendni yagona izchil tuzilmaga birlashtirish

Kompaniya ichida serverlarni boshqarish, uskunalarni boshqarish, ma’lumotlarni yig‘ish va ogohlantirishlar/monitoring uchun mas’ul bo‘lgan bir nechta backend xizmati allaqachon mavjud bo‘lib, ularning har biri o‘z mijozlar kutubxonasiga ega. Ushbu loyihada biz ulardan o‘z holicha qayta foydalandik va vositalarni domenlarga xos papkalarga ajratdik.

tools/
├── server/    ServerTools
├── device/     DeviceModelTools
├── collect/    DataCollectionTools
└── alert/      AlarmTools, ConditionTools

Ushbu tuzilmani yaratishdan maqsad amaliylik edi. Keyinchalik jamoaning boshqa a’zosi yangi domen uchun vosita qo‘shganda, “unga faqat shu papka ichida o‘xshash andozaga ega yana bir klass yaratish kifoya”ligi darhol tushunarli bo‘lishini xohladim. Spring AI annotatsiyalarga ega beanlarni avtomatik skanerlab, ularni vosita sifatida ro‘yxatdan o‘tkazadi, shuning uchun ushbu tuzilma qanchalik tartibli ishlab chiqilgani “keyingi dasturchi uni qanchalik oson kengaytira olishi”ni bevosita belgiladi.

4. Natijalar va kelgusidagi vazifalar

Natijalar

  • Biz to‘rtta domen: serverlarni boshqarish, uskunalarni boshqarish, ma’lumotlarni yig‘ish va ogohlantirishlar/monitoring bo‘yicha bir nechta MCP vositasini yaratdik.
  • MCP Inspector va curl yordamida amaldagi protokol qo‘l siqish jarayonlari (initialize → tools/list → tools/call) orqali har bir vosita to‘g‘ri ishlashini tekshirdik.
  • Dastlabki rejada ko‘rsatilgan barcha asosiy domen integratsiyalari, klaster infratuzilmasiga oid bandlardan tashqari, yakunlandi.

Ishlab chiqarish muhitiga joriy etishni yaxshilash yo‘nalishlari

  • Autentifikatsiya: Hozirda MCP endpointi uchun alohida autentifikatsiya mavjud emas. Dastlab uni faqat AI serveri korporativ tarmoq ichidan chaqiradi degan taxmin asosida ishlab chiqdik, biroq amalda ishlab chiqarish muhitiga joriy etishdan oldin buni albatta qo‘shish kerak.
  • Kengaytirish: Biz yaratgan tuzilmani (domenlarga xos papkalar tuzilmasi va mijozlar kutubxonasidan qayta foydalanish andozasini) jamoaning boshqa a’zolari bilan baham ko‘rishni va qolgan domenlarni qamrab olguncha uni kengaytirishni rejalashtirmoqdamiz.

5. Spring AI qachon yaxshi tanlov bo‘ladi (Afzalliklar va kamchiliklar)

Spring AI yordamida MCP serveri yaratishni ko‘rib chiqayotganlar uchun o‘zim bevosita boshdan kechirgan afzallik va kamchiliklarni qisqacha bayon qilaman.

Afzalliklar

  • Deyarli hech qanday qolip kodi yo‘q.Freymvork JSON-RPC marshrutlash, sessiyalarni boshqarish va Streamable HTTP transportidan tortib JSON Schema yaratishgacha bo‘lgan barcha ishni bajaradi. Dasturchilar faqat vositaga aylantiriladigan metodlar va ularning annotatsiyalariga e’tibor qaratishlari kerak.
  • Mavjud Spring Boot resurslarini o‘z holicha qayta ishlatish mumkin .DI, konfiguratsiyani boshqarish, mavjud mijozlar kutubxonalari va log yuritish kabi tanish yondashuvlar o‘z holicha saqlanib qoladi. Yangi freymvorkni noldan o‘rganishning hojati yo‘q.
  • Kengaytirish oson.Vositani qo‘shish uchun atigi “bitta metod + bitta annotatsiya” kifoya, shu sababli bu tuzilma bir nechta kishiga ishni taqsimlash, har bir kishining turli domen uchun mas’ul bo‘lishi va parallel ishlab chiqishi uchun ham qulay.

Kamchiliklar

  • Versiya yangilanadi tezda.Bu, shuningdek, API o‘zgarishi mumkinligini anglatadi. Shuning uchun eng so‘nggi versiyadan bevosita production muhitida foydalanayotganda, hatto bitta minor yangilanishda ham ehtiyot bo‘lish kerak.
  • Freymvork yashirganda narsalarni, quyi darajadagi tafsilotlarni siz nazorat qilmoqchi bo‘lgan to‘g‘ridan-to‘g‘ri siz buni qilish sizni hafsalangizni pir qilishi mumkin uchun shunday qilishga.Agar standart oqimdan chetga chiqadigan maxsus talablaringiz bo‘lsa (masalan, maxsus transport yoki protokol kengaytmasi), freymvork abstraksiyalarini olib tashlash aslida yanada qiyin bo‘lishi mumkin.

Xulosa qilib aytganda, “Spring Boot asosidagi xizmat tezda MCP serverini sozlashni istalgan bo‘lsa”agar maqsadingiz shu bo‘lsa, menimcha, bu yetarli, boshlash oson va intuitiv dizayni tufayli juda qulay.

6. Xulosa

Ushbu loyiha ustida ishlash jarayonida anglaganim shuki, MCP serverini ishlab chiqishning haqiqatan ham qiyin qismi protokolning o‘zi emas. Spring AI protokolning katta qismini biz uchun boshqardi. Aslida ko‘p vaqtni freymvork biz uchun qabul qila olmaydigan dizayn qarorlari oldi, masalan: “LLM vositani samarali tanlashi va undan foydalanishi uchun uni qanday nomlashimiz va tavsiflashimiz kerak?” hamda “Boshqa odamlar chalkashib qolmasligi uchun bir nechta backend tizimlarini qanday mezonlar asosida vositalarga ajratishimiz va ochib berishimiz kerak?”

MCP konsepsiyasini bilish va uni amalda xizmat arxitekturasiga aylantirish mutlaqo turlicha tajribalar ekan. Endi tizimimizga har safar yangi funksiya qo‘shilganda, o‘zimni tabiiy ravishda: “AI undan foydalana olishi uchun buni vosita sifatida qanday ochib berishimiz mumkin?” deb o‘ylayotganimni payqayman. AI’ning ichki tizimlarga xavfsiz va izchil tarzda ulanishiga imkon beradigan bunday abstraksiya qatlami AI funksiyalari kengayishda davom etar ekan, tobora muhim ahamiyat kasb etadi, deb hisoblayman.

sauce0127

Site footer