finished draft of quickstarts

This commit is contained in:
Zack Lee 2024-11-18 08:48:20 -05:00
commit e4dd2199fe
No known key found for this signature in database
24 changed files with 2657 additions and 711 deletions

BIN
.DS_Store vendored

Binary file not shown.

View file

@ -1,5 +0,0 @@
---
title: "Configuration"
description: "Configure MCP servers for production"
---

View file

@ -1,4 +0,0 @@
---
title: "Environment Setup"
description: "Set up your production environment"
---

View file

@ -1,8 +0,0 @@
---
title: "Monitoring"
description: "Monitor your MCP servers in production"
---
# Monitoring
Monitor your MCP servers in production

View file

235
docs/guides/claude.mdx Normal file
View file

@ -0,0 +1,235 @@
---
title: "Connecting MCP to Claude"
description: "Get started with MCP in less than 5 minutes"
---
Give Claude superpowers by connecting it to your local computer! This guide will show you how to set up Model Context Protocol (MCP) and experience its magic in just 5 minutes.
<Note>
MCP connects Claude to external data sources and tools. In this guide, we'll give Claude the ability to:
- Take screenshots and analyze them
- Control window arrangement
- Execute local automation scripts
And it does this all securely - Claude can only access what you explicitly allow through MCP servers.
</Note>
## Prerequisites
- macOS (Windows/Linux guides coming soon)
- Node.js v16 or higher (`node --version` to check)
- Git (`git --version` to check)
- [Claude desktop app](https://claude.ai/download) installed
<Accordion title="Need to install the prerequisites?">
```bash
# Using Homebrew
brew install node git
# Or download directly:
# Node.js: https://nodejs.org
# Git: https://git-scm.com
```
</Accordion>
## Installation
<Steps>
<Step title="Install example servers">
Let's start by getting some pre-built MCP servers that Claude can use:
```bash
# Clone the example servers
git clone https://github.com/modelcontextprotocol/example-servers
cd example-servers
# Install dependencies and build
npm install
npm run build
# Make servers available globally
npm install -g
```
</Step>
<Step title="Configure Claude">
Open your Claude Desktop App configuration:
```bash
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
Add this configuration (replace YOUR_USERNAME with your actual username):
```json
{
"mcpServers": {
"osascript": {
"command": "mcp-server-osascript",
}
}
}
```
Save and **restart Claude Desktop App**.
</Step>
</Steps>
## Test it out
Let's verify everything is working with a simple example. Try sending this prompt to Claude:
```
Can you take a screenshot of my desktop and describe what you see?
```
Claude will:
1. Request permission to take a screenshot
2. Capture your screen through the MCP server
3. Analyze and describe the screenshot
<Frame>
<img src="/api/placeholder/800/400" alt="Example Claude conversation showing a screenshot analysis" />
</Frame>
<Note>
The first time you use screenshot features, macOS will ask for permissions:
- Screen Recording (for screenshots)
- Automation (for window control)
You'll need to grant these to Claude.app in System Settings.
</Note>
## Try these examples
Now that MCP is working, try these increasingly powerful examples:
<AccordionGroup>
<Accordion title="Basic Window Analysis" active>
```
Could you analyze my open windows and tell me:
- How many windows I have open
- Which apps are running
- If any windows look cluttered
```
</Accordion>
<Accordion title="Window Organization">
```
Could you help organize my windows? I'd like:
- Browser on the left half
- VSCode on the right half
```
</Accordion>
<Accordion title="Create a Window Layout Script">
```
I often need this window layout for coding:
- VSCode taking up the left 60%
- Terminal in the top right
- Browser in the bottom right
Could you create an AppleScript to automate this?
```
</Accordion>
</AccordionGroup>
## What just happened?
Let's break down the magic:
1. When you installed the `osascript` server, you gave Claude a way to:
- Take screenshots (see what you see)
- Run AppleScript (control your windows)
- Automate macOS tasks
2. The MCP protocol lets Claude:
- Request these actions securely
- Get results back in real-time
- Chain actions together intelligently
3. All of this happens locally on your machine - no data leaves your computer!
## Add more capabilities
Want to give Claude even more superpowers? Add these servers to your configuration:
<AccordionGroup>
<Accordion title="File System Access" icon="folder-open">
Add this to your config to let Claude read and analyze files:
```json
"tee": {
"command": "mcp-server-tee",
"args": ["tail", "-f", "/var/log/system.log"],
"env": {
"HOME": "/Users/YOUR_USERNAME"
}
}
```
</Accordion>
<Accordion title="Database Connection" icon="database">
Connect Claude to your PostgreSQL database:
```json
"postgres": {
"command": "mcp-server-postgres",
"args": ["postgresql://localhost/mydb"],
"env": {
"HOME": "/Users/YOUR_USERNAME"
}
}
```
</Accordion>
<Accordion title="Web Automation" icon="globe">
Enable web automation capabilities:
```json
"puppeteer": {
"command": "mcp-server-puppeteer",
}
```
</Accordion>
</AccordionGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="Nothing showing up in Claude?">
1. Check if MCP is enabled:
- Click the 🔌 icon in Claude
- You should see your configured servers
2. Verify your config:
```bash
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
3. Restart Claude completely:
- Quit the app (not just close the window)
- Start it again
</Accordion>
<Accordion title="Permission errors?">
Run this command to see Claude's logs:
```bash
tail -f ~/Claude.log
```
Common fixes:
- Check `HOME` env variable in your config
- Grant missing permissions in System Settings
- Try running example commands manually in Terminal
</Accordion>
</AccordionGroup>
## Next Steps
<CardGroup cols={3}>
<Card title="Build Custom Servers" icon="code" href="/docs/guides/first-server-python">
Create your own MCP integrations to give Claude new capabilities.
</Card>
<Card title="Explore Examples" icon="microscope" href="https://github.com/modelcontextprotocol/example-servers">
Browse our collection of example servers to see what's possible.
</Card>
<Card title="Join Community" icon="users">
Share your MCP creations and connect with other developers.
[Join us →](/community)
</Card>
</CardGroup>

View file

@ -1,8 +0,0 @@
---
title: "Your First MCP Server"
description: "Build a complete MCP server from scratch"
---
# Your First MCP Server
Build a complete MCP server from scratch

View file

@ -0,0 +1,422 @@
---
title: "Your First MCP Server (Python)"
description: "Create a simple MCP server in Python in 15 minutes"
---
Let's build your first MCP server in Python! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools.
<Note>
This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along.
</Note>
## Prerequisites
<Steps>
<Step title="Install Python">
You'll need Python 3.8 or higher:
```bash
python3 --version # Should be 3.8 or higher
```
</Step>
<Step title="Set up a virtual environment">
```bash
# Create and activate virtual environment
python3 -m venv mcp-weather
cd mcp-weather
source bin/activate # On Windows: .\Scripts\activate
```
</Step>
<Step title="Install MCP SDK">
```bash
pip install modelcontextprotocol-sdk requests
```
</Step>
<Step title="Get API Key">
1. Sign up at [OpenWeatherMap](https://openweathermap.org/api)
2. Copy your API key
3. Set it as an environment variable:
```bash
export OPENWEATHER_API_KEY='your-api-key'
```
</Step>
</Steps>
## Create Your Server
<Steps>
<Step title="Create project structure">
```bash
mkdir weather_server
cd weather_server
touch weather_server.py
```
</Step>
<Step title="Add the base code">
Open `weather_server.py` and add this starter code:
```python
from modelcontextprotocol.server import Server
from modelcontextprotocol.server.stdio import StdioServerTransport
from modelcontextprotocol.types import (
ListResourcesRequestSchema,
ListToolsRequestSchema,
ReadResourceRequestSchema,
CallToolRequestSchema
)
import os
import requests
import json
from datetime import datetime
API_KEY = os.getenv('OPENWEATHER_API_KEY')
BASE_URL = 'http://api.openweathermap.org/data/2.5'
class WeatherServer:
def __init__(self):
self.server = Server(
name="example-weather-server",
version="0.1.0"
)
self.default_city = "San Francisco"
self.setup_handlers()
def setup_handlers(self):
# We'll add handlers here
pass
async def run(self):
transport = StdioServerTransport()
await self.server.connect(transport)
if __name__ == "__main__":
import asyncio
server = WeatherServer()
asyncio.run(server.run())
```
</Step>
<Step title="Add resource handlers">
Let's add handlers to expose current weather as a resource:
```python
def setup_handlers(self):
self.server.set_request_handler(
ListResourcesRequestSchema,
self.handle_list_resources
)
self.server.set_request_handler(
ReadResourceRequestSchema,
self.handle_read_resource
)
async def handle_list_resources(self, request):
return {
"resources": [{
"uri": f"weather://{self.default_city}/current",
"name": f"Current weather in {self.default_city}",
"mimeType": "application/json"
}]
}
async def handle_read_resource(self, request):
city = self.default_city
if request.params.uri != f"weather://{city}/current":
raise ValueError(f"Unknown resource: {request.params.uri}")
response = requests.get(
f"{BASE_URL}/weather",
params={
"q": city,
"appid": API_KEY,
"units": "metric"
}
)
data = response.json()
return {
"contents": [{
"uri": request.params.uri,
"mimeType": "application/json",
"text": json.dumps({
"temperature": data["main"]["temp"],
"conditions": data["weather"][0]["description"],
"humidity": data["main"]["humidity"],
"wind_speed": data["wind"]["speed"],
"timestamp": datetime.now().isoformat()
}, indent=2)
}]
}
```
</Step>
<Step title="Add tool handlers">
Now let's add a tool to fetch weather forecasts:
```python
def setup_handlers(self):
# Add these lines to the existing method
self.server.set_request_handler(
ListToolsRequestSchema,
self.handle_list_tools
)
self.server.set_request_handler(
CallToolRequestSchema,
self.handle_call_tool
)
async def handle_list_tools(self, request):
return {
"tools": [{
"name": "get_forecast",
"description": "Get weather forecast for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
},
"days": {
"type": "number",
"description": "Number of days (1-5)"
}
},
"required": ["city"]
}
}]
}
async def handle_call_tool(self, request):
if request.params.name != "get_forecast":
raise ValueError(f"Unknown tool: {request.params.name}")
args = request.params.arguments
city = args.get("city", self.default_city)
days = min(int(args.get("days", 3)), 5)
response = requests.get(
f"{BASE_URL}/forecast",
params={
"q": city,
"appid": API_KEY,
"units": "metric",
"cnt": days * 8 # API returns 3-hour intervals
}
)
data = response.json()
# Process and return daily forecasts
forecasts = []
for i in range(0, len(data["list"]), 8): # One day = 8 intervals
day_data = data["list"][i]
forecasts.append({
"date": day_data["dt_txt"].split()[0],
"temperature": day_data["main"]["temp"],
"conditions": day_data["weather"][0]["description"]
})
return {"toolResult": forecasts}
```
</Step>
<Step title="Test your server">
1. Save all changes
2. Run your server:
```bash
python weather_server.py
```
</Step>
</Steps>
## Connect to Claude
<Steps>
<Step title="Install the server">
```bash
# From your project directory
pip install -e .
```
</Step>
<Step title="Update Claude config">
Add this to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["-m", "weather_server"],
"env": {
"OPENWEATHER_API_KEY": "your-api-key",
"HOME": "/Users/YOUR_USERNAME"
}
}
}
}
```
</Step>
<Step title="Restart Claude">
1. Quit Claude completely
2. Start Claude again
3. Verify your weather server appears in the 🔌 menu
</Step>
</Steps>
## Try It Out!
<AccordionGroup>
<Accordion title="Check Current Weather" active>
Ask Claude:
```
What's the current weather in San Francisco? Can you analyze the conditions?
```
Claude will:
1. Access the weather resource
2. Parse the JSON data
3. Provide a natural language summary
</Accordion>
<Accordion title="Get a Forecast">
Ask Claude:
```
Can you get me a 5-day forecast for Tokyo and tell me if I should pack an umbrella?
```
Claude will:
1. Use the `get_forecast` tool
2. Analyze the forecast data
3. Give you packing advice
</Accordion>
</AccordionGroup>
## Understanding the Code
Let's break down the key MCP concepts used in this server:
<Tabs>
<Tab title="Resources">
```python
async def handle_list_resources(self, request):
return {
"resources": [{
"uri": f"weather://{self.default_city}/current",
"name": f"Current weather in {self.default_city}",
"mimeType": "application/json"
}]
}
```
Resources provide data that Claude can access as context. In this case, we're exposing current weather data that Claude can read and analyze.
</Tab>
<Tab title="Tools">
```python
async def handle_list_tools(self, request):
return {
"tools": [{
"name": "get_forecast",
"description": "Get weather forecast for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"days": {"type": "number"}
}
}
}]
}
```
Tools let Claude take actions through your server. The `inputSchema` defines what parameters Claude can provide.
</Tab>
<Tab title="Transport">
```python
async def run(self):
transport = StdioServerTransport()
await self.server.connect(transport)
```
The transport layer handles communication between Claude and your server. Here we're using stdio, but MCP also supports WebSocket and SSE.
</Tab>
</Tabs>
## Next Steps
Now that you've built your first MCP server, try these enhancements:
<CardGroup cols={2}>
<Card
title="Add More Resources"
icon="database"
>
- Air quality data
- Weather alerts
- Historical weather
</Card>
<Card
title="Enhance Tools"
icon="wrench"
>
- Compare multiple cities
- Get detailed hourly forecasts
- Save favorite locations
</Card>
<Card
title="Improve Error Handling"
icon="shield"
>
- Handle API errors gracefully
- Add input validation
- Rate limiting
</Card>
<Card
title="Add Subscriptions"
icon="bell"
>
- Weather alerts
- Temperature changes
- Condition updates
</Card>
</CardGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="Import Errors">
```bash
pip install modelcontextprotocol-sdk --upgrade
```
Ensure you're using the latest SDK version.
</Accordion>
<Accordion title="API Key Issues">
1. Verify your API key is set:
```bash
echo $OPENWEATHER_API_KEY
```
2. Check the API response for error messages
3. Ensure you're within free tier limits
</Accordion>
<Accordion title="Connection Issues">
1. Check Claude's logs:
```bash
tail -f ~/Claude.log
```
2. Verify your config JSON syntax
3. Ensure Python path is correct in config
</Accordion>
</AccordionGroup>
<Note>
Remember: This is just the beginning! MCP servers can provide any type of data or functionality to Claude. Think about what unique capabilities you could add to Claude through MCP.
</Note>

View file

@ -0,0 +1,533 @@
---
title: "Your First MCP Server (TypeScript)"
description: "Create a simple MCP server in TypeScript in 15 minutes"
---
Let's build your first MCP server in TypeScript! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools.
<Note>
This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along.
</Note>
## Prerequisites
<Steps>
<Step title="Install Node.js">
You'll need Node.js 16 or higher:
```bash
node --version # Should be v16 or higher
npm --version
```
</Step>
<Step title="Create a new project">
```bash
mkdir weather-server
cd weather-server
npm init -y
```
</Step>
<Step title="Install dependencies">
```bash
npm install @modelcontextprotocol/sdk axios dotenv typescript @types/node
npm install --save-dev ts-node
```
</Step>
<Step title="Configure TypeScript">
Create `tsconfig.json`:
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "node",
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true
},
"include": ["src/**/*"]
}
```
</Step>
<Step title="Set up environment">
Create `.env`:
```bash
OPENWEATHER_API_KEY=your-api-key-here
```
</Step>
</Steps>
## Create Your Server
<Steps>
<Step title="Create project structure">
```bash
mkdir src
touch src/index.ts
touch src/types.ts
```
</Step>
<Step title="Define types">
In `src/types.ts`:
```typescript
export interface WeatherData {
temperature: number;
conditions: string;
humidity: number;
wind_speed: number;
timestamp: string;
}
export interface ForecastDay {
date: string;
temperature: number;
conditions: string;
}
export interface GetForecastArgs {
city: string;
days?: number;
}
```
</Step>
<Step title="Add the base code">
In `src/index.ts`:
```typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import axios from "axios";
import dotenv from "dotenv";
import { WeatherData, ForecastDay, GetForecastArgs } from "./types.js";
dotenv.config();
const API_KEY = process.env.OPENWEATHER_API_KEY;
const BASE_URL = 'http://api.openweathermap.org/data/2.5';
const DEFAULT_CITY = 'San Francisco';
class WeatherServer {
private server: Server;
constructor() {
this.server = new Server({
name: "example-weather-server",
version: "0.1.0"
});
this.setupHandlers();
}
private setupHandlers(): void {
// We'll add handlers here
}
async run(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
}
const server = new WeatherServer();
server.run().catch(console.error);
```
</Step>
<Step title="Add resource handlers">
Add this to the `setupHandlers` method:
```typescript
private setupHandlers(): void {
this.server.setRequestHandler(
ListResourcesRequestSchema,
async () => ({
resources: [{
uri: `weather://${DEFAULT_CITY}/current`,
name: `Current weather in ${DEFAULT_CITY}`,
mimeType: "application/json"
}]
})
);
this.server.setRequestHandler(
ReadResourceRequestSchema,
async (request) => {
const city = DEFAULT_CITY;
if (request.params.uri !== `weather://${city}/current`) {
throw new Error(`Unknown resource: ${request.params.uri}`);
}
const response = await axios.get(`${BASE_URL}/weather`, {
params: {
q: city,
appid: API_KEY,
units: "metric"
}
});
const weatherData: WeatherData = {
temperature: response.data.main.temp,
conditions: response.data.weather[0].description,
humidity: response.data.main.humidity,
wind_speed: response.data.wind.speed,
timestamp: new Date().toISOString()
};
return {
contents: [{
uri: request.params.uri,
mimeType: "application/json",
text: JSON.stringify(weatherData, null, 2)
}]
};
}
);
}
```
</Step>
<Step title="Add tool handlers">
Add these handlers to the `setupHandlers` method:
```typescript
this.server.setRequestHandler(
ListToolsRequestSchema,
async () => ({
tools: [{
name: "get_forecast",
description: "Get weather forecast for a city",
inputSchema: {
type: "object",
properties: {
city: {
type: "string",
description: "City name"
},
days: {
type: "number",
description: "Number of days (1-5)"
}
},
required: ["city"]
}
}]
})
);
this.server.setRequestHandler(
CallToolRequestSchema,
async (request) => {
if (request.params.name !== "get_forecast") {
throw new Error(`Unknown tool: ${request.params.name}`);
}
const args = request.params.arguments as GetForecastArgs;
const city = args.city || DEFAULT_CITY;
const days = Math.min(args.days || 3, 5);
const response = await axios.get(`${BASE_URL}/forecast`, {
params: {
q: city,
appid: API_KEY,
units: "metric",
cnt: days * 8 // API returns 3-hour intervals
}
});
const forecasts: ForecastDay[] = [];
for (let i = 0; i < response.data.list.length; i += 8) {
const dayData = response.data.list[i];
forecasts.push({
date: dayData.dt_txt.split(' ')[0],
temperature: dayData.main.temp,
conditions: dayData.weather[0].description
});
}
return { toolResult: forecasts };
}
);
```
</Step>
<Step title="Build and test">
Add these scripts to `package.json`:
```json
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts"
}
}
```
Then run:
```bash
npm run build
npm start
```
</Step>
</Steps>
## Connect to Claude
<Steps>
<Step title="Install globally">
```bash
npm install -g
```
</Step>
<Step title="Update Claude config">
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"weather": {
"command": "weather-server",
"env": {
"OPENWEATHER_API_KEY": "your-api-key",
"HOME": "/Users/YOUR_USERNAME"
}
}
}
}
```
</Step>
<Step title="Restart Claude">
1. Quit Claude completely
2. Start Claude again
3. Look for your weather server in the 🔌 menu
</Step>
</Steps>
## Try It Out!
<AccordionGroup>
<Accordion title="Check Current Weather" active>
Ask Claude:
```
What's the current weather in San Francisco? Can you analyze the conditions?
```
</Accordion>
<Accordion title="Get a Forecast">
Ask Claude:
```
Can you get me a 5-day forecast for Tokyo and tell me if I should pack an umbrella?
```
</Accordion>
<Accordion title="Compare Weather">
Ask Claude:
```
Can you analyze the forecast for both Tokyo and San Francisco and tell me which city will be warmer this week?
```
</Accordion>
</AccordionGroup>
## Understanding the Code
<Tabs>
<Tab title="Type Safety">
```typescript
interface WeatherData {
temperature: number;
conditions: string;
humidity: number;
wind_speed: number;
timestamp: string;
}
```
TypeScript adds type safety to our MCP server, making it more reliable and easier to maintain.
</Tab>
<Tab title="Resources">
```typescript
this.server.setRequestHandler(
ListResourcesRequestSchema,
async () => ({
resources: [{
uri: `weather://${DEFAULT_CITY}/current`,
name: `Current weather in ${DEFAULT_CITY}`,
mimeType: "application/json"
}]
})
);
```
Resources provide data that Claude can access as context.
</Tab>
<Tab title="Tools">
```typescript
{
name: "get_forecast",
description: "Get weather forecast for a city",
inputSchema: {
type: "object",
properties: {
city: { type: "string" },
days: { type: "number" }
}
}
}
```
Tools let Claude take actions through your server with type-safe inputs.
</Tab>
</Tabs>
## Best Practices
<CardGroup cols={2}>
<Card
title="Error Handling"
icon="shield"
>
```typescript
try {
const response = await axios.get(url);
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(`API error: ${error.response?.data.message}`);
}
throw error;
}
```
</Card>
<Card
title="Type Guards"
icon="check"
>
```typescript
function isValidForecastArgs(args: unknown): args is GetForecastArgs {
return typeof args === "object" && args !== null &&
"city" in args;
}
```
</Card>
<Card
title="Environment Variables"
icon="gear"
>
```typescript
if (!process.env.OPENWEATHER_API_KEY) {
throw new Error("OPENWEATHER_API_KEY is required");
}
```
</Card>
<Card
title="Constants"
icon="box"
>
```typescript
const API_ENDPOINTS = {
CURRENT: "weather",
FORECAST: "forecast"
} as const;
```
</Card>
</CardGroup>
## Enhancements
Try adding these features to your server:
<CardGroup cols={3}>
<Card
title="Resource Templates"
icon="square-terminal"
>
Add dynamic city resources:
```typescript
uriTemplate: "weather://{city}/current"
```
</Card>
<Card
title="Caching"
icon="database"
>
Cache API responses:
```typescript
import NodeCache from "node-cache"
```
</Card>
<Card
title="Rate Limiting"
icon="gauge"
>
Add API rate limiting:
```typescript
import rateLimit from "axios-rate-limit"
```
</Card>
</CardGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="Build Errors">
```bash
# Check TypeScript version
npx tsc --version
# Clean and rebuild
rm -rf dist/
npm run build
```
</Accordion>
<Accordion title="Runtime Errors">
Add better error logging:
```typescript
server.onerror = (error) => {
console.error("[MCP Error]", error);
};
```
</Accordion>
<Accordion title="Type Errors">
```bash
# Check types without building
npx tsc --noEmit
```
</Accordion>
</AccordionGroup>
## Next Steps
<CardGroup cols={2}>
<Card
title="Add WebSocket Transport"
icon="bolt"
href="/guides/websocket"
>
Switch to real-time updates with WebSocket transport
</Card>
<Card
title="Add Testing"
icon="vial"
href="/guides/testing"
>
Add Jest tests for your MCP server
</Card>
</CardGroup>
<Note>
Need help? Ask Claude! Since it has access to the MCP SDK documentation, it can help you debug issues and suggest improvements to your server.
</Note>

View file

@ -1,8 +0,0 @@
---
title: "Implementing Tools"
description: "Create tools that LLMs can invoke"
---
# Implementing Tools
Create tools that LLMs can invoke

View file

@ -0,0 +1,442 @@
---
title: "Integrate MCP into Your Python App"
description: "Add MCP support to your LLM application in Python"
---
Learn how to integrate MCP into your Python LLM application. We'll build a simple web analyzer that uses Claude to analyze websites, enhanced with MCP's web automation capabilities.
<Note>
This guide uses an existing MCP server ([puppeteer](/servers/puppeteer)) rather than building one from scratch. This lets us focus on the integration patterns.
</Note>
## The example app
We'll build an "AI Web Analyzer" that:
1. Takes a URL from the user
2. Captures the webpage using MCP
3. Has the LLM analyze the page's content, design, and accessibility
<Frame>
<img src="/api/placeholder/800/400" alt="Screenshot of the Web Analyzer CLI interface" />
</Frame>
## Prerequisites
<Steps>
<Step title="Install dependencies">
```bash
pip install modelcontextprotocol-sdk anthropic click rich
```
</Step>
<Step title="Set up puppeteer server">
```bash
# Install example MCP servers
git clone https://github.com/modelcontextprotocol/example-servers
cd example-servers
npm install
npm run build
npm install -g
```
</Step>
<Step title="Get API key">
```bash
# Set your Anthropic API key
export ANTHROPIC_API_KEY='your-key-here'
```
</Step>
</Steps>
## Building the base app
First, let's create a basic version without MCP:
<Steps>
<Step title="Create project structure">
```bash
mkdir web-analyzer
cd web-analyzer
touch analyzer.py
```
</Step>
<Step title="Add base implementation">
```python
# analyzer.py
import click
import anthropic
from rich.console import Console
from rich.panel import Panel
from rich import print as rprint
console = Console()
client = anthropic.Client()
def analyze_url(url: str) -> str:
messages = [{
"role": "user",
"content": f"Please analyze this website: {url}\n\n"
f"I'd like to know about:\n"
f"1. Content quality and organization\n"
f"2. Visual design (based on the URL/description)\n"
f"3. Potential improvements"
}]
response = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=1000,
messages=messages
)
return response.content[0].text
@click.command()
@click.argument('url')
def main(url: str):
with console.status("[bold green]Analyzing website..."):
analysis = analyze_url(url)
rprint(Panel.fit(
analysis,
title="Website Analysis",
border_style="blue"
))
if __name__ == '__main__':
main()
```
</Step>
<Step title="Test the base app">
```bash
python analyzer.py https://example.com
```
</Step>
</Steps>
## Adding MCP support
Now let's enhance the app with MCP capabilities:
<Steps>
<Step title="Create MCP client">
```python
# At the top of analyzer.py
from modelcontextprotocol.client import Client
from modelcontextprotocol.client.stdio import StdioClientTransport
import asyncio
import json
from typing import Optional
class MCPWebClient:
def __init__(self):
self.client = Client(
client_info={
"name": "web-analyzer",
"version": "0.1.0"
}
)
self.transport = None
async def connect(self):
self.transport = StdioClientTransport(
server={
"command": "mcp-server-puppeteer",
}
)
await self.client.connect(self.transport)
async def navigate(self, url: str) -> Optional[str]:
try:
result = await self.client.request(
{
"method": "tools/call",
"params": {
"name": "navigate",
"arguments": {"url": url}
}
},
schema=CallToolResultSchema
)
return result.get("toolResult")
except Exception as e:
console.print(f"[red]Error navigating to URL: {e}")
return None
async def get_console_logs(self) -> str:
result = await self.client.request(
{
"method": "resources/read",
"params": {"uri": "console://logs"}
},
schema=ReadResourceResultSchema
)
return result["contents"][0]["text"]
async def close(self):
if self.transport:
await self.client.close()
```
</Step>
<Step title="Update the analyzer">
```python
async def analyze_url_with_mcp(url: str) -> str:
# Create and connect MCP client
mcp = MCPWebClient()
await mcp.connect()
# Navigate to the URL
await mcp.navigate(url)
# Get console logs (includes errors, warnings, etc.)
console_logs = await mcp.get_console_logs()
# Close the connection
await mcp.close()
# Analyze with Claude
messages = [{
"role": "user",
"content": (
f"Please analyze this website: {url}\n\n"
f"Here are the browser console logs:\n{console_logs}\n\n"
f"Please analyze:\n"
f"1. Content quality and organization\n"
f"2. Visual design\n"
f"3. Technical issues (based on console logs)\n"
f"4. Potential improvements"
)
}]
response = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=1000,
messages=messages
)
return response.content[0].text
@click.command()
@click.argument('url')
def main(url: str):
with console.status("[bold green]Analyzing website..."):
analysis = asyncio.run(analyze_url_with_mcp(url))
rprint(Panel.fit(
analysis,
title="Website Analysis",
border_style="blue"
))
```
</Step>
<Step title="Run the enhanced version">
```bash
python analyzer.py https://example.com
```
</Step>
</Steps>
## Understanding MCP integration
Let's break down the key components of MCP integration:
<Tabs>
<Tab title="Client Setup">
```python
class MCPWebClient:
def __init__(self):
self.client = Client(
client_info={
"name": "web-analyzer",
"version": "0.1.0"
}
)
```
The MCP client identifies your application and manages the connection to MCP servers.
</Tab>
<Tab title="Transport">
```python
self.transport = StdioClientTransport(
server={
"command": "mcp-server-puppeteer",
}
)
```
The transport layer handles communication with the MCP server. Here we're using stdio to talk to the puppeteer server.
</Tab>
<Tab title="Tools">
```python
result = await self.client.request(
{
"method": "tools/call",
"params": {
"name": "navigate",
"arguments": {"url": url}
}
},
schema=CallToolResultSchema
)
```
Tools let you take actions through MCP servers. Here we're using puppeteer's navigate tool.
</Tab>
<Tab title="Resources">
```python
result = await self.client.request(
{
"method": "resources/read",
"params": {"uri": "console://logs"}
},
schema=ReadResourceResultSchema
)
```
Resources provide data from MCP servers. Here we're reading console logs that puppeteer collected.
</Tab>
</Tabs>
## Enhancement ideas
Now that you have MCP working, here are some ways to enhance the analyzer:
<CardGroup cols={2}>
<Card
title="Visual Analysis"
icon="image"
>
```python
# Take screenshots with puppeteer
await client.request({
"method": "tools/call",
"params": {
"name": "screenshot",
"arguments": {...}
}
})
```
</Card>
<Card
title="Multiple Pages"
icon="layer-group">
```python
# Analyze multiple pages in sequence
for url in urls:
await navigate(url)
await analyze()
```
</Card>
<Card
title="Interactive Elements"
icon="mouse-pointer">
```python
# Test interactive features
await client.request({
"method": "tools/call",
"params": {
"name": "click",
"arguments": {"selector": "button"}
}
})
```
</Card>
</CardGroup>
Common Patterns
Here are some patterns you'll often use when integrating MCP:
<AccordionGroup>
<Accordion title="Resource Polling" active>
When you need to wait for resource updates:
```python
async def wait_for_resource(uri: str, timeout: int = 30):
start = time.time()
while time.time() - start < timeout:
result = await client.request(
{
"method": "resources/read",
"params": {"uri": uri}
},
schema=ReadResourceResultSchema
)
if some_condition(result):
return result
await asyncio.sleep(1)
raise TimeoutError()
```
</Accordion>
<Accordion title="Error Handling">
Robust error handling for MCP operations:
```python
try:
await client.request(...)
except MCPError as e:
if e.code == ErrorCode.ResourceNotFound:
# Handle missing resource
elif e.code == ErrorCode.InvalidRequest:
# Handle invalid parameters
else:
# Handle other errors
```
</Accordion>
<Accordion title="Resource Subscriptions">
Subscribe to resource updates:
```python
await client.request(
{
"method": "resources/subscribe",
"params": {"uri": "console://logs"}
},
schema=EmptyResultSchema
)
# Now you'll get notifications when logs change
```
</Accordion>
</AccordionGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="Connection Issues">
```python
# Enable debug logging
import logging
logging.basicConfig(level=logging.DEBUG)
```
Watch for connection errors and MCP protocol messages.
</Accordion>
<Accordion title="Resource Errors">
1. Check if the resource exists:
```python
resources = await client.request(
{"method": "resources/list"},
schema=ListResourcesResultSchema
)
print(resources)
```
2. Verify URI format
3. Check server logs
</Accordion>
<Accordion title="Tool Errors">
1. List available tools:
```python
tools = await client.request(
{"method": "tools/list"},
schema=ListToolsResultSchema
)
print(tools)
```
2. Check argument schema
3. Verify server capabilities
</Accordion>
</AccordionGroup>
## Next steps
<CardGroup cols={2}>
<Card
title="Add More Servers"
icon="plus"
href="/servers"
>
Connect to additional MCP servers for more capabilities
</Card>
<Card
title="Build Custom Server"
icon="code"
href="/docs/guides/first-server-python">
Create your own MCP server for custom functionality
</Card>
</CardGroup>

View file

@ -0,0 +1,885 @@
---
title: "Integrate MCP into Your TypeScript App"
description: "Add MCP support to your LLM application in TypeScript"
---
Learn how to integrate MCP into your TypeScript/React application. We'll build an AI Web Analyzer that uses Claude to analyze websites, enhanced with MCP's web automation capabilities.
<Note>
This guide uses an existing MCP server ([puppeteer](/servers/puppeteer)) rather than building one from scratch. This lets us focus on the integration patterns.
</Note>
## The example app
We'll build an "AI Web Analyzer" that:
1. Takes a URL from the user
2. Captures the webpage using MCP
3. Has Claude analyze the page's content, design, and accessibility
<Frame>
<img src="/api/placeholder/800/400" alt="Screenshot of the Web Analyzer interface" />
</Frame>
## Prerequisites
<Steps>
<Step title="Create React project">
```bash
# Create new Next.js project with TypeScript
npx create-next-app@latest web-analyzer --typescript --tailwind
cd web-analyzer
```
</Step>
<Step title="Install dependencies">
```bash
npm install @modelcontextprotocol/sdk @anthropic-ai/sdk
```
</Step>
<Step title="Set up puppeteer server">
```bash
# Install example MCP servers
git clone https://github.com/modelcontextprotocol/example-servers
cd example-servers
npm install
npm run build
npm install -g
```
</Step>
</Steps>
## Building the base app
First, let's create a basic version without MCP:
<Steps>
<Step title="Create components">
Create `components/WebAnalyzer.tsx`:
```tsx
import { useState } from 'react';
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY
});
export default function WebAnalyzer() {
const [url, setUrl] = useState('');
const [analysis, setAnalysis] = useState('');
const [loading, setLoading] = useState(false);
const analyzeUrl = async () => {
setLoading(true);
try {
const response = await anthropic.messages.create({
model: 'claude-3-opus-20240229',
max_tokens: 1000,
messages: [{
role: 'user',
content: `Please analyze this website: ${url}\n\n`
+ `I'd like to know about:\n`
+ `1. Content quality and organization\n`
+ `2. Visual design (based on URL/description)\n`
+ `3. Potential improvements`
}]
});
setAnalysis(response.content[0].text);
} catch (error) {
console.error('Error:', error);
setAnalysis('Error analyzing website');
}
setLoading(false);
};
return (
<div className="max-w-2xl mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">
AI Web Analyzer
</h1>
<div className="flex gap-2 mb-4">
<input
type="url"
value={url}
onChange={(e) => setUrl(e.target.value)}
placeholder="Enter website URL"
className="flex-1 p-2 border rounded"
/>
<button
onClick={analyzeUrl}
disabled={loading}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
Analyze
</button>
</div>
{loading && (
<div className="animate-pulse text-gray-500">
Analyzing website...
</div>
)}
{analysis && (
<div className="mt-4 p-4 border rounded bg-gray-50">
<pre className="whitespace-pre-wrap">{analysis}</pre>
</div>
)}
</div>
);
}
```
</Step>
<Step title="Update app page">
Update `app/page.tsx`:
```tsx
import WebAnalyzer from '@/components/WebAnalyzer';
export default function Home() {
return (
<main>
<WebAnalyzer />
</main>
);
}
```
</Step>
<Step title="Add environment variables">
Create `.env.local`:
```bash
NEXT_PUBLIC_ANTHROPIC_API_KEY=your-key-here
```
</Step>
</Steps>
## Adding MCP support
Now let's enhance the app with MCP capabilities:
<Steps>
<Step title="Create MCP client">
Create `lib/mcp.ts`:
```typescript
import { Client } from '@modelcontextprotocol/sdk/client';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio';
import {
CallToolResultSchema,
ReadResourceResultSchema
} from '@modelcontextprotocol/sdk/types';
export class MCPWebClient {
private client: Client;
private transport: StdioClientTransport | null = null;
constructor() {
this.client = new Client({
name: 'web-analyzer',
version: '0.1.0'
});
}
async connect() {
this.transport = new StdioClientTransport({
command: 'mcp-server-puppeteer'
});
await this.client.connect(this.transport);
}
async navigate(url: string): Promise<string | null> {
try {
const result = await this.client.request(
{
method: 'tools/call',
params: {
name: 'navigate',
arguments: { url }
}
},
CallToolResultSchema
);
return result.toolResult as string;
} catch (error) {
console.error('Error navigating:', error);
return null;
}
}
async getConsoleLogs(): Promise<string> {
const result = await this.client.request(
{
method: 'resources/read',
params: { uri: 'console://logs' }
},
ReadResourceResultSchema
);
return result.contents[0].text;
}
async close() {
if (this.transport) {
await this.client.close();
}
}
}
```
</Step>
<Step title="Create MCP context">
Create `contexts/MCPContext.tsx`:
```typescript
import { createContext, useContext, useEffect, useRef } from 'react';
import { MCPWebClient } from '@/lib/mcp';
const MCPContext = createContext<MCPWebClient | null>(null);
export function MCPProvider({ children }: { children: React.ReactNode }) {
const clientRef = useRef<MCPWebClient | null>(null);
useEffect(() => {
const initMCP = async () => {
clientRef.current = new MCPWebClient();
await clientRef.current.connect();
};
initMCP();
return () => {
if (clientRef.current) {
clientRef.current.close();
}
};
}, []);
return (
<MCPContext.Provider value={clientRef.current}>
{children}
</MCPContext.Provider>
);
}
export function useMCP() {
const context = useContext(MCPContext);
if (!context) {
throw new Error('useMCP must be used within MCPProvider');
}
return context;
}
```
</Step>
<Step title="Update the analyzer component">
Update `components/WebAnalyzer.tsx`:
```typescript
import { useState } from 'react';
import Anthropic from '@anthropic-ai/sdk';
import { useMCP } from '@/contexts/MCPContext';
const anthropic = new Anthropic({
apiKey: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY
});
export default function WebAnalyzer() {
const mcp = useMCP();
const [url, setUrl] = useState('');
const [analysis, setAnalysis] = useState('');
const [loading, setLoading] = useState(false);
const analyzeUrl = async () => {
setLoading(true);
try {
// Navigate to the URL with MCP
await mcp.navigate(url);
// Get console logs
const consoleLogs = await mcp.getConsoleLogs();
// Analyze with Claude
const response = await anthropic.messages.create({
model: 'claude-3-opus-20240229',
max_tokens: 1000,
messages: [{
role: 'user',
content: `Please analyze this website: ${url}\n\n`
+ `Here are the browser console logs:\n${consoleLogs}\n\n`
+ `Please analyze:\n`
+ `1. Content quality and organization\n`
+ `2. Visual design\n`
+ `3. Technical issues (based on console logs)\n`
+ `4. Potential improvements`
}]
});
setAnalysis(response.content[0].text);
} catch (error) {
console.error('Error:', error);
setAnalysis('Error analyzing website');
}
setLoading(false);
};
// ... rest of the component remains the same
}
```
</Step>
<Step title="Add the provider">
Update `app/layout.tsx`:
```typescript
import { MCPProvider } from '@/contexts/MCPContext';
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<MCPProvider>
{children}
</MCPProvider>
</body>
</html>
);
}
```
</Step>
</Steps>
## Understanding MCP integration
Let's break down the key components:
<Tabs>
<Tab title="Client Setup">
```typescript
export class MCPWebClient {
private client: Client;
constructor() {
this.client = new Client({
name: 'web-analyzer',
version: '0.1.0'
});
}
}
```
The MCP client manages the connection to MCP servers and handles requests.
</Tab>
<Tab title="Context Provider">
```typescript
export function MCPProvider({ children }: { children: React.ReactNode }) {
const clientRef = useRef<MCPWebClient | null>(null);
useEffect(() => {
const initMCP = async () => {
clientRef.current = new MCPWebClient();
await clientRef.current.connect();
};
initMCP();
// ... cleanup
}, []);
}
```
The context provider manages the MCP client lifecycle.
</Tab>
<Tab title="Tools">
```typescript
async navigate(url: string): Promise<string | null> {
const result = await this.client.request(
{
method: 'tools/call',
params: {
name: 'navigate',
arguments: { url }
}
},
CallToolResultSchema
);
return result.toolResult as string;
}
```
Tools let you take actions through MCP servers.
</Tab>
<Tab title="Resources">
```typescript
async getConsoleLogs(): Promise<string> {
const result = await this.client.request(
{
method: 'resources/read',
params: { uri: 'console://logs' }
},
ReadResourceResultSchema
);
return result.contents[0].text;
}
```
Resources provide data from MCP servers.
</Tab>
</Tabs>
## Enhancement ideas
Here are some ways to enhance the analyzer:
<CardGroup cols={2}>
<Card
title="Visual Snapshots"
icon="image"
>
```typescript
// Add screenshot capability
async function captureScreenshot() {
const result = await mcp.client.request({
method: 'tools/call',
params: {
name: 'screenshot',
arguments: { /* ... */ }
}
});
}
```
</Card>
<Card
title="Batch Analysis"
icon="layer-group"
>
```typescript
// Analyze multiple pages
async function analyzeBatch(urls: string[]) {
const results = [];
for (const url of urls) {
await mcp.navigate(url);
// ... analyze
}
}
```
</Card>
<Card
title="Interactive Testing"
icon="mouse-pointer"
>
```typescript
// Test interactive elements
async function testInteraction() {
await mcp.client.request({
method: 'tools/call',
params: {
name: 'click',
arguments: { selector: 'button' }
}
});
}
```
</Card>
<Card
title="Performance Analysis"
icon="gauge"
>
```typescript
// Add performance metrics
async function getPerformance() {
const metrics = await mcp.client.request({
method: 'resources/read',
params: { uri: 'metrics://performance' }
});
}
```
</Card>
</CardGroup>
## Common patterns
Here are some patterns you'll often use with MCP in React:
<AccordionGroup>
<Accordion title="Resource Polling" active>
```typescript
function useResourcePolling(uri: string, interval = 1000) {
const [data, setData] = useState(null);
useEffect(() => {
let mounted = true;
async function poll() {
while (mounted) {
const result = await mcp.client.request({
method: 'resources/read',
params: { uri }
});
if (mounted) {
setData(result);
await new Promise(r => setTimeout(r, interval));
}
}
}
poll();
return () => { mounted = false; };
}, [uri, interval]);
return data;
}
```
</Accordion>
<Accordion title="Error Boundaries">
```typescript
class MCPErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
if (error instanceof MCPError) {
// Handle MCP-specific errors
}
}
render() {
if (this.state.hasError) {
return <ErrorDisplay />;
}
return this.props.children;
}
}
```
</Accordion>
<Accordion title="Resource Subscriptions">
```typescript
function useResourceSubscription(uri: string) {
useEffect(() => {
mcp.client.request({
method: 'resources/subscribe',
params: { uri }
});
return () => {
mcp.client.request({
method: 'resources/unsubscribe',
params: { uri }
});
};
}, [uri]);
}
```
</Accordion>
</AccordionGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="Connection Issues">
```typescript
// Enable debug logging
const initMCP = async () => {
const client = new MCPWebClient({
debug: true, // Enable debug logging
onError: (error) => {
console.error('MCP Error:', error);
}
});
await client.connect();
};
```
Watch the browser console for connection errors and protocol messages.
</Accordion>
<Accordion title="React Component Lifecycle">
Common issues and solutions:
```typescript
function WebAnalyzer() {
// Don't create client on every render
const mcpRef = useRef<MCPWebClient | null>(null);
// Initialize in useEffect
useEffect(() => {
const init = async () => {
mcpRef.current = new MCPWebClient();
await mcpRef.current.connect();
};
init();
// Clean up properly
return () => {
if (mcpRef.current) {
mcpRef.current.close();
}
};
}, []);
}
```
</Accordion>
<Accordion title="Type Safety">
Use TypeScript to catch MCP issues early:
```typescript
// Define expected response types
interface ToolResponse {
toolResult: {
screenshot?: string;
logs?: string[];
error?: string;
};
}
// Use with request
const result = await client.request<ToolResponse>({
method: 'tools/call',
params: {
name: 'screenshot',
arguments: { /* ... */ }
}
});
// TypeScript will catch missing properties
console.log(result.toolResult.screenshot);
```
</Accordion>
</AccordionGroup>
## Performance optimization
<CardGroup cols={2}>
<Card
title="Caching Resources"
icon="database"
>
```typescript
function useCachedResource(uri: string) {
const [data, setData] = useState<string | null>(null);
const cache = useRef(new Map<string, string>());
useEffect(() => {
async function fetchResource() {
if (cache.current.has(uri)) {
setData(cache.current.get(uri)!);
return;
}
const result = await mcp.client.request({
method: 'resources/read',
params: { uri }
});
cache.current.set(uri, result.contents[0].text);
setData(result.contents[0].text);
}
fetchResource();
}, [uri]);
return data;
}
```
</Card>
<Card
title="Batching Requests"
icon="layer-group"
>
```typescript
class BatchedMCPClient extends MCPWebClient {
private batchQueue: Map<string, Promise<any>>;
async request(method: string, params: any) {
const key = JSON.stringify({ method, params });
if (!this.batchQueue.has(key)) {
this.batchQueue.set(
key,
super.request(method, params)
);
// Clear after resolution
this.batchQueue.get(key)!.finally(() => {
this.batchQueue.delete(key);
});
}
return this.batchQueue.get(key);
}
}
```
</Card>
</CardGroup>
## Building for production
<Steps>
<Step title="Error handling">
Add proper error boundaries:
```typescript
import { ErrorBoundary } from 'react-error-boundary';
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div className="p-4 border border-red-500 rounded">
<h2 className="text-red-500">Something went wrong:</h2>
<pre>{error.message}</pre>
<button
onClick={resetErrorBoundary}
className="mt-2 px-4 py-2 bg-red-500 text-white rounded"
>
Try again
</button>
</div>
);
}
export default function App() {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={() => {
// Reset application state
}}
>
<WebAnalyzer />
</ErrorBoundary>
);
}
```
</Step>
<Step title="Loading states">
Add proper loading indicators:
```typescript
function WebAnalyzer() {
const [state, setState] = useState<{
status: 'idle' | 'loading' | 'success' | 'error';
error?: Error;
data?: string;
}>({
status: 'idle'
});
return (
<div>
{state.status === 'loading' && (
<div className="animate-pulse">
<div className="h-4 bg-gray-200 rounded w-3/4"></div>
<div className="space-y-3 mt-4">
<div className="h-4 bg-gray-200 rounded"></div>
<div className="h-4 bg-gray-200 rounded w-5/6"></div>
</div>
</div>
)}
{state.status === 'error' && (
<div className="text-red-500">
{state.error?.message}
</div>
)}
{state.status === 'success' && (
<div>{state.data}</div>
)}
</div>
);
}
```
</Step>
<Step title="Environment configuration">
Set up proper environment variables:
```typescript
// next.config.js
module.exports = {
env: {
NEXT_PUBLIC_ANTHROPIC_API_KEY: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY,
MCP_DEBUG: process.env.NODE_ENV === 'development'
}
};
// Usage in code
const mcpClient = new MCPWebClient({
debug: process.env.MCP_DEBUG === 'true'
});
```
</Step>
</Steps>
## Security considerations
<Warning>
Always validate and sanitize URLs before passing them to MCP servers. The puppeteer server has access to execute JavaScript and interact with web pages.
</Warning>
```typescript
function validateUrl(url: string): boolean {
try {
const parsed = new URL(url);
// Add your validation rules
return parsed.protocol === 'https:';
} catch {
return false;
}
}
function WebAnalyzer() {
const analyzeUrl = async () => {
if (!validateUrl(url)) {
setError('Please enter a valid HTTPS URL');
return;
}
// ... rest of the analysis code
};
}
```
## Next steps
<CardGroup cols={2}>
<Card
title="Add Authentication"
icon="lock"
href="/guides/auth"
>
Learn how to handle authenticated web pages with MCP
</Card>
<Card
title="Custom MCP Server"
icon="server"
href="/quickstarts/first-server-typescript">
Build your own MCP server for custom functionality
</Card>
<Card
title="Testing"
icon="vial"
href="/guides/testing">
Learn how to test MCP integrations
</Card>
<Card
title="Production Setup"
icon="rocket"
href="/guides/production">
Deploy your MCP-enabled app to production
</Card>
</CardGroup>

View file

@ -1,8 +0,0 @@
---
title: "Testing and Debugging"
description: "Test and debug your MCP servers effectively"
---
# Testing and Debugging
Test and debug your MCP servers effectively

View file

@ -1,8 +0,0 @@
---
title: "Working with Resources"
description: "Learn how to expose and consume data through MCP"
---
# Working with Resources
Learn how to expose and consume data through MCP

View file

@ -1,160 +0,0 @@
---
title: "Installation"
description: "Get started with Model Context Protocol (MCP) by installing the SDK for your preferred language"
---
<Note>
MCP supports both TypeScript and Python implementations. Choose the one that best fits your project.
</Note>
<Steps>
<Step title="Choose Your SDK">
<Tabs>
<Tab title="TypeScript">
Install the TypeScript SDK using npm:
```bash
npm install @modelcontextprotocol/sdk
```
</Tab>
<Tab title="Python">
Install the Python SDK using pip:
```bash
pip install modelcontextprotocol
```
</Tab>
</Tabs>
</Step>
<Step title="Verify Installation">
Verify your installation by running a simple test:
<CodeGroup>
```typescript typescript-test.ts
import { Client } from "@modelcontextprotocol/sdk";
const client = new Client({
name: "test-client",
version: "0.1.0"
});
console.log("MCP SDK installed successfully!");
```
```python python-test.py
from modelcontextprotocol import Client
client = Client(
name="test-client",
version="0.1.0"
)
print("MCP SDK installed successfully!")
```
</CodeGroup>
</Step>
<Step title="Set Up Development Environment">
<Info>
For local development, you'll need Node.js 18+ for TypeScript or Python 3.8+ for Python.
</Info>
Install the MCP Inspector for testing and debugging your implementations:
```bash
npm install -g @modelcontextprotocol/inspector
```
</Step>
</Steps>
## System Requirements
<AccordionGroup>
<Accordion title="TypeScript Requirements" icon="js">
- Node.js 18 or higher
- npm 7 or higher
- TypeScript 4.7 or higher (for TypeScript users)
Optional development tools:
- VS Code with TypeScript plugin
- ESLint for code quality
</Accordion>
<Accordion title="Python Requirements" icon="python">
- Python 3.8 or higher
- pip 20.0 or higher
- virtualenv (recommended)
Optional development tools:
- VS Code with Python extension
- pylint for code quality
</Accordion>
<Accordion title="Operating System Support" icon="computer">
MCP supports all major operating systems:
- Windows 10/11
- macOS 10.15+
- Linux (major distributions)
</Accordion>
</AccordionGroup>
## Architecture Overview
<Frame>
<img src="/images/mcp-architecture.png" />
</Frame>
```mermaid
flowchart LR
A[LLM Application] --> B[MCP Client]
B --> C[MCP Server]
C --> D[(External Resource)]
style A fill:#e0f4ff,stroke:#0077cc,stroke-width:2px
style B fill:#fff4e0,stroke:#ff8c00,stroke-width:2px
style C fill:#e0ffe0,stroke:#2d862d,stroke-width:2px
style D fill:#ffe0e0,stroke:#cc0000,stroke-width:2px
classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px
## Next Steps
<CardGroup>
<Card title="Quick Start Guide" icon="play" href="/quickstart">
Build your first MCP integration in under 5 minutes
</Card>
<Card title="Example Servers" icon="server" href="/example-servers">
Explore pre-built MCP servers for common use cases
</Card>
<Card title="API Reference" icon="book" href="/api-reference">
Dive into the complete API documentation
</Card>
</CardGroup>
<Tip>
Join our [Discord community](https://discord.gg/mcp) for help and discussions about MCP development.
</Tip>
## Troubleshooting Common Issues
<AccordionGroup>
<Accordion title="Version Conflicts">
If you encounter version conflicts, ensure all your dependencies are up to date:
```bash
# For TypeScript
npm update @modelcontextprotocol/sdk
Copy# For Python
pip install --upgrade modelcontextprotocol
```
</Accordion>
<Accordion title="Connection Issues">
If you're having trouble connecting to MCP servers:
1. Check your network configuration
2. Verify the server is running
3. Ensure your firewall isn't blocking connections
4. Check the server logs for errors
</Accordion>
<Accordion title="Build Errors">
Common build errors and their solutions:
- TypeScript type errors: Update your @types dependencies
- Python import errors: Check your PYTHONPATH
- Missing dependencies: Run package manager install commands
</Accordion>
</AccordionGroup>
<Warning>
Remember to keep your SDKs updated to the latest version for security patches and new features.
</Warning>

View file

@ -1,8 +0,0 @@
---
title: "API Integration"
description: "Wrap external APIs with MCP"
---
# API Integration
Wrap external APIs with MCP

View file

@ -1,8 +0,0 @@
---
title: "Database Integration"
description: "Connect databases to your LLM through MCP"
---
# Database Integration
Connect databases to your LLM through MCP

View file

@ -1,8 +0,0 @@
---
title: "Local File Access"
description: "Implement local file access in MCP"
---
# Local File Access
Implement local file access in MCP

View file

@ -1,8 +0,0 @@
---
title: "Real-time Updates"
description: "Handle live data updates in MCP"
---
# Real-time Updates
Handle live data updates in MCP

View file

@ -1,63 +1,142 @@
---
title: Introduction
description: 'Introduction to the Model Context Protocol'
description: 'Get started with the Model Context Protocol (MCP)'
---
The Model Context Protocol (MCP) is a protocol designed to enable LLM assistant surfaces to receive contextual information from specialized servers. Whether you’re building an IDE coding assistant, a chat interface, or any other LLM-powered application, MCP provides a standardized way to obtain and utilize relevant context.
The Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating custom AI workflows, MCP provides a standardized way to connect LLMs with the context they need.
## Quickstart Guides
## Get started
The first step to world-class documentation is setting up your editing environments.
Choose the path that best fits your needs:
<CardGroup cols={2}>
<Card
title="Edit Your Docs"
icon="pen-to-square"
href="https://mintlify.com/docs/quickstart"
title="Try MCP with Claude"
icon="bolt"
href="/docs/guides/claude"
>
Get your docs set up locally for easy development
The fastest way to see MCP in action - connect example servers to Claude in minutes
</Card>
<Card
title="Preview Changes"
icon="image"
href="https://mintlify.com/docs/development"
>
Preview your changes before you push to make sure they're perfect
</Card>
</CardGroup>
## Make it yours
Update your docs to your brand and add valuable content for the best user conversion.
<CardGroup cols={2}>
<Card
title="Customize Style"
icon="palette"
href="https://mintlify.com/docs/settings/global"
>
Customize your docs to your company's colors and brands
</Card>
<Card
title="Reference APIs"
title="Build Your First Server (TypeScript)"
icon="code"
href="https://mintlify.com/docs/api-playground/openapi"
href="/docs/guides/first-server-ts"
>
Automatically generate endpoints from an OpenAPI spec
Create a simple MCP server in TypeScript to understand the basics
</Card>
<Card
title="Add Components"
icon="screwdriver-wrench"
href="https://mintlify.com/docs/components/accordion"
title="Build Your First Server (Python)"
icon="python"
href="/docs/guides/first-server-python"
>
Build interactive features and designs to guide your users
Create a simple MCP server in Python to understand the basics
</Card>
<Card
title="Get Inspiration"
icon="stars"
href="https://mintlify.com/customers"
title="Integrate MCP (TypeScript)"
icon="plug"
href="/docs/guides/integrate-ts"
>
Check out our showcase of our favorite documentation
Add MCP support to your TypeScript/JavaScript LLM application
</Card>
<Card
title="Integrate MCP (Python)"
icon="plug"
href="/docs/guides/integrate-python"
>
Add MCP support to your Python LLM application
</Card>
</CardGroup>
## Explore MCP
Dive deeper into MCP's core concepts and capabilities:
<CardGroup cols={3}>
<Card
title="Core Architecture"
icon="sitemap"
href="/core/architecture"
>
Understand how MCP connects clients, servers, and LLMs
</Card>
<Card
title="Resources"
icon="database"
href="/core/resources"
>
Expose data and content from your servers to LLMs
</Card>
<Card
title="Prompts"
icon="message"
href="/core/prompts"
>
Create reusable prompt templates and workflows
</Card>
<Card
title="Tools"
icon="wrench"
href="/core/tools"
>
Enable LLMs to perform actions through your server
</Card>
<Card
title="Sampling"
icon="robot"
href="/core/sampling"
>
Let your servers request completions from LLMs
</Card>
<Card
title="Transport"
icon="network-wired"
href="/core/transport"
>
Learn about MCP's communication mechanisms
</Card>
</CardGroup>
## Example Use Cases
See what you can build with MCP:
<CardGroup cols={2}>
<Card
title="Custom Knowledge Base"
icon="book"
>
Connect your documentation, wikis, and internal knowledge bases to LLMs
</Card>
<Card
title="Database Integration"
icon="database"
>
Query databases and analyze results with natural language
</Card>
<Card
title="Local Development"
icon="code"
>
Build AI-powered development tools with access to local files and git
</Card>
<Card
title="Enterprise Systems"
icon="building"
>
Securely connect enterprise tools and data to AI interfaces
</Card>
</CardGroup>
## Security and Best Practices
MCP is designed with security in mind, but requires careful implementation:
<Card
title="Security Guide"
icon="shield"
href="/security"
>
Learn about MCP's security model, best practices, and implementation guidelines
</Card>
Want to contribute? Check out our [GitHub repository](https://github.com/modelcontextprotocol) or join our growing community of developers building with MCP.

Some files were not shown because too many files have changed in this diff Show more