Spaces:
Sleeping
Sleeping
File size: 4,935 Bytes
0a4b4e5 f77befc 8ae67db bfad4de 3c1606d 8ae67db ded9789 e9525f9 8a5fe3d 0f28047 8a5fe3d 0a4b4e5 5d20b78 e9525f9 2a710fe 10adf53 2a710fe 10adf53 e9525f9 90365b1 2a710fe 10adf53 2a710fe 10adf53 90365b1 ded9789 090b8ec ded9789 e9525f9 090b8ec ded9789 10adf53 064e5aa 10adf53 ded9789 064e5aa ded9789 10adf53 ded9789 10adf53 ded9789 e9525f9 ded9789 10adf53 ded9789 e80edff ded9789 f77befc ded9789 3c1606d 0a4b4e5 467f662 4ba0c26 e80edff 90365b1 4ba0c26 f77befc 3c1606d e9525f9 f77befc 0a4b4e5 bfad4de |
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 |
import gradio as gr
from fastmcp import FastMCP
import logging
import requests
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
mcp = FastMCP("Jobicy Remote Jobs Agent")
# Remaining filter options
COMPANY_INDUSTRIES = [
("", ""),
("Business Development", "business"),
("Content & Editorial", "copywriting"),
("Creative & Design", "design-multimedia"),
("Customer Success", "supporting"),
("Data Science & Analytics", "data-science"),
("DevOps & Infrastructure", "admin"),
("Finance & Accounting", "accounting-finance"),
("HR & Recruiting", "hr"),
("Legal & Compliance", "legal"),
("Marketing & Sales", "marketing"),
("Product & Operations", "management"),
("Programming", "dev"),
("Sales", "seller"),
("SEO", "seo"),
("Social Media Marketing", "smm"),
("Software Engineering", "engineering"),
("Technical Support", "technical-support"),
("Web & App Design", "web-app-design"),
]
COUNTRY_CHOICES = [
"", "APAC", "EMEA", "LATAM", "Argentina", "Australia", "Austria", "Belgium", "Brazil", "Bulgaria",
"Canada", "China", "Costa Rica", "Croatia", "Cyprus", "Czechia", "Denmark", "Estonia", "Europe",
"Finland", "France", "Germany", "Greece", "Hungary", "Ireland", "Israel", "Italy", "Japan",
"Latvia", "Lithuania", "Mexico", "Netherlands", "New Zealand", "Norway", "Philippines", "Poland",
"Portugal", "Romania", "Singapore", "Slovakia", "Slovenia", "South Korea", "Spain", "Sweden",
"Switzerland", "Thailand", "Türkiye", "UAE", "UK", "USA", "Vietnam"
]
@mcp.tool(name="search_jobs")
def search_jobs_tool(industry: str = "", country: str = "", keyword: str = "", limit: int = 20) -> dict:
"""
Search remote jobs via Jobicy API, supports filters.
Args:
industry (str): Company industry filter.
country (str): Region filter (e.g., usa, canada, ...).
keyword (str): Free-form keyword tag.
limit (int): Number of results (1–50).
Returns:
dict: {"jobs": [...]} or {"error": "..." }
"""
base = "https://jobicy.com/api/v2/remote-jobs"
params = {"count": max(1, min(limit, 50))}
if industry:
params["industry"] = industry.lower().replace(" & ", "-").replace(" ", "-")
if country and country.lower() != "anywhere":
params["geo"] = country.lower()
if keyword:
params["tag"] = keyword.strip()
logger.info(f"Requesting Jobicy API with params: {params}")
try:
resp = requests.get(base, params=params, headers={"User-Agent": "Mozilla/5.0"}, timeout=10)
resp.raise_for_status()
jobs_raw = resp.json().get("jobs", [])
except Exception as e:
return {"error": f"Fetch error: {e}"}
def fmt(j):
posted = j.get("pubDate", "")[:10]
sal_min = j.get("annualSalaryMin")
sal_max = j.get("annualSalaryMax")
cur = j.get("salaryCurrency", "")
salary = f"{sal_min}–{sal_max} {cur}".strip() if sal_min or sal_max else "Not specified"
return {
"title": j.get("jobTitle", "No Title"),
"company": j.get("companyName", ""),
"location": j.get("jobGeo", ""),
"url": j.get("url", "#"),
"pubDate": posted,
"salary": salary
}
sorted_jobs = sorted(jobs_raw, key=lambda x: x.get("pubDate", ""), reverse=True)[:params["count"]]
return {"jobs": [fmt(j) for j in sorted_jobs]}
def search_jobs_ui(industry, country, keyword, limit):
res = search_jobs_tool(industry=industry, country=country, keyword=keyword, limit=limit)
if "error" in res:
return f"❌ {res['error']}"
if not res["jobs"]:
return "No jobs found with these filters."
md = "# Remote Jobs Results\n\n"
for i, j in enumerate(res["jobs"], 1):
md += (
f"### {i}. {j['title']}\n\n"
f"**Company:** {j['company']}\n\n"
f"**Location:** {j['location']}\n\n"
f"**Salary:** {j['salary']}\n\n"
f"**Posted On:** {j['pubDate']}\n\n"
f"[Apply Here]({j['url']})\n\n---\n\n"
)
return md
app = gr.Interface(
fn=search_jobs_ui,
inputs=[
gr.Dropdown(label="Company Industry (optional) (Empty = All)", choices=COMPANY_INDUSTRIES, value=""),
gr.Dropdown(label="Country / Region (optional) (Empty = Anywhere)", choices=COUNTRY_CHOICES, value=""),
gr.Textbox(label="Keyword / Tag (optional)", placeholder="e.g., python, data, web"),
gr.Slider(minimum=1, maximum=50, value=20, step=1, label="Number of Results"),
],
outputs=gr.Markdown(),
title="Jobicy Remote Job Search",
description="Search remote jobs by industry, region, and keyword. Results sorted by most recent.",
theme="huggingface"
)
if __name__ == "__main__":
app.launch(mcp_server=True)
|