outmate-gtm-router
# Outmate — Intelligent GTM Router for Claude Code
*By Outmate*
A Claude Code plugin that exposes two read-only GTM research tools over MCP:
- **`tavily_search`** — discover relevant web pages using Tavily Search.
- **`jina_read_url`** — retrieve the readable content of a known public URL using Jina Reader.
Claude Code supplies the LLM and decides which MCP tool to invoke. The MCP server only validates arguments and executes the selected provider request; it has no LLM client of its own.
## Architecture
```text
User's natural-language request
|
v
Claude Code (LLM)
chooses the appropriate MCP tool
|
v
Outmate MCP server
(local stdio process)
/ \
v v
Tavily Search Jina Reader
\ /
v v
Structured results to Claude
```
The plugin is deliberately local/stdio for Claude Code. Each user runs the MCP process locally and stores their own Tavily/Jina credentials in Claude Code plugin secure configuration. This is not yet a remotely hosted, multi-tenant MCP service. A hosted SaaS deployment should use Streamable HTTP, authentication, per-customer credential storage, and tenant isolation as a separate deployment target.
## Requirements
- Claude Code v2.1.281 or later (plugin-declared MCP servers require this minimum; run `claude --version`).
- Node.js 20.18 or later.
- npm.
- Tavily API key.
- Jina API key.
## Setup
1. Install the plugin through `/plugin` or a marketplace. Claude Code will prompt for the two API keys because the manifest declares them as sensitive `userConfig` values. You can also run `/plugin configure outmate-gtm-router@<marketplace>`.
2. For local development, you can instead copy `.env.example` to `.env` in this plugin directory and add your keys. `.env` takes no precedence over environment variables passed by Claude Code.
3. Install dependencies and compile:
```bash
npm install
npm run build
```
Include the generated `dist/` directory in the plugin release. Generate and commit `package-lock.json` before publishing to a marketplace. Claude Code installs Node dependencies automatically for marketplace-cached plugins when `package.json` and a supported npm lockfile are present. For a local directory install, run `npm install` and `npm run build` first.
4. Validate the Claude Code plugin:
```bash
claude plugin validate .
```
5. Start Claude Code with this plugin loaded:
```bash
claude --plugin-dir /absolute/path/to/outmate-gtm-router
```
Alternatively, load it from the Plugin Manager or a marketplace after packaging/distribution is configured.
6. Inside Claude Code, run `/mcp` and confirm the `outmate-gtm-router` server is connected. If you have changed plugin files in an existing session, run `/reload-plugins`.
## Example requests
- "Research the latest funding news about Acme."
- "Find the official pricing page for HubSpot and read it."
- "Read https://example.com/pricing and summarize the plans."
- "Compare the product positioning on these two public URLs: [URL A] and [URL B]."
Claude should use `tavily_search` to discover pages and `jina_read_url` to inspect selected pages in detail. Claude performs the reasoning and orchestration; the MCP server does not make a second LLM call.
## Tool reference
### `tavily_search`
Arguments:
- `query` (required): focused search query, 2–500 characters.
- `maxResults` (optional): 1–10, default 5.
- `searchDepth` (optional): `basic` or `advanced`, default `basic`.
- `topic` (optional): `general`, `news`, or `finance`, default `general`.
- `timeRange` (optional): `day`, `week`, `month`, or `year`.
- `includeDomains` / `excludeDomains` (optional): up to 10 domains.
### `jina_read_url`
Arguments:
- `url` (required): one public HTTP/HTTPS URL.
The server rejects local/private and reserved host patterns, URLs containing credentials, and nonstandard ports. It also resolves ordinary hostnames locally and rejects private/reserved DNS answers. This is defense in depth, not a substitute for a hardened URL-fetching proxy: Jina independently resolves and fetches the hostname, so DNS rebinding between checks cannot be eliminated by this client.
## Security and operational behaviour
- Provider keys are passed to the local MCP process from Claude Code's sensitive plugin configuration (or loaded from a local `.env` for development). They are never exposed as tool arguments or returned to Claude.
- `.env` is git-ignored. Never commit provider keys.
- MCP protocol messages use stdout. Application logs go to stderr only.
- Requests have a timeout, one bounded retry on transient network/429/5xx errors, and a 16 MB provider-response size limit. Returned page text is separately truncated to the configured MCP output limit.
- Search and page-read tools are marked read-only and idempotent.
- Webpage content is untrusted input. Claude's skill instructs the model not to follow instructions embedded in retrieved pages.
- Errors identify the provider and failure class without logging credentials or raw response headers.
## Development
```bash
npm run dev
npm test
npm run build
```
To inspect the server independently of Claude Code, after building run:
```bash
npx @modelcontextprotocol/inspector node dist/index.js
```
## Distribution
For a small internal test, share this plugin directory or a zip of it. Each recipient configures their own Tavily and Jina keys in the plugin configuration (or a local `.env` during development). The shared release must include `dist/` and `package-lock.json`; do not include `.env` or `node_modules/`.
For a team marketplace, place this plugin under a marketplace repository's `plugins/` directory and create a `.claude-plugin/marketplace.json` in the marketplace repository root. Do not put marketplace.json inside this plugin's `.claude-plugin/` directory.
## Current limitations
- Two tools only: web search and public webpage reading.
- No CRM integrations, write actions, OAuth user connections, billing, or multi-tenant account storage.
- No automatic provider fallback: Tavily performs search; Jina reads a selected URL. They are complementary capabilities, not interchangeable providers.
- No server-side LLM dependency; Claude Code owns all reasoning and orchestration.
- The local plugin runs on the same machine/environment as Claude Code. A remote Streamable HTTP service is a separate deployment step.
TDQS
Scored across 2 tools
The two tools have clearly separate roles: tavily_search discovers web sources, while jina_read_url extracts content from a known URL. The descriptions explicitly cross-reference each other and warn against using one in place of the other, leaving no meaningful ambiguity.
Both names use lowercase snake_case with a vendor prefix and an action-oriented second component. The pattern is mostly predictable, though jina_read_url includes an object ('url') while tavily_search does not, a minor inconsistency.
Two tools is thin for a server named as a GTM router, even though the search-and-read pair is coherent. It is functional but borderline under-scoped for broader go-to-market research workflows.
The pair covers the core web-research lifecycle: discover relevant sources and then read a specific page. Minor gaps remain, such as batch reading or structured extraction, but no critical dead end is apparent for the stated purpose.