WorkspacesAPI Reference

Workspace API Reference

All workspace management endpoints are mounted at /api/community/mcp/workspaces. Every request requires either a JWT Bearer token or an X-API-Key account key.


Authentication

All routes accept two authentication methods:

MethodHeaderFormat
JWT BearerAuthorizationBearer eyJhbGci...
Account API KeyX-API-Keyak_...

Unauthenticated requests return 401 Unauthorized.


Workspaces

Create Workspace

POST /api/community/mcp/workspaces

Request Body:

{
  "name": "My Workspace",
  "description": "Optional description"
}
FieldTypeRequiredConstraints
namestringYesMin 2 characters
descriptionstringNoFree-form text

Response (201):

{
  "id": "uuid",
  "slug": "my-workspace",
  "name": "My Workspace",
  "description": "Optional description",
  "gateway_url": "https://mcp.aerostack.dev/ws/my-workspace",
  "created_at": 1710000000
}

Errors:

StatusErrorCause
400name is required (min 2 characters)Missing or too short name
403MCP workspace limit reached...Plan workspace limit exceeded

List Workspaces

GET /api/community/mcp/workspaces

Response (200):

{
  "workspaces": [
    {
      "id": "uuid",
      "slug": "my-workspace",
      "name": "My Workspace",
      "description": "...",
      "status": "active",
      "server_count": 3,
      "gateway_url": "https://mcp.aerostack.dev/ws/my-workspace",
      "created_at": 1710000000,
      "updated_at": 1710000000
    }
  ]
}

Get Workspace

GET /api/community/mcp/workspaces/:id

Returns the workspace with all its servers (joined with MCP server details).

Response (200):

{
  "id": "uuid",
  "slug": "my-workspace",
  "name": "My Workspace",
  "description": "...",
  "status": "active",
  "gateway_url": "https://mcp.aerostack.dev/ws/my-workspace",
  "servers": [
    {
      "ws_server_id": "link-uuid",
      "server_id": "server-uuid",
      "slug": "@acme/github",
      "name": "GitHub Tools",
      "description": "GitHub integration",
      "type": "skill",
      "hosted": true,
      "access_type": "public",
      "star_count": 42,
      "tool_count": 5,
      "is_function": false,
      "inject_secrets": ["GITHUB_TOKEN"],
      "enabled": true,
      "display_order": 0
    }
  ],
  "created_at": 1710000000,
  "updated_at": 1710000000
}

Update Workspace

PATCH /api/community/mcp/workspaces/:id

Request Body (all fields optional):

{
  "name": "Updated Name",
  "description": "Updated description"
}
FieldTypeConstraints
namestringMin 2 characters
descriptionstringFree-form text

Response (200):

{ "success": true }

Updating a workspace name does not change the slug. The slug is immutable.


Delete Workspace

DELETE /api/community/mcp/workspaces/:id

Deletes the workspace and all associated server links, tokens, and secrets.

Response (200):

{ "success": true }

Servers

Add Server to Workspace

POST /api/community/mcp/workspaces/:id/servers

Request Body:

{
  "server_id": "uuid",
  "inject_secrets": ["SECRET_KEY_1", "SECRET_KEY_2"],
  "display_order": 0
}

Or, to add a community function (auto-wrapped as a skill):

{
  "function_id": "uuid"
}
FieldTypeRequiredDescription
server_idstringOne of server_id or function_idPublished MCP server UUID
function_idstringOne of server_id or function_idDeployed community function UUID
inject_secretsstring[]NoSecret key names to inject at call time
display_ordernumberNoSort order (0-9999, lower first)

Response (201):

{
  "ws_server_id": "link-uuid",
  "server_id": "resolved-uuid",
  "name": "Server Name",
  "slug": "@owner/server-slug"
}

Errors:

StatusErrorCause
400server_id or function_id is requiredNeither provided
403This skill is private...Attempting to add a private server you do not own
404MCP server not found or not publishedServer does not exist or is not published
409Server is already in this workspaceDuplicate server link
422This function is not deployed yet...Function must be deployed before adding

Update Server in Workspace

PATCH /api/community/mcp/workspaces/:id/servers/:wsServerId

Request Body (all fields optional):

