CoolFace
Apppublic

Agents-MCP-Hackathon/Stack_Overflow_MCP_Server

sourceHugging Faceupdated 1y agoView on Hugging Face
2likes
api_query.py238 linesDownload Raw Back to root
1#!/usr/bin/env python32"""3Stack Exchange API Query Tool4 5This script allows you to directly call the Stack Exchange API with various parameters6and see the results. It's useful for testing queries and seeing the raw results.7 8Usage:9    python api_query.py search "python pandas dataframe" --tags python,pandas --min-score 1010    python api_query.py question 1234511    python api_query.py error "TypeError: cannot use a string pattern" --language python12"""13 14import os15import sys16import json17import asyncio18import argparse19from dotenv import load_dotenv20 21from stackoverflow_mcp.api import StackExchangeAPI22from stackoverflow_mcp.formatter import format_response23 24 25def setup_environment():26    """Load environment variables from .env file"""27    if os.path.exists(".env"):28        load_dotenv(".env")29    elif os.path.exists(".env.test"):30        load_dotenv(".env.test")31    else:32        print("Warning: No .env or .env.test file found. Using default settings.")33 34 35async def run_search_query(api, args):36    """Run a search query with the given arguments"""37    tags = args.tags.split(',') if args.tags else None38    39    excluded_tags = args.excluded_tags.split(',') if args.excluded_tags else None40    41    print(f"\nRunning search query: '{args.query}'")42    if args.title:43        print(f"Running search with title containing: '{args.title}'")44    if args.body:45        print(f"Running search with body containing: '{args.body}'")46    print(f"Tags: {tags}")47    print(f"Excluded tags: {excluded_tags}")48    print(f"Min score: {args.min_score}")49    print(f"Limit: {args.limit}")50    print(f"Include comments: {args.comments}\n")51    52    try:53        results = await api.search_by_query(54            query=args.query,55            tags=tags,56            title=args.title,57            body=args.body,58            excluded_tags=excluded_tags,59            min_score=args.min_score,60            limit=args.limit,61            include_comments=args.comments62        )63        64        print(f"Found {len(results)} results")65        66        if args.raw:67            for i, result in enumerate(results):68                print(f"\n--- Result {i+1} ---")69                print(f"Question ID: {result.question.question_id}")70                print(f"Title: {result.question.title}")71                print(f"Score: {result.question.score}")72                print(f"Tags: {result.question.tags}")73                print(f"Link: {result.question.link}")74                print(f"Answers: {len(result.answers)}")75                if result.comments:76                    print(f"Question comments: {len(result.comments.question)}")77        else:78            formatted = format_response(results, args.format)79            print(formatted)80        81    except Exception as e:82        print(f"Error during search: {str(e)}")83 84 85async def run_question_query(api, args):86    """Get a specific question by ID"""87    try:88        print(f"\nFetching question ID: {args.question_id}")89        print(f"Include comments: {args.comments}\n")90        91        result = await api.get_question(92            question_id=args.question_id,93            include_comments=args.comments94        )95        96        if args.raw:97            print(f"Question ID: {result.question.question_id}")98            print(f"Title: {result.question.title}")99            print(f"Score: {result.question.score}")100            print(f"Tags: {result.question.tags}")101            print(f"Link: {result.question.link}")102            print(f"Answers: {len(result.answers)}")103            if result.comments:104                print(f"Question comments: {len(result.comments.question)}")105        else:106            formatted = format_response([result], args.format)107            print(formatted)108        109    except Exception as e:110        print(f"Error fetching question: {str(e)}")111 112 113async def run_error_query(api, args):114    """Search for an error message with optional language filter"""115    technologies = args.technologies.split(',') if args.technologies else None116    117    try:118        print(f"\nSearching for error: '{args.error}'")119        print(f"Language: {args.language}")120        print(f"Technologies: {technologies}")121        if args.title:122            print(f"Title containing: '{args.title}'")123        if args.body:124            print(f"Body containing: '{args.body}'")125        print(f"Min score: {args.min_score}")126        print(f"Limit: {args.limit}")127        print(f"Include comments: {args.comments}\n")128        129        tags = []130        if args.language:131            tags.append(args.language.lower())132        if technologies:133            tags.extend([t.lower() for t in technologies])134        135        results = await api.search_by_query(136            query=args.error,137            title=args.title,138            body=args.body,139            tags=tags if tags else None,140            min_score=args.min_score,141            limit=args.limit,142            include_comments=args.comments143        )144        145        print(f"Found {len(results)} results")146        147        if args.raw:148            for i, result in enumerate(results):149                print(f"\n--- Result {i+1} ---")150                print(f"Question ID: {result.question.question_id}")151                print(f"Title: {result.question.title}")152                print(f"Score: {result.question.score}")153                print(f"Tags: {result.question.tags}")154                print(f"Link: {result.question.link}")155                print(f"Answers: {len(result.answers)}")156                if result.comments:157                    print(f"Question comments: {len(result.comments.question)}")158        else:159            formatted = format_response(results, args.format)160            print(formatted)161        162    except Exception as e:163        print(f"Error searching for error: {str(e)}")164 165 166async def main():167    """Parse arguments and run the appropriate query"""168    parser = argparse.ArgumentParser(description="Stack Exchange API Query Tool")169    subparsers = parser.add_subparsers(dest="command", help="Command to run")170    171    # Search command172    search_parser = subparsers.add_parser("search", help="Search Stack Overflow")173    search_parser.add_argument("query", help="Search query")174    search_parser.add_argument("--tags", help="Comma-separated list of tags")175    search_parser.add_argument("--title", help="Word(s) that must appear in the question title")176    search_parser.add_argument("--body", help="Word(s) that must appear in the body of the question")177    search_parser.add_argument("--excluded-tags", help="Comma-separated list of tags to exclude")178    search_parser.add_argument("--min-score", type=int, default=0, help="Minimum score")179    search_parser.add_argument("--limit", type=int, default=5, help="Maximum number of results")180    search_parser.add_argument("--comments", action="store_true", help="Include comments")181    search_parser.add_argument("--format", choices=["markdown", "json"], default="markdown", help="Output format")182    search_parser.add_argument("--raw", action="store_true", help="Print raw data structure")183    184    # Question command185    question_parser = subparsers.add_parser("question", help="Get a specific question")186    question_parser.add_argument("question_id", type=int, help="Question ID")187    question_parser.add_argument("--comments", action="store_true", help="Include comments")188    question_parser.add_argument("--format", choices=["markdown", "json"], default="markdown", help="Output format")189    question_parser.add_argument("--raw", action="store_true", help="Print raw data structure")190    191    # Error command192    error_parser = subparsers.add_parser("error", help="Search for an error message")193    error_parser.add_argument("error", help="Error message")194    error_parser.add_argument("--title", help="Word(s) that must appear in the question title")195    error_parser.add_argument("--body", help="Word(s) that must appear in the body of the question")196    error_parser.add_argument("--language", help="Programming language")197    error_parser.add_argument("--technologies", help="Comma-separated list of technologies")198    error_parser.add_argument("--min-score", type=int, default=0, help="Minimum score")199    error_parser.add_argument("--limit", type=int, default=5, help="Maximum number of results")200    error_parser.add_argument("--comments", action="store_true", help="Include comments")201    error_parser.add_argument("--format", choices=["markdown", "json"], default="markdown", help="Output format")202    error_parser.add_argument("--raw", action="store_true", help="Print raw data structure")203    204    args = parser.parse_args()205    206    if not args.command:207        parser.print_help()208        return 1209    210    setup_environment()211    212    api_key = os.getenv("STACK_EXCHANGE_API_KEY")213    214    if not api_key:215        print("Warning: No API key found. Requests may be rate limited.")216    217    api = StackExchangeAPI(api_key=api_key)218    219    try:220        if args.command == "search":221            await run_search_query(api, args)222        elif args.command == "question":223            await run_question_query(api, args)224        elif args.command == "error":225            await run_error_query(api, args)226        227    except Exception as e:228        print(f"Error: {str(e)}")229        return 1230        231    finally:232        await api.close()233    234    return 0235 236 237if __name__ == "__main__":238    sys.exit(asyncio.run(main()))