mcp-second-opinion
# mcp-second-opinion
Let your MCP-aware agent consult rival LLMs mid-conversation. One simple MCP server, four providers — OpenAI, Google Gemini, Anthropic, xAI/Grok — unified behind two tools.
## Install
```bash
pip install mcp-second-opinion
```
or with uv:
```bash
uv add mcp-second-opinion
```
## Configure
Set at least one of these environment variables:
| Variable | Provider |
|---|---|
| `OPENAI_API_KEY` | OpenAI |
| `GEMINI_API_KEY` | Google Gemini |
| `ANTHROPIC_API_KEY` | Anthropic |
| `XAI_API_KEY` | xAI/Grok |
Providers without a key set are gracefully disabled — they appear in panel responses with a friendly `error` field rather than crashing the server.
Optional:
| Variable | Default | Purpose |
|---|---|---|
| `MCP_SECOND_OPINION_PROFILE` | `flagship` | `flagship` \| `balanced` \| `cheap` — controls which model each provider uses in `ask_the_panel`. |
| `MCP_SECOND_OPINION_SELF_SKIP` | unset | Provider key to omit from panel (`openai`, `gemini`, `anthropic`, `grok`). Useful when the host is itself one of the panelists. |
| `MCP_SECOND_OPINION_TIMEOUT` | `30` | Per-provider timeout in seconds. |
| `MCP_SECOND_OPINION_MAX_TOKENS` | `2048` | Cap on rival output length. |
## Register with your MCP client
**Claude Desktop / Claude Code** (`mcp_settings.json` or equivalent):
```json
{
"mcpServers": {
"second-opinion": {
"command": "mcp-second-opinion",
"env": {
"OPENAI_API_KEY": "sk-...",
"GEMINI_API_KEY": "...",
"ANTHROPIC_API_KEY": "...",
"XAI_API_KEY": "..."
}
}
}
}
```
## Tools
### `ask_other_model(question, model, context?, system_prompt?)`
Ask one specific rival.
```
question: "is this regex correct? /^[a-z]+$/"
model: "gpt-5" | "gemini-2.5-pro" | "claude-opus-4-7" | "grok-4" | ...
context: optional — code snippets, prior reasoning, files
system_prompt: optional — persona/framing
```
Returns:
```json
{
"answer": "...",
"model": "gpt-5",
"latency_ms": 842,
"tokens": {"input": 47, "output": 92},
"cost_usd": 0.0014
}
```
### `ask_the_panel(question, context?, system_prompt?)`
Fan out to every enabled provider in parallel.
```
question: "what's wrong with this approach?"
context: optional
system_prompt: optional — applied uniformly to all panelists
```
Returns:
```json
{
"responses": {
"openai": {"answer": "...", "model": "gpt-5", "latency_ms": 800, "cost_usd": 0.001, "error": null},
"gemini": {"answer": "...", "model": "gemini-2.5-pro", "latency_ms": 750, "cost_usd": 0.0008, "error": null},
"anthropic": {"answer": null, "model": "claude-opus-4-7", "error": "skipped (self)"},
"grok": {"answer": null, "model": "grok-4", "error": "XAI_API_KEY not set"}
},
"total_cost_usd": 0.0018,
"total_latency_ms": 800
}
```
## How it works
The server is a thin layer over [LiteLLM](https://github.com/BerriAI/litellm), which provides a unified OpenAI-shaped interface to all four providers. Cost calculation comes from LiteLLM's pricing table.
## License
MIT
TDQS
Scored across 2 tools
The two tools have clear boundaries: ask_other_model queries a single rival LLM, while ask_the_panel convenes all enabled LLMs in parallel. There is no meaningful overlap between the two modes.
Both tool names follow a consistent 'ask_<target>' pattern with distinct nouns. This makes the tool set predictable and easy to understand.
Two tools is on the thin side, but it exactly matches the server's stated purpose: get a single second opinion or a panel opinion. Each tool earns its place with no redundancy.
The core use cases of requesting a single rival model or all enabled models are fully covered. A minor gap is the absence of a way to select a specific subset of models, but that may be configuration-level rather than tool-level.