ข้ามไปเนื้อหาหลัก

สร้าง MCP Server ตัวแรก: บทเรียนจาก API สภาพอากาศสเปน

วิศวกร Backend เผยประสบการณ์พัฒนา Model Context Protocol (MCP) ตัวแรกเชื่อมต่อ AEMET พร้อมเจาะลึกปัญหาการเรียก API แบบสองขั้นตอนและการจัดการ Encoding

เรียบเรียงโดย AI
Inewgen
26 Jul 2026ที่มา: Dev.to4 นาทีอ่าน (0 ครั้ง)อัปเดตล่าสุด 04 Aug 2026
แชร์
สร้าง MCP Server ตัวแรก: บทเรียนจาก API สภาพอากาศสเปน

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง

ขนาดตัวอักษร
  • นักพัฒนาสาย Backend เริ่มหันมาจับตลาด AI Agent โดยสร้าง Model Context Protocol (MCP) Server ของตัวเอง
  • เลือกใช้ AEMET API ของสเปนเป็นสนามทดลองเพราะใช้งานง่ายและไม่มีความซับซ้อนเรื่องลิขสิทธิ์
  • พบความท้าทายสำคัญคือการเรียกข้อมูลแบบสองขั้นตอน (Two-step pattern) และปัญหาการเข้ารหัสตัวอักษร ISO-8859-1
  • เป้าหมายระยะยาวคือการพัฒนา AI Agent สำหรับตรวจสอบระบบ Kubernetes ในอนาคต

ในฐานะวิศวกรระบบ Backend ที่คุ้นเคยกับ Java, Spring และ Kubernetes การขยับเข้าสู่โลกของ AI Engineering ทำให้ต้องการลงมือสร้างและเผยแพร่โปรเจกต์จริงในระบบนิเวศของ Agent แทนที่จะแค่อ่านทฤษฎี จึงเป็นที่มาของการพัฒนาและเผยแพร่ Model Context Protocol (MCP) Server ขนาดเล็กตัวแรก ซึ่งเป็นจุดเริ่มต้นของซีรีส์ที่จะมีความซับซ้อนมากขึ้นเรื่อย ๆ โดยโปรเจกต์แรกนี้ถูกออกแบบมาให้มีขอบเขตเรียบง่าย เพื่อให้กระบวนการตั้งแต่การสร้าง เผยแพร่ไปยัง npm การนำไปแสดงในรีจิสทรีทางการของ MCP จนถึงขั้นตอนนี้ใช้งานได้จริงครบถ้วน

หัวข้อที่เลือกใช้คือ AEMET ซึ่งเป็นหน่วยงานอุตุนิยมวิทยาแห่งชาติของสเปนที่มีบริการ API สาธารณะให้ใช้งานฟรี ไม่มีปัญหาเรื่องการยืนยันตัวตนที่ยุ่งยากเกินกว่าการใช้ API Key และไม่มีข้อจำกัดทางกฎหมาย จึงเป็นสนามทดลองที่สะอาดสำหรับการเรียนรู้กลไกการทำงาน โดยสิ่งที่ไม่ได้คาดคิดคือ API ที่ดูเรียบง่ายนี้กลับซ่อนบทเรียนทางวิศวกรรมที่น่าสนใจที่สุดไว้ถึงสองประการ

Model Context Protocol (MCP) เป็นโปรโตคอลแบบเปิดที่เข้ามาช่วยลดช่องว่างระหว่างโมเดล AI กับระบบภายนอก ทำให้ AI Client เช่น Claude Desktop หรือ Agent ใน IDE สามารถเรียกใช้เครื่องมือภายนอกผ่านอินเทอร์เฟซมาตรฐานได้ โดยนักพัฒนาไม่ต้องเขียนโค้ดเชื่อมต่อใหม่ทั้งหมดสำหรับแต่ละแพลตฟอร์ม

สำหรับเครื่องมือที่ถูกพัฒนาขึ้นมาในเซิร์ฟเวอร์นี้ประกอบด้วย:

  • get_municipality_forecast สำหรับดึงพยากรณ์อากาศตามเทศบาลโดยใช้รหัส INE
  • get_station_observation สำหรับข้อมูลการตรวจวัดจากสถานีอุตุนิยมวิทยา
  • get_weather_warnings สำหรับประกาศเตือนภัยสภาพอากาศในแต่ละภูมิภาค

