# OpenSEO MCP MCP Server

> **OpenSEO MCP MCP Server** is a hosted, multitenant Model Context Protocol (MCP) server run by **MewCP** (https://mewcp.com), giving AI agents managed access to OpenSEO MCP.
>
> MewCP takes care of all MCP infrastructure for you — credential storage, OAuth flows,
> token refresh, and production-grade auto-scaling — so your AI agents can connect to
> third-party services and run freely without you managing any MCP server yourself.
>
> Server page:  https://mewcp.com/mcp/openseo-mcp
> MewCP docs:   https://docs.mewcp.com
> Full catalog: https://mewcp.com/llms.txt

---

## About

OpenSEO provides an all-in-one SEO research and optimization toolkit, enabling AI agents to research keywords, analyze competitors, inspect backlinks, audit websites, track search rankings, discover local SEO opportunities, and analyze Google Search Console and Analytics data.

---

## Details

- Server ID: `openseo-mcp`
- Version: 0.0.12
- Tools: 81
- Authentication: OAuth, managed by MewCP
- Transport: http

---

## Access

The gateway URL below serves your **entire MewCP toolset**, not this server on its
own. Pasting a config snippet is not enough — OpenSEO MCP has to be in the toolset
first. In order:

1. Add OpenSEO MCP to your toolset at https://mewcp.com/mcp/openseo-mcp
2. Connect your OpenSEO MCP account (OAuth); MewCP stores the credential and attaches it to each call
3. Copy your MewCP API key from the dashboard (Developer)
4. Configure your client with the snippet for it below

Once connected, an agent does **not** see this server's tools as top-level tools.
It sees four meta-tools and reaches everything through them:

- `search(query)` — find tools by keyword across the toolset
- `get_schema(tools)` — full description and arguments for the tools you picked
- `list_accounts(provider)` — only when one app has several connected accounts
- `call_tool(server_maskedId, tool_name, args)` — execute

So the list below is what `search` can return for this server, not a set of
callable tool names on their own.

---

## Tools (81)

Descriptions are truncated to 160 characters; call `get_schema`
for the full text and the argument schema. Where a tool is annotated, its type
is shown — treat `destructive` as irreversible.

- `whoami` _(write)_ — Confirms the connected OpenSEO account, server mode, token scopes, and current credit balance when the user asks to check their account or connection.…
- `list_projects` _(read)_ — Lists the user's projects. Uses no credits — does not call DataForSEO. Use this whenever you need a `projectId` for another OpenSEO tool. Returns an array of…
- `create_project` _(write)_ — Create a new project in the user's organization. Uses no credits — does not call DataForSEO. Provide a name, and optionally a domain and default market…
- `research_project_website` _(write)_ — Fill missing project basics, business competitors, and Prompt Research topics using saved context and verified website pages. Each field is independent: reuse…
- `save_project_website_setup` _(destructive)_ — Fill missing website domain, business overview, and competitors after the user confirms setup. Existing project values and competitor lists are authoritative…
- `get_project_context` _(read)_ — Reads a project's shared memory: business overview, current goal, positioning, writing preferences, custom sections, competitors, key pages, and the recent…
- `update_project_context` _(destructive)_ — Adds, edits, or deletes a project's shared memory so the app, SAM, and other agents see it. Uses no credits. Use the current project context to find the…
- `list_saved_keywords` _(read)_ — Lists keywords saved to a project (with cached metrics like search volume, difficulty, CPC, and tags if available). Uses no credits — reads from OpenSEO's…
- `remove_saved_keywords` _(destructive)_ — Permanently deletes keywords from a project's saved-keywords list by their row ID. Uses no credits — does not call DataForSEO. Missing, foreign-project, and…
- `research_keywords` _(write)_ — Research keyword data (search volume, difficulty, CPC, related ideas) for 1-5 seed keywords in one call. Charges credits per seed (~54 at the default result…
- `save_keywords` _(destructive)_ — Save keywords to a project's saved-keywords list. Uses no credits — does not call DataForSEO. Idempotent: re-saving an existing keyword is a no-op. If tags are…
- `get_domain_overview` _(write)_ — Returns a high-level view of a domain's organic footprint: estimated organic traffic, organic keyword count, backlinks, and referring domains. Use this first…
- `get_domain_keyword_suggestions` _(write)_ — Returns the organic keywords a domain ranks for, including position and available metrics. Use after get_domain_overview when you want the detailed keyword…
- `get_backlinks_overview` _(write)_ — Returns a backlinks profile summary (total backlinks, referring domains, top referring domains). Charges credits (~50 typical for a domain, ~25 for a single…
- `get_backlinks_profile` _(write)_ — Returns one bounded page of detailed backlink rows for a domain or page: linking URLs, target URLs, anchors, dofollow/nofollow, authority/spam signals, and…
- `get_serp_results` _(write)_ — Fetch live Google organic search results for 1-10 keywords. Use this to inspect who ranks for a query, verify competitors, compare SERPs across keywords, or…
- `search_serp_locations` _(read)_ — Find the exact DataForSEO location name of a city, county, or region. Returns up to 50 matches; pass the chosen `locationName` verbatim to create_rank_tracker…
- `get_ai_visibility_tracker` _(read)_ — Read AI tracking setup, topics, exact prompts, the project-context brand and competitors that answers are matched against, engine/country capabilities, and…
- `explore_prompt` _(write)_ — Ask one prompt in ChatGPT, or compare answers from selected AI models. Returns answer text, citations, search queries, brand mentions, and per-model errors.…
- `generate_ai_visibility_prompts` _(write)_ — Generate editable topic and prompt suggestions from shared Project context. Uses existing usage credits for one model call. Supply topic to add unique prompts…
- `research_ai_visibility_prompts` _(read)_ — Find questions about a keyword with ChatGPT's answers to them (DataForSEO has US English data only). The questions come from DataForSEO's question database,…
- `complete_ai_research_setup` _(write)_ — Set up Prompt Research keywords for a project with a saved website. Before starting missing setup, get the user's approval for paid research and any new…
- `save_ai_visibility_tracker` _(write)_ — Bulk create or patch AI tracking prompts, their topics, engines, country, and language. Pause or archive a topic by pausing or archiving each of its prompts.…
- `estimate_ai_visibility_cost` _(read)_ — Estimate one scheduled check, one-off check, and the monthly cost of a daily, weekly, or monthly schedule without collecting answers. Optional patch estimates…
- `set_ai_visibility_schedule` _(write)_ — Enable daily, weekly, or monthly AI tracking, change the cadence or run time, or pause future checks. Enabling spends credits on every check; show the user the…
- `run_ai_visibility_check` _(write)_ — Start an explicitly approved one-off paid AI check, preserving the schedule. It collects live answers, so results arrive within minutes. maxCostUsd is the…
- `get_ai_visibility_run` _(read)_ — Read AI run progress: completed, failed, and pending answer counts, and the recommended next poll interval. Uses no collection credits and does not submit,…
- `get_ai_visibility_results` _(read)_ — For a normal review make one run-wide call with these top-level arguments (there is no filters object): runId null (or a manual run's runId), topic null,…
- `get_ai_visibility_answer` _(read)_ — Read one retained exact prompt and answer, where each brand is mentioned, and the pages the answer cites, with the requested collection market. Truncation is…
- `get_ai_visibility_sources` _(read)_ — For a normal review make one run-wide call using the result runId and these top-level arguments (there is no filters object): topic null, engines null,…
- `get_ai_visibility_trend` _(read)_ — Answer whether AI visibility is improving or declining. Compares the latest N days with the N days before, using neutral prompts from finished runs, including…
- `export_ai_visibility_data` _(read)_ — Create a private project-authorized CSV or JSON download of retained AI visibility observations in the requested scope. Returns an expiring link, not a large…
- `create_rank_tracker` _(write)_ — Create a rank tracking configuration for a project. Creating an empty tracker uses no credits and starts no check, but daily, weekly, and monthly trackers will…
- `get_rank_tracker` _(read)_ — Read-only access to rank tracker configs and their latest results. With `trackerId`, returns config + a page of latest snapshots (pinned keywords first),…
- `add_rank_tracking_keywords` _(write)_ — Add keywords to an existing rank tracker. It also fetches search volume, difficulty and CPC for the tracker's keywords, which uses credits like…
- `remove_rank_tracking_keywords` _(destructive)_ — Stop tracking keywords by their trackingKeywordId. Uses no credits and preserves historical snapshots. Missing, stale, foreign, and repeated IDs are ignored;…
- `pin_rank_tracking_keywords` _(write)_ — Pin or unpin tracked keywords by their trackingKeywordId. Pinned keywords stay at the top of the tracker's keyword table for everyone in the project, and…
- `estimate_rank_tracker_cost` _(read)_ — Estimate rank tracker cost without spending credits or starting a check. Each estimate is the most a check can cost: it includes up to two queued retries of…
- `run_rank_tracker` _(write)_ — Start an explicit live rank check for every keyword and configured device. This spends credits: call estimate_rank_tracker_cost, show the estimate to the user,…
- `get_ranked_keywords` _(write)_ — Returns market-specific keyword, URL, rank, search volume, CPC, intent, and traffic rows for a domain or page. Accepts country-level DataForSEO Labs…
- `find_serp_competitors` _(write)_ — Compares domains competing in Google results for a supplied keyword set in a country-level DataForSEO Labs market. Accepts location/language codes; not…
- `search_local_businesses` _(write)_ — Searches local business listings near a coordinate, with optional rating, review-count, and claimed-status filters. Use this to discover businesses you cannot…
- `get_local_serp_results` _(write)_ — Fetches one Google Maps or Local Finder SERP near a coordinate. Returns trimmed provider rows (identity, rank, rating, categories, hours) with rank fields…
- `get_google_business_questions` _(write)_ — Fetches Google Business Profile questions and answers for one business (by businessName, cid, or placeId) near a coordinate. Run this only when Q&A evidence is…
- `get_business_profile` _(write)_ — Reads one Google Business Profile by name, cid, or placeId: categories, rating and review count, rating breakdown, address, phone, website, claimed status,…
- `get_business_reviews` _(write)_ — Collects Google reviews for a business, with rating, author, text, and the owner's reply. Use it for review-gap analysis against competitors and to spot…
- `get_business_updates` _(write)_ — Collects the posts (updates, offers, events) published on a Google Business Profile. Use it to check posting activity and recency on your profile or a…
- `list_business_categories` _(read)_ — Lists the Google Business categories DataForSEO recognizes, ranked by how many businesses use them. Use it to find valid category slugs for…
- `get_local_rank_grid` _(write)_ — Runs one Google Maps search per point of a square grid around a coordinate and reports where the target business ranks at each point — plus each point's result…
- `get_keyword_metrics` _(write)_ — Hydrate up to 700 known keywords with search volume, keyword difficulty (KD), search intent, CPC, competition, and monthly trends in a single call. Use it to…
- `list_search_console_sites` _(read)_ — Lists the Search Console properties visible to each Google account the calling user has connected in the OpenSEO dashboard, and flags the one bound to the…
- `set_search_console_site` _(write)_ — Binds a project to a verified Search Console property through a Google account the user already connected in the OpenSEO dashboard (gscAccountId from…
- `get_search_console_performance` _(read)_ — Query the connected Search Console property's Search Analytics: clicks, impressions, CTR, and average position by query/page/country/device/date. First-party…
- `inspect_urls` _(read)_ — Read Google Search Console's existing index status for up to 10 URLs of the connected property: index/coverage state, last crawl time, Google-selected vs…
- `submit_indexnow_urls` _(write)_ — Tells Bing, Yandex, Seznam, Naver, Yep and other IndexNow search engines that pages on the project's website changed, so they recrawl them sooner. Google does…
- `list_google_analytics_properties` _(read)_ — Lists the GA4 properties visible to each Google account the calling user has connected in the OpenSEO dashboard, and flags the one bound to the project. Use it…
- `set_google_analytics_property` _(write)_ — Binds a project to a GA4 property through a Google account the user already connected in the OpenSEO dashboard (ga4AccountId from…
- `get_google_analytics_organic_landing_pages` _(read)_ — Read organic-search landing page sessions, engagement, key events, transactions, and revenue from the project's connected GA4 property. Defaults to the last 28…
- `get_google_analytics_page_performance` _(read)_ — Read page views, users, engagement duration, and key events from the connected GA4 property. Organic Search is the default; set channel to all to include every…
- `get_google_analytics_key_events` _(read)_ — Read active GA4 key events with counts and users by event or organic landing page. Previous-period comparison is available for the event breakdown. Reads only…
- `get_search_opportunities` _(read)_ — Join Search Console pages ranking in positions 4–20 with GA4 organic landing-page outcomes, then score matched opportunities by demand, business value, and…
- `get_google_analytics_organic_overview` _(read)_ — Answer whether organic traffic is improving with top-line sessions, users, engagement, key events, transactions, revenue, an equal-length previous-period…
- `get_google_analytics_traffic_acquisition` _(read)_ — Compare session acquisition by channel group, source/medium, or campaign, including sessions, users, engagement, key events, transactions, and revenue.…
- `get_google_analytics_measurement_health` _(read)_ — Diagnose the connected property's data streams, web measurement IDs, enhanced-measurement settings, key events, and custom definitions. Reads only the GA4…
- `get_google_analytics_ecommerce_performance` _(read)_ — Read item views, add-to-cart units, purchases, and item revenue by item, or transactions and purchase revenue by landing page. Returns a detected, none, or…
- `get_google_analytics_site_search` _(read)_ — Read measured internal search terms with search events, users, sessions, engaged sessions, and engagement rate. Requires GA4 site-search measurement. Reads…
- `get_google_analytics_audience_breakdown` _(read)_ — Read device, country, or new-versus-returning users, sessions, engagement, and key events. Previous-period comparison is available for device and…
- `run_site_audit` _(write)_ — Start a site audit: crawls the site (robots.txt-aware, same-origin), checks every page for SEO issues (broken links, duplicate/missing titles and descriptions,…
- `list_site_audits` _(read)_ — Lists this project's site audits with IDs, URLs, status, page counts, and dates, newest first. Uses no credits. Use this to find an older audit to read or…
- `delete_site_audit` _(destructive)_ — Permanently deletes one site audit and its crawled pages, issues, and Lighthouse results, freeing audit capacity. Uses the same workflow-stop and cleanup…
- `get_audit_status` _(write)_ — Check the progress of a site audit (phase, pages crawled, Lighthouse progress). Free — reads OpenSEO state and may reconcile a dead workflow by marking its…
- `get_audit_issues` _(read)_ — Read the prioritized issue report from a completed site audit. Every issue carries a how_to_fix with concrete remediation steps an agent can act on. Free —…
- `get_audit_pages` _(read)_ — List crawled pages from a site audit with per-page SEO data (status, title, description, word count, indexability, crawl depth, link counts). Free — reads…
- `save_report` _(destructive)_ — Saves a finished HTML report to this project, where anyone in the workspace can read and print it. Uses no credits. New reports are private; replacing a report…
- `list_reports` _(read)_ — Lists this project's saved reports, newest update first: id, title, skill, who saved it, when, and a short summary preview. Uses no credits. Call this before…
- `get_report` _(read)_ — Reads one saved report: title, skill, attribution, size, the full summary, and shareUrl (null when private or public sharing is unavailable on this…
- `set_report_sharing` _(destructive)_ — Enables or revokes public sharing for one saved report. Uses no credits. New reports are private. Only enable sharing when the user explicitly asks for it in…
- `delete_report` _(destructive)_ — Permanently deletes one saved report and makes its shared link unavailable. Uses no credits. Call list_reports to find the exact reportId. Does not delete site…
- `list_report_templates` _(read)_ — Lists this project's report templates. Uses no credits. A template is a reusable brief — audience, sections in order, tone, sign-off — that replaces a skill's…
- `save_report_template` _(destructive)_ — Saves a reusable report brief to this project. Uses no credits. Only do this when the user asks for a template, or agrees to one — a one-off report needs no…
- `delete_report_template` _(destructive)_ — Permanently deletes one reusable report template from this project. Uses no credits. Call list_report_templates to find its templateId. Existing saved reports…

---

## Connect

Gateway URL: https://gateway.mewcp.com/personal/mcp

Every request carries one header:

    Authorization: Bearer <API_KEY>

Replace `API_KEY` with your own key from the dashboard (Developer).

## Apps

### Claude Desktop

Mac & Windows app

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "mewcp": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote@latest",
        "https://gateway.mewcp.com/personal/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer API_KEY"
      }
    }
  }
}
```

Already have an "mcpServers" section in your config? Just add the server entry inside it.

1. Open Claude Desktop → Settings → Developer → "Edit Config"
2. Paste the snippet inside the outer { } of the config file (merge with your existing "mcpServers" section if you have one)
3. Save the file, then quit Claude Desktop completely and reopen it
4. Start a new conversation — your tool will be available

### VS Code

Copilot / Cline

- Command Palette → "MCP: Open User Configuration" (opens mcp.json). For one project only, use .vscode/mcp.json instead.

```json
{
  "mcp.servers": {
    "mewcp": {
      "type": "http",
      "url": "https://gateway.mewcp.com/personal/mcp",
      "headers": {
        "Authorization": "Bearer API_KEY"
      }
    }
  }
}
```

Already have a "servers" section in your mcp.json? Just add the server entry inside it.

1. Open VS Code → Command Palette (Cmd+Shift+P / Ctrl+Shift+P)
2. Run "MCP: Open User Configuration" to open your mcp.json
3. Paste the snippet and save
4. Start the server when prompted (or from the MCP servers view) and use it in Copilot Chat

### Cursor

AI-first editor

- macOS: `~/.cursor/mcp.json`
- Windows: `%USERPROFILE%\.cursor\mcp.json`

```json
{
  "mcpServers": {
    "mewcp": {
      "url": "https://gateway.mewcp.com/personal/mcp",
      "headers": {
        "Authorization": "Bearer API_KEY"
      }
    }
  }
}
```

Already have an "mcpServers" section in your mcp.json? Just add the server entry inside it.

1. Open Cursor → Settings → Cursor Settings → MCP
2. Click "Add new global MCP server"
3. Paste the snippet and save
4. Restart Cursor

### Codex

OpenAI's CLI agent

- Add the snippet to your Codex MCP config or your standard MCP config file for the CLI tool you use.

```json
{
  "mcpServers": {
    "mewcp": {
      "type": "http",
      "url": "https://gateway.mewcp.com/personal/mcp",
      "headers": {
        "Authorization": "Bearer API_KEY"
      }
    }
  }
}
```

Codex generally reads a standard MCP server block, so you can add this alongside your other configured servers.

1. Open your Codex MCP config or project-level config file
2. Paste the MewCP server block inside the config JSON/TOML structure your tool expects
3. Save the file and restart Codex
4. Verify the tool is available inside a fresh session

### Claude Code

Anthropic's CLI agent

- ~/.claude.json (user scope) or .mcp.json in your project root — create it if it doesn't exist. Or skip the file and use the CLI command below.

```json
{
  "mcpServers": {
    "mewcp": {
      "type": "http",
      "url": "https://gateway.mewcp.com/personal/mcp",
      "headers": {
        "Authorization": "Bearer API_KEY"
      }
    }
  }
}
```

Already have an "mcpServers" section in your config? Just add the server entry inside it.

1. Open ~/.claude.json (or .mcp.json in your project root) in a text editor
2. Paste the snippet inside the outer { } (merge with your existing "mcpServers" section if you have one)
3. Save the file and start (or restart) Claude Code
4. Or skip the file entirely and run the CLI command below instead

### OpenCode

Open-source terminal agent

- ~/.config/opencode/opencode.json (global) or opencode.json in your project root — create it if it doesn't exist.

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mewcp": {
      "type": "remote",
      "url": "https://gateway.mewcp.com/personal/mcp",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer API_KEY"
      }
    }
  }
}
```

Already have an "mcp" section in your opencode.json? Just add the server entry inside it.

1. Open ~/.config/opencode/opencode.json (or opencode.json in your project root) in a text editor
2. Paste the snippet inside the outer { } (merge with your existing "mcp" section if you have one)
3. Save the file and start (or restart) OpenCode

### OpenClaw

Self-hosted agent gateway

- ~/.openclaw/openclaw.json — create it if it doesn't exist.

```json
{
  "mcp": {
    "servers": {
      "mewcp": {
        "transport": "streamable-http",
        "url": "https://gateway.mewcp.com/personal/mcp",
        "enabled": true,
        "headers": {
          "Authorization": "Bearer API_KEY"
        }
      }
    }
  }
}
```

Already have an "mcp" section in your openclaw.json? Just add the server entry inside "servers".

1. Open ~/.openclaw/openclaw.json in a text editor
2. Paste the snippet inside the outer { } (merge with your existing "mcp" section if you have one)
3. Save the file and restart OpenClaw

### Antigravity

Google's agentic IDE

- ~/.gemini/config/mcp_config.json (global) or .agents/mcp_config.json (workspace-local) — create it if it doesn't exist.

```json
{
  "mcpServers": {
    "mewcp": {
      "serverUrl": "https://gateway.mewcp.com/personal/mcp",
      "headers": {
        "Authorization": "Bearer API_KEY"
      }
    }
  }
}
```

Already have an "mcpServers" section in your config? Just add the server entry inside it. Remote servers must use the "serverUrl" field — the legacy "url"/"httpUrl" fields aren't supported.

1. In the editor's agent side panel, click "…" → "MCP Servers" → "Manage MCP Servers" → "View raw config" (Antigravity CLI: type /mcp instead to open the Interactive MCP Manager)
2. Paste the snippet inside the outer { } (merge with your existing "mcpServers" section if you have one)
3. Save the file — the server connects automatically

### Hermes

Nous Research's CLI agent

- config.yaml in your Hermes config directory (~/.hermes) — add this under a top-level "mcp_servers:" key.

```yaml
mcp_servers:
  mewcp:
    url: "https://gateway.mewcp.com/personal/mcp"
    headers:
      Authorization: "Bearer API_KEY"
```

Already have an "mcp_servers" section in your config.yaml? Just add the server entry inside it.

1. Open config.yaml in your Hermes config directory
2. Paste the snippet under the top-level "mcp_servers:" key (merge with existing entries if you have any)
3. Save the file, then run /reload-mcp in Hermes (or start a fresh session)
4. Ask Hermes "Tell me which MCP-backed tools are available right now" to confirm it connected

### DeepSeek Harness

DeepSeek's agent harness

- cordis.yml in your DSH project — or the patch file you mount plugins from.

```yaml
- id: mcp-mewcp
  name: '@deepseek-ai/dsh-mcp-client'
  config:
    serverName: mewcp
    transport: streamable-http
    url: https://gateway.mewcp.com/personal/mcp
    headers:
      Authorization: "Bearer API_KEY"
```

One plugin instance = one MCP server. Add this entry to your plugin list; don't nest it inside another entry.

1. Open cordis.yml (or your patch file) in your DSH project
2. Paste the entry into your plugin list, keeping the leading dash and indentation
3. Restart DSH (or let HMR reload) — tools register as mcp__mewcp__<tool_name>
4. Verify with: dsh web --dump-config | grep -A3 mcp

## SDKs

### Python

fastmcp client

```python
import asyncio
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

SERVER_URL = "https://gateway.mewcp.com/personal/mcp"
API_KEY = "API_KEY"

transport = StreamableHttpTransport(
    url=SERVER_URL,
    headers={
        "Authorization": f"Bearer {API_KEY}",
    }
)

async def main():
    client = Client(transport)
    async with client:
        tools = await client.list_tools()
        print(tools)

asyncio.run(main())
```

1. Install fastmcp: pip install fastmcp
2. Copy the snippet into your project
3. Replace API_KEY with your key from the dashboard
4. Run your script

### TypeScript

MCP SDK

```typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const SERVER_URL = "https://gateway.mewcp.com/personal/mcp";
const API_KEY = "API_KEY";

const transport = new StreamableHTTPClientTransport(new URL(SERVER_URL), {
  requestInit: {
    headers: {
      Authorization: `Bearer ${API_KEY}`,
    },
  },
});

const client = new Client({ name: "mewcp-client", version: "1.0.0" });
await client.connect(transport);

const tools = await client.listTools();
console.log(tools.tools.map((t) => t.name));
```

1. Install: npm install @modelcontextprotocol/sdk
2. Copy the snippet into your project
3. Replace API_KEY with your key from the dashboard
4. Run with Node 18+ as an ES module (e.g. npx tsx script.ts)