Skip to main content
Glama

stop_app_sim

Stop an app running in an iOS simulator by specifying the simulator UUID and app bundle identifier. Simplifies app management during testing and development.

Instructions

Stops an app running in an iOS simulator. Requires simulatorUuid and bundleId.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bundleIdYesBundle identifier of the app to stop (e.g., 'com.example.MyApp')
simulatorUuidYesUUID of the simulator (obtained from list_simulators)

Implementation Reference

  • The main handler function that executes the tool logic: looks up simulator if needed, then terminates the app using xcrun simctl.
    export async function stop_app_simLogic(
      params: StopAppSimParams,
      executor: CommandExecutor,
    ): Promise<ToolResponse> {
      let simulatorId = params.simulatorId;
      let simulatorDisplayName = simulatorId ?? '';
    
      if (params.simulatorName && !simulatorId) {
        log('info', `Looking up simulator by name: ${params.simulatorName}`);
    
        const simulatorListResult = await executor(
          ['xcrun', 'simctl', 'list', 'devices', 'available', '--json'],
          'List Simulators',
          true,
        );
        if (!simulatorListResult.success) {
          return {
            content: [
              {
                type: 'text',
                text: `Failed to list simulators: ${simulatorListResult.error}`,
              },
            ],
            isError: true,
          };
        }
    
        const simulatorsData = JSON.parse(simulatorListResult.output) as {
          devices: Record<string, Array<{ udid: string; name: string }>>;
        };
    
        let foundSimulator: { udid: string; name: string } | null = null;
        for (const runtime in simulatorsData.devices) {
          const devices = simulatorsData.devices[runtime];
          const simulator = devices.find((device) => device.name === params.simulatorName);
          if (simulator) {
            foundSimulator = simulator;
            break;
          }
        }
    
        if (!foundSimulator) {
          return {
            content: [
              {
                type: 'text',
                text: `Simulator named "${params.simulatorName}" not found. Use list_sims to see available simulators.`,
              },
            ],
            isError: true,
          };
        }
    
        simulatorId = foundSimulator.udid;
        simulatorDisplayName = `"${params.simulatorName}" (${foundSimulator.udid})`;
      }
    
      if (!simulatorId) {
        return {
          content: [
            {
              type: 'text',
              text: 'No simulator identifier provided',
            },
          ],
          isError: true,
        };
      }
    
      log('info', `Stopping app ${params.bundleId} in simulator ${simulatorId}`);
    
      try {
        const command = ['xcrun', 'simctl', 'terminate', simulatorId, params.bundleId];
        const result = await executor(command, 'Stop App in Simulator', true, undefined);
    
        if (!result.success) {
          return {
            content: [
              {
                type: 'text',
                text: `Stop app in simulator operation failed: ${result.error}`,
              },
            ],
            isError: true,
          };
        }
    
        return {
          content: [
            {
              type: 'text',
              text: `✅ App ${params.bundleId} stopped successfully in simulator ${simulatorDisplayName || simulatorId}`,
            },
          ],
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        log('error', `Error stopping app in simulator: ${errorMessage}`);
        return {
          content: [
            {
              type: 'text',
              text: `Stop app in simulator operation failed: ${errorMessage}`,
            },
          ],
          isError: true,
        };
      }
    }
  • Zod schema defining input parameters: simulatorId or simulatorName (exclusive), bundleId. Includes refinements for validation.
    const baseSchemaObject = z.object({
      simulatorId: z
        .string()
        .optional()
        .describe(
          'UUID of the simulator to use (obtained from list_sims). Provide EITHER this OR simulatorName, not both',
        ),
      simulatorName: z
        .string()
        .optional()
        .describe(
          "Name of the simulator (e.g., 'iPhone 16'). Provide EITHER this OR simulatorId, not both",
        ),
      bundleId: z.string().describe("Bundle identifier of the app to stop (e.g., 'com.example.MyApp')"),
    });
    
    const baseSchema = z.preprocess(nullifyEmptyStrings, baseSchemaObject);
    
    const stopAppSimSchema = baseSchema
      .refine((val) => val.simulatorId !== undefined || val.simulatorName !== undefined, {
        message: 'Either simulatorId or simulatorName is required.',
      })
      .refine((val) => !(val.simulatorId !== undefined && val.simulatorName !== undefined), {
        message: 'simulatorId and simulatorName are mutually exclusive. Provide only one.',
      });
  • Default export registering the tool: name, description, public schema (hides simulator fields), and wrapped handler with internal schema and logic.
    const publicSchemaObject = baseSchemaObject
      .omit({
        simulatorId: true,
        simulatorName: true,
      } as const)
      .strict();
    
    export default {
      name: 'stop_app_sim',
      description: 'Stops an app running in an iOS simulator.',
      schema: publicSchemaObject.shape,
      handler: createSessionAwareTool<StopAppSimParams>({
        internalSchema: stopAppSimSchema as unknown as z.ZodType<StopAppSimParams>,
        logicFunction: stop_app_simLogic,
        getExecutor: getDefaultCommandExecutor,
        requirements: [
          { oneOf: ['simulatorId', 'simulatorName'], message: 'Provide simulatorId or simulatorName' },
        ],
        exclusivePairs: [['simulatorId', 'simulatorName']],
      }),
    };
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the required parameters but does not describe what 'Stops' entails (e.g., whether it force-quits the app, if it's reversible, error conditions, or side effects). For a mutation tool with zero annotation coverage, this lack of detail is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose in the first sentence and follows with parameter requirements. It is appropriately sized with two sentences and no wasted words, though it could be slightly more structured by separating usage notes from prerequisites for better clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of stopping an app (a mutation operation) with no annotations and no output schema, the description is incomplete. It lacks details on behavioral outcomes, error handling, or what constitutes success, which are crucial for an agent to invoke the tool correctly in a development or testing context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both parameters (simulatorUuid and bundleId) fully documented in the input schema. The description adds minimal value by restating the requirements but does not provide additional context or meaning beyond what the schema already specifies, such as parameter interactions or examples of valid inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Stops') and target resource ('an app running in an iOS simulator'), distinguishing it from sibling tools like stop_app_device or stop_mac_app by specifying the iOS simulator context. It provides a verb+resource combination that is precise and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by mentioning 'Requires simulatorUuid and bundleId,' which suggests prerequisites but does not explicitly state when to use this tool versus alternatives like stop_app_sim_name_ws or stop_app_device. There is no guidance on exclusions or specific scenarios, leaving usage somewhat inferred rather than clearly defined.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/XcodeBuildMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server