{ "cells": [ { "cell_type": "raw", "metadata": { "vscode": { "languageId": "raw" } }, "source": [ "# ๐Ÿš€ Your First MCP Server\n", "\n", "Welcome to your first hands-on MCP development experience! In this notebook, you'll build a simple \"Hello World\" MCP server from scratch and learn the fundamental concepts of MCP development.\n", "\n", "## ๐ŸŽฏ Learning Objectives\n", "\n", "By the end of this notebook, you will:\n", "- Understand the basic structure of an MCP server\n", "- Build your first working MCP server with a simple tool\n", "- Learn how to run and test your MCP server\n", "- Understand the request/response flow in MCP\n", "\n", "## ๐Ÿ› ๏ธ What You'll Build\n", "\n", "We'll create a simple MCP server with a **greeting tool** that:\n", "- Takes a name as input\n", "- Returns a personalized greeting message\n", "- Demonstrates the core MCP concepts in action\n", "\n", "## ๐Ÿ“š Table of Contents\n", "\n", "1. [MCP Server Basics](#mcp-server-basics)\n", "2. [Creating Your First Server](#creating-server)\n", "3. [Adding a Simple Tool](#adding-tool)\n", "4. [Running the Server](#running-server)\n", "5. [Testing Your MCP](#testing)\n", "6. [Understanding the Flow](#understanding-flow)\n", "7. [Next Steps](#next-steps)\n", "\n", "---\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Let's build our first MCP server!\n", "# We'll create a simple greeting server with one tool\n", "\n", "from typing import Any, Dict, List\n", "import asyncio\n", "from dataclasses import dataclass\n", "\n", "# First, let's define our MCP server structure\n", "# In a real MCP implementation, you'd import from the mcp library\n", "# For this tutorial, we'll simulate the core concepts\n", "\n", "@dataclass\n", "class MCPTool:\n", " \"\"\"Represents an MCP tool (function) that can be called\"\"\"\n", " name: str\n", " description: str\n", " parameters: Dict[str, Any]\n", " handler: callable\n", "\n", "@dataclass\n", "class MCPRequest:\n", " \"\"\"Represents a request to an MCP tool\"\"\"\n", " tool_name: str\n", " arguments: Dict[str, Any]\n", "\n", "@dataclass \n", "class MCPResponse:\n", " \"\"\"Represents a response from an MCP tool\"\"\"\n", " success: bool\n", " result: Any = None\n", " error: str = None\n", "\n", "class SimpleMCPServer:\n", " \"\"\"A simplified MCP server for learning purposes\"\"\"\n", " \n", " def __init__(self, name: str):\n", " self.name = name\n", " self.tools: Dict[str, MCPTool] = {}\n", " \n", " def add_tool(self, tool: MCPTool):\n", " \"\"\"Register a new tool with the server\"\"\"\n", " self.tools[tool.name] = tool\n", " print(f\"โœ… Registered tool: {tool.name}\")\n", " \n", " def list_tools(self) -> List[str]:\n", " \"\"\"Get list of available tools\"\"\"\n", " return list(self.tools.keys())\n", " \n", " async def call_tool(self, request: MCPRequest) -> MCPResponse:\n", " \"\"\"Execute a tool and return the response\"\"\"\n", " if request.tool_name not in self.tools:\n", " return MCPResponse(\n", " success=False, \n", " error=f\"Tool '{request.tool_name}' not found\"\n", " )\n", " \n", " try:\n", " tool = self.tools[request.tool_name]\n", " result = await tool.handler(**request.arguments)\n", " return MCPResponse(success=True, result=result)\n", " except Exception as e:\n", " return MCPResponse(\n", " success=False, \n", " error=f\"Tool execution failed: {str(e)}\"\n", " )\n", "\n", "# Create our first MCP server\n", "server = SimpleMCPServer(\"HelloMCP Server\")\n", "print(f\"๐Ÿš€ Created MCP server: {server.name}\")\n", "print(f\"๐Ÿ“‹ Available tools: {server.list_tools()}\")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Now let's create our first tool - a greeting function!\n", "\n", "async def greet_user(name: str, greeting_style: str = \"friendly\") -> str:\n", " \"\"\"\n", " A simple greeting function that personalizes messages\n", " \n", " Args:\n", " name: The name of the person to greet\n", " greeting_style: Style of greeting (friendly, formal, excited)\n", " \n", " Returns:\n", " A personalized greeting message\n", " \"\"\"\n", " \n", " greetings = {\n", " \"friendly\": f\"Hello there, {name}! ๐Ÿ‘‹ How are you doing today?\",\n", " \"formal\": f\"Good day, {name}. I hope you are well.\",\n", " \"excited\": f\"Hey {name}! ๐ŸŽ‰ So great to meet you! This is awesome!\",\n", " \"casual\": f\"Hey {name}, what's up? ๐Ÿ˜Ž\"\n", " }\n", " \n", " # Default to friendly if style not found\n", " greeting = greetings.get(greeting_style, greetings[\"friendly\"])\n", " \n", " # Add a personal touch\n", " extra_msg = f\"\\\\n\\\\n๐Ÿ’ก By the way, your name '{name}' has {len(name)} letters!\"\n", " \n", " return greeting + extra_msg\n", "\n", "# Create the MCP tool definition\n", "greeting_tool = MCPTool(\n", " name=\"greet_user\",\n", " description=\"Generate a personalized greeting message for a user\",\n", " parameters={\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"name\": {\n", " \"type\": \"string\",\n", " \"description\": \"The name of the person to greet\"\n", " },\n", " \"greeting_style\": {\n", " \"type\": \"string\", \n", " \"description\": \"Style of greeting\",\n", " \"enum\": [\"friendly\", \"formal\", \"excited\", \"casual\"],\n", " \"default\": \"friendly\"\n", " }\n", " },\n", " \"required\": [\"name\"]\n", " },\n", " handler=greet_user\n", ")\n", "\n", "# Register the tool with our server\n", "server.add_tool(greeting_tool)\n", "\n", "print(f\"๐Ÿ“‹ Server now has {len(server.tools)} tool(s): {server.list_tools()}\")\n", "print()\n", "print(\"๐ŸŽ‰ Your first MCP server is ready with a greeting tool!\")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Let's test our MCP server! \n", "# We'll simulate requests from an AI assistant\n", "\n", "async def test_mcp_server():\n", " \"\"\"Test our MCP server with different requests\"\"\"\n", " \n", " print(\"๐Ÿงช Testing Your First MCP Server\")\n", " print(\"=\" * 50)\n", " print()\n", " \n", " # Test 1: Basic greeting\n", " print(\"๐Ÿ“จ Test 1: Basic friendly greeting\")\n", " request1 = MCPRequest(\n", " tool_name=\"greet_user\",\n", " arguments={\"name\": \"Alice\"}\n", " )\n", " \n", " response1 = await server.call_tool(request1)\n", " if response1.success:\n", " print(\"โœ… SUCCESS!\")\n", " print(f\"๐Ÿค– AI Response: {response1.result}\")\n", " else:\n", " print(f\"โŒ ERROR: {response1.error}\")\n", " \n", " print(\"\\\\n\" + \"-\" * 30 + \"\\\\n\")\n", " \n", " # Test 2: Formal greeting\n", " print(\"๐Ÿ“จ Test 2: Formal greeting style\")\n", " request2 = MCPRequest(\n", " tool_name=\"greet_user\", \n", " arguments={\"name\": \"Dr. Smith\", \"greeting_style\": \"formal\"}\n", " )\n", " \n", " response2 = await server.call_tool(request2)\n", " if response2.success:\n", " print(\"โœ… SUCCESS!\")\n", " print(f\"๐Ÿค– AI Response: {response2.result}\")\n", " else:\n", " print(f\"โŒ ERROR: {response2.error}\")\n", " \n", " print(\"\\\\n\" + \"-\" * 30 + \"\\\\n\")\n", " \n", " # Test 3: Excited greeting\n", " print(\"๐Ÿ“จ Test 3: Excited greeting style\")\n", " request3 = MCPRequest(\n", " tool_name=\"greet_user\",\n", " arguments={\"name\": \"Bob\", \"greeting_style\": \"excited\"}\n", " )\n", " \n", " response3 = await server.call_tool(request3)\n", " if response3.success:\n", " print(\"โœ… SUCCESS!\")\n", " print(f\"๐Ÿค– AI Response: {response3.result}\")\n", " else:\n", " print(f\"โŒ ERROR: {response3.error}\")\n", " \n", " print(\"\\\\n\" + \"-\" * 30 + \"\\\\n\")\n", " \n", " # Test 4: Error case - nonexistent tool\n", " print(\"๐Ÿ“จ Test 4: Testing error handling (nonexistent tool)\")\n", " request4 = MCPRequest(\n", " tool_name=\"calculate_meaning_of_life\",\n", " arguments={}\n", " )\n", " \n", " response4 = await server.call_tool(request4)\n", " if response4.success:\n", " print(\"โœ… SUCCESS!\")\n", " print(f\"๐Ÿค– AI Response: {response4.result}\")\n", " else:\n", " print(f\"โŒ EXPECTED ERROR: {response4.error}\")\n", " \n", " print(\"\\\\n๐ŸŽ‰ All tests completed!\")\n", "\n", "# Run the tests\n", "await test_mcp_server()\n" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 }