{
  "inject_secrets": ["GITHUB_TOKEN"],
  "display_order": 2,
  "enabled": true
}
FieldTypeDescription
inject_secretsstring[]Secret key names to inject
display_ordernumberSort order (0-9999)
enabledbooleanEnable or disable the server
disabledbooleanInverted alias for enabled

Response (200):

{ "success": true }

Remove Server from Workspace

DELETE /api/community/mcp/workspaces/:id/servers/:wsServerId

Response (200):

{ "success": true }

Test Server Connectivity

POST /api/community/mcp/workspaces/:id/servers/:wsServerId/test

Sends a test request to the upstream server to verify connectivity and list available tools.

Response (200 — success):

{
  "ok": true,
  "tools_count": 5,
  "tools": ["create_issue", "list_repos", "search_code", "get_pr", "merge_pr"]
}

Response (200 — failure):

{
  "ok": false,
  "error": "HTTP 401: Unauthorized"
}

Tokens

Issue Token

POST /api/community/mcp/workspaces/:id/tokens

Request Body:

{
  "name": "Alice Cursor",
  "expires_in": 2592000
}
FieldTypeRequiredDescription
namestringYesHuman-readable label
expires_innumberNoSeconds until expiry
expirynumberNoAlias for expires_in

Response (201):

{
  "id": "token-uuid",
  "token": "mwt_7a3f9c...",
  "name": "Alice Cursor",
  "expires_at": 1712592000,
  "mcp_json": {
    "mcpServers": {
      "my-workspace": {
        "url": "https://mcp.aerostack.dev/ws/my-workspace",
        "headers": { "Authorization": "Bearer mwt_7a3f9c..." }
      }
    }
  },
  "warning": "Save this token now. It will not be shown again."
}
⚠️

The token field is returned only in this response. It cannot be retrieved later — save it immediately.


List Tokens

GET /api/community/mcp/workspaces/:id/tokens

Response (200):

{
  "tokens": [
    {
      "id": "token-uuid",
      "name": "Alice Cursor",
      "active": true,
      "last_used_at": 1710500000,
      "created_at": 1710000000,
      "revoked_at": null,
      "expires_at": 1712592000
    }
  ]
}

Revoke Token

DELETE /api/community/mcp/workspaces/:id/tokens/:tokenId

Sets revoked_at timestamp. The token stops working immediately.

Response (200):

{ "success": true }

Secrets

List Secrets

GET /api/community/mcp/workspaces/:id/secrets

Returns secret names only. Values are never returned.

Response (200):

{
  "secrets": [
    {
      "id": "secret-uuid",
      "key_name": "GITHUB_TOKEN",
      "key": "GITHUB_TOKEN",
      "created_at": 1710000000
    }
  ]
}

Create or Update Secret

POST /api/community/mcp/workspaces/:id/secrets

Request Body:

{
  "key": "GITHUB_TOKEN",
  "value": "ghp_abc123..."
}
FieldTypeRequiredDescription
keystringYesKey name (auto-uppercased, sanitized to [A-Z0-9_])
key_namestringNoAlias for key
valuestringYesSecret value (encrypted at rest)

Upsert behavior: if a secret with the same key name exists, the value is overwritten.

Response (201):

{
  "id": "secret-uuid",
  "key": "GITHUB_TOKEN",
  "success": true
}

Delete Secret

DELETE /api/community/mcp/workspaces/:id/secrets/:secretId

The :secretId parameter accepts either a UUID or a key name (e.g. GITHUB_TOKEN).

Response (200):

{ "success": true }

Errors:

StatusErrorCause
404Secret not foundNo secret matches the ID or key name

Gateway Endpoints

These endpoints are on the gateway, not the management API. They require a workspace token (mwt_...) instead of a JWT.

MCP JSON-RPC Gateway

POST https://mcp.aerostack.dev/ws/:slug
Authorization: Bearer mwt_...
Content-Type: application/json

Supported methods: initialize, ping, tools/list, tools/call

OpenAI Tools Adapter

GET https://mcp.aerostack.dev/ws/:slug/openai-tools
Authorization: Bearer mwt_...

Gemini Tools Adapter

GET https://mcp.aerostack.dev/ws/:slug/gemini-tools
Authorization: Bearer mwt_...