moka.json
Moka reads a single JSON file (see lookup order). Everything in the Settings UI maps to this file.
{ "$schema": "https://unpkg.com/@mokalabs/sandbox/dist/moka.schema.json", "version": 1, "activeWorkspaceId": "demo", "llms": [], "mcpServers": [], "skills": [], "agents": [], "catalogs": [], "workspaces": []}Environment references
Section titled “Environment references”Any secret-ish string (API keys, URLs, headers, env values, commands, args) supports:
| Syntax | Meaning |
|---|---|
env:NAME | The whole value is $NAME |
${NAME} | Interpolated inside a string, e.g. Bearer ${TOKEN} |
Missing variables resolve to an empty string.
llms[]
Section titled “llms[]”| Field | Type | Description |
|---|---|---|
id | string | Unique id, referenced by workspaces |
name | string | Display name |
provider | openai · anthropic · google · azure · ollama · openai-compatible | Provider type |
model | string | Model id (Azure: deployment name) |
apiKey | string? | Literal, env:NAME or ${NAME} |
baseURL | string? | Required for openai-compatible; optional override otherwise |
headers | object? | Extra HTTP headers |
resourceName | string? | Azure resource name |
apiVersion | string? | Azure API version |
useChatApi | boolean? | OpenAI: use Chat Completions instead of Responses |
stream | boolean? | false: ask for each reply in one response instead of a stream (for gateways that don’t stream reliably). Default: stream |
temperature | number? | 0–2 |
maxOutputTokens | integer? | |
providerOptions | object? | Passed to the AI SDK as providerOptions |
mcpServers[]
Section titled “mcpServers[]”| Field | Type | Description |
|---|---|---|
id | string | Unique id (also the tool-name prefix) |
name | string | Display name |
transport | stdio · http · sse | http is Streamable HTTP |
command | string? | stdio: executable. moka:demo = built-in demo server |
args | string[]? | stdio: arguments |
env | object? | stdio: extra environment variables |
cwd | string? | stdio: working directory |
url | string? | http/sse: endpoint |
headers | object? | http/sse: request headers |
disabledTools | string[]? | Tools hidden from the model |
timeoutMs | integer? | Connect timeout (default 30000), and the tool-call timeout when toolTimeoutMs isn’t set |
toolTimeoutMs | integer? | How long to wait for a tool call (default 120000) |
resetTimeoutOnProgress | boolean? | Progress notifications restart the tool timeout (default true; the MCP SDK’s own default is false) |
maxTotalTimeoutMs | integer? | Hard limit for a tool call, even while progress keeps arriving |
oauth | boolean | object? | http/sse: false disables OAuth sign-in; { clientId?, clientSecret?, scopes? } for pre-registered clients. See sign-in |
sampling | ask · auto · deny? | How to handle MCP sampling requests (default: ask) |
protocol | auto · 2025 · 2026? | MCP revision. auto uses 2026-07-28 when the server offers it (default for http and the demo server); 2025 for stdio and sse by default. See MCP 2026-07-28 |
approval | object? | { default?: "auto" | "ask", tools?: { [tool]: "auto" | "ask" } }. See tool approvals |
skills[]
Section titled “skills[]”| Field | Type | Description |
|---|---|---|
id | string | Unique id |
path | string? | Skill folder or SKILL.md path (relative to the config file, ~ expanded) |
content | string? | Inline SKILL.md (instead of path) |
name | string? | Override frontmatter name |
description | string? | Override frontmatter description |
agents[]
Section titled “agents[]”Remote agents. See Remote agents.
| Field | Type | Description |
|---|---|---|
id | string | Unique id, referenced by workspaces[].agentId |
name | string | Display name |
protocol | a2a · ag-ui | |
url | string | A2A: agent card or endpoint. AG-UI: run endpoint |
headers | object? | Request headers (env:NAME / ${NAME} supported) |
shareTools | boolean? | AG-UI: offer the workspace’s MCP tools as frontend tools |
catalogs[]
Section titled “catalogs[]”A2UI component catalogs. See custom catalogs.
| Field | Type | Description |
|---|---|---|
id | string | Unique id, referenced by workspaces[].generativeUi.catalogIds |
name | string? | Display name override |
path | string? | Catalog JSON file (relative to the config file) |
url | string? | Catalog JSON over HTTP(S) |
catalog | object? | Inline catalog |
workspaces[]
Section titled “workspaces[]”| Field | Type | Description |
|---|---|---|
id | string | Unique id |
name | string | Display name |
llmId | string? | Default model (falls back to the first) |
agentId | string? | Chat with this remote agent instead of the model |
mcpServerIds | string[] | Enabled servers |
skillIds | string[] | Enabled skills |
systemPrompt | string? | |
starterPrompts | string[]? | Chips on an empty chat |
maxSteps | integer? | 1–100, default 12 |
generativeUi | boolean | object? | false to turn off the render tool, or settings: toolName, catalogIds, standard, allow, deny, instructions, description, examples, repair, theme. Default on |
requireApproval | boolean? | Ask before every MCP tool call in this workspace |
tests | object[]? | Tool tests: id, name?, prompt, expectTools?, forbidTools?, expectArgs? (by tool name), answerIncludes? |
App preferences, also under Settings → Config file → Preferences.
| Field | Type | Description |
|---|---|---|
branding | boolean? | Show Moka’s branding: the puppy and name in the header, the puppy and “What are we brewing?” on the empty chat, “Message Moka…” in the composer, the tab title and the star line. Default true. Set it to false for a neutral chat when you demo your own product |
animations | boolean? | Animate the puppy on the empty chat: its eyes follow your cursor, and it plays peekaboo when clicked. Default true. The OS “reduce motion” setting also stops it |
starLink | boolean? | Show the small “Star it on GitHub” line on the empty chat screen and in the terminal banner. Default true; the line’s Hide link sets it to false |
Full example
Section titled “Full example”{ "$schema": "https://unpkg.com/@mokalabs/sandbox/dist/moka.schema.json", "version": 1, "activeWorkspaceId": "support", "llms": [ { "id": "gpt", "name": "OpenAI", "provider": "openai", "model": "gpt-5-mini", "apiKey": "env:OPENAI_API_KEY" }, { "id": "gw", "name": "Gateway", "provider": "openai-compatible", "model": "llama-3.3-70b", "baseURL": "https://llm.internal.example.com/v1", "apiKey": "env:GATEWAY_KEY", "headers": { "X-Team": "support" } } ], "mcpServers": [ { "id": "demo", "name": "Demo tools", "transport": "stdio", "command": "moka:demo" }, { "id": "gh", "name": "GitHub", "transport": "http", "url": "https://api.githubcopilot.com/mcp/", "headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }, "disabledTools": ["delete_repository"] } ], "skills": [{ "id": "voice", "path": "skills/brand-voice" }], "workspaces": [ { "id": "support", "name": "Support", "llmId": "gpt", "mcpServerIds": ["demo", "gh"], "skillIds": ["voice"], "systemPrompt": "You are a friendly support agent.", "starterPrompts": ["Draft a reply to a late-delivery complaint"] } ]}