Skip to content

Commit 7a1b65a

Browse files
committed
get config through context and remove dupe create server fn
1 parent a3e79bd commit 7a1b65a

File tree

2 files changed

+33
-103
lines changed

2 files changed

+33
-103
lines changed

.python-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/scrapegraph_mcp/server.py

Lines changed: 33 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@
1414
from typing import Any, Dict, Optional, List, Union
1515

1616
import httpx
17-
import uvicorn
18-
from fastmcp import FastMCP
17+
from fastmcp import FastMCP, Context
1918
from smithery.decorators import smithery
2019
from pydantic import BaseModel, Field
21-
from starlette.middleware.cors import CORSMiddleware
2220

2321

2422
class ScapeGraphClient:
@@ -307,48 +305,16 @@ def close(self) -> None:
307305

308306
# Pydantic configuration schema for Smithery
309307
class ConfigSchema(BaseModel):
310-
api_key: str = Field(description="Your Scrapegraph API key")
308+
api_key: str = Field(..., description="Your Scrapegraph API key")
311309

312310

313311
# Create MCP server
314312
mcp = FastMCP("ScapeGraph API MCP Server")
315313

316-
# Default API key (will be overridden in main or by direct assignment)
317-
default_api_key = os.environ.get("SGAI_API_KEY")
318-
scrapegraph_client = ScapeGraphClient(default_api_key) if default_api_key else None
319-
320-
321-
# Smithery server function with config schema
322-
@smithery.server(config_schema=ConfigSchema)
323-
def create_server(config: Optional[ConfigSchema] = None) -> FastMCP:
324-
"""
325-
Create and return the FastMCP server instance for Smithery deployment.
326-
327-
Args:
328-
config: Configuration object with api_key
329-
330-
Returns:
331-
Configured FastMCP server instance
332-
"""
333-
global scrapegraph_client
334-
335-
# Get API key from config or environment
336-
api_key = None
337-
if config and hasattr(config, 'api_key'):
338-
api_key = config.api_key
339-
else:
340-
api_key = os.environ.get("SGAI_API_KEY")
341-
342-
# Initialize client if API key is available
343-
if api_key:
344-
scrapegraph_client = ScapeGraphClient(api_key)
345-
346-
return mcp
347-
348314

349315
# Add tool for markdownify
350316
@mcp.tool()
351-
def markdownify(website_url: str) -> Dict[str, Any]:
317+
def markdownify(website_url: str, ctx: Context) -> Dict[str, Any]:
352318
"""
353319
Convert a webpage into clean, formatted markdown.
354320
@@ -358,11 +324,9 @@ def markdownify(website_url: str) -> Dict[str, Any]:
358324
Returns:
359325
Dictionary containing the markdown result
360326
"""
361-
if scrapegraph_client is None:
362-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
363-
364327
try:
365-
return scrapegraph_client.markdownify(website_url)
328+
client = ScapeGraphClient(ctx.session_config.api_key)
329+
return client.markdownify(website_url)
366330
except Exception as e:
367331
return {"error": str(e)}
368332

