{
  "name": "Layer",
  "description": "Layer is the AI platform for creative teams in games and entertainment. These MCP servers expose asset generation, custom style training, node-based workflows, and workspace administration as tools any MCP client can call.",
  "vendor": "Layer",
  "homepage": "https://layer.ai",
  "documentation_url": "https://layer.ai/docs/mcp",
  "specification": "https://modelcontextprotocol.io",
  "mcp_apps": {
    "supported": true,
    "specification": {
      "name": "MCP Apps",
      "extension": "io.modelcontextprotocol/ui",
      "version": "2026-01-26",
      "url": "https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx",
      "documentation_url": "https://apps.extensions.modelcontextprotocol.io/api/"
    },
    "mime_type": "text/html;profile=mcp-app",
    "view_delivery": "inline",
    "view_url_template": "https://mcp.app.layer.ai/apps/{view}/index.html",
    "description": "Layer's creative MCP server ships an MCP Apps view. Tools that carry `_meta.ui.resourceUri` return a `ui://` HTML resource the host renders inline, so a generation appears as an interactive result in the conversation rather than as a run id to poll. Hosts that do not negotiate the `io.modelcontextprotocol/ui` extension are unaffected — the tools return their normal structured result.",
    "documentation_url": "https://layer.ai/docs/mcp",
    "servers": [
      "creative"
    ],
    "views": [
      {
        "server": "creative",
        "uri": "ui://layer/execute-generation",
        "name": "execute-generation",
        "mimeType": "text/html;profile=mcp-app",
        "url": "https://mcp.app.layer.ai/apps/execute-generation/index.html"
      }
    ]
  },
  "servers": [
    {
      "name": "Layer MCP Server",
      "id": "creative",
      "description": "Generate and edit images, video, 3D, and audio; run Blueprint workflows; train styles; assemble video timelines; upload and score files.",
      "url": "https://mcp.app.layer.ai/mcp",
      "transport": "streamable-http",
      "documentation_url": "https://layer.ai/docs/mcp",
      "setup_url": "https://layer.ai/docs/mcp/setup",
      "instructions": "IMPORTANT: Call tool `get_instructions` first for general platform guidance.\n\nIf any tool call fails with an authentication error (401 Unauthorized), tell the user they need to connect their Layer account — they should complete the OAuth flow in their MCP client settings.",
      "authorization": {
        "type": "oauth2",
        "flow": "authorization_code",
        "pkce_required": true,
        "dynamic_client_registration": true,
        "authorization_servers": [
          "https://auth.app.layer.ai/"
        ],
        "authorization_server_metadata": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
        "scopes_supported": [
          "openid",
          "profile",
          "email",
          "offline_access"
        ],
        "description": "Unauthenticated requests return 401 with a `WWW-Authenticate: Bearer resource_metadata=…` challenge pointing at the RFC 9728 protected-resource metadata for that server. Follow it to the authorization server, register dynamically, and run the authorization-code + PKCE flow.",
        "protected_resource_metadata": "https://mcp.app.layer.ai/.well-known/oauth-protected-resource/mcp"
      },
      "tool_count": 43,
      "tools": [
        {
          "name": "cancel_inference",
          "title": "Cancel model generation",
          "description": "Request cancellation of an in-flight inference launched with execute_forge.\nFire-and-forget: returns immediately after signalling the run to stop; poll get_forge_run for the\neventual CANCELLED status. A run that already COMPLETED can no longer be cancelled and errors with\nINFERENCE_ALREADY_COMPLETE; the other terminal states are idempotent no-ops.\nPass the `inference_id` that execute_forge returned.",
          "annotations": {
            "title": "Cancel model generation",
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": true,
            "openWorldHint": false
          }
        },
        {
          "name": "cancel_training_run",
          "title": "Cancel training run",
          "description": "Cancel an in-flight training run and release any reserved Creative Units.\n\nOnly runs that are initializing or running can be cancelled. Errors:\ntraining-run-not-found, invalid-status (run already finished).",
          "annotations": {
            "title": "Cancel training run",
            "readOnlyHint": false,
            "destructiveHint": true,
            "openWorldHint": false
          }
        },
        {
          "name": "cancel_workflow_run",
          "title": "Cancel workflow run",
          "description": "Cancel a running workflow. Stops generation immediately. Creative Units reserved but not yet consumed are released. Already-completed steps are not refunded.\n\nFor multi-step workflow guidance, call get_workflow_instructions.",
          "annotations": {
            "title": "Cancel workflow run",
            "readOnlyHint": false,
            "destructiveHint": true,
            "openWorldHint": false
          }
        },
        {
          "name": "compose_image",
          "title": "Compose image",
          "description": "Stack workspace images into one flat PNG: overlays, backgrounds with a foreground, or collages.\n\nA deterministic file operation: no model runs and no Creative Units are spent. Each layer places\none image in a box on the canvas (by default the size of the first layer's image), positioned by edge anchors and filled by its\nresize strategy; layers stack bottom first and blend by their alpha. Parts of the canvas no\nlayer covers stay transparent.\nThe image is saved to the workspace library and, when the call runs in a session, placed on\nits board (`image.placed_on_board`).",
          "annotations": {
            "title": "Compose image",
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false
          }
        },
        {
          "name": "create_reference_set",
          "title": "Create reference set",
          "description": "Create a new reference set from a list of image or video files in the workspace.\n\nA reference set is a curated collection of image or video assets used to train a LoRA style model.\nCall this when the user wants to start training from assets they have already uploaded.\nAfter creating the reference set, call draft_captions then start_training.\n\nCover thumbnails: pass cover_file_ids to choose them explicitly, or omit it to auto-pick the\nfirst few image files. The output's cover_count reports how many were set.\n\nErrors: invalid-dataset (no usable assets / all files foreign to the workspace),\ninvalid-session (the session does not belong to the workspace),\npermission errors propagated as-is.\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Create reference set",
            "readOnlyHint": false,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "estimate_forge_price",
          "title": "Estimate model generation price",
          "description": "Estimate the Creative Units price of a forge run before executing it.\n\nRequires either a `base_model_id` or at least one reference set; passing neither is an error.\nPrices through the same reference-set translation and model selection as `execute_forge`, so\nthe returned price matches what the run itself charges for identical inputs. A seam repair or\nbackground removal that runs after it as its own child run is billed separately and is not\nincluded. Executes nothing.\n\nFor forge lifecycle guidance, call get_forge_instructions.",
          "annotations": {
            "title": "Estimate model generation price",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "estimate_training_price",
          "title": "Estimate training price",
          "description": "Estimate the Creative Units cost of training a LoRA for a reference set.\n\nRead-only. Resolves and validates the base model the same way start_training would, then prices the run.\nErrors: unknown-base-model (id not trainable), unsupported-training-framework (framework not\navailable for this base model), model-disabled (base model disabled for this workspace),\ninvalid-dataset (reference set not found or has no training images).\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Estimate training price",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "estimate_video_timeline_price",
          "title": "Estimate video timeline price",
          "description": "Estimate the Creative Units price of a video editor render without rendering anything.\n\nAuthor the timeline exactly as for `render_video_timeline`. Prices through the same estimator the\nrender charges against, so the price matches for identical inputs. Returns the price plus the\nworkspace balance. Produces no file.",
          "annotations": {
            "title": "Estimate video timeline price",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "estimate_workflow_price",
          "title": "Estimate workflow price",
          "description": "Estimate the Creative Units price of running a workflow before executing it.\n\nUse this tool to check price and verify the workspace has sufficient Creative Units\nbalance before executing. Does not execute anything.\n\nFor multi-step workflow guidance, call get_workflow_instructions.",
          "annotations": {
            "title": "Estimate workflow price",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "execute_forge",
          "title": "Generate with a model",
          "description": "Execute a forge run to generate images, videos, 3D models, or audio.\n\nPass a `base_model_id`, at least one entry in `reference_sets`, or both. With reference sets\nand no base model, a compatible model is picked automatically from the sets.\n\nReturns immediately with an inference ID, which can be polled with `get_forge_run` for results.\n\nCall `get_forge_instructions` first for full forge lifecycle guidance.",
          "annotations": {
            "title": "Generate with a model",
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": false
          },
          "_meta": {
            "ui": {
              "resourceUri": "ui://layer/execute-generation"
            }
          }
        },
        {
          "name": "execute_workflow",
          "title": "Run workflow",
          "description": "Run one of the workspace's saved workflows to produce images, videos, 3D models, or audio.\n\nA workflow is a fixed pipeline the user built in Layer. Its steps are Layer's own\noperations: model generations, image/video/audio edits, text templating, fixed values,\nAI image judging, and filing outputs into the workspace's Drive. Every step reads and\nwrites only the workspace's own files. `inputs` must match the input schema list_workflows\nreturns for the workflow. Spends Creative Units.\n\nReturns immediately with a run ID. Poll with `get_workflow_run` for results.\n\nCall `get_workflow_instructions` first for full workflow lifecycle guidance.",
          "annotations": {
            "title": "Run workflow",
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": false
          },
          "_meta": {
            "ui": {
              "resourceUri": "ui://layer/execute-generation"
            }
          }
        },
        {
          "name": "export_tileset",
          "title": "Export tileset",
          "description": "Lay finished tiles out as a tileset a game engine imports, and return a download link to the zip.\n\nA deterministic file operation: no model runs and no Creative Units are spent. The tiles are\nused as they are stored, each placed by where it stands on its grid (recorded when it was made\nwith `tile_grid`), so they line up on the engine's own isometric, hex or square grid without\nany adjustment. Facings of one subject are named after it (`tower_0`, `tower_90`) and carry\ntheir subject and facing as tile properties. The zip holds a README with the engine's import\nsteps and the grid settings the map needs. Use `pack_sprite_sheet` instead for a single sheet\nimage on the board.",
          "annotations": {
            "title": "Export tileset",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "export_ui_kit",
          "title": "Export UI kit",
          "description": "Export 9-slice UI elements (buttons, frames, panels) with the files an engine stretches them by,\nand return a download link to the zip.\n\nA deterministic file operation: no model runs and no Creative Units are spent. Every element must\ncarry 9-slice insets, recorded when it was generated with `nine_slice` or made as a 9-slice copy;\nthey are used as stored, so the corners never scale and the cleaned edges and centre stretch\nwithout smearing. The zip holds a README with the engine's import steps and each element's insets.",
          "annotations": {
            "title": "Export UI kit",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_base_model",
          "title": "Get base model",
          "description": "Get full details for a specific base model.\n\nReturns capabilities, timing, pricing, and the model's prompt guide,\nsourced from the model registry (not a Style row).\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Get base model",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_blueprint_system_config",
          "title": "Get blueprint system config",
          "description": "Discover every Blueprint type, node kind, and casting rule available in this workspace.\n\nReturns:\n  - `types`: each available `BlueprintType` with its JSON schema. Static\n    values you set on a node input or output MUST conform to the type's\n    `json_schema` (resolving `$ref` via `json_schema_defs`) or the\n    backend will reject the mutation.\n  - `node_kinds`: every available `NodeKind` with full input/output\n    port specs (port_key, type, is_required, must_be_static, default).\n    Noop kinds (key prefix `noop.`) are static-data nodes used by the\n    workflow architect in lieu of parameters during early editing.\n  - `json_schema_defs`: shared `$defs` referenced by the per-type\n    schemas.\n  - `casting_rules`: type-compat edges. An output of type A may only\n    be wired to an input of type B when (A, B) is a casting rule (or\n    A == B). Rules carrying a `transformer` are NOT auto-inserted\n    in v1 — treat them as blocked and wire through the named\n    transformer node_kind explicitly if needed.\n\nCall this once per session and reuse the result; the config is\nworkspace-scoped but otherwise stable.\n",
          "annotations": {
            "title": "Get blueprint system config",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_file_scores",
          "title": "Get file scores",
          "description": "Read the output scoring verdicts recorded against one file.\n\nReturns the current score per rule (0-100 with the judge's rationale), plus the headline\nscore stamped on the file by whichever rule its scope nominated — that stamp is what the\nlibrary badge and score sort read.\n\nAn empty `scores` list means the file has not been judged yet, not that it scored zero.\nCall score_files to have it judged; scoring is asynchronous, so poll this afterwards.",
          "annotations": {
            "title": "Get file scores",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_forge_instructions",
          "title": "Get model generation instructions",
          "description": "Get the guide for generating with a single model (execute_forge, get_forge_run, estimate_forge_price,\ncancel_inference). Read-only: returns text and runs nothing.\nCall this before generating. Covers the full generation lifecycle, guidance files, polling, and limits.\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Get model generation instructions",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_forge_run",
          "title": "Get model generation status",
          "description": "Get the status and output files of a single-model generation started with execute_forge.\nReturns generated asset URLs and metadata when complete. Poll at the suggested interval.\nPass the `inference_id` that execute_forge returned.\n\nIMPORTANT: Call `get_forge_instructions` for full lifecycle guidance.",
          "annotations": {
            "title": "Get model generation status",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_generation_run",
          "title": "Get generation run",
          "description": "Check status of a generation run launched with a generation tool (e.g. render_video_timeline).\nReturns the output asset URLs and metadata when complete.\nPass the `generation_id` that the launch tool returned.",
          "annotations": {
            "title": "Get generation run",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_instructions",
          "title": "Get instructions",
          "description": "Get general instructions for using the Layer MCP server.\nALWAYS call this tool first in order to understand the platform, available tools, and common patterns.\nAll other tools reference this for general guidance.",
          "annotations": {
            "title": "Get instructions",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_project",
          "title": "Get project",
          "description": "Get details for a single project in a workspace.\n\nReturns the project's name, status, linked object count, description, instructions,\nthe store ids its game is published under, and the user-explicit linked library\nobjects (paginated, newest first). Implicit links (auto-added via generation\nworkflows) are counted but not returned here.\nUse list_projects to discover project ids.\n\n`instructions` is deprecated: standing guidance for a project belongs in a skill\nattached to it, and this field reads back null once a project's instructions have\nbeen converted into one.",
          "annotations": {
            "title": "Get project",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_reference_set",
          "title": "Get reference set",
          "description": "Fetch everything about a reference set: its metadata, files and trained finetunes.\n\nA reference set is a curated collection of reference files (images, video, audio; optionally\ncaptioned) describing a character, style or concept, and may carry trained finetunes. Call this to\ninspect, analyze, or describe a reference set. It returns the set's name, description, category,\nstatus and color palette, every attached reference file with its download URL, content type,\ncaption, and multi-view tag, the set's logo and font files as `brand_assets`, and its trained\nfinetunes as `trained_bindings` (a `voice` binding means the set speaks in a trained voice on that\ntext-to-speech model).\n\nUse the returned `file_id` / `url` to act on individual files (e.g. analyze_media, or as a\nreference input for generation). Pass a `brand_assets` logo as a guidance image only when the\nuser asks for it. Do not surface raw UUIDs or download URLs in prose.\n\nFor forge lifecycle guidance, call get_forge_instructions.",
          "annotations": {
            "title": "Get reference set",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_trained_model",
          "title": "Get trained model",
          "description": "Retrieve the trained LoRA for a completed training run. Gated on\nterminal-success — if the run is not complete, raises so the caller polls first.",
          "annotations": {
            "title": "Get trained model",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_training_status",
          "title": "Get training status",
          "description": "Poll a training run. Maps run status to in_progress / terminal_success /\nterminal_failure. Do not fetch the trained model until terminal_success.",
          "annotations": {
            "title": "Get training status",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_workflow_instructions",
          "title": "Get workflow instructions",
          "description": "Get detailed instructions for running generation workflows.\nCall this before using workflow tools. Covers the full generation lifecycle, file inputs, polling, and pricing.\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Get workflow instructions",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_workflow_run",
          "title": "Get workflow run",
          "description": "Check status of a running workflow.\nReturns step information while in progress. Can be used to display a compact progress summary, and to display the completed/total ratio.\nReturns full results (asset URLs, metadata, price) only when generation is complete. Poll at the suggested interval.\n\nFor multi-step workflow guidance, call get_workflow_instructions.",
          "annotations": {
            "title": "Get workflow run",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_workspace",
          "title": "Get workspace",
          "description": "Get details for a single workspace including Creative Units balance.\n\nReturns workspace id, slug, display name, balance, reserved units, available balance,\nand last activity timestamp. The authenticated user must be a member of the workspace.\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Get workspace",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "import_workflow",
          "title": "Import workflow",
          "description": "Import a complete workflow graph as a new private workflow, optionally into a project.\n\nSaves a definition only: importing runs none of the graph's steps and spends no Creative\nUnits. The graph may only use the node kinds get_blueprint_system_config lists, all of them\nLayer operations; running the workflow later is a separate execute_workflow call.\n\nUse this to bring in a workflow authored outside the Blueprint editor, such as one\nconverted from another workflow tool, in one call. Call get_blueprint_system_config\nfirst for the node kinds, ports and value schemas the graph must use, then call with\n`validate_only=true` and fix the reported problems until `is_valid` is true.\n\nThe workflow is always created private and unfeatured; making it public or featured is\na separate curation step in the app. By default the version is published so the\nworkflow can run right away with execute_workflow; an invalid graph is then rejected and\nnothing is created. With `publish=false` a draft is created even when the graph has\nproblems.\n",
          "annotations": {
            "title": "Import workflow",
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_base_models",
          "title": "List base models",
          "description": "List the base AI models available for generation in a workspace.\n\nSourced from the model registry and the workspace's feature config — not the Style table —\nso every enabled base model is listed. Results are ranked by the requested `sort`, which\ndefaults to Layer's curated recommendation order.\n\nTo choose a model for a task, pass `filter.use_case` (and any required capabilities) and\ntake the first result. When the task has craft knowledge attached to it — pixel art,\nstoryboards, seamless textures, and similar — load the matching `model-guidance` skill for\nprompt and workflow technique before generating.\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "List base models",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_output_scoring_rules",
          "title": "List output scoring rules",
          "description": "List the output scoring rules in force for a workspace or project.\n\nEach rule is a studio's own standard that generated assets are judged against, scored\n0-100. Read this before score_files to know what a scope asks and which rule ids you can\nnarrow to, and after get_file_scores to interpret a score — the same number means\ndifferent things under different rules.\n\nRules cannot be authored here; they are configured in workspace or project settings.",
          "annotations": {
            "title": "List output scoring rules",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_projects",
          "title": "List projects",
          "description": "List projects in a workspace with their name, status, and linked object count.\n\nProjects group related library objects (images, videos, models, etc.) into a shared\ncollection. By default only active projects are returned; set filter.include_archived\nto also include archived projects. Deleted projects are never returned.",
          "annotations": {
            "title": "List projects",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_reference_sets",
          "title": "List reference sets",
          "description": "List the reference sets (the user's trained styles / custom models) for a workspace.\n\nReturns compact summaries; optional fulltext matches on name/description. Only sets that are\nready to generate with are listed: archived sets, and empty ones — no usable input files, no\nactive finetune, and no prompt fragments — are omitted.\n\nFor forge lifecycle guidance, call get_forge_instructions.",
          "annotations": {
            "title": "List reference sets",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_training_runs",
          "title": "List training runs",
          "description": "List training runs for the workspace (filterable by reference set and state).\n\nUse this to answer \"how's my training going?\" without a specific run id.\nResults are paginated.",
          "annotations": {
            "title": "List training runs",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_workflows",
          "title": "List workflows",
          "description": "List the saved generation workflows (published blueprints) in a workspace. Read-only.\n\nA workflow is a fixed pipeline of Layer operations (model generations, image/video/audio\nedits and fixed values) that the user built in Layer. Each entry carries its input/output\nschemas, which execute_workflow validates `inputs` against.\n\nFor multi-step workflow guidance, call get_workflow_instructions.",
          "annotations": {
            "title": "List workflows",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_workspaces",
          "title": "List workspaces",
          "description": "List every workspace the current user belongs to.\n\nReturns workspace id, slug, display name, and last activity timestamp for each\nworkspace, ordered by most recently active first. Does NOT include Creative Units\nbalance — call `get_workspace` with a workspace_id to get the balance for one\nworkspace (do not call it for every workspace just to compare balances).\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "List workspaces",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "pack_sprite_sheet",
          "title": "Pack sprite sheet",
          "description": "Pack separate frame images into one uniform-cell sprite sheet on a transparent background.\n\nA deterministic file operation: no model runs and no Creative Units are spent. Frames fill\nthe grid in the order given; every frame is centred at its own scale in a cell of one size,\nso frames cut from one sheet or drawn at one scale stay registered. The tool centres: it\ndoes not align ground lines or rescale one frame against another. A frame larger than the\ncell is scaled down to fit, never cropped; a smaller one is never enlarged.\n\nWhen every frame is a game tile (made with `tile_grid`), the frames are aligned on their\nanchor instead: each keeps its scale, every frame's anchor (the bottom centre of the cell it\nstands on) sits at the same point of its cell, `cell_width`/`cell_height` are ignored, and\n`frames` lists each frame's rect on the sheet with its cell centre, anchor and Unity pivot.\nFor a tileset an engine imports directly, use `export_tileset` instead. The sheet is saved to the\nworkspace library and, when the call runs in a session, placed on its board\n(`sheet.placed_on_board`).",
          "annotations": {
            "title": "Pack sprite sheet",
            "readOnlyHint": false,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "render_text",
          "title": "Render text",
          "description": "Render exact text into a PNG in a chosen font, such as an uploaded brand font.\n\nA deterministic file operation: no model runs and no Creative Units are spent. Use it for\ntext that must read exactly or be set in a given typeface: image models misspell text and\ncannot use a font file. It sets flat, single-colour type, so lettering that must look drawn\ninto the art is a generation instead. The font is a workspace font file (`font_file_id`) or\nelse a named `font_family`. The text wraps at the canvas width and sits on the canvas by\nits alignments; text that does not fit is refused with the size it needs. The background is\ntransparent unless `background_color` is set. Size the canvas to roughly the box the text\nwill fill in the final image, so it is barely scaled there. To letter an image, pass the\nreturned `file_id` to `compose_image` as a layer above the base image, placed with\n`anchors` and sized with `fit_and_pad`.\nThe image is saved to the workspace library and, when the call runs in a session, placed on\nits board (`image.placed_on_board`).",
          "annotations": {
            "title": "Render text",
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": false
          }
        },
        {
          "name": "render_video_timeline",
          "title": "Render video timeline",
          "description": "Edit assets the user already has into ONE finished video — sequence clips, add transitions, overlay\ntext or logos, layer audio. This is editing, not generating new content.\n\nEstimate with `estimate_video_timeline_price` first. The render is asynchronous; check the returned\n`generation_id` with `get_generation_run`.\n\nPass `timeline_object_id` whenever that board timeline already exists — one you placed with\n`create_canvas_timeline` or read with `read_canvas_timelines` — so the render updates it in place\ninstead of placing a duplicate. It is the one input `estimate_video_timeline_price` does not take,\nso add it back on top of the arguments you estimated with. Omit it only when no board timeline\nexists yet.",
          "annotations": {
            "title": "Render video timeline",
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "request_file_upload_url",
          "title": "Request file upload URL",
          "description": "Request a signed URL to upload a file directly to storage.\n\nReturns a signed upload URL and file_id. After receiving the URL, perform\nthe upload using this two-step resumable upload flow:\n\nStep 1 — Initiate the resumable upload:\n  POST {upload_url}\n  Headers:\n    Content-Type: {content_type}\n    x-goog-resumable: start\n  Body: (empty)\n  Response: 201 with Location header containing the session URI.\n\nStep 2 — Upload file content:\n  PUT {session_uri_from_Location_header}\n  Headers:\n    Content-Type: {content_type}\n  Body: raw file bytes\n  Response: 200 on success.\n\nAfter upload completes, use the returned file_id as input to generation tools.\nThe upload URL expires in 15 minutes. Maximum file size: 100 MB for video, 64 MB for images and audio.\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Request file upload URL",
            "readOnlyHint": false,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "score_files",
          "title": "Score files",
          "description": "Score files against the workspace's (and optionally a project's) output scoring rules.\n\nEach rule is a studio's own standard — \"does this read as our art direction?\" — judged by a\nvision model against the rule's prompt and reference images, returning 0-100 with a\nrationale. Use list_output_scoring_rules to see what a scope asks; use get_file_scores to\nread the verdicts back.\n\nAsynchronous and billed: returns as soon as the run is queued, and every (file, rule) pair\nis a model call that spends creative units. Poll get_file_scores for the results — a large\nrequest takes a few minutes. Scoring the same file again is allowed and appends a fresh\nverdict rather than replacing the old one.",
          "annotations": {
            "title": "Score files",
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "split_sprite_sheet",
          "title": "Split sprite sheet",
          "description": "Cut a sprite sheet into its cells as separate image files, in reading order.\n\nA deterministic file operation: no model runs and no Creative Units are spent. Frames keep\ntheir full cell so an animation cycle stays registered; use `inset` to drop thin gutters or\ndivider lines rather than trimming. The frames are saved to the workspace library and, when\nthe call runs in a session, placed on its board (each frame reports `placed_on_board`) —\nreference them by `file_id` afterwards. All frames are written or none: a failure part-way\ndeletes the frames already written, so the call can simply be retried.",
          "annotations": {
            "title": "Split sprite sheet",
            "readOnlyHint": false,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "start_training",
          "title": "Start training",
          "description": "Submit a LoRA training job for a reference set.\n\nAsynchronous: returns a training_run_id immediately. Errors: invalid-dataset\n(too few images / missing captions), unknown-base-model (id not trainable),\nunsupported-training-framework (framework not available for this base model),\nmodel-disabled (base model disabled for this workspace), insufficient-balance\n(not enough Creative Units), and internal errors when the run fails to start.\nOther coded errors propagate unchanged.\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Start training",
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "upload_file",
          "title": "Upload file",
          "description": "Upload an image or video file from a URL for use as workflow input.\n\nReturns a file_id to pass as input to workflows or forge runs. Upload files before\nexecuting a generation — uploaded files can be reused across multiple runs.\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "Upload file",
            "readOnlyHint": false,
            "destructiveHint": false,
            "openWorldHint": true
          }
        }
      ],
      "resources": [
        {
          "uri": "ui://layer/execute-generation",
          "name": "execute-generation",
          "mimeType": "text/html;profile=mcp-app"
        }
      ],
      "mcp_apps": {
        "supported": true,
        "specification": {
          "name": "MCP Apps",
          "extension": "io.modelcontextprotocol/ui",
          "version": "2026-01-26",
          "url": "https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx",
          "documentation_url": "https://apps.extensions.modelcontextprotocol.io/api/"
        },
        "mime_type": "text/html;profile=mcp-app",
        "view_delivery": "inline",
        "view_url_template": "https://mcp.app.layer.ai/apps/{view}/index.html",
        "description": "Layer's creative MCP server ships an MCP Apps view. Tools that carry `_meta.ui.resourceUri` return a `ui://` HTML resource the host renders inline, so a generation appears as an interactive result in the conversation rather than as a run id to poll. Hosts that do not negotiate the `io.modelcontextprotocol/ui` extension are unaffected — the tools return their normal structured result.",
        "documentation_url": "https://layer.ai/docs/mcp",
        "views": [
          {
            "uri": "ui://layer/execute-generation",
            "name": "execute-generation",
            "mimeType": "text/html;profile=mcp-app",
            "url": "https://mcp.app.layer.ai/apps/execute-generation/index.html"
          }
        ],
        "tools": [
          {
            "name": "execute_forge",
            "resource_uri": "ui://layer/execute-generation"
          },
          {
            "name": "execute_workflow",
            "resource_uri": "ui://layer/execute-generation"
          }
        ]
      }
    },
    {
      "name": "Layer Management MCP Server",
      "id": "management",
      "description": "Administer a workspace: projects, groups, members, roles, usage limits, and Creative Unit consumption. Kept separate so admin tools do not crowd the creative toolset.",
      "url": "https://mcp.app.layer.ai/mcp-management",
      "transport": "streamable-http",
      "documentation_url": "https://layer.ai/docs/mcp/management",
      "setup_url": "https://layer.ai/docs/mcp/management/setup",
      "instructions": "Layer workspace management server. Use these tools to administer a workspace: invite, suspend, and reactivate members; create, update, and delete projects; add and remove project members; and review Creative Units usage. Start with list_workspaces to find a workspace id, then list_workspace_members / list_projects to find the members and projects to act on. Every operation runs as your Layer user and is subject to your workspace role.\n\nIf any tool call fails with an authentication error (401 Unauthorized), tell the user they need to connect their Layer account by completing the OAuth flow in their MCP client settings.",
      "authorization": {
        "type": "oauth2",
        "flow": "authorization_code",
        "pkce_required": true,
        "dynamic_client_registration": true,
        "authorization_servers": [
          "https://auth.app.layer.ai/"
        ],
        "authorization_server_metadata": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
        "scopes_supported": [
          "openid",
          "profile",
          "email",
          "offline_access"
        ],
        "description": "Unauthenticated requests return 401 with a `WWW-Authenticate: Bearer resource_metadata=…` challenge pointing at the RFC 9728 protected-resource metadata for that server. Follow it to the authorization server, register dynamically, and run the authorization-code + PKCE flow.",
        "protected_resource_metadata": "https://mcp.app.layer.ai/.well-known/oauth-protected-resource/mcp-management"
      },
      "tool_count": 22,
      "tools": [
        {
          "name": "add_group_member",
          "description": "Add a workspace member to a group by email (they must already be a workspace member).\n\nFails for identity-provider-managed groups. Requires workspace billing-admin permission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "add_project_members",
          "description": "Add existing workspace members to a project by email.\n\nEvery email must already be an active member of the project's workspace (invite them\nto the workspace first with invite_member). The add is all-or-nothing and idempotent.\nRequires workspace project-edit permission plus being a project member (workspace\nadmins are exempt).",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "create_group",
          "description": "Create a workspace group, optionally granting its members a role.\n\nMembers added to a role-bearing group inherit that role's permissions. Requires\nworkspace billing-admin permission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "create_project",
          "description": "Create a new project in a workspace.\n\nProjects group related library objects into a shared collection. The caller is\nadded as the project's first member. Fails if a project with the same name already\nexists in the workspace or the workspace project limit is reached. Requires\nworkspace project-edit permission.\n\n`instructions` is deprecated: attach a skill to the project instead of writing\nstanding guidance here.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "delete_group",
          "description": "Delete a workspace group, revoking its role and cap from members.\n\nFails for identity-provider-managed groups (delete them in the IdP). Requires workspace\nbilling-admin permission.",
          "annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false
          }
        },
        {
          "name": "delete_project",
          "description": "Delete a project (soft-delete: it is removed from listings and can't be used).\n\nOnly the project's creator or a workspace admin may delete it, and public projects\ncannot be deleted. Requires workspace project-delete (or admin-settings) permission.",
          "annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false
          }
        },
        {
          "name": "get_project",
          "title": "Get project",
          "description": "Get details for a single project in a workspace.\n\nReturns the project's name, status, linked object count, description, instructions,\nthe store ids its game is published under, and the user-explicit linked library\nobjects (paginated, newest first). Implicit links (auto-added via generation\nworkflows) are counted but not returned here.\nUse list_projects to discover project ids.\n\n`instructions` is deprecated: standing guidance for a project belongs in a skill\nattached to it, and this field reads back null once a project's instructions have\nbeen converted into one.",
          "annotations": {
            "title": "Get project",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "get_workspace_usage",
          "description": "Report a workspace's Creative Units balance and recent consumption.\n\nReturns the current balance (available and reserved) plus the total and per-day\nCreative Units consumed over the last `days` days (default 30). Use this to see how\nmuch a workspace has spent and how much it has left. Requires workspace billing\n(member) permission.",
          "annotations": {
            "readOnlyHint": true
          }
        },
        {
          "name": "invite_member",
          "description": "Invite a user to a workspace by email, creating the Layer user if needed.\n\nThe invited user is added with the given role (default: member) and an ACTIVE\nmembership; they receive an invite notification. Fails if the workspace has\ninvites disabled or the user is already a member. Requires workspace member-edit\npermission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "list_group_members",
          "description": "List a group's members with their email and status.\n\nRequires workspace billing-admin permission on the group's workspace.",
          "annotations": {
            "readOnlyHint": true
          }
        },
        {
          "name": "list_groups",
          "description": "List a workspace's groups with their name and granted role.\n\nGroups bundle members under a shared workspace role and/or a Creative-Units cap. Use\nthis to find group ids for the other group tools. Requires workspace billing-admin.",
          "annotations": {
            "readOnlyHint": true
          }
        },
        {
          "name": "list_projects",
          "title": "List projects",
          "description": "List projects in a workspace with their name, status, and linked object count.\n\nProjects group related library objects (images, videos, models, etc.) into a shared\ncollection. By default only active projects are returned; set filter.include_archived\nto also include archived projects. Deleted projects are never returned.",
          "annotations": {
            "title": "List projects",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "list_workspace_members",
          "description": "List the members of a workspace with their email, role, and status.\n\nUse this to discover who belongs to a workspace and to find the email addresses\nthat the suspend_member, reactivate_member, add_project_members, and\nremove_project_member tools take. Both active and suspended members are returned.",
          "annotations": {
            "readOnlyHint": true
          }
        },
        {
          "name": "list_workspaces",
          "title": "List workspaces",
          "description": "List every workspace the current user belongs to.\n\nReturns workspace id, slug, display name, and last activity timestamp for each\nworkspace, ordered by most recently active first. Does NOT include Creative Units\nbalance — call `get_workspace` with a workspace_id to get the balance for one\nworkspace (do not call it for every workspace just to compare balances).\n\nIMPORTANT: Call tool `get_instructions` first for general platform guidance.",
          "annotations": {
            "title": "List workspaces",
            "readOnlyHint": true,
            "destructiveHint": false,
            "openWorldHint": false
          }
        },
        {
          "name": "reactivate_member",
          "description": "Reactivate a suspended workspace member, restoring their access.\n\nThe membership is set back to ACTIVE with its previous role. This is the inverse\nof suspend_member. Fails if the workspace has invites disabled or the email is not\na current member. Requires workspace member-edit permission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "remove_group_member",
          "description": "Remove a member from a group by email.\n\nFails for identity-provider-managed groups. Requires workspace billing-admin permission.",
          "annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false
          }
        },
        {
          "name": "remove_group_usage_limit",
          "description": "Remove a group's Creative-Units cap.\n\nRequires workspace billing-admin permission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "remove_project_member",
          "description": "Remove a member from a project by email.\n\nRemoving another member requires workspace project-edit permission plus being a\nproject member (workspace admins are exempt); a user can always remove themselves.\nDoes not remove them from the workspace — use suspend_member for that.",
          "annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false
          }
        },
        {
          "name": "set_group_usage_limit",
          "description": "Set a group's Creative-Units cap for a period.\n\nRequires workspace billing-admin permission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "suspend_member",
          "description": "Suspend a workspace member, revoking their access without deleting them.\n\nThe membership is set to SUSPENDED (reversible with reactivate_member); the\nmember's role is preserved. Fails if the workspace has suspends disabled or the\nemail is not a current member. Requires workspace member-edit permission.",
          "annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false
          }
        },
        {
          "name": "update_group_role",
          "description": "Set or clear the workspace role a group grants its members.\n\nTakes effect immediately for all members. Requires workspace billing-admin permission.",
          "annotations": {
            "readOnlyHint": false
          }
        },
        {
          "name": "update_project",
          "description": "Update a project's name, description, instructions, or archive status.\n\nContent fields (name/description/instructions) can only be changed while the project\nis active — unarchive it first. To delete a project use delete_project. Requires\nworkspace project-edit permission.\n\n`instructions` is deprecated: attach a skill to the project instead of writing\nstanding guidance here.",
          "annotations": {
            "readOnlyHint": false
          }
        }
      ],
      "resources": [],
      "mcp_apps": {
        "supported": false,
        "specification": {
          "name": "MCP Apps",
          "extension": "io.modelcontextprotocol/ui",
          "version": "2026-01-26",
          "url": "https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx",
          "documentation_url": "https://apps.extensions.modelcontextprotocol.io/api/"
        },
        "views": [],
        "tools": []
      }
    }
  ],
  "mcpServers": {
    "layer": {
      "type": "http",
      "url": "https://mcp.app.layer.ai/mcp"
    },
    "layer-management": {
      "type": "http",
      "url": "https://mcp.app.layer.ai/mcp-management"
    }
  },
  "developer_resources": [
    {
      "name": "Layer developer documentation",
      "url": "https://layer.ai/docs",
      "type": "text/html"
    },
    {
      "name": "Layer API quickstart",
      "url": "https://layer.ai/docs/quickstart",
      "type": "text/html"
    },
    {
      "name": "Layer API authentication",
      "url": "https://layer.ai/docs/authentication",
      "type": "text/html"
    },
    {
      "name": "Layer REST API reference",
      "url": "https://layer.ai/docs/v2/rest-api",
      "type": "text/html"
    },
    {
      "name": "Layer OpenAPI description",
      "url": "https://layer.ai/openapi.json",
      "type": "application/json"
    },
    {
      "name": "Layer API index",
      "url": "https://layer.ai/api/index.json",
      "type": "application/json"
    },
    {
      "name": "Layer agent onboarding",
      "url": "https://layer.ai/api/onboarding.json",
      "type": "application/json"
    },
    {
      "name": "Layer self-serve access guide",
      "url": "https://layer.ai/docs/self-serve-access",
      "type": "text/html"
    },
    {
      "name": "Layer API catalog",
      "url": "https://layer.ai/.well-known/api-catalog",
      "type": "application/linkset+json"
    },
    {
      "name": "Layer AI catalog",
      "url": "https://layer.ai/.well-known/ai-catalog.json",
      "type": "application/json"
    },
    {
      "name": "Layer ARD manifest",
      "url": "https://layer.ai/.well-known/ard.json",
      "type": "application/json"
    },
    {
      "name": "Layer Agent Skills index",
      "url": "https://layer.ai/.well-known/agent-skills/index.json",
      "type": "application/json"
    },
    {
      "name": "Layer Agent Skills pack",
      "url": "https://layer.ai/agent-skills",
      "type": "text/html"
    },
    {
      "name": "Layer MCP server",
      "url": "https://layer.ai/mcp",
      "type": "text/html"
    },
    {
      "name": "Layer command-line interface",
      "url": "https://layer.ai/cli",
      "type": "text/html"
    },
    {
      "name": "Layer command-line interface on PyPI",
      "url": "https://pypi.org/project/layer/",
      "type": "text/html"
    },
    {
      "name": "Layer JavaScript SDK",
      "url": "https://layer.ai/docs/sdk",
      "type": "text/html"
    },
    {
      "name": "Layer JavaScript SDK on npm",
      "url": "https://www.npmjs.com/package/@layer_ai/sdk",
      "type": "text/html"
    },
    {
      "name": "Layer MCP manifest",
      "url": "https://layer.ai/.well-known/mcp",
      "type": "application/json"
    },
    {
      "name": "Layer MCP setup guide",
      "url": "https://layer.ai/docs/mcp/setup",
      "type": "text/html"
    },
    {
      "name": "Layer API rate limits",
      "url": "https://layer.ai/docs/rate-limits",
      "type": "text/html"
    },
    {
      "name": "Layer API versioning",
      "url": "https://layer.ai/docs/versioning",
      "type": "text/html"
    },
    {
      "name": "Layer API deprecation policy",
      "url": "https://layer.ai/docs/deprecation",
      "type": "text/html"
    },
    {
      "name": "Layer API errors",
      "url": "https://layer.ai/docs/errors",
      "type": "text/html"
    },
    {
      "name": "Layer OAuth authorization server metadata",
      "url": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
      "type": "application/json"
    }
  ]
}
