---
title: Setup and Generation tools
description: The Extentos MCP server's Setup and Generation surface — generateConnectionModule (the one-shot project scaffold that emits the bootstrap module, build-script changes, dependencies, permissions, and the integration manifest) plus the four connection-page-config tools (getConnectionPageConfig, setConnectionPageConfig, regenerateConnectionPageFile, adoptConnectionPageFile). After scaffolding, the customer (or their agent) writes handler classes against the SDK primitives surfaced by getCapabilityGuide / getCodeExample.
type: reference
platform: mcp
related:
  - /docs/mcp-server/tools
  - /docs/mcp-server/tools/discovery
  - /docs/mcp-server/tools/validation
---

Post pure-SDK pivot, the Setup and Generation category is **five tools**: `generateConnectionModule` (the one-shot project scaffold, below) plus four connection-page-config tools that manage the per-project theming / section-visibility config the dashboard holds. Handler code is the customer's authoring surface — there is no `initSpec` / `updateSpec` / `generateConsumer` because there's no spec to populate, no callback dispatch table to generate. The agent peels from `getCodeExample(pattern)` to write the handler in Kotlin/Swift directly.

> **For your installed agent:** call `generateConnectionModule` once per fresh project, then write handler classes. Subsequent code iterations don't need any more generation tool calls — rebuild + reinstall the app and the simulator auto-reattaches. This page is the reference for the one tool that does emit files.

## `generateConnectionModule`

One-shot project scaffold. Emits the bootstrap module that wires `Extentos.create(...)` into the host app, build-script changes (Gradle / SPM), dependencies, permissions, and `extentos.manifest.json`. Two-call flow: the first call returns a placement question; the second call (after the developer picks where `ExtentosConnectionPage` should live) returns the full file set.

### When to use

- Exactly once per platform per project — Android scaffolding on first Android target, iOS scaffolding on first iOS target
- After Extentos is removed (e.g., the dev wiped the `/extentos` directory) and you need to re-scaffold

### When NOT to use

- When Extentos is already installed (use `inspectIntegration` to read current state)
- For per-handler code generation — there is no per-handler tool; write the handler against the SDK primitives by hand

### Parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `platform` | `"android" \| "ios"` | yes | Target platform for this scaffold call |
| `glasses` | `"meta" \| "meta_rayban" \| "android_xr"` | yes | Vendor. **Canonical: `meta`**; `meta_rayban` is a legacy alias for the same vendor. `android_xr` is accepted by the schema but scaffolding is Meta-only today, so it is rejected with a dedicated message. |
| `appPackage` | string | yes | The **Extentos app id** for this project (e.g. `com.example.myapp`) — baked into the scaffold as `config.appId`, which keys telemetry, agent config, and sounds. Conventionally your Android `applicationId` / iOS bundle identifier, but deliberately **decoupled** from the store id: pass the SAME value on both platforms and they share one Extentos project even when the store bundle ids differ. |
| `libraryVersion` | string | no | Pin to a specific library version. Defaults to latest stable. |
| `placement` | enum | conditional | `dedicated_route` / `settings_subscreen` / `bottom_tab` / `modal_sheet` / `headless`. Omit on the first call to receive the placement question. |
| `projectPath` | string | no | Absolute path to the project root. **Android:** when given, the handler reads `AndroidManifest.xml` and, if you already have an `Application` subclass, emits an init-helper `object` + a `manual_patch` for it instead of clobbering your class. Omit → greenfield (emits a full `Application` subclass). |
| `capabilities` | string[] | no | The SDK capabilities your app uses (feature names from `getPlatformInfo`, e.g. `["capture_photo", "transcription_incremental", "speak", "display"]`). Recorded in the manifest **and** emitted as `ExtentosConfig.usedCapabilities` on both platforms (Kotlin `setOf(CapabilityKind.X, …)` / Swift `[.camera, …]`) so the connection page shows one tile per capability — lit when the connected glasses provide it, dimmed when they don't. Omit → no capability tiles and no derived camera/mic/speaker permissions (declare nothing, show nothing — valid for a connection-only app; re-run with `capabilities` set to add them). |
| `responseFormat` | `"concise" \| "detailed"` | no | `detailed` (default) includes per-step `wireInstructions` + `notes`. `concise` omits the per-step `wireInstructions` + `notes`; it still returns the full files / dependencies / rendering payload. |

### Two-call flow

**Call 1 — without `placement`:**

```json
{ "platform": "android", "glasses": "meta_rayban", "appPackage": "com.example.myapp" }
```

Returns `status: "needs_placement"` plus the placement question and the 5 valid IDs. The agent reads the question to the developer, gets their pick, and calls again.

**Call 2 — with `placement`:**

```json
{ "platform": "android", "glasses": "meta_rayban", "appPackage": "com.example.myapp", "placement": "dedicated_route" }
```

Returns the full file set: `files[]` (the bootstrap module to write), `manifest` (the `extentos.manifest.json` content), `dependencies[]`, `repositories[]`, `buildConfigFields[]`, `permissions[]`, `suggestedRendering` (the Compose / SwiftUI snippet for the chosen placement), plus `developerInstructions` walking the agent through applying everything.

### What gets emitted

