Skip to main content
Glama
baanish

@baanish/synthetic-search-mcp

by baanish

@baanish/synthetic-search-mcp

A minimal Model Context Protocol server that exposes Synthetic web search over stdio.

It provides two MCP tools:

  • search: run a web search against Synthetic and return a small set of results with url, title, published, and a truncated page-text snippet.

  • search_quota: check the remaining hourly search quota (limit, requests, remaining, and reset time) so an agent can stay within budget.

The server is designed for local MCP clients such as Claude Code, Codex CLI, Cursor, and VS Code.

Features

  • Two focused tools: search and search_quota

  • Fresh web results from Synthetic's /v2/search API

  • Quota visibility via Synthetic's /v2/quotas (search is capped per hour)

  • Clear 429 rate-limit errors, including Retry-After when provided

  • Truncates extracted page text to about 2000 characters per result

  • Repairs malformed control characters when JSON.parse fails, instead of giving up

  • Bounded requests: a 30s timeout and a 10 MB response cap prevent hangs

  • Drops results whose URL is not http(s):

  • Reads credentials from SYNTHETIC_API_KEY

  • Speaks the stateless 2026-07-28 MCP protocol revision while still serving 2025-era clients from the same server factory

  • Runs over stdio for local MCP integrations

Related MCP server: web-mcp-server

Protocol support

The server speaks both MCP protocol eras from one factory:

  • 2026-07-28 (stateless): a modern client's opening request is served statelessly — no initialize handshake, no Mcp-Session-Id, with the protocol version, client identity, and client capabilities carried in the per-request _meta envelope. The server implements the spec-required server/discover RPC, so clients can probe it up front. Protocol state travels on the request itself, so no server-side session state is required: if you wrap createServer in an HTTP entry (createMcpHandler), each request can be answered by a fresh instance from the factory behind a plain load balancer.

  • 2025-era (legacy): a client that opens with the legacy initialize handshake is pinned to a 2025-era instance built from the same factory and served exactly as a hand-wired stdio server would be, so existing hosts (Claude Code, Cursor, VS Code, Codex CLI) keep working unchanged.

The stdio entry picks the era once per connection, from how the client opens, and pins one instance from the factory for the connection's lifetime — a property of the one-process-per-client stdio deployment, not of the protocol. No configuration is required.

Requirements

  • Node.js 20+

  • A Synthetic API key in SYNTHETIC_API_KEY

Installation

Use npx:

npx -y @baanish/synthetic-search-mcp

Or install globally:

npm install -g @baanish/synthetic-search-mcp
synthetic-search-mcp

MCP Client Setup

The server command is:

{
  "command": "npx",
  "args": ["-y", "@baanish/synthetic-search-mcp"],
  "env": {
    "SYNTHETIC_API_KEY": "your_api_key_here"
  }
}

Claude Code

Add a project-level .mcp.json file:

{
  "mcpServers": {
    "synthetic-search": {
      "command": "npx",
      "args": ["-y", "@baanish/synthetic-search-mcp"],
      "env": {
        "SYNTHETIC_API_KEY": "your_api_key_here"
      }
    }
  }
}

Codex CLI

Add this to ~/.codex/config.toml:

[mcp_servers.synthetic-search]
command = "npx"
args = ["-y", "@baanish/synthetic-search-mcp"]
env = { SYNTHETIC_API_KEY = "your_api_key_here" }

Cursor

Add this to .cursor/mcp.json in your project or the equivalent Cursor MCP settings file:

{
  "mcpServers": {
    "synthetic-search": {
      "command": "npx",
      "args": ["-y", "@baanish/synthetic-search-mcp"],
      "env": {
        "SYNTHETIC_API_KEY": "your_api_key_here"
      }
    }
  }
}

VS Code / GitHub Copilot

Add this to .vscode/mcp.json:

{
  "servers": {
    "synthetic-search": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@baanish/synthetic-search-mcp"],
      "env": {
        "SYNTHETIC_API_KEY": "your_api_key_here"
      }
    }
  }
}

Tool

Search the public web through Synthetic.

Input:

{
  "query": "latest model context protocol news"
}

Output:

[
  {
    "url": "https://example.com/article",
    "title": "Example result",
    "text": "Truncated extracted page text...",
    "published": "2026-03-12T10:15:00.000Z"
  }
]

