πŸš€μ²« 번째 MCP μ„œλ²„ ꡬ좕: μ™„μ „ κ°€μ΄λ“œ

λ°œν–‰: (2025λ…„ 12μ›” 2일 μ˜€ν›„ 01:42 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

μ†Œκ°œ

Model Context Protocol (MCP)은 AI μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ™ΈλΆ€ 도ꡬ 및 데이터 μ†ŒμŠ€μ™€ μƒν˜Έ μž‘μš©ν•˜λŠ” 방식을 ν˜μ‹ ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. Claude 톡합, VSCode ν™•μž₯ λ˜λŠ” λ§žμΆ€ν˜• AI μ›Œν¬ν”Œλ‘œλ₯Ό κ΅¬μΆ•ν•˜λ“ , MCP μ„œλ²„λ₯Ό μ΄ν•΄ν•˜λŠ” 것은 ν˜„λŒ€ AI κ°œλ°œμ— ν•„μˆ˜μ μž…λ‹ˆλ‹€.

이 κ°€μ΄λ“œμ—μ„œλŠ” μ²˜μŒλΆ€ν„° μ™„μ „ν•œ κΈ°λŠ₯을 κ°–μΆ˜ MCP μ„œλ²„λ₯Ό κ΅¬μΆ•ν•˜κ³ , ν΄λΌμš°λ“œμ— λ°°ν¬ν•œ λ’€, 인기 μžˆλŠ” MCP ν΄λΌμ΄μ–ΈνŠΈμ™€ μ—°κ²°ν•˜λŠ” 방법을 λ‹€λ£Ήλ‹ˆλ‹€. μ΅œμ’…μ μœΌλ‘œ λͺ¨λ“  MCP ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‚¬μš©ν•  수 μžˆλŠ” 날씨 정보 μ„œλ²„λ₯Ό λ§Œλ“€κ²Œ λ©λ‹ˆλ‹€.

MCP (Model Context Protocol)λŠ” AI μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ™ΈλΆ€ 데이터 μ†ŒμŠ€μ™€ 도ꡬ에 μ—°κ²°ν•˜λŠ” 방식을 ν‘œμ€€ν™”ν•˜λŠ” μ˜€ν”ˆ ν”„λ‘œν† μ½œμž…λ‹ˆλ‹€. 이λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€, API, 파일 μ‹œμŠ€ν…œ, λΉ„μ¦ˆλ‹ˆμŠ€ 도ꡬ 등에 μ•ˆμ „ν•˜κ²Œ μ ‘κ·Όν•  수 있게 ν•΄μ£ΌλŠ” λ²”μš© μ–΄λŒ‘ν„°λΌκ³  μƒκ°ν•˜λ©΄ λ©λ‹ˆλ‹€.

  • ν‘œμ€€ν™”λœ 톡합: ν•˜λ‚˜μ˜ ν”„λ‘œν† μ½œλ‘œ λͺ¨λ“  MCP ν˜Έν™˜ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ λ™μž‘
  • λ³΄μ•ˆ μš°μ„ : λ‚΄μž₯된 인증 및 κΆŒν•œ μ œμ–΄
  • μœ μ—°ν•œ μ•„ν‚€ν…μ²˜: 둜컬 및 원격 μ„œλ²„ 지원
  • 도ꡬ 탐색: ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‚¬μš© κ°€λŠ₯ν•œ κΈ°λŠ₯을 μžλ™μœΌλ‘œ 발견

MCP μ„œλ²„λŠ” μ„Έ κ°€μ§€ μ£Όμš” ꡬ성 μš”μ†Œλ‘œ μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€:

  1. Resources – μ„œλ²„κ°€ μ œκ³΅ν•  수 μžˆλŠ” 데이터 μ†ŒμŠ€(파일, λ°μ΄ν„°λ² μ΄μŠ€ λ ˆμ½”λ“œ, API 데이터)
  2. Tools – μ„œλ²„κ°€ μˆ˜ν–‰ν•  수 μžˆλŠ” μž‘μ—…(생성, μ—…λ°μ΄νŠΈ, μ‚­μ œ λ“±)
  3. 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.

Back to Blog

κ΄€λ ¨ κΈ€

더 보기 Β»

계정 μ „ν™˜

@blink_c5eb0afe3975https://dev.to/blink_c5eb0afe3975 μ—¬λŸ¬λΆ„λ„ μ•Œλ‹€μ‹œν”Ό μ €λŠ” λ‹€μ‹œ 제 μ§„ν–‰ 상황을 κΈ°λ‘ν•˜κΈ° μ‹œμž‘ν–ˆμœΌλ‹ˆ, 이것을 λ‹€λ₯Έβ€¦

Strands μ—μ΄μ „νŠΈ + Agent Core AWS

μ‹œμž‘ κ°€μ΄λ“œ: Amazon Bedrock AgentCore λͺ©μ°¨ - 사전 μš”κ΅¬ 사항 requisitos‑previos - νˆ΄ν‚· μ„€μΉ˜ instalaciΓ³n‑del‑toolkit - 생성 …