> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uselamina.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Integration Patterns

> How coding agents should use Lamina through MCP, discover apps safely, execute with webhooks, and consume results reliably.

## Use Hosted MCP When Your Agent Supports Remote Install

The preferred agent integration is Lamina's hosted remote MCP server. It lets MCP clients install Lamina through OAuth, bind access to a Lamina workspace, and call the five high-level creative tools without placing an API key in every tool call.

Install page:

```text theme={null}
https://app.uselamina.ai/mcp/install
```

Hosted endpoint:

```text theme={null}
https://app.uselamina.ai/mcp/agent
```

The endpoint supports OAuth discovery:

* protected resource metadata: `/.well-known/oauth-protected-resource/mcp/agent`
* authorization server metadata: `/.well-known/oauth-authorization-server`
* authorization endpoint: `/mcp/oauth/authorize`
* token endpoint: `/mcp/oauth/token`
* dynamic client registration: `/mcp/oauth/register`

Read [MCP OAuth Install](/guides/mcp-oauth-install) for the full install and verification flow.
Read [Agent Recipes](/guides/agent-recipes) for end-to-end create, wait, clarification, brand
context, and artifact reuse examples.
Use [Agent Runtime Benchmarks](/guides/agent-runtime-benchmarks) to measure install success, auth reliability, first generation time, clarification loops, and output usability across MCP clients.

## Use Local MCP When Your Agent Can Spawn Tools

If your agent platform only supports local stdio MCP, run the Lamina MCP server locally and let the agent call tools instead of hand-rolling HTTP requests.

Today, the MCP server lives in this repository and can be started with:

```bash theme={null}
lamina mcp serve
```

Or directly:

```bash theme={null}
npx -y @uselamina/mcp
```

The local stdio MCP server uses the same Lamina API key resolution order as the CLI:

1. explicit `--api-key`
2. `LAMINA_API_KEY`
3. saved CLI login from `~/.lamina/config.json`

## MCP Tool Surface

The MCP server intentionally exposes five high-level tools. This keeps agent tool selection simple while preserving the full `/v1` REST API for developer integrations and power users.

* `lamina_create` - create brand-aware content from a natural-language brief
* `lamina_status` - check a run or wait for generated assets
* `lamina_discover` - find what Lamina can make for a creative goal
* `lamina_brand` - load brand memory, guidance, and winning patterns
* `lamina_batch` - queue up to 10 related content creations

Lower-level operations such as direct app inspection, direct app execution, publishing, asset transfer, usage, templates, and webhook management remain available through `/v1`.

## Example MCP Client Configuration

For hosted remote MCP clients, add the remote server URL and complete OAuth in the client:

```json theme={null}
{
  "mcpServers": {
    "lamina": {
      "url": "https://app.uselamina.ai/mcp/agent"
    }
  }
}
```

For local agent clients that support a spawned process:

```json theme={null}
{
  "mcpServers": {
    "lamina": {
      "command": "npx",
      "args": ["-y", "@uselamina/mcp"],
      "env": {
        "LAMINA_API_KEY": "lma_your_api_key"
      }
    }
  }
}
```

If the agent runs under the same user account as your CLI login, it can also reuse the saved key from `~/.lamina/config.json`.

## Build Agents Around Outcomes, Not Raw APIs

Lamina apps are not single-shot utility functions. They are packaged creative workflows with asynchronous execution. Agents should usually describe the desired outcome to `lamina_create` instead of chaining low-level calls themselves.

An agent should treat Lamina as a system with:

* discoverable app capabilities
* brand-aware prompt and input mapping
* asynchronous execution
* polling-based result delivery through `lamina_status`
* typed outputs

The best integrations do **not** guess raw workflow inputs from app names alone. They let Lamina select and run the workflow, and only pass `appId` or advanced `inputs` when a developer already knows the exact workflow contract.

## Recommended Agent Flow

