From e4dd2199fefbf2321e1398ae365ac2064aa67803 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Mon, 18 Nov 2024 08:48:20 -0500 Subject: [PATCH] finished draft of quickstarts --- .DS_Store | Bin 6148 -> 8196 bytes docs/deployment/configuration.mdx | 5 - docs/deployment/environment-setup.mdx | 4 - docs/deployment/monitoring.mdx | 8 - docs/development.mdx | 0 docs/guides/claude.mdx | 235 +++++++ docs/guides/first-mcp-server.mdx | 8 - docs/guides/first-server-python.mdx | 422 ++++++++++++ docs/guides/first-server-ts.mdx | 533 +++++++++++++++ docs/guides/implementing-tools.mdx | 8 - docs/guides/integrate-python.mdx | 442 ++++++++++++ docs/guides/integrate-ts.mdx | 885 +++++++++++++++++++++++++ docs/guides/testing-debugging.mdx | 8 - docs/guides/working-with-resources.mdx | 8 - docs/installation.mdx | 160 ----- docs/recipes/api-integration.mdx | 8 - docs/recipes/database-integration.mdx | 8 - docs/recipes/local-files.mdx | 8 - docs/recipes/realtime-updates.mdx | 8 - introduction.mdx | 161 +++-- logo/dark.svg | 66 +- logo/light.svg | 56 +- mint.json | 42 +- quickstart.mdx | 305 --------- 24 files changed, 2667 insertions(+), 721 deletions(-) delete mode 100644 docs/deployment/configuration.mdx delete mode 100644 docs/deployment/environment-setup.mdx delete mode 100644 docs/deployment/monitoring.mdx delete mode 100644 docs/development.mdx create mode 100644 docs/guides/claude.mdx delete mode 100644 docs/guides/first-mcp-server.mdx create mode 100644 docs/guides/first-server-python.mdx create mode 100644 docs/guides/first-server-ts.mdx delete mode 100644 docs/guides/implementing-tools.mdx create mode 100644 docs/guides/integrate-python.mdx create mode 100644 docs/guides/integrate-ts.mdx delete mode 100644 docs/guides/testing-debugging.mdx delete mode 100644 docs/guides/working-with-resources.mdx delete mode 100644 docs/installation.mdx delete mode 100644 docs/recipes/api-integration.mdx delete mode 100644 docs/recipes/database-integration.mdx delete mode 100644 docs/recipes/local-files.mdx delete mode 100644 docs/recipes/realtime-updates.mdx delete mode 100644 quickstart.mdx diff --git a/.DS_Store b/.DS_Store index a123578f911e8d1eab8bfaea4ddf9c04be790c6f..c2cd63df2ba7efc55f73110e36efb638b6dcb733 100644 GIT binary patch delta 351 zcmZ8dy-or_7@W<1(M3)X0>p-h55PrVfQX3&g|V=-FbAAya=BFwttn_NF54O#A7NX2 z<9qlHmO5*qL3cCX|IU7y<^J+;2Y@=dn;ZZkG(_;*)$+Do#(S+s=radqNO4Kf`?_h1 z@0thwylzankn=FMi3B&eMsIZ#ImSqbnH`TZI||IifQUc84yLc>uSMzOkv%NytaO``?Fb| v*?dZ3g8r8y2VQHl@kYR#cLjf|mEK|%P7=uv+GcGXI9 delta 132 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{Mvv5r;6q~50D9Qtp2aDw}D)Bpqm+(5z=WYEUK@640=WjsN~GB81` N0NKj0Ii6<@GXU8D7J~o) diff --git a/docs/deployment/configuration.mdx b/docs/deployment/configuration.mdx deleted file mode 100644 index 91b7311..0000000 --- a/docs/deployment/configuration.mdx +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Configuration" -description: "Configure MCP servers for production" ---- - diff --git a/docs/deployment/environment-setup.mdx b/docs/deployment/environment-setup.mdx deleted file mode 100644 index 102a91f..0000000 --- a/docs/deployment/environment-setup.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Environment Setup" -description: "Set up your production environment" ---- \ No newline at end of file diff --git a/docs/deployment/monitoring.mdx b/docs/deployment/monitoring.mdx deleted file mode 100644 index 72aa561..0000000 --- a/docs/deployment/monitoring.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Monitoring" -description: "Monitor your MCP servers in production" ---- - -# Monitoring - -Monitor your MCP servers in production diff --git a/docs/development.mdx b/docs/development.mdx deleted file mode 100644 index e69de29..0000000 diff --git a/docs/guides/claude.mdx b/docs/guides/claude.mdx new file mode 100644 index 0000000..8c862f0 --- /dev/null +++ b/docs/guides/claude.mdx @@ -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. + + +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. + + +## 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 + + +```bash +# Using Homebrew +brew install node git + +# Or download directly: +# Node.js: https://nodejs.org +# Git: https://git-scm.com +``` + + +## Installation + + + + 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 + ``` + + + + 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**. + + + +## 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 + + + Example Claude conversation showing a screenshot analysis + + +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. + + +## Try these examples + +Now that MCP is working, try these increasingly powerful examples: + + + + ``` + Could you analyze my open windows and tell me: + - How many windows I have open + - Which apps are running + - If any windows look cluttered + ``` + + + ``` + Could you help organize my windows? I'd like: + - Browser on the left half + - VSCode on the right half + ``` + + + ``` + 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? + ``` + + + +## 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: + + + 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" + } + } + ``` + + + + Connect Claude to your PostgreSQL database: + ```json + "postgres": { + "command": "mcp-server-postgres", + "args": ["postgresql://localhost/mydb"], + "env": { + "HOME": "/Users/YOUR_USERNAME" + } + } + ``` + + + + Enable web automation capabilities: + ```json + "puppeteer": { + "command": "mcp-server-puppeteer", + } + ``` + + + +## Troubleshooting + + + + 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 + + + + 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 + + + +## Next Steps + + + + Create your own MCP integrations to give Claude new capabilities. + + + + Browse our collection of example servers to see what's possible. + + + + Share your MCP creations and connect with other developers. + [Join us →](/community) + + diff --git a/docs/guides/first-mcp-server.mdx b/docs/guides/first-mcp-server.mdx deleted file mode 100644 index f2df732..0000000 --- a/docs/guides/first-mcp-server.mdx +++ /dev/null @@ -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 diff --git a/docs/guides/first-server-python.mdx b/docs/guides/first-server-python.mdx new file mode 100644 index 0000000..da5be94 --- /dev/null +++ b/docs/guides/first-server-python.mdx @@ -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. + + +This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along. + + +## Prerequisites + + + + You'll need Python 3.8 or higher: + + ```bash + python3 --version # Should be 3.8 or higher + ``` + + + + ```bash + # Create and activate virtual environment + python3 -m venv mcp-weather + cd mcp-weather + source bin/activate # On Windows: .\Scripts\activate + ``` + + + + ```bash + pip install modelcontextprotocol-sdk requests + ``` + + + + 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' + ``` + + + +## Create Your Server + + + + ```bash + mkdir weather_server + cd weather_server + touch weather_server.py + ``` + + + + 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()) + ``` + + + + 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) + }] + } + ``` + + + + 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} + ``` + + + + 1. Save all changes + 2. Run your server: + ```bash + python weather_server.py + ``` + + + +## Connect to Claude + + + + ```bash + # From your project directory + pip install -e . + ``` + + + + 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" + } + } + } + } + ``` + + + + 1. Quit Claude completely + 2. Start Claude again + 3. Verify your weather server appears in the 🔌 menu + + + +## Try It Out! + + + + 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 + + + + 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 + + + +## Understanding the Code + +Let's break down the key MCP concepts used in this server: + + + + ```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. + + + + ```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. + + + + ```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. + + + +## Next Steps + +Now that you've built your first MCP server, try these enhancements: + + + + - Air quality data + - Weather alerts + - Historical weather + + + + - Compare multiple cities + - Get detailed hourly forecasts + - Save favorite locations + + + + - Handle API errors gracefully + - Add input validation + - Rate limiting + + + + - Weather alerts + - Temperature changes + - Condition updates + + + +## Troubleshooting + + + + ```bash + pip install modelcontextprotocol-sdk --upgrade + ``` + Ensure you're using the latest SDK version. + + + + 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 + + + + 1. Check Claude's logs: + ```bash + tail -f ~/Claude.log + ``` + 2. Verify your config JSON syntax + 3. Ensure Python path is correct in config + + + + +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. + \ No newline at end of file diff --git a/docs/guides/first-server-ts.mdx b/docs/guides/first-server-ts.mdx new file mode 100644 index 0000000..c94021f --- /dev/null +++ b/docs/guides/first-server-ts.mdx @@ -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. + + +This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along. + + +## Prerequisites + + + + You'll need Node.js 16 or higher: + + ```bash + node --version # Should be v16 or higher + npm --version + ``` + + + + ```bash + mkdir weather-server + cd weather-server + npm init -y + ``` + + + + ```bash + npm install @modelcontextprotocol/sdk axios dotenv typescript @types/node + npm install --save-dev ts-node + ``` + + + + Create `tsconfig.json`: + ```json + { + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "esModuleInterop": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true + }, + "include": ["src/**/*"] + } + ``` + + + + Create `.env`: + ```bash + OPENWEATHER_API_KEY=your-api-key-here + ``` + + + +## Create Your Server + + + + ```bash + mkdir src + touch src/index.ts + touch src/types.ts + ``` + + + + 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; + } + ``` + + + + 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 { + const transport = new StdioServerTransport(); + await this.server.connect(transport); + } + } + + const server = new WeatherServer(); + server.run().catch(console.error); + ``` + + + + 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) + }] + }; + } + ); + } + ``` + + + + 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 }; + } + ); + ``` + + + + 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 + ``` + + + +## Connect to Claude + + + + ```bash + npm install -g + ``` + + + + Add to `claude_desktop_config.json`: + + ```json + { + "mcpServers": { + "weather": { + "command": "weather-server", + "env": { + "OPENWEATHER_API_KEY": "your-api-key", + "HOME": "/Users/YOUR_USERNAME" + } + } + } + } + ``` + + + + 1. Quit Claude completely + 2. Start Claude again + 3. Look for your weather server in the 🔌 menu + + + +## Try It Out! + + + + Ask Claude: + ``` + What's the current weather in San Francisco? Can you analyze the conditions? + ``` + + + + Ask Claude: + ``` + Can you get me a 5-day forecast for Tokyo and tell me if I should pack an umbrella? + ``` + + + + Ask Claude: + ``` + Can you analyze the forecast for both Tokyo and San Francisco and tell me which city will be warmer this week? + ``` + + + +## Understanding the Code + + + + ```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. + + + + ```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. + + + + ```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. + + + +## Best Practices + + + + ```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; + } + ``` + + + + ```typescript + function isValidForecastArgs(args: unknown): args is GetForecastArgs { + return typeof args === "object" && args !== null && + "city" in args; + } + ``` + + + + ```typescript + if (!process.env.OPENWEATHER_API_KEY) { + throw new Error("OPENWEATHER_API_KEY is required"); + } + ``` + + + + ```typescript + const API_ENDPOINTS = { + CURRENT: "weather", + FORECAST: "forecast" + } as const; + ``` + + + +## Enhancements + +Try adding these features to your server: + + + + Add dynamic city resources: + ```typescript + uriTemplate: "weather://{city}/current" + ``` + + + + Cache API responses: + ```typescript + import NodeCache from "node-cache" + ``` + + + + Add API rate limiting: + ```typescript + import rateLimit from "axios-rate-limit" + ``` + + + +## Troubleshooting + + + + ```bash + # Check TypeScript version + npx tsc --version + + # Clean and rebuild + rm -rf dist/ + npm run build + ``` + + + + Add better error logging: + ```typescript + server.onerror = (error) => { + console.error("[MCP Error]", error); + }; + ``` + + + + ```bash + # Check types without building + npx tsc --noEmit + ``` + + + +## Next Steps + + + + Switch to real-time updates with WebSocket transport + + + + Add Jest tests for your MCP server + + + + +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. + \ No newline at end of file diff --git a/docs/guides/implementing-tools.mdx b/docs/guides/implementing-tools.mdx deleted file mode 100644 index da25884..0000000 --- a/docs/guides/implementing-tools.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Implementing Tools" -description: "Create tools that LLMs can invoke" ---- - -# Implementing Tools - -Create tools that LLMs can invoke diff --git a/docs/guides/integrate-python.mdx b/docs/guides/integrate-python.mdx new file mode 100644 index 0000000..e84e9de --- /dev/null +++ b/docs/guides/integrate-python.mdx @@ -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. + + +This guide uses an existing MCP server ([puppeteer](/servers/puppeteer)) rather than building one from scratch. This lets us focus on the integration patterns. + + +## 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 + + + Screenshot of the Web Analyzer CLI interface + + +## Prerequisites + + + + ```bash + pip install modelcontextprotocol-sdk anthropic click rich + ``` + + + + ```bash + # Install example MCP servers + git clone https://github.com/modelcontextprotocol/example-servers + cd example-servers + npm install + npm run build + npm install -g + ``` + + + + ```bash + # Set your Anthropic API key + export ANTHROPIC_API_KEY='your-key-here' + ``` + + + +## Building the base app + +First, let's create a basic version without MCP: + + + + ```bash + mkdir web-analyzer + cd web-analyzer + touch analyzer.py + ``` + + + + ```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() + ``` + + + + ```bash + python analyzer.py https://example.com + ``` + + + +## Adding MCP support + +Now let's enhance the app with MCP capabilities: + + + + ```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() + ``` + + + ```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" + )) + ``` + + + ```bash + python analyzer.py https://example.com + ``` + + + +## Understanding MCP integration + +Let's break down the key components of MCP integration: + + + ```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. + + + ```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. + + + ```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. + + + ```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. + + + +## Enhancement ideas + +Now that you have MCP working, here are some ways to enhance the analyzer: + + + ```python + # Take screenshots with puppeteer + await client.request({ + "method": "tools/call", + "params": { + "name": "screenshot", + "arguments": {...} + } + }) + ``` + + + ```python + # Analyze multiple pages in sequence + for url in urls: + await navigate(url) + await analyze() + ``` + + + ```python + # Test interactive features + await client.request({ + "method": "tools/call", + "params": { + "name": "click", + "arguments": {"selector": "button"} + } + }) + ``` + + + +Common Patterns +Here are some patterns you'll often use when integrating MCP: + + + 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() + ``` + + + 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 + ``` + + + 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 + ``` + + + +## Troubleshooting + + + + ```python + # Enable debug logging + import logging + logging.basicConfig(level=logging.DEBUG) + ``` + Watch for connection errors and MCP protocol messages. + + + 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 + + + 1. List available tools: + ```python + tools = await client.request( + {"method": "tools/list"}, + schema=ListToolsResultSchema + ) + print(tools) + ``` + 2. Check argument schema + 3. Verify server capabilities + + + +## Next steps + + + + Connect to additional MCP servers for more capabilities + + +Create your own MCP server for custom functionality + + \ No newline at end of file diff --git a/docs/guides/integrate-ts.mdx b/docs/guides/integrate-ts.mdx new file mode 100644 index 0000000..fdb3a2e --- /dev/null +++ b/docs/guides/integrate-ts.mdx @@ -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. + + +This guide uses an existing MCP server ([puppeteer](/servers/puppeteer)) rather than building one from scratch. This lets us focus on the integration patterns. + + +## 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 + + + Screenshot of the Web Analyzer interface + + +## Prerequisites + + + + ```bash + # Create new Next.js project with TypeScript + npx create-next-app@latest web-analyzer --typescript --tailwind + cd web-analyzer + ``` + + + + ```bash + npm install @modelcontextprotocol/sdk @anthropic-ai/sdk + ``` + + + + ```bash + # Install example MCP servers + git clone https://github.com/modelcontextprotocol/example-servers + cd example-servers + npm install + npm run build + npm install -g + ``` + + + +## Building the base app + +First, let's create a basic version without MCP: + + + + 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 ( +
+

