#!/usr/bin/env python3 """PromptGarage MCP Server — search and use your prompt archive.""" import os import sys # Ensure project modules are importable sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from mcp.server.fastmcp import FastMCP from db import get_prompt, increment_use, init_db, search_fts, list_prompts mcp = FastMCP("promptgarage") @mcp.tool() async def search(query: str) -> str: """Search PromptGarage for prompts matching a query. Returns compact results (title + ID only) to save context. Use 'show' to get full content of a specific prompt.""" init_db() from search import search as do_search results = do_search(query) if not results: return "No matches found." # Max 5 results, compact format lines = [] for r in results[:5]: star = "*" if r["is_starred"] else " " tags = f" [{r['tags']}]" if r["tags"] else "" lines.append(f"{star}#{r['id']} {r['title'][:70]}{tags}") return "\n".join(lines) @mcp.tool() async def show(prompt_id: int) -> str: """Get full content of a specific prompt by ID. Use after search to see the complete prompt text.""" init_db() r = get_prompt(prompt_id) if not r: return f"Prompt #{prompt_id} not found." star = " (starred)" if r["is_starred"] else "" tags = f"\nTags: {r['tags']}" if r["tags"] else "" return f"#{r['id']} {r['title']}{star}{tags}\nUses: {r['use_count']}\n\n{r['content']}" @mcp.tool() async def use(prompt_id: int) -> str: """Mark a prompt as used (increments use_count) and return its content. Call this when you actually use a prompt from the garage.""" init_db() r = get_prompt(prompt_id) if not r: return f"Prompt #{prompt_id} not found." increment_use(prompt_id) return f"#{r['id']} (use_count: {r['use_count'] + 1})\n\n{r['content']}" @mcp.tool() async def random_prompt(starred_only: bool = False) -> str: """Get a random prompt for inspiration. Set starred_only=True for curated prompts only.""" import random init_db() rows = list_prompts(starred=starred_only, limit=10000) if not rows: return "No prompts found." r = random.choice(rows) star = " (starred)" if r["is_starred"] else "" return f"#{r['id']} {r['title']}{star}\n\n{r['content']}" @mcp.tool() async def stats() -> str: """Get compact PromptGarage statistics.""" from db import get_stats init_db() s = get_stats() lines = [f"Total: {s['total']}, Starred: {s['starred']}"] if s["by_source"]: top_sources = sorted(s["by_source"].items(), key=lambda x: -x[1])[:5] lines.append("Sources: " + ", ".join(f"{k}:{v}" for k, v in top_sources)) return "\n".join(lines) if __name__ == "__main__": mcp.run()