Spaces:
Running
Running
File size: 5,246 Bytes
a4b9277 ebcb262 a38d810 ebcb262 a4b9277 a38d810 a4b9277 ebcb262 a4b9277 37828a6 a4b9277 37828a6 a4b9277 a38d810 ebcb262 a38d810 a4b9277 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
import gradio as gr
import requests
import json
from typing import Dict, Any, Optional
def get_xkcd_comic(comic_id: str = "") -> str:
"""
Fetch XKCD comic information by ID or get the latest comic.
Args:
comic_id (str): Comic ID number (leave empty for latest comic)
Returns:
str: JSON string containing comic information including title, alt text, and image URL
"""
try:
if comic_id.strip():
# Get specific comic by ID
url = f"https://xkcd.com/{comic_id.strip()}/info.0.json"
else:
# Get latest comic
url = "https://xkcd.com/info.0.json"
response = requests.get(url, timeout=10)
response.raise_for_status()
comic_data = response.json()
# Format the response nicely
formatted_response = {
"num": comic_data["num"],
"title": comic_data["title"],
"alt": comic_data["alt"],
"img": comic_data["img"],
"year": comic_data["year"],
"month": comic_data["month"],
"day": comic_data["day"],
"transcript": comic_data.get("transcript", ""),
"safe_title": comic_data["safe_title"]
}
return json.dumps(formatted_response, indent=2)
except requests.exceptions.RequestException as e:
return f"Error fetching comic: {str(e)}"
except KeyError as e:
return f"Error parsing comic data: Missing field {str(e)}"
except Exception as e:
return f"Unexpected error: {str(e)}"
def search_xkcd_transcript(search_term: str) -> str:
"""
Search for XKCD comics by searching their transcripts and titles.
Note: This is a simple demonstration - in a real implementation you'd want a proper search index.
Args:
search_term (str): Term to search for in comic transcripts and titles
Returns:
str: JSON string containing matching comics information
"""
try:
# Get latest comic number first
latest_response = requests.get("https://xkcd.com/info.0.json", timeout=10)
latest_response.raise_for_status()
latest_num = latest_response.json()["num"]
matches = []
search_term_lower = search_term.lower()
# Search through comics that are more likely to have transcripts (1-500 range for faster results)
# Recent comics often don't have transcripts, so we search older ones first
max_search_range = min(500, latest_num)
for comic_num in range(1, max_search_range + 1):
try:
url = f"https://xkcd.com/{comic_num}/info.0.json"
response = requests.get(url, timeout=2)
response.raise_for_status()
comic_data = response.json()
# Check if search term is in title, alt text, safe_title, or transcript
if (search_term_lower in comic_data["title"].lower() or
search_term_lower in comic_data["alt"].lower() or
search_term_lower in comic_data.get("safe_title", "").lower() or
search_term_lower in comic_data.get("transcript", "").lower()):
matches.append({
"num": comic_data["num"],
"title": comic_data["title"],
"alt": comic_data["alt"][:100] + "..." if len(comic_data["alt"]) > 100 else comic_data["alt"],
"img": comic_data["img"]
})
# Limit results to prevent long search times
if len(matches) >= 10:
break
except:
continue # Skip comics that can't be fetched
return json.dumps({"search_term": search_term, "matches": matches}, indent=2)
except Exception as e:
return f"Search error: {str(e)}"
# Create Gradio interface
with gr.Blocks(title="XKCD MCP Server") as demo:
gr.Markdown("# XKCD MCP Server")
gr.Markdown("This server provides tools to fetch and search XKCD comics via MCP protocol.")
with gr.Tab("Get Comic"):
comic_input = gr.Textbox(
label="Comic ID",
placeholder="Leave empty for latest comic",
value=""
)
comic_output = gr.Textbox(
label="Comic Data (JSON)",
lines=15
)
comic_btn = gr.Button("Get Comic")
comic_btn.click(get_xkcd_comic, inputs=[comic_input], outputs=[comic_output])
with gr.Tab("Search Comics"):
search_input = gr.Textbox(
label="Search Term",
placeholder="Enter term to search in titles, alt text, and transcripts"
)
search_output = gr.Textbox(
label="Search Results (JSON)",
lines=15
)
search_btn = gr.Button("Search")
search_btn.click(search_xkcd_transcript, inputs=[search_input], outputs=[search_output])
if __name__ == "__main__":
demo.launch(mcp_server=True, share=True) |