@@ -372,6 +336,7 @@ def markdownify(website_url: str) -> Dict[str, Any]:
372336
def smartscraper(
373337
user_prompt: str,
374338
website_url: str,
339+
ctx: Context,
375340
number_of_scrolls: int = None,
376341
markdown_only: bool = None
377342
) -> Dict[str, Any]:
@@ -387,11 +352,9 @@ def smartscraper(
387352
Returns:
388353
Dictionary containing the extracted data or markdown content
389354
"""
390-
if scrapegraph_client is None:
391-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
392-
393355
try:
394-
return scrapegraph_client.smartscraper(user_prompt, website_url, number_of_scrolls, markdown_only)
356+
client = ScapeGraphClient(ctx.session_config.api_key)
357+
return client.smartscraper(user_prompt, website_url, number_of_scrolls, markdown_only)
395358
except Exception as e:
396359
return {"error": str(e)}
397360

@@ -400,6 +363,7 @@ def smartscraper(
400363
@mcp.tool()
401364
def searchscraper(
402365
user_prompt: str,
366+
ctx: Context,
403367
num_results: int = None,
404368
number_of_scrolls: int = None
405369
) -> Dict[str, Any]:
@@ -414,11 +378,9 @@ def searchscraper(
414378
Returns:
415379
Dictionary containing search results and reference URLs
416380
"""
417-
if scrapegraph_client is None:
418-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
419-
420381
try:
421-
return scrapegraph_client.searchscraper(user_prompt, num_results, number_of_scrolls)
382+
client = ScapeGraphClient(ctx.session_config.api_key)
383+
return client.searchscraper(user_prompt, num_results, number_of_scrolls)
422384
except Exception as e:
423385
return {"error": str(e)}
424386

@@ -427,6 +389,7 @@ def searchscraper(
427389
@mcp.tool()
428390
def smartcrawler_initiate(
429391
url: str,
392+
ctx: Context,
430393
prompt: str = None,
431394
extraction_mode: str = "ai",
432395
depth: int = None,
@@ -451,11 +414,9 @@ def smartcrawler_initiate(
451414
Returns:
452415
Dictionary containing the request ID for async processing
453416
"""
454-
if scrapegraph_client is None:
455-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
456-
457417
try:
458-
return scrapegraph_client.smartcrawler_initiate(
418+
client = ScapeGraphClient(ctx.session_config.api_key)
419+
return client.smartcrawler_initiate(
459420
url=url,
460421
prompt=prompt,
461422
extraction_mode=extraction_mode,
@@ -469,7 +430,7 @@ def smartcrawler_initiate(
469430

470431
# Add tool for fetching SmartCrawler results
471432
@mcp.tool()
472-
def smartcrawler_fetch_results(request_id: str) -> Dict[str, Any]:
433+
def smartcrawler_fetch_results(request_id: str, ctx: Context) -> Dict[str, Any]:
473434
"""
474435
Fetch the results of a SmartCrawler operation.
475436
@@ -480,30 +441,26 @@ def smartcrawler_fetch_results(request_id: str) -> Dict[str, Any]:
480441
Dictionary containing the crawled data (structured extraction or markdown)
481442
and metadata about processed pages
482443
"""
483-
if scrapegraph_client is None:
484-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
485-
486444
try:
487-
return scrapegraph_client.smartcrawler_fetch_results(request_id)
445+
client = ScapeGraphClient(ctx.session_config.api_key)
446+
return client.smartcrawler_fetch_results(request_id)
488447
except Exception as e:
489448
return {"error": str(e)}
490449

491450

492451
# Add tool for basic scrape
493452
@mcp.tool()
494-
def scrape(website_url: str, render_heavy_js: Optional[bool] = None) -> Dict[str, Any]:
453+
def scrape(website_url: str, ctx: Context, render_heavy_js: Optional[bool] = None) -> Dict[str, Any]:
495454
"""
496455
Fetch page content for a URL.
497456
498457
Args:
499458
website_url: URL to scrape
500459
render_heavy_js: Whether to render heavy JS (optional)
501460
"""
502-
if scrapegraph_client is None:
503-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
504-
505461
try:
506-
return scrapegraph_client.scrape(website_url=website_url, render_heavy_js=render_heavy_js)
462+
client = ScapeGraphClient(ctx.session_config.api_key)
463+
return client.scrape(website_url=website_url, render_heavy_js=render_heavy_js)
507464
except httpx.HTTPError as http_err:
508465
return {"error": str(http_err)}
509466
except ValueError as val_err:
@@ -512,18 +469,16 @@ def scrape(website_url: str, render_heavy_js: Optional[bool] = None) -> Dict[str
512469

513470
# Add tool for sitemap extraction
514471
@mcp.tool()
515-
def sitemap(website_url: str) -> Dict[str, Any]:
472+
def sitemap(website_url: str, ctx: Context) -> Dict[str, Any]:
516473
"""
517474
Extract sitemap for a website.
518475
519476
Args:
520477
website_url: Base website URL
521478
"""
522-
if scrapegraph_client is None:
523-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
524-
525479
try:
526-
return scrapegraph_client.sitemap(website_url=website_url)
480+
client = ScapeGraphClient(ctx.session_config.api_key)
481+
return client.sitemap(website_url=website_url)
527482
except httpx.HTTPError as http_err:
528483
return {"error": str(http_err)}
529484
except ValueError as val_err:
@@ -534,6 +489,7 @@ def sitemap(website_url: str) -> Dict[str, Any]:
534489
@mcp.tool()
535490
def agentic_scrapper(
536491
url: str,
492+
ctx: Context,
537493
user_prompt: Optional[str] = None,
538494
output_schema: Optional[Union[str, Dict[str, Any]]] = None,
539495
steps: Optional[Union[str, List[str]]] = None,
@@ -544,9 +500,6 @@ def agentic_scrapper(
544500
"""
545501
Run the Agentic Scraper workflow. Accepts flexible input forms for steps and schema.
546502
"""
547-
if scrapegraph_client is None:
548-
return {"error": "ScapeGraph client not initialized. Please provide an API key."}
549-
550503
# Normalize inputs
551504
normalized_steps: Optional[List[str]] = None
552505
if isinstance(steps, list):
@@ -576,7 +529,8 @@ def agentic_scrapper(
576529
return {"error": f"Invalid JSON for output_schema: {str(e)}"}
577530

578531
try:
579-
return scrapegraph_client.agentic_scrapper(
532+
client = ScapeGraphClient(ctx.session_config.api_key)
533+
return client.agentic_scrapper(
580534
url=url,
581535
user_prompt=user_prompt,
582536
output_schema=normalized_schema,
@@ -593,44 +547,21 @@ def agentic_scrapper(
593547
return {"error": str(val_err)}
594548

595549

596-
# Config schema for Smithery
597-
CONFIG_SCHEMA = {
598-
"type": "object",
599-
"required": ["scrapegraphApiKey"],
600-
"properties": {
601-
"scrapegraphApiKey": {
602-
"type": "string",
603-
"description": "Your Scrapegraph API key"
604-
}
605-
}
606-
}
607-
608-
609-
@smithery.server(config_schema=CONFIG_SCHEMA)
610-
def create_server(config: Optional[Dict[str, Any]] = None) -> FastMCP:
550+
# Smithery server function with Pydantic config schema
551+
@smithery.server(config_schema=ConfigSchema)
552+
def create_server(config: Optional[ConfigSchema] = None) -> FastMCP:
611553
"""
612554
Create and return the FastMCP server instance for Smithery deployment.
555+
556+
The API key is provided via session config in the Context object,
557+
which is passed to each tool at runtime.
613558
614559
Args:
615-
config: Configuration dictionary with optional keys:
616-
- scrapegraphApiKey: API key for ScapeGraph API
560+
config: Configuration object with api_key (passed via Context to tools)
617561
618562
Returns:
619563
Configured FastMCP server instance
620564
"""
621-
global scrapegraph_client
622-
623-
# Get API key from config or environment
624-
api_key = None
625-
if config and "scrapegraphApiKey" in config:
626-
api_key = config["scrapegraphApiKey"]
627-
else:
628-
api_key = os.environ.get("SGAI_API_KEY")
629-
630-
# Initialize client if API key is available
631-
if api_key:
632-
scrapegraph_client = ScapeGraphClient(api_key)
633-
634565
return mcp
635566

636567

0 commit comments

Comments
 (0)