- **`files[]`** — `ExtentosBootstrap.kt` (Android) or `ExtentosBootstrap.swift` (iOS), with `action: "create"` (fully tool-managed; safe to overwrite on re-run). On iOS, also an `action: "manual_patch"` entry for the developer's `App.swift` with `onOpenURL` + `scenePhase` wiring instructions.
- **`manifest`** — `extentos.manifest.json` v2 content: library version, installedAt, platform / glasses / appPackage metadata, `gradle` or `spm` build-config record, empty `permissions[]` + `capabilities[]` + `handlerNames[]` arrays for the agent to populate as the handler grows.
- **`dependencies[]`** — `com.extentos:glasses` + `com.extentos:glasses-ui` (Android), **plus `com.extentos:glasses-meta` when the declared `capabilities` include camera or display** — that module is what carries the vendor SDK; a voice-only footprint omits it
- **`repositories[]`** — the Meta DAT GitHub Packages repo (Android only), for the `mwdat-*` artifacts that arrive through `com.extentos:glasses-meta`. **Emitted ONLY for a camera/display footprint** — a voice-only scaffold returns an empty `repositories[]` and needs no token.
- **`buildConfigFields[]`** — `EXTENTOS_SESSION_URL = null` placeholder (Android). Default null routes to auto-bind; only a URL-bake fallback (from `createSimulatorSession`) replaces it.
- **`permissions[]`** — base Bluetooth + INTERNET permissions. Capability-specific permissions get added later when the agent calls `getPermissions(capabilities, platform)` after declaring capabilities in the manifest.
- **`suggestedRendering`** — the Compose (Android) or SwiftUI (iOS) snippet for the chosen `placement`. Same shape `searchDocs(topic: "connection_ui_placement")` returns.
- **`developerInstructions`** — numbered steps for the agent to apply the scaffold + know what to do next (write handler code, update manifest.capabilities, validateIntegration, …).

### What does NOT get emitted

- Handler classes. Those are the customer's authoring surface. The agent peels from `getCodeExample(pattern)` and writes them directly to the customer's repo.
- An `extentos.spec.json`. There is no spec runtime post-pivot.
- Callback dispatch stubs. There is no `app_callback` dispatch.

### Errors

- **`invalid_arguments` — `platform must be "android" or "ios"`**
- **`invalid_arguments` — `glasses must be "meta" — or the legacy alias "meta_rayban"`** — `android_xr` gets its own message explaining that code scaffolding is Meta-only
- **`invalid_arguments` — `appPackage is required and must be a non-empty string`**
- **`invalid_arguments` — `placement must be one of dedicated_route, settings_subscreen, bottom_tab, modal_sheet, headless`** — only those 5 are valid
- **`account_required` (HTTP 402)** — the scaffold step (with `placement`) mints an account-bound project key; anonymous installs get the device-code login flow, same as `createSimulatorSession`. The informational first call (no `placement`) works anonymously

---

## Connection-page config tools

The connection page (the screen the end user sees to pair their glasses) can be themed and have its sections toggled per project. These four tools manage that config: the dashboard/server is the single source of truth when a project is **managed**, and a committed `extentos.connection-page.json` mirrors it into the repo so the app themes correctly offline. The writes are account-scoped (run `extentos-mcp login` once).

| Tool | Direction | What it does |
|---|---|---|
| `getConnectionPageConfig` | read | Read the per-project config (theming tokens + section visibility) the dashboard holds. Returns `{ managed, config }` — `managed: true` means the server is the single source of truth (the SDK applies `server.overlay(defaults)` at render time). |
| `setConnectionPageConfig` | write (server) | Persist theming tokens + section visibility to the dashboard, making the project **managed**. Validated against the connection-page schema; unknown keys surface as a warning, not a block. |
| `regenerateConnectionPageFile` | server → file | Regenerate the committed `extentos.connection-page.json` from the server config. Returns `{ path, content }` to write — it carries a generated `_comment` marker, so don't hand-edit it; edits belong in the dashboard. |
| `adoptConnectionPageFile` | file → server | Seed an existing committed `extentos.connection-page.json` up to the dashboard. Drift-protected: if a differing managed config already exists it returns `needs_confirmation` and does **not** clobber — re-call with `confirm: true` to let the file win. |

The file-sync pair (`regenerate` / `adopt`) is Android-only today (iOS file-sync is Phase 4). The web dashboard's **Connection** section is the human-facing equivalent of `set`.

---

## Retired generation tools

Pre-pivot the MCP server also exposed `initSpec`, `updateSpec`, and `generateConsumer`. All three are retired with the pure-SDK pivot:

- `initSpec` populated the first `extentos.spec.json` from agent-composed primitives → no spec to populate post-pivot.
- `updateSpec` mutated an existing spec and live-pushed the change to the simulator → no spec, no live-push.
- `generateConsumer` stubbed `app_callback` / stream-consumer handler classes from spec declarations → handler code is now hand-authored against the SDK directly.

Calls to these tool names against the post-pivot MCP server return `unknown_tool`. Use `getCodeExample(pattern)` for canonical compositions and write handler code directly.

## Related

- **[Discovery tools](/docs/mcp-server/tools/discovery)** — `getPlatformInfo` / `getCapabilityGuide` / `getCodeExample` (what the agent calls *before* this)
- **[Validation tools](/docs/mcp-server/tools/validation)** — `inspectIntegration` / `validateIntegration` (what the agent calls *after* this + after writing handler code)
- **[file_actions topic](/docs/mcp-server/tools/search)** — how to apply each `action` value (`create` / `manual_patch`)
