summaryrefslogtreecommitdiff
path: root/servers/hello_world/src
diff options
context:
space:
mode:
Diffstat (limited to 'servers/hello_world/src')
-rw-r--r--servers/hello_world/src/mcp_server_hello_world/__init__.py25
-rw-r--r--servers/hello_world/src/mcp_server_hello_world/__main__.py9
-rw-r--r--servers/hello_world/src/mcp_server_hello_world/cli.py99
-rw-r--r--servers/hello_world/src/mcp_server_hello_world/server.py84
4 files changed, 217 insertions, 0 deletions
diff --git a/servers/hello_world/src/mcp_server_hello_world/__init__.py b/servers/hello_world/src/mcp_server_hello_world/__init__.py
new file mode 100644
index 0000000..cff1acb
--- /dev/null
+++ b/servers/hello_world/src/mcp_server_hello_world/__init__.py
@@ -0,0 +1,25 @@
+import argparse
+import asyncio
+
+from . import server
+
+def main() -> None:
+ """Main entry point for the package."""
+ parser = argparse.ArgumentParser(description='Hello World MCP Server')
+ parser.add_argument('--transport',
+ default="stdio",
+ choices=["stdio", "remote"],
+ help='Transport method (stdio or remote)')
+ parser.add_argument('--host',
+ default="127.0.0.1",
+ help='Host for remote transport (default: 127.0.0.1)')
+ parser.add_argument('--port',
+ type=int,
+ default=8080,
+ help='Port for remote transport (default: 8080)')
+
+ args = parser.parse_args()
+ asyncio.run(server.main(args.transport, args.host, args.port))
+
+# Expose important items at package level
+__all__ = ["server", "main"]
diff --git a/servers/hello_world/src/mcp_server_hello_world/__main__.py b/servers/hello_world/src/mcp_server_hello_world/__main__.py
new file mode 100644
index 0000000..0caafee
--- /dev/null
+++ b/servers/hello_world/src/mcp_server_hello_world/__main__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+"""
+Command-line interface for the Hello World MCP server.
+"""
+
+from .cli import run_server
+
+if __name__ == "__main__":
+ run_server() \ No newline at end of file
diff --git a/servers/hello_world/src/mcp_server_hello_world/cli.py b/servers/hello_world/src/mcp_server_hello_world/cli.py
new file mode 100644
index 0000000..006581e
--- /dev/null
+++ b/servers/hello_world/src/mcp_server_hello_world/cli.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+"""
+Common CLI functionality for the Hello World MCP server.
+"""
+
+import argparse
+import asyncio
+import logging
+import sys
+
+from .server import main
+
+logger = logging.getLogger("mcp_hello_world_server")
+
+def parse_args() -> argparse.Namespace:
+ """Parse command-line arguments."""
+ parser = argparse.ArgumentParser(description="Hello World MCP Server")
+ parser.add_argument(
+ "--transport",
+ choices=["stdio", "remote"],
+ default="stdio",
+ help="Transport type (stdio or remote)",
+ )
+ parser.add_argument(
+ "--host",
+ default="127.0.0.1",
+ help="Host to bind to for remote transport (default: 127.0.0.1)",
+ )
+ parser.add_argument(
+ "--port",
+ type=int,
+ default=8080,
+ help="Port to bind to for remote transport (default: 8080)",
+ )
+ parser.add_argument(
+ "--log-level",
+ choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
+ default="INFO",
+ help="Set the logging level (default: INFO)",
+ )
+ return parser.parse_args()
+
+def validate_args(args: argparse.Namespace) -> argparse.Namespace:
+ """Validate command-line arguments."""
+ if (args.transport == "remote" and args.port < 1024
+ and not sys.platform.startswith("win")):
+ logger.warning(
+ "Using a port below 1024 may require root privileges on Unix-like systems."
+ )
+ return args
+
+def setup_logging(level: str, transport: str) -> None:
+ """Set up logging configuration.
+
+ Args:
+ level: The base logging level from command line args
+ transport: The transport type being used (stdio or remote)
+ """
+ # Create logs directory if it doesn't exist
+ import os
+ os.makedirs("logs", exist_ok=True)
+
+ # Configure file handler for all logs
+ file_handler = logging.FileHandler("logs/mcp_server.log")
+ file_handler.setLevel(getattr(logging, level))
+ file_handler.setFormatter(logging.Formatter(
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
+ ))
+
+ # Configure console handler with appropriate level
+ console_handler = logging.StreamHandler()
+ # Use WARNING level for stdio transport to reduce interference
+ if transport == "stdio":
+ console_handler.setLevel(logging.WARNING)
+ else:
+ console_handler.setLevel(getattr(logging, level))
+ console_handler.setFormatter(logging.Formatter(
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
+ ))
+
+ # Configure root logger
+ root_logger = logging.getLogger()
+ root_logger.setLevel(getattr(logging, level)) # Base level for all handlers
+ root_logger.handlers = [] # Remove any existing handlers
+ root_logger.addHandler(file_handler)
+ root_logger.addHandler(console_handler)
+
+def run_server() -> None:
+ """Run the server with CLI arguments."""
+ args = validate_args(parse_args())
+ setup_logging(args.log_level, args.transport)
+
+ try:
+ asyncio.run(main(args.transport, args.host, args.port))
+ except KeyboardInterrupt:
+ logger.info("Server stopped by user")
+ except Exception as e:
+ logger.error(f"Error running server: {e}")
+ sys.exit(1)
diff --git a/servers/hello_world/src/mcp_server_hello_world/server.py b/servers/hello_world/src/mcp_server_hello_world/server.py
new file mode 100644
index 0000000..a329897
--- /dev/null
+++ b/servers/hello_world/src/mcp_server_hello_world/server.py
@@ -0,0 +1,84 @@
+import logging
+import os
+import sys
+
+from mcp.server.fastmcp import FastMCP
+
+# reconfigure UnicodeEncodeError prone default (i.e. windows-1252) to utf-8
+if sys.platform == "win32" and os.environ.get('PYTHONIOENCODING') is None:
+ sys.stdin.reconfigure(encoding="utf-8")
+ sys.stdout.reconfigure(encoding="utf-8")
+ sys.stderr.reconfigure(encoding="utf-8")
+
+logger = logging.getLogger('mcp_hello_world_server')
+
+# Simple prompt template
+GREETING_PROMPT_TEMPLATE = """
+Hello there! You've chosen to use the greeting prompt with the name: {name}.
+
+This is a simple demonstration of how MCP prompts work. You can use this as a
+starting point
+for creating your own MCP servers with more complex functionality.
+
+Here's what this Hello World MCP server can do:
+
+1. Provide a greeting prompt (which you're using now)
+2. Offer a simple "hello" tool that returns a greeting message
+3. Expose a static resource with a welcome message
+
+Feel free to explore these capabilities and use this server as a template
+for building more advanced MCP servers!
+"""
+
+class HelloWorldServer:
+ def __init__(self) -> None:
+ self.welcome_message = "Welcome to the Hello World MCP Server! " \
+ "This is a simple static resource."
+
+ def get_greeting(self, name: str) -> str:
+ """Generate a greeting message for the given name"""
+ return f"Hello, {name}! Welcome to the Hello World MCP Server."
+
+def create_server(host: str = "127.0.0.1", port: int = 8080) -> FastMCP:
+ """Create and configure the FastMCP server."""
+ # Create a FastMCP server with host and port settings
+ mcp = FastMCP("Hello World", host=host, port=port)
+
+ # Create a HelloWorldServer instance
+ hello_world = HelloWorldServer()
+
+ # Add a static resource
+ @mcp.resource("hello://welcome")
+ def welcome_resource() -> str:
+ """A simple welcome message resource"""
+ return hello_world.welcome_message
+
+ # Add a greeting tool
+ @mcp.tool()
+ def hello(name: str) -> str:
+ """Get a personalized greeting message"""
+ return hello_world.get_greeting(name)
+
+ # Add a greeting prompt
+ @mcp.prompt()
+ def greeting(name: str) -> str:
+ """A simple greeting prompt that demonstrates MCP functionality"""
+ return GREETING_PROMPT_TEMPLATE.format(name=name)
+
+ return mcp
+
+async def main(transport_type: str, host: str, port: int) -> None:
+ """Start the server with the specified transport."""
+ logger.info("Starting MCP Hello World Server")
+ logger.info(f"Starting Hello World MCP Server with {transport_type} transport")
+
+ # Create the server with host and port
+ mcp = create_server(host=host, port=port)
+
+ # Run the server with the appropriate transport
+ if transport_type == "stdio":
+ logger.info("Server running with stdio transport")
+ await mcp.run_stdio_async()
+ else: # remote transport
+ logger.info(f"Server running with remote transport on {host}:{port}")
+ await mcp.run_sse_async()