MCP Server

The @air/mcp package connects MCP-compatible AI clients to an Air workspace. It exposes tools for finding and previewing assets, organizing boards, applying tags and custom fields, importing files from URLs, and uploading local files.

The server supports:

Prerequisites

Configuration

The server reads these environment variables:

Variable Required Description
AIR_API_KEY Yes API key used to authenticate with Air
AIR_WORKSPACE_ID Yes Workspace that all MCP tools operate on
AIR_API_URL No API base URL override for non-production environments

Credentials stay in the MCP server process. Do not place them in prompts or tool arguments.

Command-line options

Option Description
--http Use Streamable HTTP instead of STDIO
--port <number> Set the initial HTTP port. The default is 3000; if occupied, the server tries up to 10 subsequent ports.
--debug In HTTP mode, log parsed MCP requests and responses to stderr

HTTP mode binds to 127.0.0.1 and serves MCP requests at /mcp.

Set up a client

Claude Desktop

Add the server to your Claude Desktop config. On macOS, the file is ~/Library/Application Support/Claude/claude_desktop_config.json.

JSON

{
  "mcpServers": {
    "air": {
      "command": "npx",
      "args": ["-y", "@air/mcp"],
      "env": {
        "AIR_API_KEY": "your-api-key",
        "AIR_WORKSPACE_ID": "your-workspace-id"
      }
    }
  }
}

If Claude Desktop does not load the Node.js version from your shell profile, set command to the full path of a Node 18+ npx executable. See the Claude Desktop MCP guide.

Claude Code

Bash

claude mcp add \
  --env AIR_API_KEY=your-api-key \
  --env AIR_WORKSPACE_ID=your-workspace-id \
  --transport stdio \
  air \
  -- npx -y @air/mcp

See the Claude Code MCP documentation.

Codex

Add the server to ~/.codex/config.toml:

TOML

[mcp_servers.air]
command = "npx"
args = ["-y", "@air/mcp"]

[mcp_servers.air.env]
AIR_API_KEY = "your-api-key"
AIR_WORKSPACE_ID = "your-workspace-id"

Or use the CLI:

Bash

codex mcp add air \
  --env AIR_API_KEY=your-api-key \
  --env AIR_WORKSPACE_ID=your-workspace-id \
  -- npx -y @air/mcp

See the Codex MCP documentation.

Cursor

Add the server to .cursor/mcp.json in a project or ~/.cursor/mcp.json globally:

JSON

See the Cursor MCP documentation.

Windsurf

Add the server to ~/.codeium/windsurf/mcp_config.json:

JSON

See the Windsurf MCP documentation.

VS Code with GitHub Copilot

Add the server to .vscode/mcp.json, or open the user-level file with MCP: Open User Configuration:

JSON

{
  "servers": {
    "air": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@air/mcp"],
      "env": {
        "AIR_API_KEY": "your-api-key",
        "AIR_WORKSPACE_ID": "your-workspace-id"
      }
    }
  }
}

Use Copilot in Agent mode to call MCP tools. See the VS Code MCP documentation.

Zed

Add the server to ~/.config/zed/settings.json:

JSON

{
  "context_servers": {
    "air": {
      "command": "npx",
      "args": ["-y", "@air/mcp"],
      "env": {
        "AIR_API_KEY": "your-api-key",
        "AIR_WORKSPACE_ID": "your-workspace-id"
      }
    }
  }
}

See the Zed context server documentation.

Run with Streamable HTTP

Start a local HTTP server with credentials in the process environment:

Bash

AIR_API_KEY=your-api-key \
AIR_WORKSPACE_ID=your-workspace-id \
npx -y @air/mcp --http

Connect a local HTTP-capable MCP client to:

Text

http://localhost:3000/mcp

For example, add --port 4000 to choose another initial port or --debug to inspect MCP traffic.

Tool reference

The server registers 23 tools in six categories. A parameter followed by ? is optional.

List tools return a JSON object with data, pagination, and total. To request another page, pass the returned pagination cursor into the next call.

Assets

