server.py•2.99 kB
"""
MCP Server with Keyword Search Tool
This server provides a tool to search for keywords within files.
"""
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
import os
from pathlib import Path
app = FastAPI(title="MCP Keyword Search Server", version="1.0.0")
class SearchRequest(BaseModel):
"""Request model for keyword search"""
file_path: str
keyword: str
case_sensitive: Optional[bool] = False
class SearchResult(BaseModel):
"""Response model for search results"""
file_path: str
keyword: str
total_matches: int
matches: List[dict]
@app.get("/")
async def root():
"""Root endpoint"""
return {
"message": "MCP Keyword Search Server",
"version": "1.0.0",
"endpoints": {
"/search": "POST - Search for keyword in a file",
"/health": "GET - Health check"
}
}
@app.get("/health")
async def health():
"""Health check endpoint"""
return {"status": "healthy"}
@app.post("/search", response_model=SearchResult)
async def search_keyword(request: SearchRequest):
"""
Search for a keyword within a file.
Args:
request: SearchRequest containing file_path, keyword, and case_sensitive flag
Returns:
SearchResult with matched lines and their line numbers
"""
file_path = request.file_path
keyword = request.keyword
case_sensitive = request.case_sensitive
# Validate file path
if not os.path.exists(file_path):
raise HTTPException(status_code=404, detail=f"File not found: {file_path}")
if not os.path.isfile(file_path):
raise HTTPException(status_code=400, detail=f"Path is not a file: {file_path}")
# Read file and search for keyword
matches = []
try:
with open(file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
search_keyword = keyword if case_sensitive else keyword.lower()
for line_num, line in enumerate(lines, start=1):
search_line = line if case_sensitive else line.lower()
if search_keyword in search_line:
matches.append({
"line_number": line_num,
"content": line.rstrip('\n'),
"occurrences": search_line.count(search_keyword)
})
except UnicodeDecodeError:
raise HTTPException(
status_code=400,
detail=f"Unable to read file as text: {file_path}"
)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Error reading file: {str(e)}"
)
return SearchResult(
file_path=file_path,
keyword=keyword,
total_matches=len(matches),
matches=matches
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)