yellop 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yellop-0.1.0/PKG-INFO +7 -0
- yellop-0.1.0/pyproject.toml +12 -0
- yellop-0.1.0/setup.cfg +4 -0
- yellop-0.1.0/src/yellop/__init__.py +3 -0
- yellop-0.1.0/src/yellop/server.py +96 -0
- yellop-0.1.0/src/yellop.egg-info/PKG-INFO +7 -0
- yellop-0.1.0/src/yellop.egg-info/SOURCES.txt +9 -0
- yellop-0.1.0/src/yellop.egg-info/dependency_links.txt +1 -0
- yellop-0.1.0/src/yellop.egg-info/entry_points.txt +2 -0
- yellop-0.1.0/src/yellop.egg-info/requires.txt +2 -0
- yellop-0.1.0/src/yellop.egg-info/top_level.txt +1 -0
yellop-0.1.0/PKG-INFO
ADDED
yellop-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import httpx
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from mcp.server.fastmcp import FastMCP
|
|
5
|
+
|
|
6
|
+
# Create the MCP server
|
|
7
|
+
mcp = FastMCP("Yellow Pages Scraper")
|
|
8
|
+
|
|
9
|
+
# Define the base Outscraper API endpoint for Yellow Pages
|
|
10
|
+
# For standard search it is usually https://api.app.outscraper.com/yellow-pages/search-v3
|
|
11
|
+
OUTSCRAPER_API_URL = "https://api.app.outscraper.com/yellow-pages/search-v3"
|
|
12
|
+
|
|
13
|
+
@mcp.tool()
|
|
14
|
+
async def search_yellow_pages(
|
|
15
|
+
query: List[str],
|
|
16
|
+
location: str = "New York, NY",
|
|
17
|
+
limit: int = 100,
|
|
18
|
+
region: Optional[str] = None,
|
|
19
|
+
enrichment: Optional[List[str]] = None,
|
|
20
|
+
fields: Optional[str] = None,
|
|
21
|
+
outscraper_api_key: Optional[str] = None,
|
|
22
|
+
) -> str:
|
|
23
|
+
"""
|
|
24
|
+
Search Yellow Pages via Outscraper.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
query: Categories to search for (e.g., ["bars", "restaurants"]). Supports up to 1000 categories.
|
|
28
|
+
location: The parameter specifies where to search.
|
|
29
|
+
limit: The limit of items to get from one query.
|
|
30
|
+
region: The country to use for website (e.g., US, UK, CA).
|
|
31
|
+
enrichment: Data enrichments to apply (e.g., ["contacts_n_leads", "company_websites_finder"]).
|
|
32
|
+
Note applying enrichments will increase response time.
|
|
33
|
+
fields: Which fields to include with each item. E.g. "name,phone,website"
|
|
34
|
+
outscraper_api_key: The API key for Outscraper. If not provided here, it will look for the OUTSCRAPER_API_KEY environment variable.
|
|
35
|
+
"""
|
|
36
|
+
api_key = outscraper_api_key or os.environ.get("OUTSCRAPER_API_KEY")
|
|
37
|
+
if not api_key:
|
|
38
|
+
return "Error: Outscraper API key is required. Please provide it via the 'outscraper_api_key' parameter or 'OUTSCRAPER_API_KEY' environment variable."
|
|
39
|
+
|
|
40
|
+
params = []
|
|
41
|
+
|
|
42
|
+
# Add queries (multiple query parameters with the same name 'query')
|
|
43
|
+
for q in query:
|
|
44
|
+
params.append(("query", q))
|
|
45
|
+
|
|
46
|
+
params.append(("location", location))
|
|
47
|
+
params.append(("limit", str(limit)))
|
|
48
|
+
|
|
49
|
+
# We enforce sync behavior because MCP tools should return data back directly
|
|
50
|
+
# (unless the client explicitly handles async Task IDs).
|
|
51
|
+
params.append(("async", "false"))
|
|
52
|
+
|
|
53
|
+
if region:
|
|
54
|
+
params.append(("region", region))
|
|
55
|
+
|
|
56
|
+
if enrichment:
|
|
57
|
+
for e in enrichment:
|
|
58
|
+
params.append(("enrichment", e))
|
|
59
|
+
|
|
60
|
+
if fields:
|
|
61
|
+
params.append(("fields", fields))
|
|
62
|
+
|
|
63
|
+
headers = {
|
|
64
|
+
"X-API-KEY": api_key,
|
|
65
|
+
"Accept": "application/json"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
# Given Outscraper's async results limit when sync is forced, we use a generous timeout
|
|
70
|
+
async with httpx.AsyncClient(timeout=180.0) as client:
|
|
71
|
+
response = await client.get(
|
|
72
|
+
OUTSCRAPER_API_URL,
|
|
73
|
+
params=params,
|
|
74
|
+
headers=headers
|
|
75
|
+
)
|
|
76
|
+
response.raise_for_status()
|
|
77
|
+
data = response.json()
|
|
78
|
+
|
|
79
|
+
# The API usually wraps the results in a 'data' array. We can format it nicely
|
|
80
|
+
import json
|
|
81
|
+
return json.dumps(data, indent=2, ensure_ascii=False)
|
|
82
|
+
|
|
83
|
+
except httpx.HTTPStatusError as e:
|
|
84
|
+
error_msg = f"HTTP Error {e.response.status_code}: {e.response.text}"
|
|
85
|
+
return f"Error executing Yellow Pages search: {error_msg}"
|
|
86
|
+
except Exception as e:
|
|
87
|
+
return f"Error executing Yellow Pages search: {str(e)}"
|
|
88
|
+
|
|
89
|
+
return "Error: Unexpected execution path."
|
|
90
|
+
|
|
91
|
+
def main():
|
|
92
|
+
"""Main entry point for running the server."""
|
|
93
|
+
mcp.run()
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
main()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
src/yellop/__init__.py
|
|
3
|
+
src/yellop/server.py
|
|
4
|
+
src/yellop.egg-info/PKG-INFO
|
|
5
|
+
src/yellop.egg-info/SOURCES.txt
|
|
6
|
+
src/yellop.egg-info/dependency_links.txt
|
|
7
|
+
src/yellop.egg-info/entry_points.txt
|
|
8
|
+
src/yellop.egg-info/requires.txt
|
|
9
|
+
src/yellop.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
yellop
|