Tool Inputs Description
list_assets parentBoardId?, includeNestedAssets?, tag?, customField?, search?, limit?, cursor?, includeThumbnails? List assets with board, tag, custom-field, and search filters. tag and customField accept one string or an array. includeThumbnails adds inline images for up to the first 10 results.
list_nested_assets boardId, limit?, cursor?, includeThumbnails? List assets in a board and all nested sub-boards. Can include up to 10 inline thumbnails.
get_asset assetId Get asset details, cover version, metadata, custom fields, and a canonical Air web app url.
get_asset_download_url assetId, versionId? Get a temporary download URL. If versionId is omitted, the cover version is used.
get_asset_boards assetId, limit?, cursor? List every board that contains an asset.
get_asset_image assetId, size? Return an inline base64 image content block. size is thumbnail (default) or preview.
rename_asset assetId, title, versionId? Update only the display title. Defaults to the cover version and does not change the underlying file name.
update_asset assetId, title?, description?, versionId? Update the display title and/or description. Defaults to the cover version.
add_tag_to_asset assetId, tagId, versionId? Add a tag to an asset version. Defaults to the cover version.
remove_tag_from_asset assetId, tagId, versionId? Remove a tag from an asset version. Defaults to the cover version.
update_asset_custom_field assetId, customFieldId, value?, values? Set or clear a custom field value. Field-specific rules are described below.

Boards

Tool Inputs Description
list_boards name?, parentBoardId?, limit?, cursor? List boards, optionally filtered by name or parent.
get_board boardId Get board details and a canonical Air web app url.
create_board title, description?, parentBoardId? Create a root board or a board nested under another board. Returns a canonical url.
update_board boardId, title?, description?, parentBoardId? Update a board. Pass parentBoardId: null to move it to the workspace root.
add_asset_to_board boardId, assetIds Add one or more asset IDs to a board.

Tags

Tool Inputs Description
list_tags name?, limit?, cursor? List tags, optionally filtered by name.
create_tag name Create a tag in the workspace.

Custom fields

Tool Inputs Description
list_custom_fields limit?, cursor? List custom fields defined in the workspace.
get_custom_field customFieldId Get a field's type and its possible select options.

Imports

Tool Inputs Description
create_import sourceUrl, fileName?, ext?, recordedAt?, parentBoardId?, assetId?, description?, title?, customFields?, tags? Import an asset from a URL. Optionally place it in a board, add it as a new version, and set metadata. Returns an import task ID, asset ID, version ID, and canonical url.
get_import_status importId Poll an import task. Status is pending, inProgress, succeeded, or failed; failures include an error object.

Uploads

Tool Inputs Description
upload_asset filePath, parentBoardId?, assetId?, customFields?, tags? Upload a local file. The SDK detects its type and upload strategy. Optionally place it in a board or add it as a new asset version. Returns the asset ID, version ID, and canonical url.

filePath must be an absolute path that the MCP server process can read. For STDIO, this is normally the same machine as the client. For HTTP, the path refers to the server machine, not the machine running the remote client.

Tool behavior

Canonical Air URLs

get_asset, get_board, create_board, create_import, and upload_asset return a canonical url when applicable. Agents should use this field instead of constructing Air URLs from asset, version, or board IDs.

Asset images and thumbnails

get_asset_image returns an MCP image content block that supported clients can render directly. list_assets and list_nested_assets can include image content blocks by setting includeThumbnails: true.

For list calls, thumbnail fetching is limited to the first 10 returned assets. Images are fetched only from trusted Air or Imgix HTTPS hosts.

Custom-field values

update_asset_custom_field fetches the custom-field definition and validates values before updating the asset:

The customFields parameter accepted by create_import and upload_asset uses an array of objects with this shape:

JSON

[\
  {\
    "id": "text-or-date-field-id",\
    "value": "text-or-date-value"\\
  },\
  {\
    "id": "select-field-id",\
    "values": [{ "id": "select-option-id" }]\
  }\
]

Use the member appropriate for the field type. The tags parameter for imports and uploads is an array of { "id": "tag-id" } objects.

Imports and uploads

URL imports are asynchronous. After create_import, call get_import_status with the returned import task ID until the status is succeeded or failed.

Pass assetId to create_import or upload_asset to add the new file as a version of an existing asset. Pass parentBoardId to place a newly created asset in a board.

For create_import, fileName excludes the extension, ext excludes the leading dot, and recordedAt is an ISO 8601 date string.

Errors

Air API failures are returned as MCP tool errors containing the HTTP status and API error message. Invalid custom-field input is returned as a tool error with guidance about the expected value shape or valid select options.