Skip to content

Agent documentation

Run local services through airmsh.

Add a server as a device, register its local database, MCP, or API service, then control access with an owner-managed policy.

Start here if the service is on your device and an approved person or tool needs to use it. For a private website or API address, follow the Endpoint guide. For a coding assistant, use the AI plugin guide.

01

Install the CLI

Use the Linux installer, then confirm its background service is running.

02

Bring the device online

Sign in with your own account and check that the server appears in Devices.

03

Register local services

Map a stable agent ID and tag to a database, MCP server, or HTTP API on this device.

04

Enforce a policy

The organization owner chooses callers, resources, actions, groups, limits, and sensitive-data behavior for this agent.

remote caller
  -> authenticated user and source device
  -> target device ID + agent tag
  -> resource and action policy
  -> request limits
  -> destination-local service authentication
  -> request PII handling
  -> database, MCP, or API
  -> response limits and PII handling
  -> signed audit

Server setup

Use an interactive password prompt. Never put an account password or access token in a shell command, service file, or log.

Install on a Linux server

First inspect the installer. It chooses and checks the right Linux build, keeps an existing login, sets up private device access, and enables the background service. Replace the email with your own account; enter the password only when prompted.

curl -fsSL https://airmsh.com/install-cli.sh | sudo sh -s -- --email you@example.com

Confirm the installed build and active service below. The server should then appear online in Devices. For manual packages, use Downloads.

Check the background service

The installer enables airmsh-cli.service. If it could not prompt for a first login, sign in separately and start the service. Do not run another interactive tunnel at the same time.

sudo airmsh-cli --version
sudo systemctl is-active airmsh-cli
# Only if first login was skipped:
sudo airmsh-cli resource login you@example.com
sudo systemctl start airmsh-cli

The service should say active. If it does not, run sudo journalctl -u airmsh-cli -n 50 --no-pager to see the error.

Add agents

Run these commands on the destination server. Definitions are stored locally, and the running service reloads changes automatically. Local addresses and credentials stay on that server.

Databases

sudo airmsh-cli agent add db reports MongoDB mongodb://127.0.0.1:27017 analytics db:reports
sudo airmsh-cli agent add db cache Redis redis://127.0.0.1:6379 - db:cache
sudo airmsh-cli agent add db analytics MySQL mysql://127.0.0.1:3306 analytics db:analytics
sudo airmsh-cli agent add db warehouse Postgres postgres://127.0.0.1:5432 warehouse db:warehouse
sudo airmsh-cli agent add db cloud Neon postgres://ep-example.neon.tech/app app db:neon
sudo airmsh-cli agent add db local SQLite sqlite:///srv/app/data.sqlite - db:local

Use filedb:///absolute/path.db as an alias for SQLite. Database passwords are configured separately and stored only on the destination device.

read -r -s -p 'Database password: ' AIRMSH_AGENT_SECRET; echo
export AIRMSH_AGENT_SECRET
sudo --preserve-env=AIRMSH_AGENT_SECRET airmsh-cli agent auth reports password reporter
unset AIRMSH_AGENT_SECRET

MCP over HTTP

sudo airmsh-cli agent add mcp tools LocalMCP http://127.0.0.1:9000/mcp mcp:tools

sudo airmsh-cli agent pin tools

The pin command records the approved MCP tool-schema digest. A later schema change is denied until the owner reviews and pins it again.

HTTP API bridge

sudo airmsh-cli agent add api python PythonAPI http://127.0.0.1:8080 api:python

Bind the local service to loopback. Remote clients route to the device and tag; they do not receive the loopback port or destination credentials.

# After exporting AIRMSH_AGENT_SECRET with the secure prompt above
sudo --preserve-env=AIRMSH_AGENT_SECRET airmsh-cli agent auth python bearer

# Other supported HTTP authentication
sudo --preserve-env=AIRMSH_AGENT_SECRET airmsh-cli agent auth python api-key X-API-Key
sudo --preserve-env=AIRMSH_AGENT_SECRET airmsh-cli agent auth python basic service-user
Listagent list
Replaceagent update ...
Removeagent delete <id>

Run and test requests

On the calling device, connect to the destination device, open Agents, choose the agent shown under that device, and run one of these payloads. The app fills the signed-in user, source device, target device, and agent tag.

Where curl fits

Use curl on the destination device to confirm that a local HTTP service works before registering it. Airmsh then carries the same HTTP intent through its authenticated device channel.

