explain_why
Explains why a specific MCP server is a good fit for your project by evaluating the server name and project description.
Instructions
Explain why a specific MCP server is a good fit for a given project. Example: server_name="github", project_description="open source Python library with CI/CD"
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| server_name | Yes | ||
| project_description | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/kothar/server.py:119-144 (handler)The MCP tool handler function 'explain_why' that takes server_name and project_description, looks up the server via lookup_by_name, generates a rationale, and returns a formatted explanation string.
@mcp.tool() def explain_why(server_name: str, project_description: str) -> str: """ Explain why a specific MCP server is a good fit for a given project. Example: server_name="github", project_description="open source Python library with CI/CD" """ try: _ensure_index() server = lookup_by_name(server_name) if server is None: return ( f"Could not find '{server_name}' in the index. " f"Try a partial name or check spelling." ) rationale = generate_rationale(server, project_description) return ( f"## Why {server['name']} fits your project\n\n" f"**Server:** {server['name']}\n" f"**URL:** {server['url']}\n" f"**Category:** {server['category']}\n" f"**Description:** {server['description']}\n\n" f"**Rationale:** {rationale}" ) except Exception as e: return _error_response(f"explaining fit for '{server_name}'", e) - src/kothar/server.py:119-119 (registration)The @mcp.tool() decorator above the function registers 'explain_why' as an MCP tool on the FastMCP server instance.
@mcp.tool() - src/kothar/search.py:117-143 (helper)The generate_rationale function used by explain_why to produce a template-based textual rationale describing why the server fits the project.
def generate_rationale(server: dict, project_description: str) -> str: """ Template-based rationale: why this server fits this project. No LLM call — grounded, fast, offline. """ name = server["name"] desc = server["description"] category = server["category"] score = server.get("score", 0) # Extract key nouns from project description (simple word overlap) proj_words = set(re.findall(r"[a-z0-9]+", project_description.lower())) desc_words = set(re.findall(r"[a-z0-9]+", desc.lower())) overlap = (proj_words & desc_words) - STOPWORDS if overlap: match_hint = f"It shares focus on: {', '.join(sorted(overlap)[:5])}." else: match_hint = f"It falls under the '{category}' category, which aligns with your project's needs." confidence = "strong" if score > 0.55 else "moderate" if score > 0.40 else "potential" return ( f"{name} — {desc} " f"[{confidence} match | category: {category}] " f"{match_hint}" ) - src/kothar/search.py:146-175 (helper)The lookup_by_name function used by explain_why to find a server in the index by name (exact, short-name, prefix, or substring match).
def lookup_by_name(server_name: str) -> dict | None: """Find a server by name, ranked: exact → short-name exact → prefix → substring.""" if not server_name or not server_name.strip(): return None q = server_name.strip().lower() con = get_connection() rows = con.execute( "SELECT name, description, url, category FROM servers WHERE lower(name) LIKE ?", [f"%{q}%"], ).fetchall() con.close() if not rows: return None def _rank(row): n = row[0].lower() parts = n.split("/", 1) owner = parts[0] if len(parts) == 2 else "" short = parts[-1] if n == q or short == q: return (0, 0) # owner exact match is a stronger prefix signal if owner == q: return (1, 0) if n.startswith(q) or short.startswith(q): return (1, 1) return (2, 0) name, desc, url, cat = min(rows, key=_rank) return {"name": name, "description": desc, "url": url, "category": cat} - src/kothar/server.py:120-124 (schema)The function signature defines the input schema: server_name (str) and project_description (str). The return type is str. No Pydantic model is used; the FastMCP framework infers the schema from type annotations.
def explain_why(server_name: str, project_description: str) -> str: """ Explain why a specific MCP server is a good fit for a given project. Example: server_name="github", project_description="open source Python library with CI/CD" """