โดยใช้ Node.js ร่วมกับ TypeScript ผ่านชุดคำสั่งอย่างเป็นทางการอย่าง @modelcontextprotocol/sdk ใช้การสื่อสารผ่าน stdio และตรวจสอบข้อมูลนำเข้าด้วย Zod

ไม่อยากพลาดข่าวใหม่?

สมัครรับสรุปข่าวสารใหม่ทางอีเมล ไม่บ่อยจนรำคาญ

โฆษณา

API architecture diagram flowchart

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง

จุดที่น่าสนใจที่สุดคือรูปแบบการทำงานแบบสองขั้นตอน (Two-step pattern) ของ AEMET OpenData API ซึ่งแตกต่างจากที่เคยพบทั่วไป เพราะการเรียกใช้งานครั้งแรกจะไม่ส่งข้อมูลสภาพอากาศกลับมาทันที แต่จะส่งพอยเตอร์หรือลิงก์ชี้ไปยังตำแหน่งของข้อมูลแทน ตัวอย่างเช่น JSON ที่ตอบกลับมาจะมีฟิลด์ datos ที่ระบุ URL เช่น https://opendata.aemet.es/opendata/sh/abc123 โดยไม่มีอุณหภูมิแม้แต่ตัวเดียว จากนั้นจึงต้องทำการส่งคำขอครั้งที่สองไปยัง URL นั้นอีกครั้งโดยไม่ต้องใช้ API Key จึงจะได้รับข้อมูลจริง ซึ่งมีลักษณะคล้ายกับรูปแบบ S3 presigned URL ของ AWS หรือการทำงานคล้าย HTTP 302 ที่ต้องติดตามเส้นทางเองผ่านเนื้อหา JSON

2ขั้นตอนการดึงข้อมูลผ่าน API
200สถานะ HTTP ที่อาจซ่อนข้อผิดพลาดไว้ใน JSON

บทเรียนด้านการออกแบบคือควรห่อหุ้มการทำงานทั้งสองขั้นตอนนี้ไว้ในฟังก์ชันเดียว เพื่อให้เครื่องมืออื่น ๆ ไม่จำเป็นต้องรับรู้ถึงความซับซ้อนนี้ นอกจากนี้ยังมีปัญหาเฉพาะหน้าที่มักพบเจอแต่ไม่มีบันทึกไว้ในเอกสาร ได้แก่ สถานะ estado ใน JSON อาจขัดแย้งกับ HTTP Status โดย HTTP อาจตอบกลับมาเป็น 200 OK แต่ตัวเนื้อหา JSON กลับระบุ "estado": 404 หรือ 401 รวมถึงปัญหาเรื่องการเข้ารหัสที่ใช้แบบ ISO-8859-1 (latin1) แทนที่จะเป็น UTF-8 ส่งผลให้ตัวอักษรภาษาสเปนอย่าง Cádiz กลายเป็น Cdiz หากใช้คำสั่ง response.json() แบบทั่วไป จึงต้องอ่านข้อมูลในรูปแบบ Buffer และทำการถอดรหัสอย่างชัดเจน

ในส่วนของการเผยแพร่บน npm สิ่งที่มักทำให้เซิร์ฟเวอร์ MCP ล้มเหลวคือการติดตั้งแล้วไม่สามารถรันผ่าน npx ได้ ซึ่งสามารถแก้ไขได้ด้วยการกำหนดฟิลด์ bin ใน package.json ให้ชี้ไปที่ไฟล์คอมไพล์ dist/index.js และใส่ shebang ไว้ที่บรรทัดแรกสุดของไฟล์ รวมถึงข้อควรระวังเฉพาะตัวสำหรับการขนส่งแบบ stdio คือ ห้ามมีข้อความใด ๆ ส่งออกไปยัง stdout นอกเหนือจากโปรโตคอล JSON-RPC เพราะจะทำให้สตรีมข้อความเสียหายและเซิร์ฟเวอร์หยุดทำงานเงียบ ๆ โดยต้องเปลี่ยนไปส่ง log ผ่าน stderr แทน

ที่มา: Dev.to

ความคิดเห็น

แสดงความคิดเห็น
0/2000

พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้