<Steps>
  <Step title="Create from a brief">
    Call `lamina_create` with the user's creative request, target platform, and modality when known.
  </Step>

  <Step title="Track the run">
    Call `lamina_status` with the returned `runId`. Set `wait=true` when the agent should block for final assets.
  </Step>

  <Step title="Discover options when unsure">
    Call `lamina_discover` when the user asks what Lamina can make, or when the agent needs workflow suggestions before creating.
  </Step>

  <Step title="Load brand context when useful">
    Call `lamina_brand` when the agent needs explicit voice, visual, guardrail, or pattern context for planning.
  </Step>

  <Step title="Batch related work">
    Call `lamina_batch` for catalog shots, campaign variants, or content series.
  </Step>
</Steps>

## Webhooks For REST Integrations

The MCP surface uses `lamina_status` for result polling. If you are building a server-side integration against `/v1`, you can use REST webhooks instead:

1. expose a public HTTPS callback URL from your integration
2. start a run with `POST /v1/apps/{appId}/runs?webhook=<public_callback_url>`
3. verify the signed callback when Lamina sends completion data

This lets your application react to the Lamina callback directly instead of polling.

## Direct REST App Runs

When using direct REST app execution instead of `lamina_create`, fetch app metadata unless you already have fresh metadata cached for that exact `appId`.

This is important because the app metadata is the source of truth for:

* parameter names
* whether fields are required
* valid `options` labels
* whether a field expects a media URL

## Use Parameter Names Exactly

When calling `POST /v1/apps/{appId}/runs`, `inputs` should be keyed by parameter name.

Example:

```json theme={null}
{
  "inputs": {
    "Front": "https://example.com/front.jpg",
    "Location": "Studio"
  }
}
```

Do not invent aliases or normalize parameter names unless your integration keeps a reliable mapping layer.

## Handle `options` Carefully

For parameters of type `options`, send one of the labels returned by the app metadata.

If the app says the valid options are:

```json theme={null}
["Male", "Female"]
```

then the execution request should send one of those exact labels.

## Prefer Webhooks In Production

For production agent integrations, always use webhooks instead of polling:

```
POST /v1/apps/{appId}/runs?webhook=https://your-agent.com/lamina-callback
```

Benefits over polling:

* No polling loop to manage
* Results arrive immediately when ready
* Signed with ED25519 - verify authenticity
* Automatic retries if your endpoint is temporarily down

For MCP clients, prefer `lamina_create` followed by `lamina_status` unless your integration needs direct REST webhook control.

## Webhook Payload Structure

The webhook payload matches the polling response exactly:

```json theme={null}
{
  "data": {
    "runId": "...",
    "workflowId": "...",
    "status": "completed",
    "outputs": [
      { "id": "...", "label": "Generated Image", "type": "image", "value": "https://...", "status": "completed", "error": null }
    ],
    "errorMessage": null,
    "startedAt": "...",
    "completedAt": "...",
    "createdAt": "..."
  }
}
```

`data.executionId` may also be present as a deprecated compatibility alias for `data.runId`. New integrations should store and compare `runId`.

## Read Output Type Before Consuming Value

Do not assume every output is an image URL.

Check:

* `type`
* `status`
* `value`

Examples of output types include:

* `image`
* `video`
* `text`
* `pending`

## Handle Failures Explicitly

If execution fails:

* inspect top-level `errorMessage`
* inspect each output's `error`
* avoid blindly retrying the same invalid inputs

If the failure is caused by invalid inputs, fetch the app metadata again and rebuild the request payload.

## Good Agent Behaviors

* use `lamina_create` for brief-to-result work
* cache app metadata briefly, but refresh when uncertain
* use `lamina_status` for MCP result delivery
* preserve `runId` for later retrieval
* branch logic on output `type`
* verify webhook signatures
* surface execution failure with the returned error details

## Poor Agent Behaviors

* guessing parameter names from natural language
* sending internal option IDs that were never returned by the API
* treating execution as synchronous
* resubmitting the same long-running request repeatedly because output is not immediate
* ignoring webhook signatures
