Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [Unreleased]

### Added

- Added `shutdown_sim` (CLI: `mobilebuildmcp simulator-management shutdown`) to shut down a simulator by `simulatorId` or `simulatorName`. Shutting down a simulator that is not booted reports the `simctl` error.

### Changed

- `sim_statusbar` now accepts `time`, `wifiMode`, `wifiBars`, `cellularMode`, `cellularBars`, `batteryState`, and `batteryLevel` overrides, and `dataNetwork` is optional. All supplied fields are applied in one `simctl status_bar override` call; at least one field is required, and `dataNetwork: "clear"` must be used alone.
- `sim_statusbar` and `shutdown_sim` return `mobilebuildmcp.output.simulator-action-result` schema version 3, which adds the `shutdown` action and the new status bar fields. Validators pinned to version 2 must accept version 3 for these tools; other simulator action tools still return version 2.

## [2.7.1]

### Changed
Expand Down
14 changes: 14 additions & 0 deletions manifests/tools/shutdown_sim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
id: shutdown_sim
module: mcp/tools/simulator-management/shutdown_sim
names:
mcp: shutdown_sim
cli: shutdown
description: Shut down a booted simulator.
outputSchema:
schema: mobilebuildmcp.output.simulator-action-result
version: "3"
annotations:
title: Shut Down Simulator
readOnlyHint: false
destructiveHint: false
openWorldHint: false
4 changes: 2 additions & 2 deletions manifests/tools/sim_statusbar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ module: mcp/tools/simulator-management/sim_statusbar
names:
mcp: sim_statusbar
cli: statusbar
description: Set sim status bar network.
description: Override or clear sim status bar time, network, signal, and battery.
outputSchema:
schema: mobilebuildmcp.output.simulator-action-result
version: "2"
version: "3"
annotations:
title: Simulator Statusbar
readOnlyHint: true
Expand Down
1 change: 1 addition & 0 deletions manifests/workflows/simulator-management.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ description: Tools for managing simulators from booting, opening simulators, lis
targetPlatforms: [iOS, tvOS, watchOS, visionOS]
tools:
- boot_sim
- shutdown_sim
- list_sims
- open_sim
- erase_sims
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/getsentry/MobileBuildMCP/main/schemas/structured-output/mobilebuildmcp.output.simulator-action-result/3.schema.json",
"type": "object",
"additionalProperties": false,
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/getsentry/MobileBuildMCP/main/schemas/structured-output/_defs/common.schema.json#/$defs/errorConsistency"
}
],
"properties": {
"schema": {
"const": "mobilebuildmcp.output.simulator-action-result"
},
"schemaVersion": {
"const": "3"
},
"didError": {
"type": "boolean"
},
"error": {
"type": [
"string",
"null"
]
},
"data": {
"type": "object",
"additionalProperties": false,
"properties": {
"summary": {
"$ref": "https://raw.githubusercontent.com/getsentry/MobileBuildMCP/main/schemas/structured-output/_defs/common.schema.json#/$defs/statusSummary"
},
"action": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "boot"
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "erase"
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "open"
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "reset-location"
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "set-location"
},
"coordinates": {
"type": "object",
"additionalProperties": false,
"properties": {
"latitude": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"minimum": -180,
"maximum": 180
}
},
"required": [
"latitude",
"longitude"
]
}
},
"required": [
"type",
"coordinates"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "set-appearance"
},
"appearance": {
"type": "string"
}
},
"required": [
"type",
"appearance"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "shutdown"
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "statusbar"
},
"time": {
"type": "string"
},
"dataNetwork": {
"type": "string"
},
"wifiMode": {
"type": "string"
},
"wifiBars": {
"type": "integer",
"minimum": 0,
"maximum": 3
},
"cellularMode": {
"type": "string"
},
"cellularBars": {
"type": "integer",
"minimum": 0,
"maximum": 4
},
"batteryState": {
"type": "string"
},
"batteryLevel": {
"type": "integer",
"minimum": 0,
"maximum": 100
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "toggle-software-keyboard"
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "toggle-connect-hardware-keyboard"
}
},
"required": [
"type"
]
}
]
},
"artifacts": {
"type": "object",
"additionalProperties": false,
"properties": {
"simulatorId": {
"type": "string"
}
},
"required": [],
"minProperties": 1
},
"diagnostics": {
"$ref": "https://raw.githubusercontent.com/getsentry/MobileBuildMCP/main/schemas/structured-output/_defs/common.schema.json#/$defs/basicDiagnostics"
}
},
"required": [
"summary",
"action"
]
},
"nextSteps": {
"$ref": "https://raw.githubusercontent.com/getsentry/MobileBuildMCP/main/schemas/structured-output/_defs/common.schema.json#/$defs/nextSteps"
}
},
"required": [
"schema",
"schemaVersion",
"didError",
"error",
"data"
]
}
40 changes: 40 additions & 0 deletions src/core/__tests__/structured-output-schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,46 @@ describe('structured output schema bundling', () => {
).toBe(true);
});

it('accepts shutdown and extended statusbar actions only in simulator action result v3', () => {
const ajv = new Ajv2020({ allErrors: true, strict: true, validateSchema: true });
const actionV2 = ajv.compile(
getMcpOutputSchema({ schema: 'mobilebuildmcp.output.simulator-action-result', version: '2' }),
);
const actionV3 = ajv.compile(
getMcpOutputSchema({ schema: 'mobilebuildmcp.output.simulator-action-result', version: '3' }),
);
const envelope = (action: JsonObject): JsonObject => ({
schema: 'mobilebuildmcp.output.simulator-action-result',
schemaVersion: '3',
didError: false,
error: null,
data: {
summary: { status: 'SUCCEEDED' },
action,
artifacts: { simulatorId: 'SIM-1' },
},
});
const statusbarEnvelope = envelope({
type: 'statusbar',
time: '9:41',
dataNetwork: 'wifi',
wifiMode: 'active',
wifiBars: 3,
cellularMode: 'active',
cellularBars: 4,
batteryState: 'charged',
batteryLevel: 100,
});
const shutdownEnvelope = envelope({ type: 'shutdown' });

expect(actionV2({ ...statusbarEnvelope, schemaVersion: '2' })).toBe(false);
expect(actionV2({ ...shutdownEnvelope, schemaVersion: '2' })).toBe(false);
expect(actionV3(statusbarEnvelope)).toBe(true);
expect(actionV3(shutdownEnvelope)).toBe(true);
expect(actionV3(envelope({ type: 'statusbar', dataNetwork: 'clear' }))).toBe(true);
expect(actionV3(envelope({ type: 'statusbar', batteryLevel: 101 }))).toBe(false);
});

it('accepts video recording capture payloads in the bumped capture contract', () => {
const schema = getMcpOutputSchema({
schema: 'mobilebuildmcp.output.capture-result',
Expand Down
Loading