mcp-emre-kalem
Version:
Test amaçlı MCP server - liste arama işlemleri
302 lines (267 loc) • 7.44 kB
JavaScript
import dotenv from 'dotenv';
import path from 'path';
// .env dosyasını mevcut çalışma dizininde ara
dotenv.config({ path: path.join(process.cwd(), '.env') });
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { sampleData } from "./data.js";
import { initializeAuth, requireAuth, getAuthStatus } from "./auth.js";
// MCP Server oluşturma
const server = new Server(
{
name: "mcp-sample-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Araçları listeleme
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "search_items",
description: "Liste içinde arama yapar. İsim, kategori, açıklama ve etiketlerde arama yapabilir.",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Aranacak metin",
},
category: {
type: "string",
description: "Belirli bir kategoride arama yapmak için (opsiyonel)",
},
difficulty: {
type: "string",
description: "Belirli bir zorluk seviyesinde arama yapmak için (opsiyonel)",
},
},
required: ["query"],
},
},
{
name: "get_item_by_id",
description: "ID'ye göre öğe getirir",
inputSchema: {
type: "object",
properties: {
id: {
type: "number",
description: "Getirilecek öğenin ID'si",
},
},
required: ["id"],
},
},
{
name: "list_all_items",
description: "Tüm öğeleri listeler",
inputSchema: {
type: "object",
properties: {},
},
},
{
name: "get_categories",
description: "Mevcut kategorileri listeler",
inputSchema: {
type: "object",
properties: {},
},
},
{
name: "filter_by_tags",
description: "Belirli etiketlere sahip öğeleri filtreler",
inputSchema: {
type: "object",
properties: {
tags: {
type: "array",
items: {
type: "string",
},
description: "Filtrelenecek etiketler",
},
},
required: ["tags"],
},
},
{
name: "auth_status",
description: "Giriş durumunu kontrol eder",
inputSchema: {
type: "object",
properties: {},
},
},
],
};
});
// Araç çağrılarını işleme
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
// Her araç çağrısında auth kontrolü
const user = requireAuth();
console.error(`🔧 Araç kullanımı: ${name} - Kullanıcı: ${user.username}`);
switch (name) {
case "search_items":
return await searchItems(args.query, args.category, args.difficulty);
case "get_item_by_id":
return await getItemById(args.id);
case "list_all_items":
return await listAllItems();
case "get_categories":
return await getCategories();
case "filter_by_tags":
return await filterByTags(args.tags);
case "auth_status":
return await authStatus();
default:
throw new Error(`Bilinmeyen araç: ${name}`);
}
} catch (error) {
return {
content: [
{
type: "text",
text: `Hata: ${error.message}`,
},
],
};
}
});
// Arama fonksiyonu
async function searchItems(query, category = null, difficulty = null) {
const searchTerm = query.toLowerCase();
let results = sampleData.filter(item => {
const matchesQuery =
item.name.toLowerCase().includes(searchTerm) ||
item.description.toLowerCase().includes(searchTerm) ||
item.tags.some(tag => tag.toLowerCase().includes(searchTerm));
const matchesCategory = !category || item.category.toLowerCase() === category.toLowerCase();
const matchesDifficulty = !difficulty || item.difficulty.toLowerCase() === difficulty.toLowerCase();
return matchesQuery && matchesCategory && matchesDifficulty;
});
return {
content: [
{
type: "text",
text: `Arama sonuçları "${query}" için:\n\n${formatResults(results)}`,
},
],
};
}
// ID'ye göre öğe getirme
async function getItemById(id) {
const item = sampleData.find(item => item.id === id);
if (!item) {
throw new Error(`ID ${id} ile öğe bulunamadı`);
}
return {
content: [
{
type: "text",
text: formatSingleItem(item),
},
],
};
}
// Tüm öğeleri listeleme
async function listAllItems() {
return {
content: [
{
type: "text",
text: `Tüm öğeler (${sampleData.length} adet):\n\n${formatResults(sampleData)}`,
},
],
};
}
// Kategorileri listeleme
async function getCategories() {
const categories = [...new Set(sampleData.map(item => item.category))];
return {
content: [
{
type: "text",
text: `Mevcut kategoriler:\n${categories.map(cat => `• ${cat}`).join('\n')}`,
},
],
};
}
// Etiketlere göre filtreleme
async function filterByTags(tags) {
const results = sampleData.filter(item =>
tags.some(tag =>
item.tags.some(itemTag =>
itemTag.toLowerCase().includes(tag.toLowerCase())
)
)
);
return {
content: [
{
type: "text",
text: `"${tags.join(', ')}" etiketlerine sahip öğeler:\n\n${formatResults(results)}`,
},
],
};
}
// Sonuçları formatlama
function formatResults(items) {
if (items.length === 0) {
return "Sonuç bulunamadı.";
}
return items.map(item => formatSingleItem(item)).join('\n---\n');
}
// Tek öğeyi formatlama
function formatSingleItem(item) {
return `🆔 ID: ${item.id}
📛 İsim: ${item.name}
📂 Kategori: ${item.category}
📝 Açıklama: ${item.description}
⚡ Zorluk: ${item.difficulty}
🏷️ Etiketler: ${item.tags.join(', ')}`;
}
// Auth durumu
async function authStatus() {
const status = getAuthStatus();
return {
content: [
{
type: "text",
text: status.authenticated
? `✅ Giriş yapılmış\n👤 Kullanıcı: ${status.name}\n📧 Email: ${status.user}`
: "❌ Giriş yapılmamış",
},
],
};
}
// Server'ı başlatma
async function main() {
console.error("🚀 MCP Server başlatılıyor...");
// Microsoft auth kontrolü
const authSuccess = await initializeAuth();
if (!authSuccess) {
console.error("❌ Authentication başarısız - Server kapatılıyor");
process.exit(1);
}
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("✅ MCP Server başlatıldı ve Microsoft auth aktif!");
}
main().catch((error) => {
console.error("Server hatası:", error);
process.exit(1);
});