manage_exit_nodes
Control and configure Tailscale exit nodes for routing operations. List, set, clear, advertise, or stop advertising routes like 0.0.0.0/0 or ::/0 using device IDs for precise network management.
Instructions
Manage Tailscale exit nodes and routing
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| deviceId | No | Device ID for exit node operations | |
| operation | Yes | Exit node operation to perform | |
| routes | Yes | Routes to advertise (e.g., ["0.0.0.0/0", "::/0"] for full exit node) |
Implementation Reference
- src/tools/admin-tools.ts:244-336 (handler)The main handler function implementing manage_exit_nodes tool logic for listing, advertising, setting, and clearing exit nodes.async function manageExitNodes( args: z.infer<typeof ExitNodeSchema>, context: ToolContext, ): Promise<CallToolResult> { try { logger.debug("Managing exit nodes:", args); switch (args.operation) { case "list": { const devicesResult = await context.api.listDevices(); if (!devicesResult.success) { return returnToolError(devicesResult.error); } const devices = devicesResult.data || []; const exitNodes = devices.filter( (device) => device.advertisedRoutes?.includes("0.0.0.0/0") || device.advertisedRoutes?.includes("::/0"), ); if (exitNodes.length === 0) { return returnToolSuccess("No exit nodes found in the network"); } const exitNodeList = exitNodes .map((node) => { return `**${node.name}** (${node.hostname}) - ID: ${node.id} - OS: ${node.os} - Routes: ${node.advertisedRoutes?.join(", ") || "None"} - Status: ${node.authorized ? "Authorized" : "Unauthorized"}`; }) .join("\n\n"); return returnToolSuccess( `Exit Nodes (${exitNodes.length}):\n\n${exitNodeList}`, ); } case "advertise": { if (!args.deviceId || !args.routes) { return returnToolError( "Device ID and routes are required for advertise operation", ); } const result = await context.api.setDeviceExitNode( args.deviceId, args.routes, ); if (!result.success) { return returnToolError(result.error); } return returnToolSuccess( `Device ${ args.deviceId } is now advertising routes: ${args.routes.join(", ")}`, ); } case "set": { const nodeId = args.deviceId ?? ""; const cliResult = await context.cli.setExitNode(nodeId); if (!cliResult.success) { return returnToolError(cliResult.error); } return returnToolSuccess( `Exit node set to: ${args.deviceId || "auto"}`, ); } case "clear": { const cliResult = await context.cli.setExitNode(); if (!cliResult.success) { return returnToolError(cliResult.error); } return returnToolSuccess("Exit node cleared successfully"); } default: return returnToolError( "Invalid exit node operation. Use: list, set, clear, advertise", ); } } catch (error) { logger.error("Error managing exit nodes:", error); return returnToolError(error); } }
- src/tools/admin-tools.ts:26-40 (schema)Zod input schema defining parameters for the manage_exit_nodes tool (operation, deviceId, routes).const ExitNodeSchema = z.object({ operation: z .enum(["list", "set", "clear", "advertise", "stop_advertising"]) .describe("Exit node operation to perform"), deviceId: z .string() .optional() .describe("Device ID for exit node operations"), routes: z .array(z.string()) .min(1, "At least one route must be specified") .describe( 'Routes to advertise (e.g., ["0.0.0.0/0", "::/0"] for full exit node)', ), });
- src/tools/admin-tools.ts:564-569 (registration)Registration of the manage_exit_nodes tool in the adminTools ToolModule, linking name, schema, and handler.{ name: "manage_exit_nodes", description: "Manage Tailscale exit nodes and routing", inputSchema: ExitNodeSchema, handler: manageExitNodes, },