diff --git a/gemini_server.py b/gemini_server.py index 32214f4..dba229c 100755 --- a/gemini_server.py +++ b/gemini_server.py @@ -7,6 +7,7 @@ Enhanced for large-scale code analysis with 1M token context window import asyncio import json import os +from datetime import datetime from pathlib import Path from typing import Any, Dict, List, Optional, Tuple @@ -17,6 +18,11 @@ from mcp.server.stdio import stdio_server from mcp.types import TextContent, Tool from pydantic import BaseModel, Field +# Version and metadata +__version__ = "2.2.0" +__updated__ = "2025-06-08" +__author__ = "Fahad Gilani" + # Default to Gemini 2.5 Pro Preview with maximum context DEFAULT_MODEL = "gemini-2.5-pro-preview-06-05" MAX_CONTEXT_TOKENS = 1000000 # 1M tokens @@ -277,6 +283,11 @@ async def handle_list_tools() -> List[Tool]: description="List available Gemini models", inputSchema={"type": "object", "properties": {}}, ), + Tool( + name="get_version", + description="Get the version and metadata of the Gemini MCP Server", + inputSchema={"type": "object", "properties": {}}, + ), ] @@ -426,6 +437,33 @@ marked with their paths and content boundaries.""" except Exception as e: return [TextContent(type="text", text=f"Error listing models: {str(e)}")] + elif name == "get_version": + # Return version and metadata information + version_info = { + "version": __version__, + "updated": __updated__, + "author": __author__, + "default_model": DEFAULT_MODEL, + "max_context_tokens": f"{MAX_CONTEXT_TOKENS:,}", + "python_version": f"{os.sys.version_info.major}.{os.sys.version_info.minor}.{os.sys.version_info.micro}", + "server_started": datetime.now().isoformat(), + } + + return [TextContent( + type="text", + text=f"""🤖 Gemini MCP Server v{__version__} +Updated: {__updated__} +Author: {__author__} + +Configuration: +• Default Model: {DEFAULT_MODEL} +• Max Context: {MAX_CONTEXT_TOKENS:,} tokens +• Python: {version_info['python_version']} +• Started: {version_info['server_started']} + +For updates, visit: https://github.com/BeehiveInnovations/gemini-mcp-server""" + )] + else: return [TextContent(type="text", text=f"Unknown tool: {name}")] diff --git a/tests/test_gemini_server.py b/tests/test_gemini_server.py index 452c23d..6ea46b3 100644 --- a/tests/test_gemini_server.py +++ b/tests/test_gemini_server.py @@ -139,12 +139,13 @@ class TestToolHandlers: async def test_handle_list_tools(self): """Test listing available tools""" tools = await handle_list_tools() - assert len(tools) == 3 + assert len(tools) == 4 # Updated to include get_version tool_names = [tool.name for tool in tools] assert "chat" in tool_names assert "analyze_code" in tool_names assert "list_models" in tool_names + assert "get_version" in tool_names @pytest.mark.asyncio async def test_handle_call_tool_unknown(self): diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..b1c88a9 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,86 @@ +""" +Test version functionality +""" + +import pytest +import json +from pathlib import Path +import sys + +# Add parent directory to path for imports +parent_dir = Path(__file__).resolve().parent.parent +if str(parent_dir) not in sys.path: + sys.path.insert(0, str(parent_dir)) + +from gemini_server import ( + __version__, + __updated__, + __author__, + handle_list_tools, + handle_call_tool, +) + + +class TestVersionFunctionality: + """Test version-related functionality""" + + @pytest.mark.asyncio + async def test_version_constants_exist(self): + """Test that version constants are defined""" + assert __version__ is not None + assert isinstance(__version__, str) + assert __updated__ is not None + assert isinstance(__updated__, str) + assert __author__ is not None + assert isinstance(__author__, str) + + @pytest.mark.asyncio + async def test_version_tool_in_list(self): + """Test that get_version tool appears in tool list""" + tools = await handle_list_tools() + tool_names = [tool.name for tool in tools] + assert "get_version" in tool_names + + # Find the version tool + version_tool = next(t for t in tools if t.name == "get_version") + assert version_tool.description == "Get the version and metadata of the Gemini MCP Server" + + @pytest.mark.asyncio + async def test_get_version_tool_execution(self): + """Test executing the get_version tool""" + result = await handle_call_tool("get_version", {}) + + assert len(result) == 1 + assert result[0].type == "text" + + # Check the response contains expected information + response_text = result[0].text + assert __version__ in response_text + assert __updated__ in response_text + assert __author__ in response_text + assert "Gemini MCP Server" in response_text + assert "Default Model:" in response_text + assert "Max Context:" in response_text + assert "Python:" in response_text + assert "Started:" in response_text + assert "github.com/BeehiveInnovations/gemini-mcp-server" in response_text + + @pytest.mark.asyncio + async def test_version_format(self): + """Test that version follows semantic versioning""" + parts = __version__.split(".") + assert len(parts) == 3 # Major.Minor.Patch + for part in parts: + assert part.isdigit() # Each part should be numeric + + @pytest.mark.asyncio + async def test_date_format(self): + """Test that updated date follows expected format""" + # Expected format: YYYY-MM-DD + parts = __updated__.split("-") + assert len(parts) == 3 + assert len(parts[0]) == 4 # Year + assert len(parts[1]) == 2 # Month + assert len(parts[2]) == 2 # Day + for part in parts: + assert part.isdigit() \ No newline at end of file