tinyfish-search-fetch-mcp
by dummie21
README.md
# TinyFish Search/Fetch MCP Server
A lightweight, stdio-based Model Context Protocol (MCP) server designed to provide search and fetch capabilities through the TinyFish ecosystem.
**Note:** This MCP server provides access exclusively to the TinyFish Free Access API (Search & Fetch).
## Overview
TinyFish Search/Fetch MCP Server is a standalone MCP server that offers web search via the TinyFish Search API and content fetching via the TinyFish Fetch API. It uses stdio transport for seamless integration with MCP-compatible clients such as Claude Desktop, Cursor, Windsurf, or any custom client supporting the stdio protocol.
## Features
- **Search**: Quickly find relevant information using TinyFish search capabilities.
- **Fetch**: Retrieve content from web resources efficiently.
- **Burst Fetch**: Fetch and extract clean content from up to 10 URLs in a single request.
- **Stdio Transport**: Designed for seamless integration with MCP clients (e.g. Claude Desktop, Cursor).
## Available Tools
### `search`
Search the web using TinyFish Search API.
**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Search query. Search operators such as `site:example.com` may be used. |
| `location` | string | No | Country code, e.g. `JP`, `US`, `GB`, `FR`. |
| `language` | string | No | Language code, e.g. `ja`, `en`, `fr`. |
| `max_results` | integer | No | Local truncation count for returned results. Must be positive. |
**Returns:** JSON text containing the TinyFish search response.
### `fetch_content`
Fetch and extract clean content from a single URL using TinyFish Fetch API.
**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `url` | string | Yes | URL to fetch. Must use `http` or `https` scheme. |
| `format` | string | No | Output format: `markdown` (default), `html`, or `json`. |
| `links` | boolean | No | Include extracted page links when supported. Default: `false`. |
| `image_links` | boolean | No | Include extracted image links when supported. Default: `false`. |
**Returns:** JSON text containing the TinyFish fetch response.
### `fetch_contents`
Fetch and extract clean content from up to 10 URLs using TinyFish Fetch API.
**Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `urls` | string[] | Yes | Non-empty list of URLs to fetch. Maximum 10. Each must use `http` or `https` scheme. |
| `format` | string | No | Output format: `markdown` (default), `html`, or `json`. |
| `links` | boolean | No | Include extracted page links when supported. Default: `false`. |
| `image_links` | boolean | No | Include extracted image links when supported. Default: `false`. |
**Returns:** JSON text containing the TinyFish fetch response.
## Tool Schemas
### search
```json
{
"name": "search",
"parameters": {
"type": "object",
"additionalProperties": false,
"properties": {
"query": {
"type": "string",
"description": "Search query. Search operators such as site:example.com may be used."
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional country code, e.g. JP, US, GB, FR."
},
"language": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional language code, e.g. ja, en, fr."
},
"max_results": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"minimum": 1,
"description": "Optional local truncation count for returned results."
}
},
"required": ["query"]
}
}
```
### fetch_content
```json
{
"name": "fetch_content",
"parameters": {
"type": "object",
"additionalProperties": false,
"properties": {
"url": {
"type": "string",
"description": "URL to fetch. Must be http or https."
},
"format": {
"type": "string",
"enum": ["markdown", "html", "json"],
"default": "markdown",
"description": "Output format: markdown, html, or json."
},
"links": {
"type": "boolean",
"default": false,
"description": "Include extracted page links when supported."
},
"image_links": {
"type": "boolean",
"default": false,
"description": "Include extracted image links when supported."
}
},
"required": ["url"]
}
}
```
### fetch_contents
```json
{
"name": "fetch_contents",
"parameters": {
"type": "object",
"additionalProperties": false,
"properties": {
"urls": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 10,
"description": "URLs to fetch. Maximum 10. Each must be http or https."
},
"format": {
"type": "string",
"enum": ["markdown", "html", "json"],
"default": "markdown",
"description": "Output format: markdown, html, or json."
},
"links": {
"type": "boolean",
"default": false,
"description": "Include extracted page links when supported."
},
"image_links": {
"type": "boolean",
"default": false,
"description": "Include extracted image links when supported."
}
},
"required": ["urls"]
}
}
```
## Comparison with the Official Integration
While TinyFish provides an official MCP integration using OAuth 2.1 for secure authentication (which requires a browser-based flow for initial setup), this implementation uses a **single TinyFish API Key**. This makes it better suited for:
- **Headless Environments**: Ideal for servers or environments where no web browser is available.
- **Free Access**: Optimized specifically for usage with the TinyFish Free Access API.
[Learn more about the official integration here.](https://docs.tinyfish.ai/mcp-integration)
## Prerequisites
- Python >= 3.11
- An MCP-compatible client
## Installation
### Using `uv` (Recommended)
For a clean installation as a standalone tool with isolated dependencies, use [uv](https://github.com/astral-sh/uv):
```bash
uv tool install .
```
### Using `pip`
If you are already working in a virtual environment:
```bash
pip install .
```
## Usage
Before running the server, set your TinyFish API Key as an environment variable.
**Linux / macOS (bash, zsh):**
```bash
export TINYFISH_API_KEY="<your tinyfish api key>"
```
**Windows PowerShell:**
```powershell
$env:TINYFISH_API_KEY="<your tinyfish api key>"
```
API keys are obtained by logging in at [https://agent.tinyfish.ai/](https://agent.tinyfish.ai/). Once your API key is set, the server can be invoked via its command-line entry point:
```bash
tinyfish-search-fetch-mcp
```
You can optionally provide a Python logging configuration file. JSON files are loaded with `logging.config.dictConfig`; other extensions are loaded with `logging.config.fileConfig`. Ensure custom handlers write to stderr, not stdout, because stdout is reserved for MCP JSON-RPC messages.
```bash
tinyfish-search-fetch-mcp --log-config ./logging.json
```
## Integration with Claude Desktop
To use this server with Claude Desktop, add the following to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"tinyfish-search-fetch": {
"command": "tinyfish-search-fetch-mcp",
"env": {
"TINYFISH_API_KEY": "<your tinyfish api key>"
}
}
}
}
```
*Note: If you have already defined `TINYFISH_API_KEY` in your shell environment (e.g. via `~/.bashrc`, `~/.zshrc`), the `"env"` block above is optional and can be omitted.*
*If you installed via pip in a virtual environment, ensure the command points to the correct executable path.*
## Troubleshooting
### Empty search query error
If you see an error such as `valueerror: query must not be empty`, ensure the `query` parameter contains non-whitespace characters. Leading or trailing whitespace is automatically trimmed.
### Invalid fetch format error
If you see an error such as `valueerror: format must be one of: html, json, markdown`, set `format` to `markdown`, `html`, or `json`.
### Invalid URL scheme error
If you see an error such as `valueerror: url scheme must be http or https`, ensure the `url` parameter uses either `http://` or `https://` as the scheme.
### Unsupported URL
If you see an error such as `valueerror: url must include a host`, the provided URL does not contain a valid hostname. Provide a full URL including domain (e.g. `https://example.com`).
### Stdio fallback mode
In environments where FastMCP's default stdio wrapper hangs, set `TINYFISH_MCP_THREAD_STDIO=1` to use the thread-based stdio fallback. This fallback is also selected automatically when `CODEX_SANDBOX_NETWORK_DISABLED` is truthy.
### Logging privacy
The server logs search queries and fetch URLs to stderr by default. Avoid putting secrets in queries or URLs, or provide a custom `--log-config` that adjusts the log level or redacts messages.
## Development
### Local Installation
Clone and install this server in editable mode:
**With pip:**
```bash
git clone <repository-url>
cd tinyfish-search-fetch-mcp
pip install -e ".[dev]"
```
**With uv:**
```bash
git clone <repository-url>
cd tinyfish-search-fetch-mcp
uv pip install -e ".[dev]"
```
### Running Tests
This project uses `pytest`. To run the test suite:
```bash
pip install -e ".[dev]"
python -m pytest
```
With uv, sync the default development dependency group first:
```bash
uv sync
uv run python -m pytest
```
Live tests exercise the real TinyFish Search/Fetch APIs. They require both network access and `TINYFISH_API_KEY`.
- If `TINYFISH_API_KEY` is not set, live tests are skipped.
- If `CODEX_SANDBOX_NETWORK_DISABLED=1`, live tests are skipped because outbound network access is unavailable.
- With network access and an API key, the live tests call all three MCP tools and cover parameter variants such as `location`, `language`, `max_results`, `format`, `links`, and `image_links`.
### Coding Standards
Dependencies are intentionally version-bounded in `pyproject.toml` to reduce breakage from FastMCP and TinyFish SDK changes. The uv `dev` dependency group is included by default so `uv run python -m pytest` has pytest available; use `uv run --no-dev ...` for runtime-only checks. If you change dependency bounds or dependency groups, update `uv.lock` as well.
Use `ruff` for linting:
```bash
python -m ruff check src tests
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
TDQS
A3.5/5.0
Scored across 3 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: single URL fetch, batch fetch, and web search. The names and descriptions unambiguously differentiate them.
Naming Consistency4/5
Two tools follow the verb_noun snake_case pattern ('fetch_content', 'fetch_contents'), while 'search' is a single verb. The pattern is mostly consistent and predictable.
Tool Count4/5
Three tools is a small but reasonable set for a search and fetch service. It covers the core operations without being too minimal or excessive.
Completeness4/5
The set covers the main use cases: fetching a single URL, fetching multiple URLs, and searching. Minor gaps like metadata retrieval are absent but not critical for basic functionality.
Maintenance
ActivitySlowing
ResponsivenessNo issues