seekpeek
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@seekpeeksearch the web for the latest DeepSeek model release and summarize it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
seekpeek
Give your AI agents eyes on the live web — search it, or peek at any page.
seekpeek is a Model Context Protocol server that wraps the
DeepSeek Search & Fetch API (/v1/tools/search, /v1/tools/fetch) into tools any MCP host can call:
Claude Code, Claude Desktop, Cursor, VS Code, Codex, Cline, Windsurf, and the rest.
Why
Most agents are frozen at their training cutoff. DeepSeek's Search API is a good, cheap way to thaw them
out: a self-built index, structured results carrying a relevance rerank score and an authority
rating, a short snippet for humans and a long summary written for models.
seekpeek turns that into tools a model can actually use well, and handles the boring parts:
The boring part | What seekpeek does |
Context blowups | Caps page bodies with a visible |
Random 429s | Client-side rate limiting (the account allows 5 QPS) plus exponential backoff with jitter on |
Cryptic failures |
|
N+1 round trips |
|
Related MCP server: free-web-mcp
Features
🔎
search— web search with the full DeepSeek query syntax (site:,-site:,lang:,after:,before:, phrases, exclusions)📄
fetch— any URL → clean Markdown📚
fetch_many— batch fetching, concurrency-limited, per-URL error reporting🧠 Model-friendly output — Markdown by default, raw JSON on request; prefers the long
summaryover the humansnippet🧭 Guided prompt + resource — a
web-researchprompt and aseekpeek://search-syntaxcheatsheet for hosts that support them🖥️ Two transports —
stdiofor local hosts,streamable-httpfor shared or remote deployments🧰 Also a CLI —
seekpeek search "…",seekpeek fetch <url>,seekpeek doctor
Quick start
You need a DeepSeek API key: https://platform.deepseek.com/api_keys.
1. Add it to your MCP host
Claude Code
claude mcp add seekpeek --env DEEPSEEK_API_KEY=sk-your-key -- uvx seekpeekAny JSON-configured host (Claude Desktop, Cursor, VS Code, Cline, Windsurf, …) — add this to the
mcpServers block:
{
"mcpServers": {
"seekpeek": {
"command": "uvx",
"args": ["seekpeek"],
"env": {
"DEEPSEEK_API_KEY": "sk-your-key"
}
}
}
}Not on PyPI yet? Install straight from Git instead:
{
"mcpServers": {
"seekpeek": {
"command": "uvx",
"args": ["--from", "git+https://github.com/penn0312/seekpeek", "seekpeek"],
"env": { "DEEPSEEK_API_KEY": "sk-your-key" }
}
}
}2. Ask something that needs the web
"Search for the latest DeepSeek model release and summarise what changed."
The model calls seekpeek → search, then fetch (or fetch_many) whichever pages it wants in full.
Remote / HTTP deployment
DEEPSEEK_API_KEY=sk-... seekpeek --transport streamable-http --host 127.0.0.1 --port 8765
# MCP endpoint: http://127.0.0.1:8765/mcpExposed beyond localhost? Put it behind a reverse proxy with authentication — seekpeek itself is unauthenticated and spends your DeepSeek quota.
Tools
search
search(
query: str, # 1-128 chars, supports the operators below
count: int = 10, # 1-50
ori_question: str | None = None, # the user's original question, sharpens intent matching
need_content: bool = False, # also return full page text
localization: str | None = None, # IP address used to prefer localised results
max_content_chars: int = 12000, # per-result body cap, 0 = unlimited
response_format: "markdown" | "json" = "markdown",
) -> strReal output (need_content=true, bodies capped at 200 chars for this sample):
# seekpeek · search
Query: `DeepSeek 模型 site:github.com OR site:huggingface.co lang:zh` — 2 results, bodies capped at 200 chars each
## 1. DeepSeek V4 模型发布
- URL: https://example.com/deepseek-v4
- Relevance: 2.4/3.0 (high-quality) · Authority: 3/4 (authoritative) · Published: 2026-06-01 · Site: Example News
DeepSeek 发布了 V4 模型。此次发布改进了工具调用与长上下文能力,适合 Agent 工作流。
**Page content** (from `https://example.com/deepseek-v4`):
DeepSeek V4 现已正式上线……DeepSeek V4 现已正式上线……DeepSeek V4 现已正式上线……DeepSeek V4 现已正式上线……
… [truncated: 600 more characters]
## 2. Some older thread
- URL: https://forum.example.org/t/123
- Relevance: 0.8/3.0 · Authority: 1/4 · Published: 2024-11-02
A discussion from last year.Every result is ranked. rerank_score ≥ 1.5 is flagged high-quality, authority ≥ 3 is flagged
authoritative, so the model can triage before spending context on a page. The long summary (written
for models) is used when available, snippet only as a fallback.
fetch
fetch(url: str, max_chars: int = 12000, response_format: "markdown" | "json" = "markdown") -> strReturns the page title plus its Markdown body. max_chars=0 disables truncation. Bare hosts are accepted
(example.com/doc), and the URL is validated before it costs you a request.
fetch_many
fetch_many(urls: list[str], max_chars: int = 12000, response_format: … ) -> strUp to 10 URLs, fetched concurrently under the shared rate limiter. One dead link never fails the call:
# seekpeek · fetch_many (1/2 succeeded)
## 1. Example article
- URL: https://example.com/article
# Example article
Article content.
## 2. https://broken.example.com/article
Failed: No usable content for https://broken.example.com/article (404). The page may be unreachable,
blocked by the site, served as an unsupported content type, or contain no extractable Markdown.Prompt & resource
Prompt
web-research— takes atopicand adepth(quick/standard/deep), and returns a research brief that teaches the model the query syntax and when to fetch.Resource
seekpeek://search-syntax— the operator cheatsheet and result-field thresholds as Markdown.
Search syntax
Passed straight through to DeepSeek; combine as many operators as you like in one query.
Operator | Example | Effect |
|
| Restrict to a site. Several: |
|
| Exclude sites |
|
| Exclude pages containing a keyword |
|
| Exclude an exact phrase |
|
| Exact phrase match |
|
| Restrict languages |
|
| Published after a date ( |
|
| Published before a date |
Configuration
Variable | Default | Meaning |
| — | Required. Your DeepSeek API key |
|
| API base URL (proxy or gateway) |
|
| Per-request timeout in seconds |
|
| Retries on |
|
| Client-side search rate limit |
|
| Client-side fetch rate limit |
seekpeek doctor prints the effective configuration and probes the API:
$ seekpeek doctor
seekpeek 0.1.0 — configuration
DEEPSEEK_API_KEY sk-abc…f123
DEEPSEEK_BASE_URL https://api.deepseek.com
SEEKPEEK_TIMEOUT 60s
SEEKPEEK_MAX_RETRIES 2
SEEKPEEK_SEARCH_QPS 5
SEEKPEEK_FETCH_QPS 5
• Probing https://api.deepseek.com/v1/tools/search …
✓ Search works — 1 result billed. Top hit: …CLI
uvx seekpeek # stdio MCP server (what hosts launch)
uvx seekpeek --transport streamable-http # HTTP MCP server on 127.0.0.1:8765/mcp
uvx seekpeek doctor [--offline] # verify key, endpoint and limits
uvx seekpeek search "DeepSeek V4 site:github.com" --count 5 --content
uvx seekpeek search "latest MCP news" --json | jq '.results[].url'
uvx seekpeek fetch https://api-docs.deepseek.com/zh-cn/guides/search
uvx seekpeek fetch example.com/docs api-docs.deepseek.com # several URLs at onceCost & limits
Search and Fetch are billed per successful request (¥5 per 1,000 requests at the time of writing) —
count and need_content do not change the price. Failed calls, empty result sets and timeouts are free.
Both endpoints allow 5 QPS per account, which seekpeek mirrors client-side.
See the official guide for the current numbers.
Development
git clone https://github.com/penn0312/seekpeek && cd seekpeek
uv sync # install runtime + dev dependencies
cp .env.example .env # add your key
uv run seekpeek doctor
uv run pytest -q # 80 tests: unit, wire-protocol and stdio end-to-end
uv run ruff check . && uv run ruff format --check .The test suite spins up a mock DeepSeek endpoint and drives the real server over stdio, so it needs no network and no key. A live smoke test is available on request:
SEEKPEEK_E2E_LIVE=1 uv run pytest -k live # spends one search requestLayout:
src/seekpeek/
├── cli.py # argparse entry point: server, doctor, search, fetch
├── client.py # DeepSeek HTTP client: auth, rate limiting, retries, URL handling
├── config.py # environment-driven Settings
├── errors.py # error types + the human/model-readable `describe()`
├── formatting.py # Markdown / JSON renderers (pure functions)
├── models.py # pydantic response models, FetchOutcome
└── server.py # MCPServer: tools, prompt, resource, instructionsPull requests are welcome — especially new hosts' config snippets, extra search-syntax examples, and translations of the README.
Disclaimer
seekpeek is an independent project and is not affiliated with DeepSeek. It reads public pages through the DeepSeek API, so what you point it at is subject to DeepSeek's terms and to the target site's policies.
License
Available Tools
3 toolsfetchFetch a pageARead-only
Fetch one web page (DeepSeek Fetch API) and return its title plus the full text as Markdown.
Use it on a url returned by search when the summary is not enough, or on any URL the user provides.
Returns an explanatory error when the page is unreachable, blocked, or has no extractable content.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute http(s) URL. A bare host such as `example.com/post` is accepted too. | |
| max_chars | No | Cap on returned characters. 0 disables the cap. | |
| response_format | No | `markdown` for reading, `json` for tooling. | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=true, openWorldHint=true, idempotentHint=false). The description adds value beyond them by disclosing the failure surface: an explanatory error when the page is unreachable, blocked, or has no extractable content, and the shape of a successful return.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, followed by usage and return/error behavior in three short paragraphs with no filler. Slightly more line-broken than needed, but every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only fetch tool with no output schema, the description covers return shape, error behavior, and usage context. It is nearly complete; only a note on truncation interaction with max_chars would close the remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are already documented, including url normalization and max_chars=0 semantics. The description adds nothing about max_chars or response_format, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch one web page') and names the exact return payload ('title plus the full text as Markdown') and the backing API. The word 'one' implicitly separates it from the sibling fetch_many.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete trigger ('use it on a url returned by search when the summary is not enough, or on any URL the user provides'), which is clear when-to-use context tied to the search sibling. It never states when NOT to use it or explicitly contrasts with fetch_many, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_manyFetch several pagesARead-only
Fetch up to 10 web pages in one call and return each as Markdown.
Fetches run concurrently under the account rate limit, and one failing URL never fails the call — the
error is reported in place. Prefer this over several fetch calls when you already know which URLs
you need (for example the top three results of a search).
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | 1-10 absolute http(s) URLs (bare hosts are accepted). | |
| max_chars | No | Per-page cap on returned characters. 0 disables the cap. | |
| response_format | No | `markdown` for reading, `json` for tooling. | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly/openWorld/non-idempotent), it discloses concurrency behavior, that fetches run 'under the account rate limit', and critically that a single failing URL does not fail the call but is 'reported in place'. That partial-failure contract materially changes how an agent should interpret results and cannot be inferred from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core capability and size limits, followed by the failure/rate-limit contract and routing advice, with no filler. The second paragraph opens with a sentence fragment and an awkward mid-sentence line break, which slightly hurts readability but not substance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description covers the return shape (Markdown per page), the failure semantics, batch bounds and when to choose it over siblings. For a simple 3-parameter read-only tool, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents `urls` (1-10 absolute URLs, bare hosts accepted), `max_chars` (0 disables cap) and `response_format`. The description only restates the batch cap and Markdown default, adding no syntax or semantics beyond the structured fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch up to 10 web pages in one call and return each as Markdown'), including the hard batch limit and output format. It is clearly distinguishable from the sibling `fetch` (single) and `search` (discovery) tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to 'prefer this over several `fetch` calls when you already know which URLs you need', naming the alternative and the selecting condition. The parenthetical example (top three search results) makes the intended `search` -> `fetch_many` workflow concrete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchWeb searchARead-only
Search the live web (DeepSeek Search API) and get ranked, structured results.
Each result carries a rerank score (0-3; >=1.5 is high-quality), site authority (0-4; >=3 is highly
authoritative), publication date, a short snippet and a long model-oriented summary. Set
need_content=true to also receive the page text. Supports inline operators: site:, -site:,
"exact phrase", -word, lang:, after:, before:.
Use it for anything after your training cutoff, current events, versions, prices or APIs.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | How many results to return (1-50). | |
| query | Yes | Search query, 1-128 characters. Supports `site:`, `-site:`, `"exact phrase"`, `-word`, `lang:zh,en`, `after:2025-01-01`, `before:2026-06`. | |
| localization | No | IP address used to prefer locally relevant results, e.g. `203.0.113.7`. Leave unset for global results. | |
| need_content | No | Also return each page's full text in `content` (larger output; one billed request either way). | |
| ori_question | No | The user's original question when it differs from `query` — improves intent matching. Max 128 characters. | |
| response_format | No | `markdown` for reading, `json` for programmatic use. | markdown |
| max_content_chars | No | Per-result cap for page bodies when `need_content=true`. 0 disables the cap. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/openWorld/non-idempotent; the description goes well beyond them by explaining the rerank score scale (0-3, >=1.5 high quality), site authority scale (0-4), the presence of both a snippet and a model-oriented summary, and the cost note that need_content produces larger output for the same billed request. That is exactly the kind of operational context an agent needs to interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then the result anatomy, then the usage trigger — a sensible order with no filler sentences. It loses a point for duplicating the operator list and the need_content explanation that already appear verbatim in the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly compensates by describing the returned fields and their scoring scales, and it notes the cost implication of need_content. It stops short of addressing pagination/breadth (count caps at 50) or when to fall back to fetch/fetch_many, leaving a small gap for a 7-parameter open-world tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all seven parameters are already documented in the schema. The description largely repeats what the schema says (operator syntax, need_content behavior), adding no new format or constraint detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Search the live web") plus the API behind it and the shape of the result ("ranked, structured results"). An agent can immediately distinguish this from the fetch/fetch_many siblings, which retrieve known pages rather than discover them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear trigger condition: "anything after your training cutoff, current events, versions, prices or APIs." It does not, however, name the fetch/fetch_many alternatives or state when not to search (e.g., for a known URL), so the routing guidance is contextual but not exclusionary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
fetch - First observed
fetch_many - First observed
search
TDQS
Scored across 3 tools
search (discovery), fetch (single page), and fetch_many (batch page) target clearly separable operations. The only potential overlap—fetch vs fetch_many—is explicitly resolved in the description, which tells the agent to prefer fetch_many when URLs are already known. No realistic misselection risk.
All names are lowercase snake_case verbs, and fetch_many follows the same verb as fetch with a transparent bulk suffix. The pattern is fully predictable across the set.
Three tools is well-scoped for a web search-and-retrieve server: one discovery tool, one single-item retrieval, one batch retrieval. Each tool earns its place with no redundancy or filler.
search + fetch + fetch_many covers the core retrieval lifecycle, including batch retrieval, error handling per URL, and rich result metadata. Minor gaps remain, such as no documented pagination/offset for search or structured extraction beyond Markdown.
Maintenance
Related MCP Connectors
Scrape, crawl and search the web for AI agents via MCP.
Fetch pages as markdown, search web and news, extract structured data. For AI agents.
Live AI-native web search with citations. One tool for every MCP client. Flat per-request pricing.
Web search, fetch, extract, and research for AI agents. Markdown output + AI-synthesized answers.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables AI agents to perform multi-engine web search, fetch web pages, and extract clean Markdown content via MCP, with no API keys required.396 PyPI8MIT
- AlicenseAqualityBmaintenanceEnables AI agents to search the web and fetch webpage content as clean text via MCP, with optional headless rendering for dynamic pages.3MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to perform web research over MCP: search with a real browser, fetch JS-rendered pages, download PDFs and convert them to Markdown, then search and page through large documents using bounded previews so the context window isn't flooded.BSD Zero Clause
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to fetch web pages, extract clean Markdown, save and search versions offline, crawl sites within bounds, and retrieve stable citations through MCP tools.15 npmApache 2.0