+ AI Web Analyzer +

+ +
+ setUrl(e.target.value)} + placeholder="Enter website URL" + className="flex-1 p-2 border rounded" + /> + +
+ + {loading && ( +
+ Analyzing website... +
+ )} + + {analysis && ( +
+
{analysis}
+
+ )} +
+ ); + } + ``` +
+ + + Update `app/page.tsx`: + + ```tsx + import WebAnalyzer from '@/components/WebAnalyzer'; + + export default function Home() { + return ( +
+ +
+ ); + } + ``` +
+ + + Create `.env.local`: + + ```bash + NEXT_PUBLIC_ANTHROPIC_API_KEY=your-key-here + ``` + +
+ +## Adding MCP support + +Now let's enhance the app with MCP capabilities: + + + + 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 { + 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 { + 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(); + } + } + } + ``` + + + + Create `contexts/MCPContext.tsx`: + + ```typescript + import { createContext, useContext, useEffect, useRef } from 'react'; + import { MCPWebClient } from '@/lib/mcp'; + + const MCPContext = createContext(null); + + export function MCPProvider({ children }: { children: React.ReactNode }) { + const clientRef = useRef(null); + + useEffect(() => { + const initMCP = async () => { + clientRef.current = new MCPWebClient(); + await clientRef.current.connect(); + }; + + initMCP(); + + return () => { + if (clientRef.current) { + clientRef.current.close(); + } + }; + }, []); + + return ( + + {children} + + ); + } + + export function useMCP() { + const context = useContext(MCPContext); + if (!context) { + throw new Error('useMCP must be used within MCPProvider'); + } + return context; + } + ``` + + + + 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 + } + ``` + + + + Update `app/layout.tsx`: + + ```typescript + import { MCPProvider } from '@/contexts/MCPContext'; + + export default function RootLayout({ + children, + }: { + children: React.ReactNode + }) { + return ( + + + + {children} + + + + ); + } + ``` + + + +## Understanding MCP integration + +Let's break down the key components: + + + + ```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. + + + + ```typescript + export function MCPProvider({ children }: { children: React.ReactNode }) { + const clientRef = useRef(null); + + useEffect(() => { + const initMCP = async () => { + clientRef.current = new MCPWebClient(); + await clientRef.current.connect(); + }; + + initMCP(); + // ... cleanup + }, []); + } + ``` + The context provider manages the MCP client lifecycle. + + + + ```typescript + async navigate(url: string): Promise { + 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. + + + + ```typescript + async getConsoleLogs(): Promise { + 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. + + + +## Enhancement ideas + +Here are some ways to enhance the analyzer: + + + + ```typescript + // Add screenshot capability + async function captureScreenshot() { + const result = await mcp.client.request({ + method: 'tools/call', + params: { + name: 'screenshot', + arguments: { /* ... */ } + } + }); + } + ``` + + + + ```typescript + // Analyze multiple pages + async function analyzeBatch(urls: string[]) { + const results = []; + for (const url of urls) { + await mcp.navigate(url); + // ... analyze + } + } + ``` + + + + ```typescript + // Test interactive elements + async function testInteraction() { + await mcp.client.request({ + method: 'tools/call', + params: { + name: 'click', + arguments: { selector: 'button' } + } + }); + } + ``` + + + + ```typescript + // Add performance metrics + async function getPerformance() { + const metrics = await mcp.client.request({ + method: 'resources/read', + params: { uri: 'metrics://performance' } + }); + } + ``` + + + +## Common patterns + +Here are some patterns you'll often use with MCP in React: + + + + ```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; + } + ``` + + + + ```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 ; + } + return this.props.children; + } + } + ``` + + + + ```typescript + function useResourceSubscription(uri: string) { + useEffect(() => { + mcp.client.request({ + method: 'resources/subscribe', + params: { uri } + }); + + return () => { + mcp.client.request({ + method: 'resources/unsubscribe', + params: { uri } + }); + }; + }, [uri]); + } + ``` + + + +## Troubleshooting + + + + ```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. + + + + Common issues and solutions: + ```typescript + function WebAnalyzer() { + // Don't create client on every render + const mcpRef = useRef(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(); + } + }; + }, []); + } + ``` + + + + 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({ + method: 'tools/call', + params: { + name: 'screenshot', + arguments: { /* ... */ } + } + }); + + // TypeScript will catch missing properties + console.log(result.toolResult.screenshot); + ``` + + + +## Performance optimization + + + + ```typescript + function useCachedResource(uri: string) { + const [data, setData] = useState(null); + const cache = useRef(new Map()); + + 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; + } + ``` + + + + ```typescript + class BatchedMCPClient extends MCPWebClient { + private batchQueue: Map>; + + 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); + } + } + ``` + + + +## Building for production + + + + Add proper error boundaries: + + ```typescript + import { ErrorBoundary } from 'react-error-boundary'; + + function ErrorFallback({ error, resetErrorBoundary }) { + return ( +
+

Something went wrong:

+
{error.message}
+ +
+ ); + } + + export default function App() { + return ( + { + // Reset application state + }} + > + + + ); + } + ``` +
+ + + Add proper loading indicators: + + ```typescript + function WebAnalyzer() { + const [state, setState] = useState<{ + status: 'idle' | 'loading' | 'success' | 'error'; + error?: Error; + data?: string; + }>({ + status: 'idle' + }); + + return ( +
+ {state.status === 'loading' && ( +
+
+
+
+
+
+
+ )} + + {state.status === 'error' && ( +
+ {state.error?.message} +
+ )} + + {state.status === 'success' && ( +
{state.data}
+ )} +
+ ); + } + ``` +
+ + + 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' + }); + ``` + +
+ +## Security considerations + + +Always validate and sanitize URLs before passing them to MCP servers. The puppeteer server has access to execute JavaScript and interact with web pages. + + +```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 + + + + Learn how to handle authenticated web pages with MCP + + + Build your own MCP server for custom functionality + + + Learn how to test MCP integrations + + + Deploy your MCP-enabled app to production + + + + + + diff --git a/docs/guides/testing-debugging.mdx b/docs/guides/testing-debugging.mdx deleted file mode 100644 index a936680..0000000 --- a/docs/guides/testing-debugging.mdx +++ /dev/null @@ -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 diff --git a/docs/guides/working-with-resources.mdx b/docs/guides/working-with-resources.mdx deleted file mode 100644 index f77ad53..0000000 --- a/docs/guides/working-with-resources.mdx +++ /dev/null @@ -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 diff --git a/docs/installation.mdx b/docs/installation.mdx deleted file mode 100644 index 66ffc35..0000000 --- a/docs/installation.mdx +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: "Installation" -description: "Get started with Model Context Protocol (MCP) by installing the SDK for your preferred language" ---- - - - MCP supports both TypeScript and Python implementations. Choose the one that best fits your project. - - - - - - - Install the TypeScript SDK using npm: - ```bash - npm install @modelcontextprotocol/sdk - ``` - - - Install the Python SDK using pip: - ```bash - pip install modelcontextprotocol - ``` - - - - - - Verify your installation by running a simple test: - - - ```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!") - ``` - - - - - - For local development, you'll need Node.js 18+ for TypeScript or Python 3.8+ for Python. - - - Install the MCP Inspector for testing and debugging your implementations: - ```bash - npm install -g @modelcontextprotocol/inspector - ``` - - - -## System Requirements - - - - - 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 - - - - - Python 3.8 or higher - - pip 20.0 or higher - - virtualenv (recommended) - - Optional development tools: - - VS Code with Python extension - - pylint for code quality - - - - MCP supports all major operating systems: - - Windows 10/11 - - macOS 10.15+ - - Linux (major distributions) - - - -## Architecture Overview - - - - - -```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 - - - Build your first MCP integration in under 5 minutes - - - Explore pre-built MCP servers for common use cases - - - Dive into the complete API documentation - - - - Join our [Discord community](https://discord.gg/mcp) for help and discussions about MCP development. - - -## Troubleshooting Common Issues - - - - 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 -``` - - - 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 - - - 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 - - - - Remember to keep your SDKs updated to the latest version for security patches and new features. - diff --git a/docs/recipes/api-integration.mdx b/docs/recipes/api-integration.mdx deleted file mode 100644 index f3787b0..0000000 --- a/docs/recipes/api-integration.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "API Integration" -description: "Wrap external APIs with MCP" ---- - -# API Integration - -Wrap external APIs with MCP diff --git a/docs/recipes/database-integration.mdx b/docs/recipes/database-integration.mdx deleted file mode 100644 index dbcf630..0000000 --- a/docs/recipes/database-integration.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Database Integration" -description: "Connect databases to your LLM through MCP" ---- - -# Database Integration - -Connect databases to your LLM through MCP diff --git a/docs/recipes/local-files.mdx b/docs/recipes/local-files.mdx deleted file mode 100644 index fb592b4..0000000 --- a/docs/recipes/local-files.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Local File Access" -description: "Implement local file access in MCP" ---- - -# Local File Access - -Implement local file access in MCP diff --git a/docs/recipes/realtime-updates.mdx b/docs/recipes/realtime-updates.mdx deleted file mode 100644 index a7d2b58..0000000 --- a/docs/recipes/realtime-updates.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Real-time Updates" -description: "Handle live data updates in MCP" ---- - -# Real-time Updates - -Handle live data updates in MCP diff --git a/introduction.mdx b/introduction.mdx index 9f6743d..e9a1f4f 100644 --- a/introduction.mdx +++ b/introduction.mdx @@ -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: - Get your docs set up locally for easy development + The fastest way to see MCP in action - connect example servers to Claude in minutes - Preview your changes before you push to make sure they're perfect - - - -## Make it yours - -Update your docs to your brand and add valuable content for the best user conversion. - - - - Customize your docs to your company's colors and brands - - - Automatically generate endpoints from an OpenAPI spec + Create a simple MCP server in TypeScript to understand the basics - Build interactive features and designs to guide your users + Create a simple MCP server in Python to understand the basics - Check out our showcase of our favorite documentation + Add MCP support to your TypeScript/JavaScript LLM application + + + Add MCP support to your Python LLM application + +## Explore MCP + +Dive deeper into MCP's core concepts and capabilities: + + + + Understand how MCP connects clients, servers, and LLMs + + + Expose data and content from your servers to LLMs + + + Create reusable prompt templates and workflows + + + Enable LLMs to perform actions through your server + + + Let your servers request completions from LLMs + + + Learn about MCP's communication mechanisms + + + +## Example Use Cases + +See what you can build with MCP: + + + + Connect your documentation, wikis, and internal knowledge bases to LLMs + + + Query databases and analyze results with natural language + + + Build AI-powered development tools with access to local files and git + + + Securely connect enterprise tools and data to AI interfaces + + + +## Security and Best Practices + +MCP is designed with security in mind, but requires careful implementation: + + + Learn about MCP's security model, best practices, and implementation guidelines + + +Want to contribute? Check out our [GitHub repository](https://github.com/modelcontextprotocol) or join our growing community of developers building with MCP. \ No newline at end of file diff --git a/logo/dark.svg b/logo/dark.svg index a628378..b5db00b 100644 --- a/logo/dark.svg +++ b/logo/dark.svg @@ -1,55 +1,17 @@ - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/logo/light.svg b/logo/light.svg index 582b3b9..0015bd1 100644 --- a/logo/light.svg +++ b/logo/light.svg @@ -1,51 +1,11 @@ - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/mint.json b/mint.json index b93e86e..cf87c99 100644 --- a/mint.json +++ b/mint.json @@ -2,8 +2,8 @@ "$schema": "https://mintlify.com/schema.json", "name": "Model Context Protocol", "logo": { - "dark": "/logo/dark.png", - "light": "/logo/light.png" + "dark": "/logo/dark.svg", + "light": "/logo/light.svg" }, "favicon": "/favicon.svg", "theme": "quill", @@ -49,38 +49,12 @@ { "group": "Get Started", "pages": [ - "quickstart", - "docs/installation", - "docs/key-concepts", - "docs/development" - ] - }, - { - "group": "Guides", - "pages": [ - "docs/guides/first-mcp-server", - "docs/guides/integrating-with-llm", - "docs/guides/working-with-resources", - "docs/guides/implementing-tools", - "docs/guides/security-best-practices", - "docs/guides/testing-debugging" - ] - }, - { - "group": "Recipes", - "pages": [ - "docs/recipes/local-files", - "docs/recipes/database-integration", - "docs/recipes/api-integration", - "docs/recipes/realtime-updates" - ] - }, - { - "group": "Deployment", - "pages": [ - "docs/deployment/environment-setup", - "docs/deployment/configuration", - "docs/deployment/monitoring" + "introduction", + "docs/guides/claude", + "docs/guides/first-server-python", + "docs/guides/first-server-ts", + "docs/guides/integrate-python", + "docs/guides/integrate-ts" ] }, { diff --git a/quickstart.mdx b/quickstart.mdx deleted file mode 100644 index 283553b..0000000 --- a/quickstart.mdx +++ /dev/null @@ -1,305 +0,0 @@ ---- -title: "Quickstart" -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. - - -Model Context Protocol (MCP) is like giving Claude hands and eyes on your computer. It can: -- Take screenshots and analyze what's on your screen -- Read and analyze files from your computer -- Help you automate repetitive tasks -- Connect to your databases and local tools - -And it does all this while maintaining security - Claude can only access what you explicitly allow. - - -## Prerequisites - - -```bash macOS -# Check if you have Node.js installed -node --version # Should be v16 or higher - -# Check if you have git installed -git --version -``` - -```bash Installation -# Install Node.js from https://nodejs.org -# Install git from https://git-scm.com - -# Or use Homebrew -brew install node git -``` - - -## Quick Setup - - - - 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 - ``` - - - - 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", - "env": { - "HOME": "/Users/YOUR_USERNAME" - } - } - } - } - ``` - - Save and **restart Claude Desktop App**. - - - - When you first use screen capture features, macOS will ask for permissions: - - Screenshot permissions dialog - - - Grant these permissions to Claude Desktop App: - - Screen Recording (for screenshots) - - Automation (for window management) - - - -## Try It Out! 🎉 - -Now for the fun part! Try these examples to see MCP in action: - - - - Ask Claude: - ``` - Can you take a screenshot of my desktop and describe what you see? - ``` - - Claude will: - 1. Use MCP to capture your screen - 2. Add it as context to your conversation - 3. Analyze and describe what it sees - - Try follow-up questions like: - - "How many windows do I have open?" - - "What apps am I running?" - - "Is my battery level low?" - - - - Ask Claude: - ``` - I have several windows open and it's messy. Could you help me organize them? Maybe arrange my browser windows side by side? - ``` - - Claude will: - 1. Take a screenshot to assess the situation - 2. Use AppleScript to organize your windows - 3. Take another screenshot to confirm the changes - - Pro tip: You can ask Claude to create specific layouts or focus on particular apps! - - - - Ask Claude: - ``` - I often need to arrange my windows with: - - Browser on the left half - - VS Code on the top right quarter - - Terminal on the bottom right quarter - - Can you create an AppleScript to automate this layout? - ``` - - Claude will create a reusable script that you can save and run anytime! - - - -## 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: - - - - 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" - } - } - ``` - - - - Connect Claude to your PostgreSQL database: - ```json - "postgres": { - "command": "mcp-server-postgres", - "args": ["postgresql://localhost/mydb"], - "env": { - "HOME": "/Users/YOUR_USERNAME" - } - } - ``` - - - - Enable web automation capabilities: - ```json - "puppeteer": { - "command": "mcp-server-puppeteer", - "env": { - "HOME": "/Users/YOUR_USERNAME" - } - } - ``` - - - -## Quick Troubleshooting - - - - 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 - - - - 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 - - - -## Pro Tips - - - - During development: - - Use Command+R to reload Claude - - This restarts MCP servers without closing Claude - - Perfect for testing config changes! - - - - Run multiple servers for maximum capability: - ```json - { - "mcpServers": { - "osascript": { ... }, - "postgres": { ... }, - "puppeteer": { ... }, - "tee": { ... } - } - } - ``` - - Now Claude can: - - Take screenshots - - Query your database - - Automate web tasks - - Read local files - - All in the same conversation! - - - - Add `"debug": true` to see what's happening: - ```json - { - "mcpServers": { - "osascript": { - "command": "mcp-server-osascript", - "env": { ... }, - "debug": true - } - } - } - ``` - - Then watch the logs: - ```bash - tail -f ~/Claude.log - ``` - - - -## Next Steps - - -Now that you've experienced MCP, you might want to: - -1. [Build your own MCP server](/mcp-dev) - Create custom integrations -2. [Explore example servers](https://github.com/modelcontextprotocol/example-servers) - See what's possible -3. Join our [community](/community) - Share your MCP creations! - - - -Remember: Claude will help you write MCP servers! Just describe what you want to build, and Claude can guide you through the process. - \ No newline at end of file