A high-performance, asynchronous MCP server for Serper Google Search, featuring connection pooling, request retries, and intelligent input parsing.
Project description
Serper MCP Toolkit
A rebuilt Serper MCP server based on the firecrawl-toolkit architecture.
Highlights
- Unified async request layer (
httpx+ connection pooling + retries) - Compact JSON responses (single-line) for lower token usage
- Stable mapped response schemas (no upstream raw passthrough)
- Multi-page aggregation for non-image search endpoints (10 results/page granularity)
- Image search
search_numnormalization to10or100 - Multi-transport startup (
STDIO/HTTP/SSE, mutually exclusive) - Process lock to prevent duplicate server instances
Tools
serper-aggregated-searchserper-general-searchserper-image-searchserper-video-searchserper-place-searchserper-maps-searchserper-reviews-searchserper-news-searchserper-lens-searchserper-scholar-searchserper-shopping-searchserper-patents-searchserper-scrape
Core Parameter Rules
- Search tools do not expose
page; internal pagination is automatic. - Non-image endpoints:
search_numis clamped to1..100- then rounded up to nearest multiple of 10 (
25 -> 30)
- Image endpoint:
1..10 -> 10,11..100 -> 100
- Maps endpoint:
- when aggregation requires page > 1 and query mode is used,
llis required.
- when aggregation requires page > 1 and query mode is used,
Environment Variables
API and network
SERPER_API_KEYSERPER_HTTP2(0/1)SERPER_MAX_CONNECTIONSSERPER_KEEPALIVESERPER_MAX_CONCURRENT_REQUESTSSERPER_MAX_WORKERSSERPER_RETRY_COUNTSERPER_RETRY_BASE_DELAYSERPER_ENDPOINT_CONCURRENCY(JSON, e.g.{"search":10,"scrape":2})SERPER_ENDPOINT_RETRYABLE(JSON, e.g.{"scrape":false})
Transport selection (exactly one must be enabled)
SERPER_MCP_ENABLE_STDIOSERPER_MCP_ENABLE_HTTPSERPER_MCP_ENABLE_SSE
Transport host/port
SERPER_MCP_HTTP_HOSTSERPER_MCP_HTTP_PORTSERPER_MCP_SSE_HOSTSERPER_MCP_SSE_PORTSERPER_MCP_HOST(fallback)SERPER_MCP_PORT(fallback)
Lock file
SERPER_MCP_LOCK_FILE(default/tmp/serper_mcp.lockon Unix)
MCP Client Example
Use uvx to run the Python MCP server. uvx creates an isolated environment and installs package dependencies automatically:
{
"mcpServers": {
"serper-toolkit": {
"command": "uvx",
"args": ["serper-toolkit"],
"env": {
"SERPER_API_KEY": "<your-serper-api-key>",
"SERPER_MCP_ENABLE_STDIO": "1"
}
}
}
}
Go CLI
The Go CLI is located in the cli directory. It is a standalone command-line client named serper, separate from the Python MCP server.
The CLI reads the API key only from SERPER_KEY:
export SERPER_KEY="<your-serper-api-key>"
Build From Source
Build for the current platform:
cd cli
go test ./...
go build -o serper .
Run it directly after building:
./serper --help
Build all release targets locally:
cd cli
mkdir -p dist
for target in windows/amd64 windows/arm64 linux/amd64 linux/arm64 darwin/amd64 darwin/arm64; do
GOOS=${target%/*}
GOARCH=${target#*/}
binary=serper
package="serper_${GOOS}_${GOARCH}.tar.gz"
if [ "$GOOS" = windows ]; then
binary=serper.exe
package="serper_${GOOS}_${GOARCH}.zip"
fi
build_dir="build/${GOOS}_${GOARCH}"
mkdir -p "$build_dir"
CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH go build -trimpath -ldflags="-s -w" -o "$build_dir/$binary" .
if [ "$GOOS" = windows ]; then
(cd "$build_dir" && zip -q "../../dist/$package" "$binary")
else
tar -C "$build_dir" -czf "dist/$package" "$binary"
fi
(cd dist && sha256sum "$package" > "$package.sha256")
done
(cd dist && find . -maxdepth 1 -type f ! -name '*.sha256' ! -name 'SHA256SUMS' -printf '%f\n' | sort | xargs sha256sum > SHA256SUMS)
CLI Commands
The CLI exposes the same 13 tool surfaces as subcommands:
serper aggregated --query "AI news" --search-num 20 --country US --language en --search-time day --timeout 120
serper general --query "AI news" --search-num 10 --country US --language en --search-time week
serper image --query "serper logo" --search-num 10
serper video --query "web scraping tutorial" --search-num 10
serper place --query "coffee" --location "Berlin,Germany"
serper maps --query "coffee" --ll "@52.5200,13.4050,14z" --search-num 20
serper reviews --cid "<google-cid>" --search-num 10 --sort-by newest
serper news --query "OpenAI" --search-time day
serper lens --image-url "https://example.com/image.jpg"
serper scholar --query "large language models"
serper shopping --query "mechanical keyboard"
serper patents --query "battery management"
serper scrape --output example --url "https://www.example.com"
Search-style commands output compact single-line JSON with the Python toolkit schema:
{"success":true,"meta":{"requested_search_num":10,"effective_search_num":10,"pages_fetched":1,"result_count":1,"credits":1},"data":{"organic":[]},"credits":1}
CLI Search Parameters
Shared search parameters:
--query(required foraggregated,general,image,video,place,maps,news,scholar,shopping,patents): Search keywords.--search-num(optional): Number of results, range1-100. Defaults to20foraggregated, and10for other search subcommands.--country(optional): Country name or ISO code. Default isUSwhere the Serper endpoint supports country targeting.--language(optional): Language code, such asen.--search-time(optional): One ofhour,day,week,month,year. Supported byaggregated,general,image,video, andnews.--timeout(optional): Request timeout in seconds. Must be> 0. Default is120.
Subcommand-specific parameters:
place:--locationis optional.maps:--ll,--place-id, and--cidare optional. When query-mode maps aggregation fetches more than one page,--llis required.reviews: at least one of--fid,--cid, or--place-idis required.--sort-byis optional.lens:--image-urlis required.
Normalization follows the Python toolkit:
- Non-image endpoints clamp
--search-numto1-100, then round up to the nearest multiple of10. - Image search uses
10for requests1-10, and100for requests11-100. - Search tools do not expose a
pageparameter; pagination is automatic.
CLI Scrape Usage
Scrape a page and save the markdown export as example.md in the current directory:
serper scrape --output example --url "https://www.example.com" --timeout 120
Save the markdown export to a specific directory:
serper scrape --output example --path ./exports --url "https://www.example.com"
Scrape command parameters:
--output(required): Export name. The CLI writes<output>.md.--path(optional): Directory where the markdown export is saved. Supports absolute and relative paths. Defaults to the current directory. If the directory does not exist, the CLI tries to create it before scraping.--url(required): Target URL to scrape.--include-markdown(optional): Request markdown content. Default istrue.--timeout(optional): Request timeout in seconds. Must be> 0. Default is120.
Scrape output:
- On success, stdout is
true, and the CLI writes<output>.md. - On failure, stdout is
falsefollowed by the error reason, and no file is created or overwritten.
The generated markdown file uses this structure:
## title:
## description:
## url:
## credits:
---
markdown content
CI/CD
Two GitHub Actions workflows are included:
-
CI(.github/workflows/ci.yml)- Trigger: push/PR on
mainanddev, plus manualworkflow_dispatch - Python matrix:
3.12,3.13 - Steps: alias validation, unit tests, build, twine check
- Go CLI: tests, six-platform builds, and upload to the
LatestGitHub Release on push/manual runs
- Trigger: push/PR on
-
Publish to PyPI(.github/workflows/publish-pypi.yml)- Trigger: push on
main(automatic), plus manualworkflow_dispatch - Preflight: alias validation, tests, build, twine check, version-not-on-PyPI check
- Publish: trusted publishing via OIDC to PyPI
- Trigger: push on
Required repository settings
- Create GitHub Environment:
pypi - Configure PyPI Trusted Publisher for this repo/workflow/branch:
- Workflow file:
.github/workflows/publish-pypi.yml - Branch:
main
- Workflow file:
- Ensure Actions permissions allow OIDC (
id-token: writein workflow is already set)
Development Validation
python3 scripts/validate_country_aliases.py
python3 -m unittest discover -s tests -p "test_*.py"
python3 -m build
python3 -m twine check dist/*
License
GNU General Public License v3.0 or later (GPL-3.0-or-later).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file serper_toolkit-0.0.14.tar.gz.
File metadata
- Download URL: serper_toolkit-0.0.14.tar.gz
- Upload date:
- Size: 27.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7848339e8e09bd2a57880bbd795a6611113b9c067f96d4e4cffe5c42ddec6b6d
|
|
| MD5 |
beb3949ce02c8cda9c922354e5b6fc78
|
|
| BLAKE2b-256 |
cc9b6595d1c71e23bfb029630b7828b56e9e1a92bcd30c3e0fa227911ccdaa38
|
Provenance
The following attestation bundles were made for serper_toolkit-0.0.14.tar.gz:
Publisher:
publish-pypi.yml on Joey-Kot/serper-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
serper_toolkit-0.0.14.tar.gz -
Subject digest:
7848339e8e09bd2a57880bbd795a6611113b9c067f96d4e4cffe5c42ddec6b6d - Sigstore transparency entry: 1908403615
- Sigstore integration time:
-
Permalink:
Joey-Kot/serper-toolkit@3d13a7933e830efcbedcf2e410734ee25d4b6560 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Joey-Kot
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@3d13a7933e830efcbedcf2e410734ee25d4b6560 -
Trigger Event:
push
-
Statement type:
File details
Details for the file serper_toolkit-0.0.14-py3-none-any.whl.
File metadata
- Download URL: serper_toolkit-0.0.14-py3-none-any.whl
- Upload date:
- Size: 23.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b9e5f9c03e5ad711aa67105451fc9fe082614c0950573c8d06c4f744ab24d63
|
|
| MD5 |
e0abd15db20446cd8e283d99789d2655
|
|
| BLAKE2b-256 |
fe0db84a255167a7389502b6db8311b0c735611aad4e3f70436bae71e784d091
|
Provenance
The following attestation bundles were made for serper_toolkit-0.0.14-py3-none-any.whl:
Publisher:
publish-pypi.yml on Joey-Kot/serper-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
serper_toolkit-0.0.14-py3-none-any.whl -
Subject digest:
9b9e5f9c03e5ad711aa67105451fc9fe082614c0950573c8d06c4f744ab24d63 - Sigstore transparency entry: 1908403798
- Sigstore integration time:
-
Permalink:
Joey-Kot/serper-toolkit@3d13a7933e830efcbedcf2e410734ee25d4b6560 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Joey-Kot
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@3d13a7933e830efcbedcf2e410734ee25d4b6560 -
Trigger Event:
push
-
Statement type: