feat: add version checking capability to MCP server
- Add version metadata (__version__, __updated__, __author__) - Create get_version tool that returns server information - Include Python version, start time, and configuration details - Add comprehensive tests for version functionality - Update existing tests to handle new tool count Now you can check the server version from Claude by asking: "Can you get the version of the Gemini MCP server?" Version: 2.2.0 Updated: 2025-06-08 Author: Fahad Gilani 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ Enhanced for large-scale code analysis with 1M token context window
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
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 mcp.types import TextContent, Tool
|
||||||
from pydantic import BaseModel, Field
|
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 to Gemini 2.5 Pro Preview with maximum context
|
||||||
DEFAULT_MODEL = "gemini-2.5-pro-preview-06-05"
|
DEFAULT_MODEL = "gemini-2.5-pro-preview-06-05"
|
||||||
MAX_CONTEXT_TOKENS = 1000000 # 1M tokens
|
MAX_CONTEXT_TOKENS = 1000000 # 1M tokens
|
||||||
@@ -277,6 +283,11 @@ async def handle_list_tools() -> List[Tool]:
|
|||||||
description="List available Gemini models",
|
description="List available Gemini models",
|
||||||
inputSchema={"type": "object", "properties": {}},
|
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:
|
except Exception as e:
|
||||||
return [TextContent(type="text", text=f"Error listing models: {str(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:
|
else:
|
||||||
return [TextContent(type="text", text=f"Unknown tool: {name}")]
|
return [TextContent(type="text", text=f"Unknown tool: {name}")]
|
||||||
|
|
||||||
|
|||||||
@@ -139,12 +139,13 @@ class TestToolHandlers:
|
|||||||
async def test_handle_list_tools(self):
|
async def test_handle_list_tools(self):
|
||||||
"""Test listing available tools"""
|
"""Test listing available tools"""
|
||||||
tools = await handle_list_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]
|
tool_names = [tool.name for tool in tools]
|
||||||
assert "chat" in tool_names
|
assert "chat" in tool_names
|
||||||
assert "analyze_code" in tool_names
|
assert "analyze_code" in tool_names
|
||||||
assert "list_models" in tool_names
|
assert "list_models" in tool_names
|
||||||
|
assert "get_version" in tool_names
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_handle_call_tool_unknown(self):
|
async def test_handle_call_tool_unknown(self):
|
||||||
|
|||||||
86
tests/test_version.py
Normal file
86
tests/test_version.py
Normal file
@@ -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()
|
||||||
Reference in New Issue
Block a user