Skip to main content
Glama

Generate SSH config

generate_ssh_config
Idempotent

Generate SSH config Host blocks for tailnet nodes, preferring MagicDNS names with IP fallback. Preview output by default, then optionally write to a dedicated file or managed config section.

Instructions

Generate ssh-config Host blocks for tailnet nodes (MagicDNS name preferred, Tailscale IP fallback). Dry-run by default: returns the generated config text only and writes nothing. With write=true it writes a dedicated file (~/.ssh/tailscale_dev_config) and returns instructions for adding an Include line to ~/.ssh/config (never applied automatically). Direct editing of ~/.ssh/config itself additionally requires target="user_ssh_config" and is idempotent between managed markers, never touching content outside them.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "generate_ssh_config"
  }
}

Input Schema

NameRequiredDescriptionDefault
userNoRemote user to set on every Host block
writeNoActually write the config (default: false = dry-run, text only)
targetNoWrite target: "dedicated_file" (default, ~/.ssh/tailscale_dev_config) or "user_ssh_config" (edit ~/.ssh/config between managed markers)
onlineOnlyNoOnly include peers that are currently online (default: false)
includeSharedNoInclude nodes of users this node is shared with (default: false). Mullvad exit nodes are always skipped.

Output Schema

NameRequiredDescriptionDefault
noteNo
wroteNoFile written; null when nothing changed
backupNo
dryRunYes
renamedNo
skippedNo
hostCountYes
configTextNoGenerated config (dry run)
instructionsNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changedv0.4.0
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / includeShared
      Added value: +{
      +  "description": "Include nodes of users this node is shared with (default: false). Mullvad exit nodes are always skipped.",
      +  "type": "boolean"
      +}
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": false,
      +  "properties": {
      +    "backup": {
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "configText": {
      +      "description": "Generated config (dry run)",
      +      "type": "string"
      +    },
      +    "dryRun": {
      +      "type": "boolean"
      +    },
      +    "hostCount": {
      +      "type": "number"
      +    },
      +    "instructions": {
      +      "type": "string"
      +    },
      +    "note": {
      +      "type": "string"
      +    },
      +    "renamed": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "from": {
      +            "type": "string"
      +          },
      +          "hostname": {
      +            "type": "string"
      +          },
      +          "to": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "from",
      +          "to",
      +          "hostname"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "skipped": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "dnsName": {
      +            "type": "string"
      +          },
      +          "hostname": {
      +            "type": "string"
      +          },
      +          "reason": {
      +            "enum": [
      +              "no_address",
      +              "mullvad_exit_node",
      +              "shared_node"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "hostname",
      +          "dnsName",
      +          "reason"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "wrote": {
      +      "description": "File written; null when nothing changed",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    }
      +  },
      +  "required": [
      +    "dryRun",
      +    "hostCount"
      +  ],
      +  "type": "object"
      +}
  2. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare non-read-only, idempotent, and non-destructive, and the description adds substantial context beyond them: dry-run writes nothing, the Include line is never applied automatically, and direct ~/.ssh/config editing is idempotent only between managed markers and leaves outside content untouched. This is exactly the mutation-safety detail an agent needs.

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

Conciseness4/5

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

Three dense sentences, front-loaded with the dry-run default before the write and target details. Every clause carries information, though the final sentence is long enough that it could be split for easier parsing.

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?

For a mutation-capable tool with five optional parameters, the description covers defaults, side effects, write targets, and safety boundaries. An output schema exists, so return values need not be described, and nothing an agent needs in order to call it correctly is missing.

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?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: 'user' is applied to every Host block, 'write' toggles dry-run versus real output, and 'target' is coupled to the write path. It also notes that Mullvad exit nodes are always skipped, which is behavioral nuance not present in the schema.

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?

States a specific verb and resource ('Generate ssh-config Host blocks for tailnet nodes') and scopes it to MagicDNS names with Tailscale IP fallback. No sibling tool generates SSH config, so the purpose is immediately distinguishable from tailnet_status, share_*, and ping_all.

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

Usage Guidelines4/5

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

Clearly explains the default dry-run behavior versus write=true, and when to choose target="user_ssh_config" instead of the dedicated file. It lacks an explicit 'do not use this for X, use sibling Y' exclusion, but the mode-selection guidance is strong enough that an agent can pick correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.