Introduction to MCP Model Context Protocol
The Model-Context-Protocol (MCP) architecture is a design pattern that separates concerns into three main components: Model, Context, and Protocol. This separation enables cleaner code organization, better maintainability, and scalability. In this guide, we'll create an MCP server using TypeScript and integrate it with a weather API as a practical example.
- Model: Represents the data structure and business logic
- Context: Manages the state and flow of the application
- Protocol: Handles communication and API interactions
Step 1: Setting Up the Project
Let's start by initializing a new Node.js project with TypeScript support.
- Run `npm init -y` to create a package.json file
- Install TypeScript and required dependencies: `npm install typescript @types/node ts-node`
- Install Express: `npm install express cors dotenv`
- Install Axios for API calls: `npm install axios`
Step 2: Project Structure
Organize your project into the following structure:
- src/
- src/models/
- src/contexts/
- src/protocols/
- src/utils/
- src/config/
- index.ts
Step 3: Setting Up the Server
Create the main server file (`index.ts`) and set up Express:
import express, { Request, Response } from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors());
app.use(express.json());
app.get('/', (req: Request, res: Response) => {
res.status(200).json({ message: 'MCP Server is running!' });
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Step 4: Defining the Protocol
Create a protocol for handling weather data requests.
interface WeatherRequest {
city: string;
}
interface WeatherResponse {
temperature: number;
conditions: string;
city: string;
}
Step 5: Implementing the Model
Create a model to fetch weather data from an external API.
import axios from 'axios';
export class WeatherModel {
async getWeather(city: string): Promise<WeatherResponse> {
try {
const API_KEY = process.env.WEATHER_API_KEY;
const url = `http://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}`;
const response = await axios.get(url);
return {
temperature: response.data.main.temp,
conditions: response.data.weather[0].description,
city: city
} as WeatherResponse;
} catch (error) {
throw new Error('Failed to fetch weather data');
}
}
}
Step 6: Implementing the Controller
Create a controller to handle incoming requests and interact with the model.
export class WeatherController {
constructor(private weatherModel: WeatherModel) {}
async getWeather(req: Request<{}, {}, WeatherRequest>): Promise<Response> {
try {
const weatherData = await this.weatherModel.getWeather(req.body.city);
return res.status(200).json(weatherData);
} catch (error) {
return res.status(500).json({ message: error.message });
}
}
}
Step 7: Connecting Everything
Update the main server file to include the weather endpoint.
import './config';
import express, { Request, Response } from 'express';
import { WeatherModel } from './models/WeatherModel';
import { WeatherController } from './controllers/WeatherController';
const app = express();
const weatherModel = new WeatherModel();
const weatherController = new WeatherController(weatherModel);
app.post('/api/weather', weatherController.getWeather);
Testing the Server
Use Postman or your preferred tool to test the endpoint with a POST request to `http://localhost:3000/api/weather` with a body containing the city name.
Conclusion
You've successfully implemented an MCP Model Context Protocol server using TypeScript! This architecture provides a clean separation of concerns, making your code more maintainable and scalable. You can now expand this server by adding more models, contexts, and protocols for different functionalities.