Skip to main content

O'z MCP serveringizni yozish

MCP server yozish

MCP — bu protokol, ya'ni siz o'zingizning serveringizni yozib, agentga istalgan imkoniyatni bera olasiz: ichki API'ga ulanish, ma'lumotlar bazasi, korxona tizimlari. Bu qo'llanmada — noldan ishlaydigan MCP server qurish, Python (FastMCP) va TypeScript'da.

MCP server nima qiladi?

Server agentga uch turdagi narsa beradi:

  • Tools (vositalar) — agent bajaradigan amallar (funksiya chaqirish: "ob-havoni ol", "DB'ga yoz")
  • Resources (resurslar) — agent o'qiydigan ma'lumotlar (fayl, jadval, hujjat)
  • Prompts (promtlar) — tayyor shablon promtlar

Python — FastMCP bilan

Eng oson yo'l. fastmcp kutubxonasi dekoratorlar bilan ishlaydi.

O'rnatish

pip install fastmcp

Eng oddiy server

from fastmcp import FastMCP

mcp = FastMCP("Mening serverim")

@mcp.tool()
def ob_havo(shahar: str) -> str:
"""Berilgan shahar uchun ob-havoni qaytaradi."""
# bu yerda real API chaqiruvi
return f"{shahar}: 22°C, quyoshli"

if __name__ == "__main__":
mcp.run()

Tamom. @mcp.tool() dekoratori funksiyani agent uchun vositaga aylantiradi. Docstring — agentga tushuntirish (juda muhim — agent shu asosida qachon chaqirishni biladi).

Resource qo'shish

@mcp.resource("config://settings")
def get_settings() -> str:
"""Ilova sozlamalarini qaytaradi."""
return open("settings.json").read()

Parametrli tool — DB misol

import sqlite3

@mcp.tool()
def foydalanuvchi_qidir(email: str) -> dict:
"""Email bo'yicha foydalanuvchini bazadan topadi."""
conn = sqlite3.connect("app.db")
cur = conn.execute(
"SELECT id, name, email FROM users WHERE email = ?",
(email,) # parametrlangan — SQL injection'dan himoya
)
row = cur.fetchone()
conn.close()
if not row:
return {"error": "topilmadi"}
return {"id": row[0], "name": row[1], "email": row[2]}

TypeScript — MCP SDK bilan

Node muhitida ishlasangiz.

O'rnatish

npm install @modelcontextprotocol/sdk zod

Server

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "mening-server", version: "1.0.0" });

server.tool(
"ob_havo",
"Berilgan shahar uchun ob-havoni qaytaradi",
{ shahar: z.string() },
async ({ shahar }) => {
return {
content: [{ type: "text", text: `${shahar}: 22°C, quyoshli` }]
};
}
);

const transport = new StdioServerTransport();
await server.connect(transport);

zod — parametrlar sxemasi va validatsiya. Agent qaysi argumentlar kerakligini shundan biladi.

Transport turlari

  • stdio — server agent bilan bir mashinada, jarayon orqali. Eng oddiy, lokal vositalar uchun.
  • HTTP / SSE — server alohida (bulutda). Remote MCP, ko'p foydalanuvchi. Auth kerak.

Claude Code'ga ulash

stdio server uchun:

claude mcp add mening-server python /path/to/server.py

HTTP server uchun:

claude mcp add mening-server --transport http https://my-server.com/mcp

Yoki .mcp.json:

{
"mcpServers": {
"mening-server": {
"command": "python",
"args": ["/path/to/server.py"]
}
}
}

Testlash

MCP Inspector — rasmiy debug vositasi:

npx @modelcontextprotocol/inspector python server.py

Brauzer ochiladi, har bir tool/resource'ni qo'lda sinab ko'rasiz — agent ulashdan oldin.

Yaxshi tool dizayni

Agent tool'ni qanchalik to'g'ri ishlatishi — sizning dizayningizga bog'liq:

  • Aniq nom: foydalanuvchi_qidir, qidiruv emas
  • Boy docstring: nima qiladi, qachon ishlatiladi, nima qaytaradi
  • Aniq parametrlar: type hints + tavsif
  • Xato — strukturalashgan: {"error": "..."} exception emas
  • Kichik, fokuslangan: bitta tool — bitta ish. "Hamma narsa" tool — yomon
  • Idempotent bo'lsa — yaxshi: bir xil input → bir xil natija

Xavfsizlik — qisqacha

MCP server agentga kuch beradi — ehtiyot bo'ling:

  • SQL parametrlash (injection'dan)
  • Fayl yo'llarini sanitize qilish (path traversal)
  • Maxfiy ma'lumotlarni qaytarmaslik (parol, token)
  • Yozish/o'chirish amallariga ruxsat nazorati

Batafsil: MCP xavfsizligi.

Real misol: ichki CRM tool

from fastmcp import FastMCP
import httpx

mcp = FastMCP("CRM konnektor")

@mcp.tool()
async def buyurtma_holati(buyurtma_id: str) -> dict:
"""Buyurtma raqami bo'yicha uning holatini qaytaradi."""
async with httpx.AsyncClient() as client:
r = await client.get(
f"https://crm.internal/api/orders/{buyurtma_id}",
headers={"Authorization": f"Bearer {TOKEN}"}
)
if r.status_code == 404:
return {"error": "buyurtma topilmadi"}
return r.json()

if __name__ == "__main__":
mcp.run()

Endi agent: "buyurtma #1234 qayerda?" → tool chaqiradi → CRM'dan javob → foydalanuvchiga.

Anti-paternlar

  • Docstring'siz tool: agent qachon chaqirishni bilmaydi → noto'g'ri ishlatadi
  • Ulkan "do everything" tool: 10 ta parametr, 5 xil rejim — agent chalkashadi. Bo'ling
  • Xom exception: agent stack trace'ni ko'radi, tushunmaydi. Strukturalashgan xato qaytaring
  • Sinovsiz deploy: Inspector'da sinamasdan agentga ulash — debug qiyin
  • Sekin tool, timeout'siz: agent kutib qoladi. Async + timeout qo'ying

Keyingi qadamlar