chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# Model Context Protocol (MCP) Python Implementation
|
||||
|
||||
This repository contains a Python implementation of the Model Context Protocol (MCP), demonstrating how to create both a server and client application that communicate using the MCP standard.
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP implementation consists of two main components:
|
||||
|
||||
1. **MCP Server (`server.py`)** - A server that exposes:
|
||||
- **Tools**: Functions that can be called remotely
|
||||
- **Resources**: Data that can be retrieved
|
||||
- **Prompts**: Templates for generating prompts for language models
|
||||
|
||||
2. **MCP Client (`client.py`)** - A client application that connects to the server and uses its features
|
||||
|
||||
## Features
|
||||
|
||||
This implementation demonstrates several key MCP features:
|
||||
|
||||
### Tools
|
||||
- `completion` - Generates text completions from AI models (simulated)
|
||||
- `add` - Simple calculator that adds two numbers
|
||||
|
||||
### Resources
|
||||
- `models://` - Returns information about available AI models
|
||||
- `greeting://{name}` - Returns a personalized greeting for a given name
|
||||
|
||||
### Prompts
|
||||
- `review_code` - Generates a prompt for reviewing code
|
||||
|
||||
## Installation
|
||||
|
||||
To use this MCP implementation, install the required packages:
|
||||
|
||||
```powershell
|
||||
pip install mcp-server mcp-client
|
||||
```
|
||||
|
||||
## Running the Server and Client
|
||||
|
||||
### Starting the Server
|
||||
|
||||
Run the server in one terminal window:
|
||||
|
||||
```powershell
|
||||
python server.py
|
||||
```
|
||||
|
||||
The server can also be run in development mode using the MCP CLI:
|
||||
|
||||
```powershell
|
||||
mcp dev server.py
|
||||
```
|
||||
|
||||
Or installed in Claude Desktop (if available):
|
||||
|
||||
```powershell
|
||||
mcp install server.py
|
||||
```
|
||||
|
||||
### Running the Client
|
||||
|
||||
Run the client in another terminal window:
|
||||
|
||||
```powershell
|
||||
python client.py
|
||||
```
|
||||
|
||||
This will connect to the server and demonstrate all available features.
|
||||
|
||||
### Client Usage
|
||||
|
||||
The client (`client.py`) demonstrates all the MCP capabilities:
|
||||
|
||||
```powershell
|
||||
python client.py
|
||||
```
|
||||
|
||||
This will connect to the server and exercise all features including tools, resources, and prompts. The output will show:
|
||||
|
||||
1. Calculator tool result (5 + 7 = 12)
|
||||
2. Completion tool response to "What is the meaning of life?"
|
||||
3. List of available AI models
|
||||
4. Personalized greeting for "MCP Explorer"
|
||||
5. Code review prompt template
|
||||
|
||||
## Implementation Details
|
||||
|
||||
The server is implemented using the `FastMCP` API, which provides high-level abstractions for defining MCP services. Here's a simplified example of how tools are defined:
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Add two numbers together
|
||||
|
||||
Args:
|
||||
a: First number
|
||||
b: Second number
|
||||
|
||||
Returns:
|
||||
The sum of the two numbers
|
||||
"""
|
||||
logger.info(f"Adding {a} and {b}")
|
||||
return a + b
|
||||
```
|
||||
|
||||
The client uses the MCP client library to connect to and call the server:
|
||||
|
||||
```python
|
||||
async with stdio_client(server_params) as (reader, writer):
|
||||
async with ClientSession(reader, writer) as session:
|
||||
await session.initialize()
|
||||
result = await session.call_tool("add", arguments={"a": 5, "b": 7})
|
||||
```
|
||||
|
||||
## Learn More
|
||||
|
||||
For more information about MCP, visit: https://modelcontextprotocol.io/
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Clean MCP Client Example.
|
||||
|
||||
This is a clean implementation of an MCP client that demonstrates
|
||||
all capabilities of the MCP protocol with proper error handling.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import json
|
||||
import urllib.parse
|
||||
import sys
|
||||
from mcp import ClientSession, StdioServerParameters
|
||||
from mcp.client.stdio import stdio_client
|
||||
from mcp.types import TextContent, TextResourceContents
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
async def main():
|
||||
"""Main client function that demonstrates MCP client features"""
|
||||
logger.info("Starting clean MCP client")
|
||||
|
||||
server_params = StdioServerParameters(
|
||||
command="python",
|
||||
args=["server.py"],
|
||||
)
|
||||
|
||||
try:
|
||||
logger.info("Connecting to server...")
|
||||
async with stdio_client(server_params) as (reader, writer):
|
||||
async with ClientSession(reader, writer) as session:
|
||||
logger.info("Initializing session")
|
||||
await session.initialize()
|
||||
|
||||
# 1. Call the add tool
|
||||
logger.info("Testing calculator tool")
|
||||
add_result = await session.call_tool("add", arguments={"a": 5, "b": 7})
|
||||
if add_result and add_result.content:
|
||||
text_content = next((content for content in add_result.content
|
||||
if isinstance(content, TextContent)), None)
|
||||
if text_content:
|
||||
print(f"\n1. Calculator result (5 + 7) = {text_content.text}")
|
||||
|
||||
# 2. Call the completion tool
|
||||
logger.info("Testing completion tool")
|
||||
completion_result = await session.call_tool(
|
||||
"completion",
|
||||
arguments={
|
||||
"model": "gpt-4",
|
||||
"prompt": "What is the meaning of life?",
|
||||
"temperature": 0.7
|
||||
}
|
||||
)
|
||||
if completion_result and completion_result.content:
|
||||
text_content = next((content for content in completion_result.content
|
||||
if isinstance(content, TextContent)), None)
|
||||
if text_content:
|
||||
print(f"\n2. Completion: {text_content.text}")
|
||||
|
||||
# 3. Get models resource
|
||||
logger.info("Testing models resource")
|
||||
models_response = await session.read_resource("models://")
|
||||
if models_response and models_response.contents:
|
||||
text_resource = next((content for content in models_response.contents
|
||||
if isinstance(content, TextResourceContents)), None)
|
||||
if text_resource:
|
||||
models = json.loads(text_resource.text)
|
||||
print("\n3. Available models:")
|
||||
for model in models.get("models", []):
|
||||
print(f" - {model['name']} ({model['id']}): {model['description']}")
|
||||
|
||||
# 4. Get greeting resource
|
||||
logger.info("Testing greeting resource")
|
||||
name = "MCP Explorer"
|
||||
encoded_name = urllib.parse.quote(name)
|
||||
greeting_response = await session.read_resource(f"greeting://{encoded_name}")
|
||||
if greeting_response and greeting_response.contents:
|
||||
text_resource = next((content for content in greeting_response.contents
|
||||
if isinstance(content, TextResourceContents)), None)
|
||||
if text_resource:
|
||||
print(f"\n4. Greeting: {text_resource.text}")
|
||||
|
||||
# 5. Use code review prompt
|
||||
logger.info("Testing code review prompt")
|
||||
sample_code = "def hello_world():\n print('Hello, world!')"
|
||||
prompt_response = await session.get_prompt("review_code", {"code": sample_code})
|
||||
if prompt_response and prompt_response.messages:
|
||||
message = next((msg for msg in prompt_response.messages if msg.content), None)
|
||||
if message and message.content:
|
||||
text_content = next((content for content in [message.content]
|
||||
if isinstance(content, TextContent)), None)
|
||||
if text_content:
|
||||
print("\n5. Code review prompt:")
|
||||
print(f" {text_content.text}")
|
||||
|
||||
except Exception:
|
||||
logger.exception("An error occurred")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Model Context Protocol (MCP) Python Sample Implementation.
|
||||
|
||||
This module demonstrates how to implement a basic MCP server that can handle
|
||||
completion requests. It provides a mock implementation that simulates
|
||||
interaction with various AI models.
|
||||
|
||||
For more information about MCP: https://modelcontextprotocol.io/
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
# Import FastMCP - the high-level MCP server API
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# Configure module logger
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define available models
|
||||
AVAILABLE_MODELS = ["gpt-4", "llama-3-70b", "claude-3-sonnet"]
|
||||
|
||||
# Create an MCP server
|
||||
mcp = FastMCP("Python MCP Demo Server")
|
||||
|
||||
# Define a tool for generating completions
|
||||
@mcp.tool()
|
||||
def completion(model: str, prompt: str, temperature: float = 0.7, max_tokens: int = 100) -> str:
|
||||
"""Generate completions using AI models
|
||||
|
||||
Args:
|
||||
model: The AI model to use for completion
|
||||
prompt: The prompt text to complete
|
||||
temperature: Sampling temperature (0.0 to 1.0)
|
||||
max_tokens: Maximum number of tokens to generate
|
||||
"""
|
||||
# Validate model
|
||||
if model not in AVAILABLE_MODELS:
|
||||
raise ValueError(f"Model {model} not supported")
|
||||
|
||||
# In a real implementation, this would call an AI model
|
||||
# Here we provide a more comprehensive mock response based on the prompt
|
||||
logging.info(f"Processing completion request for model: {model} with temperature: {temperature}")
|
||||
|
||||
# Return different responses based on common prompts
|
||||
if "meaning of life" in prompt.lower():
|
||||
completion_text = "The meaning of life is a philosophical question that has been debated throughout human history. According to Douglas Adams in 'The Hitchhiker's Guide to the Galaxy', the answer is simply '42'. However, many philosophers suggest that the meaning of life is something each person must discover for themselves through their own experiences, values, and beliefs."
|
||||
elif "hello" in prompt.lower() or "hi" in prompt.lower():
|
||||
completion_text = "Hello! I'm a simulated AI response from the MCP server example. How can I help you today?"
|
||||
elif "who are you" in prompt.lower():
|
||||
completion_text = f"I'm a mock {model} model response from the Model Context Protocol (MCP) Python sample implementation. I'm not actually using {model}, just simulating how it would respond in a real MCP server."
|
||||
else:
|
||||
completion_text = f"This is a simulated response to your prompt about '{prompt[:30]}...' from model {model}. In a real implementation, you would get an actual AI-generated completion here."
|
||||
|
||||
# Return the response
|
||||
return completion_text
|
||||
|
||||
# Define a calculator tool to add two numbers
|
||||
@mcp.tool()
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Add two numbers together
|
||||
|
||||
Args:
|
||||
a: First number
|
||||
b: Second number
|
||||
|
||||
Returns:
|
||||
The sum of the two numbers
|
||||
"""
|
||||
logger.info(f"Adding {a} and {b}")
|
||||
return a + b
|
||||
|
||||
# Define a models resource to expose available AI models
|
||||
@mcp.resource("models://")
|
||||
def get_models() -> str:
|
||||
"""Get information about available AI models"""
|
||||
logger.info("Retrieving available models")
|
||||
models_data = [
|
||||
{
|
||||
"id": "gpt-4",
|
||||
"name": "GPT-4",
|
||||
"description": "OpenAI's GPT-4 large language model"
|
||||
},
|
||||
{
|
||||
"id": "llama-3-70b",
|
||||
"name": "LLaMA 3 (70B)",
|
||||
"description": "Meta's LLaMA 3 with 70 billion parameters"
|
||||
},
|
||||
{
|
||||
"id": "claude-3-sonnet",
|
||||
"name": "Claude 3 Sonnet",
|
||||
"description": "Anthropic's Claude 3 Sonnet model"
|
||||
}
|
||||
]
|
||||
|
||||
return json.dumps({"models": models_data})
|
||||
|
||||
# Define a greeting resource that dynamically constructs a personalized greeting
|
||||
@mcp.resource("greeting://{name}")
|
||||
def get_greeting(name: str) -> str:
|
||||
"""Return a greeting for the given name
|
||||
|
||||
Args:
|
||||
name: The name to greet
|
||||
|
||||
Returns:
|
||||
A personalized greeting message
|
||||
"""
|
||||
import urllib.parse
|
||||
# Decode URL-encoded name
|
||||
decoded_name = urllib.parse.unquote(name)
|
||||
logger.info(f"Generating greeting for {decoded_name}")
|
||||
return f"Hello, {decoded_name}!"
|
||||
|
||||
# Define a prompt for code review
|
||||
@mcp.prompt()
|
||||
def review_code(code: str) -> str:
|
||||
"""Provide a template for reviewing code
|
||||
|
||||
Args:
|
||||
code: The code to review
|
||||
|
||||
Returns:
|
||||
A prompt that asks the LLM to review the code
|
||||
"""
|
||||
logger.info(f"Creating code review prompt for {len(code)} bytes of code")
|
||||
return f"Please review this code and provide feedback on best practices, potential bugs, and improvements:\n\n```\n{code}\n```"
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info(f"MCP Server initialized")
|
||||
logger.info(f"Supported models: {', '.join(AVAILABLE_MODELS)}")
|
||||
|
||||
# Run the server with stdio transport
|
||||
# This can be tested with one of these methods:
|
||||
# 1. Direct execution: python server.py
|
||||
# 2. MCP inspector: mcp dev server.py
|
||||
# 3. Install in Claude Desktop: mcp install server.py
|
||||
mcp.run()
|
||||
Reference in New Issue
Block a user