ChiragPatankar commited on
Commit
85d69fd
·
verified ·
1 Parent(s): fecb252

Upload 6 files

Browse files
Files changed (6) hide show
  1. LICENSE +21 -0
  2. init_db.py +35 -0
  3. mcp_config.py +27 -0
  4. middleware.py +63 -0
  5. models.py +36 -0
  6. test_api.py +83 -0
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Gemini MCP Server
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
init_db.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Database initialization script for Gemini MCP Server
4
+ Run this script to create all database tables
5
+ """
6
+
7
+ from database import engine, Base
8
+ from models import ChatMessage, User, Tenant
9
+ import os
10
+
11
+ def init_database():
12
+ """Initialize the database with all tables"""
13
+ print("🚀 Initializing database...")
14
+
15
+ try:
16
+ # Create all tables
17
+ Base.metadata.create_all(bind=engine)
18
+ print("✅ Database tables created successfully!")
19
+
20
+ # Show created tables
21
+ print("\n📊 Created tables:")
22
+ for table_name in Base.metadata.tables.keys():
23
+ print(f" - {table_name}")
24
+
25
+ print(f"\n💾 Database location: {os.getenv('DATABASE_URL', 'sqlite:///./mcp_server.db')}")
26
+ print("🎉 Database initialization complete!")
27
+
28
+ except Exception as e:
29
+ print(f"❌ Error initializing database: {str(e)}")
30
+ return False
31
+
32
+ return True
33
+
34
+ if __name__ == "__main__":
35
+ init_database()
mcp_config.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+
4
+ load_dotenv()
5
+
6
+ class MCPSettings:
7
+ # Server configuration
8
+ SERVER_NAME = os.getenv("SERVER_NAME", "Gemini MCP Server")
9
+ SERVER_VERSION = os.getenv("SERVER_VERSION", "2.0.0")
10
+
11
+ # Model configuration
12
+ MODEL_NAME = "gemini-1.5-flash"
13
+ MODEL_VERSION = "1.5"
14
+ CONTEXT_PROVIDER = "internal"
15
+
16
+ # Rate limiting
17
+ RATE_LIMIT_REQUESTS = int(os.getenv("RATE_LIMIT_REQUESTS", "100"))
18
+ RATE_LIMIT_PERIOD = int(os.getenv("RATE_LIMIT_PERIOD", "60"))
19
+
20
+ # Context settings
21
+ MAX_CONTEXT_RESULTS = int(os.getenv("MAX_CONTEXT_RESULTS", "10"))
22
+
23
+ # Debug mode
24
+ DEBUG = os.getenv("DEBUG", "False").lower() == "true"
25
+
26
+ # Create global settings instance
27
+ mcp_settings = MCPSettings()
middleware.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ from typing import Dict
3
+ from fastapi import Request, Response, HTTPException
4
+ from fastapi.responses import JSONResponse
5
+ from mcp_config import mcp_settings
6
+
7
+ # Simple in-memory rate limiting (use Redis in production)
8
+ request_counts: Dict[str, Dict[str, int]] = {}
9
+
10
+ async def rate_limit_middleware(request: Request, call_next):
11
+ """Rate limiting middleware"""
12
+ client_ip = request.client.host if request.client else "unknown"
13
+ current_time = int(time.time())
14
+ window_start = current_time // mcp_settings.RATE_LIMIT_PERIOD * mcp_settings.RATE_LIMIT_PERIOD
15
+
16
+ # Initialize client data if not exists
17
+ if client_ip not in request_counts:
18
+ request_counts[client_ip] = {}
19
+
20
+ # Clean old windows
21
+ for window in list(request_counts[client_ip].keys()):
22
+ if window < window_start:
23
+ del request_counts[client_ip][window]
24
+
25
+ # Check current window
26
+ if window_start not in request_counts[client_ip]:
27
+ request_counts[client_ip][window_start] = 0
28
+
29
+ # Check rate limit
30
+ if request_counts[client_ip][window_start] >= mcp_settings.RATE_LIMIT_REQUESTS:
31
+ return JSONResponse(
32
+ status_code=429,
33
+ content={
34
+ "code": "RATE_LIMIT_EXCEEDED",
35
+ "message": f"Rate limit exceeded. Max {mcp_settings.RATE_LIMIT_REQUESTS} requests per {mcp_settings.RATE_LIMIT_PERIOD} seconds.",
36
+ "details": {
37
+ "retry_after": mcp_settings.RATE_LIMIT_PERIOD - (current_time % mcp_settings.RATE_LIMIT_PERIOD)
38
+ }
39
+ }
40
+ )
41
+
42
+ # Increment counter
43
+ request_counts[client_ip][window_start] += 1
44
+
45
+ response = await call_next(request)
46
+ return response
47
+
48
+ async def validate_mcp_request(request: Request, call_next):
49
+ """Validate MCP request format"""
50
+ try:
51
+ response = await call_next(request)
52
+ return response
53
+ except Exception as e:
54
+ if mcp_settings.DEBUG:
55
+ print(f"Request validation error: {str(e)}")
56
+ return JSONResponse(
57
+ status_code=500,
58
+ content={
59
+ "code": "INTERNAL_ERROR",
60
+ "message": "Internal server error",
61
+ "details": {"timestamp": time.time()}
62
+ }
63
+ )
models.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean
2
+ from sqlalchemy.sql import func
3
+ from database import Base
4
+
5
+ class ChatMessage(Base):
6
+ __tablename__ = "chat_messages"
7
+
8
+ id = Column(Integer, primary_key=True, index=True)
9
+ user_id = Column(Integer, nullable=False)
10
+ message = Column(Text, nullable=False)
11
+ response = Column(Text, nullable=False)
12
+ context = Column(Text) # JSON string
13
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
14
+ updated_at = Column(DateTime(timezone=True), onupdate=func.now())
15
+
16
+ class User(Base):
17
+ __tablename__ = "users"
18
+
19
+ id = Column(Integer, primary_key=True, index=True)
20
+ email = Column(String(255), unique=True, index=True, nullable=False)
21
+ name = Column(String(255), nullable=False)
22
+ hashed_password = Column(String(255), nullable=False)
23
+ is_active = Column(Boolean, default=True)
24
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
25
+ updated_at = Column(DateTime(timezone=True), onupdate=func.now())
26
+
27
+ class Tenant(Base):
28
+ __tablename__ = "tenants"
29
+
30
+ id = Column(Integer, primary_key=True, index=True)
31
+ name = Column(String(255), nullable=False)
32
+ domain = Column(String(255), unique=True, index=True)
33
+ owner_id = Column(Integer, nullable=False) # Reference to User
34
+ is_active = Column(Boolean, default=True)
35
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
36
+ updated_at = Column(DateTime(timezone=True), onupdate=func.now())
test_api.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple test script for Gemini MCP Server API
4
+ Run this after starting the server to verify it's working
5
+ """
6
+
7
+ import requests
8
+ import json
9
+ import time
10
+
11
+ # Server configuration
12
+ BASE_URL = "http://localhost:8000"
13
+ AUTH_TOKEN = "test-token" # Replace with actual token
14
+
15
+ def test_endpoint(endpoint, method="GET", data=None):
16
+ """Test a single endpoint"""
17
+ url = f"{BASE_URL}{endpoint}"
18
+ headers = {
19
+ "Content-Type": "application/json",
20
+ "x-mcp-auth": AUTH_TOKEN
21
+ }
22
+
23
+ try:
24
+ if method == "POST":
25
+ response = requests.post(url, headers=headers, json=data, timeout=30)
26
+ else:
27
+ response = requests.get(url, timeout=10)
28
+
29
+ print(f"✅ {method} {endpoint}: {response.status_code}")
30
+
31
+ if response.status_code == 200:
32
+ result = response.json()
33
+ print(f" Response: {json.dumps(result, indent=2)[:200]}...")
34
+ else:
35
+ print(f" Error: {response.text}")
36
+
37
+ return response.status_code == 200
38
+
39
+ except requests.exceptions.RequestException as e:
40
+ print(f"❌ {method} {endpoint}: Connection error - {str(e)}")
41
+ return False
42
+
43
+ def main():
44
+ """Run all tests"""
45
+ print("🧪 Testing Gemini MCP Server API...")
46
+ print(f"🌐 Server: {BASE_URL}")
47
+ print("-" * 50)
48
+
49
+ tests = [
50
+ ("Root endpoint", "/", "GET"),
51
+ ("Health check", "/mcp/health", "GET"),
52
+ ("Version info", "/mcp/version", "GET"),
53
+ ("Capabilities", "/mcp/capabilities", "GET"),
54
+ ]
55
+
56
+ # Test basic endpoints
57
+ for name, endpoint, method in tests:
58
+ print(f"\n🔍 Testing {name}...")
59
+ test_endpoint(endpoint, method)
60
+
61
+ # Test process endpoint
62
+ print(f"\n🔍 Testing MCP Process...")
63
+ test_data = {
64
+ "query": "Hello, can you help me with my account?",
65
+ "user_id": "test_user_123",
66
+ "priority": "normal",
67
+ "mcp_version": "1.0"
68
+ }
69
+ test_endpoint("/mcp/process", "POST", test_data)
70
+
71
+ # Test batch endpoint
72
+ print(f"\n🔍 Testing MCP Batch...")
73
+ batch_data = {
74
+ "queries": ["How do I reset my password?", "What are your business hours?"],
75
+ "user_id": "test_user_123",
76
+ "mcp_version": "1.0"
77
+ }
78
+ test_endpoint("/mcp/batch", "POST", batch_data)
79
+
80
+ print("\n🎉 API testing complete!")
81
+
82
+ if __name__ == "__main__":
83
+ main()