Skip to main content
Glama

Configure a service

add
Destructive

Register a named private Tailscale service to proxy HTTP, serve files, or forward TCP, and control who can reach it; optionally publish via Funnel.

Instructions

Setting funnel true on this tool publishes the service to the entire public internet, so ask the user before doing that; otherwise it writes a registry entry for a proxy, file, or TCP service reachable on the user's private Tailscale network. Without allow, every member of the user's tailnet can reach an HTTP service. Use this instead of share when the user wants a named, configured service rather than a one-shot share; it installs the background service when absent unless no_daemon_install is true. Installation announcements go to stderr. After setup it returns current URL/enrollment evidence without an additional URL wait; use url to poll pending endpoints.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dirNoAbsolute directory path for file. Rejected for proxy and tcp.
nameYesRegistry service name (DNS label). An existing entry with this name is replaced.
tagsNoACL tags applied to the tailnet node, each prefixed tag:. Defaults to the configured default tag.
typeYesproxy forwards HTTP to target; file serves the directory dir; tcp forwards a raw stream to target.
allowNoPrincipals allowed to reach the service over HTTP: email addresses, or tag:<name> ACL tags. Omitting it leaves an HTTP service readable by every member of the user's tailnet. Unsupported for tcp and rejected together with funnel.
funnelNoPublish to the public internet through Tailscale Funnel. Requires type proxy, public_ack true, no allow entries, and no control_url.
healthNo
remoteNoHTTPS MagicDNS upstream in the gateway tailnet. Replaces target for type proxy and implies portal_only; requires an observed tagged gateway.
targetNohost:port or URL for proxy, host:port for tcp. Rejected for file. The daemon will proxy to any address it can reach on its own network; link-local and cloud-metadata addresses are refused only as literal IP addresses (unspecified addresses too) or the metadata.google.internal hostname: hostnames are not resolved and nothing is checked at connect time, so a name that resolves to one of those addresses is accepted.
ephemeralNoRegister an ephemeral tailnet node that disappears on disconnect.
funnel_ttlNoRelative lifetime (descending unique units w,d,h,m,s,ms,us,ns) or until <RFC3339|YYYY-MM-DD|YYYY-MM-DDTHH:MM>. Local unless offset given; DST gaps/folds require an offset. Minimum 1h. Presets: 1h, 8h, 24h, 3d, 7d. Default 24h; guest/public maximum defaults to 7d, configurable in durations.public_max. Never refused. Omission on add preserves an existing deadline.
public_ackNoExplicit acknowledgement that funnel exposes the service publicly. funnel true without it is rejected.
control_urlNoPer-service custom control server URL, for example a Headscale deployment. A custom control server never receives the stored Tailscale credential or an auth key minted with it: while a credential is stored the daemon does not start such a service (credential_control_url_mismatch), and without one the node enrolls interactively on that server. Rejected together with funnel.
portal_onlyNoCreate no app node; assign a route on the enabled gateway. App becomes people-scoped.
portal_portNoStable port for portal_only or remote.
requestableNoDisclose this private HTTP/file app in the portal request form; default off.
preserve_hostNoProxy only: forward this node's trusted canonical external name in Host and X-Forwarded-Host; fail closed if unavailable. Default false keeps upstream Host rewriting.
request_limitsNo
no_auto_provisionNoDisable automatic Funnel policy provisioning. Only valid with funnel true.
no_daemon_installNoSave configuration without installing the background service.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYes
nameYes
nextNo
typeYes
createdYesTrue when this call created the registry entry; false when it replaced an existing entry with the same name.
auth_urlNo
endpointYes
exposureYes
warningsNo
requestableNo
url_pendingYes
preserve_hostNoProxy only: forward this node's trusted canonical external name in Host and X-Forwarded-Host; fail closed if unavailable. Default false keeps upstream Host rewriting.
daemon_runningNo
funnel_rearmedYes
request_limitsNo
replaced_fieldsYesregistry.json fields the replace changed or dropped, sorted; empty when created is true. add sets every field from this call, so a field not given again is dropped.
daemon_installedNoPresent only when this call installed TSLink's background service, a persistent OS autostart entry; absent when the service already ran or no_daemon_install was true.
funnel_expires_atNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.7/5.0
Behavior5/5

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

Annotations flag destructiveness/open-world, and the description adds real behavioral context beyond them: funnel publishes to the entire public internet and requires user confirmation, omitting 'allow' leaves the service readable by every tailnet member, the daemon installs itself unless no_daemon_install is set, announcements go to stderr, and setup returns URL/enrollment evidence immediately. These are exactly the consequences an agent needs to reason about before invoking.

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?

It is a dense paragraph rather than a bulleted list, but it is well front-loaded: the highest-risk behavior (public internet exposure) comes first, followed by default reachability, sibling routing, install behavior, and return behavior. Every sentence carries information, though the density makes it slightly harder to scan than it could be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 20-parameter mutation tool with nested objects, the description covers the critical decision points (public exposure, default access, install side effect, return timing) and an output schema exists so return values need no elaboration. It leaves the many secondary parameters entirely to the schema, which is acceptable at 90% coverage but not exhaustive.

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 description coverage is already 90%, so the baseline is 3; the description still adds meaning by explaining the default-open behavior of 'allow', the public-exposure semantics of 'funnel', and the install-suppression role of no_daemon_install. It does not, however, touch several other parameters (tags, health, request_limits, ephemeral), which the schema carries alone.

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?

Despite the generic name 'add', the description states a specific action and resource: it writes a registry entry for a proxy, file, or TCP service on the user's tailnet, or publishes it publicly via funnel. It explicitly separates itself from the sibling 'share' ('Use this instead of share...'), so an agent can route correctly without opening either schema.

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

Usage Guidelines5/5

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

It names the alternative tool and the condition that selects it ('use this instead of share when the user wants a named, configured service rather than a one-shot share') and points to 'url' for polling pending endpoints. It also gives a clear when-to-ask rule for the funnel case.

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