Tender MCP — Client Installation
Live at https://tender.datatozen.com/install — share that link directly with teammates.
One-page guide for installing the deployed tender MCP server into
your local Claude environment. After install, your Claude session gains
14 read/write ops tools wired against
tender.datatozen.com.
What you get
| Tool | Effect | Approval? |
|---|---|---|
inventory.list_targets |
list configured target IDs | — |
server.status |
host uptime + load | — |
server.read_file |
read a file (cursor-paged) | — |
server.processes |
top processes | — |
server.disk |
disk usage | — |
server.tail_log |
tail a log file | — |
server.systemctl_status |
systemctl status <unit> |
— |
server.exec_readonly |
argv-allowlisted read-only commands | — |
db.query |
SELECT-only SQL (parser-gated) | — |
db.describe_schema |
dump table schema | — |
db.explain |
EXPLAIN <query> |
— |
echo |
sanity test | — |
server.restart_service |
systemctl restart <unit> |
yes — human approval |
db.apply_migration |
DDL (CREATE/ALTER/DROP) | yes — human approval |
The set of targets (the actual machines and databases the
tools talk to) varies by deployment. Discover them at runtime by calling
inventory.list_targets once you're connected — that's the
source of truth for which target IDs are wired up and which tools each
one exposes.
Step 0 — get the bearer token
Ask your tender admin via an internal secure channel — 1Password, Bitwarden, Signal, or a direct message inside your team's IM. The token is a 63-character string.
Do not request it over public email, group chats, issue trackers, or any channel where the message persists somewhere indexable.
Once you have it, set it in your shell:
export TENDER_TOKEN='<paste the 63-char token here>'Step 1 — install
Option A — Claude Code CLI (recommended)
claude mcp add --transport http --scope user tender \
https://tender.datatozen.com/proxy/mcp \
--header "Authorization: Bearer $TENDER_TOKEN"Verify:
claude mcp list | grep tender
# tender: https://tender.datatozen.com/proxy/mcp (HTTP) - ✓ ConnectedIf you previously had a local tender MCP, remove it first:
claude mcp remove tender -s userOption B — Claude Desktop (Mac)
Edit
~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"tender": {
"url": "https://tender.datatozen.com/proxy/mcp",
"type": "http",
"headers": {
"Authorization": "Bearer <paste-your-token-here>"
}
}
}
}Restart Claude Desktop.
Step 2 — smoke test
Direct HTTP probe (proves token + connectivity):
curl -sS -H "Authorization: Bearer $TENDER_TOKEN" \
-H "Content-Type: application/json" \
-X POST https://tender.datatozen.com/proxy/mcp \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
| python3 -c "import json,sys; print(len(json.load(sys.stdin)['result']['tools']), 'tools')"
# expect: 14 toolsIn Claude (new session), try:
"List the tender targets."
Should invoke mcp__tender__inventory_list_targets and
return whatever the gateway has configured.
Step 3 — try real calls
A good first prompt:
"List the tender targets, then describe the schema of every database target you see."
Then explore from there — once you know the target IDs and the
schemas, you can ask follow-ups like "tail the application log on host
<id>" or "show me the row count of
<table> on <id>". The gateway
discloses what's reachable; ask your admin which sources are intended
for which audiences.
For write tools (server.restart_service,
db.apply_migration), the gateway returns
approval_pending and emits an SSE event on
/events. A human must approve before the action runs.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
tender: … ✗ in claude mcp list |
wrong token / unreachable host | run the curl in Step 2; if curl fails, network; if 401, token |
401 Unauthorized |
token wrong or expired | request a fresh one from admin |
503 Service Unavailable |
gateway side is down | tell admin |
404 / nginx error page |
URL typo, missing /proxy/mcp suffix |
check exact URL
https://tender.datatozen.com/proxy/mcp |
not_found: target_id "X" |
target id doesn't exist on this gateway | call inventory.list_targets to see what's
configured |
validation: … |
tool input failed schema or parser gate | look at message — usually SQL DML on SELECT-only path, or unit name
missing .service suffix |
Security notes
- The token is a credential. Treat it like an SSH key — don't paste it into chat, don't commit to git, don't share over email.
- Token rotation: when the admin rotates the bearer, every client must re-install with the new token. No staggered rotation in current design.
- All tool calls are audited. SHA256 hash chain on the gateway side — tamper-evident. Admin can verify the chain status at any time.
- Write tools require human approval. No control plane can unilaterally restart services or run DDL.
- Read-only tools are still scoped.
server.read_filerejects anything outside the path allowlist (/var/log/,/etc/,/proc/,/sys/,/run/log/,/usr/share/).db.queryrejects anything that isn'tSELECT(parser AST, not regex —WITH … DELETEandEXPLAIN ANALYZE INSERTare caught).