# Run on the destination device
curl -i 'http://127.0.0.1:8080/users?limit=10' \
  -H 'Accept: application/json'

# Equivalent Airmsh API-agent payload
{
  "method": "GET",
  "path": "/users",
  "query": {"limit": 10},
  "headers": {"accept": "application/json"}
}

The response includes the status, content type, and body returned by the service. Test the local web address with curl; use Airmsh to reach it from another device.

MCP examples

Select protocol MCP. Use action tools/list to discover tools or tools/call to invoke one.

// List tools
{"method":"tools/list","params":{}}

// Call the ping tool
{
  "method": "tools/call",
  "params": {"name": "ping", "arguments": {}}
}

Database examples

Select protocol Database and action query. The destination daemon converts the payload to the database’s native wire protocol.

MongoDB

{"command":{"ping":1}}

Redis

{"args":["PING"]}

MySQL

{"query":"SELECT 1 AS ok"}

PostgreSQL / Neon

{"query":"SELECT current_database()"}

SQLite / FileDB

{"query":"SELECT name FROM sqlite_master LIMIT 10"}

Remote SDK request shape

The app creates this automatically. Integrations identify the destination device and agent; Airmsh checks their identity and permissions before opening the service.

{
  "endpoint": "d-target-device.airmsh:51821",
  "target_device_id": "target-device-id",
  "agent_tag": "db:warehouse",
  "protocol": "database",
  "action": "query",
  "resource_id": "local-database",
  "payload": {"query": "SELECT 1 AS ok"}
}

The full SDK request also includes the authenticated source identity. Copy those IDs from the signed-in device rather than inventing them. The destination verifies the source, target device, agent tag, action, resource, policy, and signature before execution.

Access policy

Only the organization owner can change an agent policy. Other members can use agents when allowed, but cannot edit these controls.

Always on

Base checks

Authenticated device-and-tag routing, payload bounds, and destination-local credentials apply before a service is called.

Owner enabled per agent

Enforced policy

Adds the selected callers, actions and resources, request limits, sensitive-data decisions, and audit checks for this agent.

Policy fields

Allowed users

Specific airmsh user IDs. Empty means any authenticated user in the tenant.

Source devices

Device IDs allowed to originate the request. Empty means any tenant device.

Source agents

Agent IDs allowed to call this agent. Empty means any authenticated source agent.

Allowed groups

One or more tenant group IDs. A user may match through any listed group.

Group roles

Roles such as operator or viewer that must match group membership.

Resources

Logical targets such as mysql-prod, local-mcp, or local-api.

Allowed actions

Operations such as query, tools/call, request, read, or write.

Example: reporting agent may query production MySQL

Target device: server-device-id
Target agent: analytics

Allowed users: user-vineet-id
Source devices: laptop-device-id
Source agents: reporting-agent
Allowed groups: reporting-group-id
Group roles: operator
Resources: mysql-prod
Allowed actions: query

Requests per minute: 10
Concurrent requests: 2
Maximum rows: 1000
Maximum response: 10 MB
Execution timeout: 30 seconds
Sensitive data: mask

Open Agents, choose the destination agent, select Policy, enter these values, turn on Enforce policy for this agent, and save. Empty selector fields are wildcards, so fill user, device, group, resource, and action fields when access must be narrow.

What the policy checks

tenant
user
source device
source agent
group and group role
target device
target agent
resource
action

The target device and target agent must match exactly. A network address is only a transport path and is never accepted as agent identity.

Verify the setup

airmsh> status
airmsh> devices
airmsh> agent list

The tunnel is running and the server device is online.

The destination service is listening only on 127.0.0.1.

The adapter appears in agent list with the expected ID and tag.

The calling device is connected and allowed by the destination policy.

An allowed action succeeds and a different user, resource, or action is denied.

The audit view records the source identity, decision, limits, and result.

Troubleshooting

Device is offline

A saved login is not a running client. Start airmsh-cli, enter online, and keep that process alive.

Agent is listed but unreachable

Confirm the local service is listening on loopback, its credentials are valid, and the CLI process that owns the adapter is still running.

Policy denies a valid user

Check the exact user ID, source device, source agent, group role, target agent, resource, and action. IDs are matched exactly.

MCP schema changed

Review the current tools and inputs on the destination server. If the change is expected, the tenant owner pins the new schema.

TUN permission denied

Verify cap_net_admin on Linux or start through the operating system administrator flow on desktop.