Notes:

  • Synthetic only supports a single query parameter.

  • Result text is truncated to keep MCP context manageable.

  • published may be null when the source does not provide a date.

search_quota

Report the remaining Synthetic search quota. Takes no input.

Output:

{
  "hourly": {
    "limit": 250,
    "requests": 32,
    "remaining": 218,
    "renewsAt": "2026-06-26T21:00:00.000Z"
  },
  "subscription": {
    "limit": 750,
    "requests": 10,
    "remaining": 740,
    "renewsAt": "2026-07-01T00:00:00.000Z"
  }
}

Notes:

  • Search is rate-limited per hour; hourly reflects the current window.

  • remaining is derived as limit - requests (clamped at 0).

  • A window is null if Synthetic does not report it.

  • Checking the quota does not count against your search limit.

Development

npm install
npm run build

Run locally:

SYNTHETIC_API_KEY=your_api_key_here npm run dev

Testing

npm run typecheck   # tsc --noEmit over src + tests
npm test            # vitest: unit, integration (both MCP protocol eras), and fuzz tests

The suite includes an opt-in live smoke test that calls the real Synthetic API. It runs only when SYNTHETIC_API_KEY is available (copy .env.example to .env and add your key) and is skipped automatically otherwise — including in CI.

Security

Credential redaction

Upstream API error bodies are redacted of the active API key and bearer-token-like material before they are returned over stdio. This prevents a hostile or misconfigured upstream from reflecting the SYNTHETIC_API_KEY back through MCP tool output.

Transitive dependency advisories

The runtime MCP dependency is the v2 SDK package @modelcontextprotocol/server, whose tree is just @modelcontextprotocol/core and zod — it pulls in no HTTP web-middleware packages. The npm overrides this repo previously carried (for hono, @hono/node-server, path-to-regexp, fast-uri, ip-address, and qs, all pulled in transitively by the v1 @modelcontextprotocol/sdk) are therefore removed, and none of those advisories appear in this repository's dependency tree anymore.

Remaining local advisory:

  • esbuild (dev-only, via tsx): affects the esbuild development server on Windows only; not used at runtime and not published in the npm tarball.

License

MIT

Available Tools

2 tools
search_quotaA
Read-only

Check how much Synthetic web search quota remains. Search is capped per hour; this returns the hourly search limit, requests used so far, remaining requests, and when the window resets (plus the subscription-period quota). Use it to decide whether you still have search budget before calling search. Checking the quota does not itself count against the limit.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already signals a safe read operation, and the description adds meaningful behavioral context beyond that: the check does not consume the quota and returns a reset time plus subscription-period quota. This is more transparency than a bare read-only declaration would provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the core purpose, and every sentence adds value. There is no repetition of schema or annotation content, and the structure flows logically from what the tool returns to when to use it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by listing the key return fields (hourly limit, requests used, remaining, reset, subscription quota) and the non-counting behavior. For a simple, zero-parameter tool, this is fully sufficient context for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and an empty schema, so there is nothing to document. The baseline of 4 for a no-parameter tool is appropriate, and the description handles usage entirely without needing parameter detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'Check' and names the 'Synthetic web search quota' resource, clearly distinguishing this from the sibling `search` tool. It also enumerates the exact data returned (limit, used, remaining, reset), leaving no ambiguity about the tool's function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool: 'Use it to decide whether you still have search budget before calling `search`.' This directly ties usage to the sibling tool and gives a clear decision-making context. It also notes that checking quota does not count against the limit, which is practical guidance.

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.

  1. 2 tool updatesv2.0.0
    • First observedsearch
    • First observedsearch_quota

TDQS

A4.4/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have completely distinct purposes: one performs web searches, the other checks quota usage. There is no overlap or ambiguity in their roles.

Naming Consistency5/5

Both tools follow a clean verb_noun pattern: 'search' and 'search_quota' are consistent and clearly derive from the same domain, maintaining a predictable structure.

Tool Count3/5

With only two tools, the server is below the typical 3-15 range. However, for a simple search-focused MCP server, the minimal set is justifiable, though it still feels slightly thin.

Completeness4/5

The core search functionality is covered, and the quota tool supports operational awareness. A minor gap is the lack of advanced search options like pagination or filters, but the server appears intentionally simple and whole for its stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers