π첫 λ²μ§Έ MCP μλ² κ΅¬μΆ: μμ κ°μ΄λ
Source: Dev.to
μκ°
Model Context Protocol (MCP)μ AI μ ν리μΌμ΄μ μ΄ μΈλΆ λꡬ λ° λ°μ΄ν° μμ€μ μνΈ μμ©νλ λ°©μμ νμ νκ³ μμ΅λλ€. Claude ν΅ν©, VSCode νμ₯ λλ λ§μΆ€ν AI μν¬νλ‘λ₯Ό ꡬμΆνλ , MCP μλ²λ₯Ό μ΄ν΄νλ κ²μ νλ AI κ°λ°μ νμμ μ λλ€.
μ΄ κ°μ΄λμμλ μ²μλΆν° μμ ν κΈ°λ₯μ κ°μΆ MCP μλ²λ₯Ό ꡬμΆνκ³ , ν΄λΌμ°λμ λ°°ν¬ν λ€, μΈκΈ° μλ MCP ν΄λΌμ΄μΈνΈμ μ°κ²°νλ λ°©λ²μ λ€λ£Ήλλ€. μ΅μ’ μ μΌλ‘ λͺ¨λ MCP ν΄λΌμ΄μΈνΈκ° μ¬μ©ν μ μλ λ μ¨ μ 보 μλ²λ₯Ό λ§λ€κ² λ©λλ€.
MCP (Model Context Protocol)λ AI μ ν리μΌμ΄μ μ΄ μΈλΆ λ°μ΄ν° μμ€μ λꡬμ μ°κ²°νλ λ°©μμ νμ€ννλ μ€ν νλ‘ν μ½μ λλ€. μ΄λ₯Ό λ°μ΄ν°λ² μ΄μ€, API, νμΌ μμ€ν , λΉμ¦λμ€ λꡬ λ±μ μμ νκ² μ κ·Όν μ μκ² ν΄μ£Όλ λ²μ© μ΄λν°λΌκ³ μκ°νλ©΄ λ©λλ€.
- νμ€νλ ν΅ν©: νλμ νλ‘ν μ½λ‘ λͺ¨λ MCP νΈν ν΄λΌμ΄μΈνΈμμ λμ
- 보μ μ°μ : λ΄μ₯λ μΈμ¦ λ° κΆν μ μ΄
- μ μ°ν μν€ν μ²: λ‘컬 λ° μ격 μλ² μ§μ
- λꡬ νμ: ν΄λΌμ΄μΈνΈκ° μ¬μ© κ°λ₯ν κΈ°λ₯μ μλμΌλ‘ λ°κ²¬
MCP μλ²λ μΈ κ°μ§ μ£Όμ κ΅¬μ± μμλ‘ μ΄λ£¨μ΄μ§λλ€:
- Resources β μλ²κ° μ 곡ν μ μλ λ°μ΄ν° μμ€(νμΌ, λ°μ΄ν°λ² μ΄μ€ λ μ½λ, API λ°μ΄ν°)
- Tools β μλ²κ° μνν μ μλ μμ (μμ±, μ λ°μ΄νΈ, μμ λ±)
- Prompts β μΌλ° μμ μ μν μ¬μ μ μλ ν νλ¦Ώ
μλμμλ κ³΅κ° APIλ₯Ό νμ©ν΄ λ μ¨ μ 보λ₯Ό μ 곡νλ μ€μ©μ μΈ MCP μλ²λ₯Ό ꡬμΆν©λλ€.
νλ‘μ νΈ μ€μ
mkdir weather-mcp-server
cd weather-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk axios dotenv
npm install -D @types/node typescript
νλ‘μ νΈ κ΅¬μ‘°
weather-mcp-server/
βββ src/
β βββ index.ts
β βββ server.ts
β βββ weatherService.ts
βββ package.json
βββ tsconfig.json
βββ .env
tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
package.json (μ€ν¬λ¦½νΈ)
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsc && node dist/index.js"
},
"type": "module"
}
λ μ¨ μλΉμ€ (src/weatherService.ts)
import axios from 'axios';
export interface WeatherData {
location: string;
temperature: number;
condition: string;
humidity: number;
windSpeed: number;
description: string;
}
export class WeatherService {
private apiKey: string;
private baseUrl = 'https://api.openweathermap.org/data/2.5';
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async getCurrentWeather(city: string): Promise {
try {
const response = await axios.get(`${this.baseUrl}/weather`, {
params: {
q: city,
appid: this.apiKey,
units: 'metric'
}
});
const data = response.data;
return {
location: `${data.name}, ${data.sys.country}`,
temperature: Math.round(data.main.temp),
condition: data.weather[0].main,
humidity: data.main.humidity,
windSpeed: data.wind.speed,
description: data.weather[0].description
};
} catch (error) {
throw new Error(`Failed to fetch weather data: ${error}`);
}
}
async getForecast(city: string, days: number = 5): Promise {
try {
const response = await axios.get(`${this.baseUrl}/forecast`, {
params: {
q: city,
appid: this.apiKey,
units: 'metric',
cnt: days * 8 // API returns 3βhour intervals
}
});
return response.data;
} catch (error) {
throw new Error(`Failed to fetch forecast data: ${error}`);
}
}
}
MCP μλ² (src/server.ts)
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema
} from '@modelcontextprotocol/sdk/types.js';
import { WeatherService } from './weatherService.js';
export class WeatherMCPServer {
private server: Server;
private weatherService: WeatherService;
constructor(apiKey: string) {
this.weatherService = new WeatherService(apiKey);
this.server = new Server(
{
name: 'weather-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {}
},
}
);
this.setupHandlers();
}
private setupHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'get_current_weather',
description: 'Get current weather information for a city',
inputSchema: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'City name (e.g., "London", "New York")'
}
},
required: ['city']
}
},
{
name: 'get_forecast',
description: 'Get weather forecast for upcoming days',
inputSchema: {
type: 'object',
properties: {
city: {
type: 'string',
description: 'City name'
},
days: {
type: 'number',
description: 'Number of days (1-5)',
default: 5
}
},
required: ['city']
}
}
]
}));
// Handle tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === 'get_current_weather') {
const weather = await this.weatherService.getCurrentWeather(
args.city as string
);
return {
content: [
{
type: 'text',
text: JSON.stringify(weather, null, 2)
}
]
};
}
if (name === 'get_forecast') {
const forecast = await this.weatherService.getForecast(
args.city as string,
(args.days as number) || 5
);
return {
content: [
{
type: 'text',
text: JSON.stringify(forecast, null, 2)
}
]
};
}
throw new Error(`Unknown tool: ${name}`);
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error}`
}
],
isError: true
};
}
});
// List available resources
this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{
uri: 'weather://cities',
name: 'Popular Cities',
description: 'List of popular cities for weather queries',
mimeType: 'application/json'
}
]
}));
// Read resources
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
if (uri === 'weather://cities') {
const cities = [
'London', 'New York', 'Tokyo', 'Paris', 'Sydney',
'Berlin', 'Toronto', 'Singapore', 'Dubai', 'Mumbai'
];
return {
contents: [
{
type: 'application/json',
data: JSON.stringify(cities, null, 2)
}
]
};
}
// Fallback for unknown resources
return {
contents: [],
isError: true,
errorMessage: `Resource not found: ${uri}`
};
});
}
// Start the server (e.g., using stdio transport)
public start() {
const transport = new StdioServerTransport(this.server);
transport.start();
}
}
μλ² μ€ν
Create a .env file with your OpenWeatherMap API key:
OPENWEATHER_API_KEY=your_api_key_here
Then start the server:
npm run build
npm start
The server will listen on standard I/O, ready for any MCPβcompatible client (e.g., Claude) to discover the get_current_weather and get_forecast tools, as well as the weather://cities resource.