Membangun Server MCP Pertama Anda
Gunakan Python MCP SDK untuk membuat server yang menyediakan sumber daya, alat, dan perintah, lalu hubungkan server tersebut ke Claude Desktop untuk melihatnya bekerja dari awal hingga akhir.
Membangun Server MCP Pertama Anda adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.
Penyiapan Proyek untuk Server MCP
Membangun server MCP dalam Python memerlukan SDK mcp dan lingkungan Python. Anda akan membuat server yang dapat dihubungkan ke Claude Desktop atau klien MCP mana pun melalui stdio. Mulailah dengan menginstal paket dan membuat file server Anda.
# Create a project directory
# mkdir my_mcp_server && cd my_mcp_server
# Create a virtual environment
# python -m venv venv && source venv/bin/activate
# Install the MCP SDK
# pip install mcp httpx
# Project structure:
# my_mcp_server/
# server.py <- Your MCP server
# requirements.txt
# README.mdMembuat Objek Server
Impor dari paket mcp dan buat instans Server dengan nama server Anda. Nama tersebut ditampilkan kepada klien dalam daftar server MCP mereka—pilih nama yang deskriptif. Objek server menjadi titik masuk untuk mendaftarkan semua alat, sumber daya, dan perintah Anda.
# server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
import asyncio
import httpx
# Create the server — name is shown in Claude Desktop
app = Server('weather-server')
# --- Tool registrations go here ---
# Entry point
if __name__ == '__main__':
asyncio.run(stdio_server(app))Mendaftarkan Alat dengan @app.list_tools()
Dekorator @app.list_tools() mendaftarkan penangan yang mengembalikan daftar alat yang tersedia saat klien memintanya. Setiap alat didefinisikan dengan nama, deskripsi, dan inputSchema—JSON Schema yang menjelaskan parameternya. Klien mengirimkan daftar ini kepada LLM agar LLM mengetahui alat mana yang dapat dipanggilnya.
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name='get_weather',
description='Get current weather for a city. Use when the user asks about weather in a specific location.',
inputSchema={
'type': 'object',
'properties': {
'city': {
'type': 'string',
'description': 'City name, e.g. London or New York'
},
'units': {
'type': 'string',
'enum': ['metric', 'imperial'],
'description': 'Temperature units. Default is metric.'
}
},
'required': ['city']
}
),
types.Tool(
name='list_cities',
description='Return a list of major cities the user can query weather for.',
inputSchema={'type': 'object', 'properties': {}, 'required': []}
)
]Menerapkan Eksekusi Alat
Dekorator @app.call_tool() menangani eksekusi alat. Saat klien memanggil suatu alat, penangan ini menerima nama alat dan argumennya. Jalankan logika yang sesuai, lalu kembalikan daftar objek TextContent yang berisi string hasil.
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == 'list_cities':
cities = ['London', 'New York', 'Tokyo', 'Paris', 'Sydney']
return [types.TextContent(type='text', text=', '.join(cities))]
if name == 'get_weather':
city = arguments['city']
units = arguments.get('units', 'metric')
unit_symbol = 'C' if units == 'metric' else 'F'
# Call real weather API (stub here)
async with httpx.AsyncClient() as client:
# Replace with actual API call
result = f'{city}: 18{chr(176)}{unit_symbol}, partly cloudy, humidity 65%'
return [types.TextContent(type='text', text=result)]
raise ValueError(f'Unknown tool: {name}')Mengekspos Resource
Resource adalah data statis atau dinamis yang dapat dibaca model—anggap saja seperti file. Tentukan URI resource dan implementasikan pembaca resource. Resource muncul di klien sebagai item yang dapat dirujuk AI, sehingga berguna untuk konfigurasi, dokumentasi, atau snapshot data yang sering diakses.
@app.list_resources()
async def list_resources() -> list[types.Resource]:
return [
types.Resource(
uri='weather://supported-cities',
name='Supported Cities List',
description='Complete list of cities available in this weather server.',
mimeType='text/plain'
)
]
@app.read_resource()
async def read_resource(uri: str) -> str:
if uri == 'weather://supported-cities':
cities = ['London', 'New York', 'Tokyo', 'Paris', 'Sydney', 'Dubai', 'Singapore']
return '\n'.join(cities)
raise ValueError(f'Unknown resource URI: {uri}')Mendaftarkan Templat Prompt
Prompt adalah templat pesan yang dapat digunakan kembali dan ditampilkan klien kepada pengguna sebagai perintah garis miring atau tindakan cepat. Prompt menerima parameter dan mengembalikan daftar pesan yang menjadi konteks awal percakapan. Prompt sangat berguna untuk merangkum instruksi kompleks yang dapat dipicu pengguna dengan satu perintah.
@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
return [
types.Prompt(
name='weather-report',
description='Generate a formatted weather report for a city.',
arguments=[
types.PromptArgument(name='city', description='City name', required=True)
]
)
]
@app.get_prompt()
async def get_prompt(name: str, arguments: dict) -> types.GetPromptResult:
if name == 'weather-report':
city = arguments.get('city', 'London')
return types.GetPromptResult(
description=f'Weather report for {city}',
messages=[
types.PromptMessage(
role='user',
content=types.TextContent(
type='text',
text=f'Use the get_weather tool to look up {city} and give me a detailed weather report including what clothing I should wear.'
)
)
]
)
raise ValueError(f'Unknown prompt: {name}')Menghubungkan ke Claude Desktop
Untuk menggunakan server MCP Anda dengan Claude Desktop, tambahkan server tersebut ke file konfigurasi Claude Desktop. Di macOS, lokasinya adalah ~/Library/Application Support/Claude/claude_desktop_config.json. Tentukan perintah untuk memulai server serta variabel lingkungan yang dibutuhkannya.
# ~/Library/Application Support/Claude/claude_desktop_config.json
# Add this JSON configuration:
# {
# "mcpServers": {
# "weather-server": {
# "command": "/path/to/venv/bin/python",
# "args": ["/path/to/my_mcp_server/server.py"],
# "env": {
# "WEATHER_API_KEY": "your_api_key_here"
# }
# }
# }
# }
# After saving, restart Claude Desktop.
# Your server's tools will appear in Claude's tool list.Menguji Server Anda dengan CLI MCP
Sebelum menghubungkannya ke Claude Desktop, uji server Anda menggunakan pemeriksa MCP atau alat CLI. Perintah mcp dev memulai server dan membuka pemeriksa berbasis peramban yang memungkinkan Anda memanggil alat secara manual serta melihat pesan protokol mentah, sehingga masalah mudah di-debug.
# Install the MCP development tools
# pip install 'mcp[cli]'
# Start the inspector with your server
# mcp dev server.py
# The inspector opens at http://localhost:5173
# You can:
# - See all registered tools and their schemas
# - Call tools with custom arguments
# - Browse available resources
# - Test prompt templates
# - View the full JSON-RPC message exchangePenanganan Error pada Server MCP
Server MCP tidak boleh crash akibat input yang buruk. Bungkus semua eksekusi alat dalam try/except dan kembalikan pesan error sebagai TextContent, bukan melempar pengecualian. Untuk error fatal seperti masalah konfigurasi atau kunci API yang tidak ada, catat error tersebut saat startup dan lempar pengecualian sebelum server memasuki perulangan utamanya.
@app.call_tool()
async def call_tool_safe(name: str, arguments: dict) -> list[types.TextContent]:
try:
if name == 'get_weather':
city = arguments.get('city')
if not city:
return [types.TextContent(type='text', text='Error: city argument is required.')]
result = await fetch_weather(city, arguments.get('units', 'metric'))
return [types.TextContent(type='text', text=result)]
raise ValueError(f'Unknown tool: {name}')
except httpx.TimeoutException:
return [types.TextContent(type='text', text='Error: Weather API timed out. Try again.')]
except Exception as e:
return [types.TextContent(type='text', text=f'Error: {str(e)}')]Logging untuk Server MCP
Karena server MCP berkomunikasi dengan klien melalui stdio, pernyataan cetak akan merusak protokol. Selalu gunakan stderr untuk logging—arus ini terpisah sehingga tidak mengganggu pertukaran pesan MCP. Konfigurasikan modul logging Python agar menulis ke stderr.
import logging
import sys
# Configure logging to stderr (NOT stdout — that's the MCP channel)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
stream=sys.stderr
)
logger = logging.getLogger('weather-server')
# In your tool handler:
# logger.info(f'Getting weather for {city}')
# logger.error(f'API call failed: {e}')
# Claude Desktop captures stderr to a log file:
# ~/Library/Logs/Claude/mcp-server-weather-server.logMengemas Server MCP
Bagikan server MCP Anda dengan mengemasnya menggunakan pyproject.toml lalu menerbitkannya ke PyPI, atau distribusikan sebagai kontainer Docker untuk tim. Gunakan variabel lingkungan untuk semua rahasia—kunci API dan URL basis data—agar konfigurasi server tetap terpisah dari kode. Dokumentasikan variabel lingkungan yang diperlukan dan contoh konfigurasi dalam README yang jelas.
Pemeriksaan Cepat
Uji pemahaman Anda tentang pembuatan server MCP dengan Python.
Ringkasan Pelajaran
Dalam pelajaran ini, Anda mempelajari bahwa: server MCP mengekspos alat melalui dekorator @app.list_tools() dan @app.call_tool(), resource dan prompt memperluas server dengan data yang dapat dibaca serta templat yang dapat digunakan kembali, dan logging harus menggunakan stderr agar tidak merusak kanal protokol MCP melalui stdio. Selanjutnya, kita akan menghubungkan server MCP ke basis data dan mengekspos resource dinamis dengan paginasi.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Membangun Server MCP Pertama Anda” gratis?
Ya — teks lengkap “Membangun Server MCP Pertama Anda” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Membangun Server MCP Pertama Anda”?
Gunakan Python MCP SDK untuk membuat server yang menyediakan sumber daya, alat, dan perintah, lalu hubungkan server tersebut ke Claude Desktop untuk melihatnya bekerja dari awal hingga akhir. Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?
Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.
Berapa lama pelajaran “Membangun Server MCP Pertama Anda” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?
Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Apa Itu MCP dan Mengapa Penting
- Membangun Server MCP Pertama Anda
- Menyediakan Sumber Daya Basis Data melalui MCP
- Keamanan dan Autentikasi MCP