Skip to main content
Glama

rivian_get_vehicle_state

Retrieve current vehicle status including battery level, range, door locks, tire pressure, location, climate settings, and software updates to monitor your Rivian's condition.

Instructions

Check your vehicle's current status — battery, range, doors, tires, location, climate, software, and more.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
vehicle_idYesVehicle ID from your account info
propertiesNoSpecific properties to check. Leave empty for a full status report.

Implementation Reference

  • The core implementation of getVehicleState that constructs a GraphQL query using specified properties (or defaults) and fetches vehicle state data from the Rivian API gateway.
    export async function getVehicleState(vehicleId, properties) {
      const props = properties || DEFAULT_VEHICLE_STATE_PROPERTIES;
      const fragment = [...props]
        .map((p) => `${p} ${TEMPLATE_MAP[p] || VALUE_TEMPLATE}`)
        .join('\n    ');
    
      const body = {
        operationName: 'GetVehicleState',
        query: `query GetVehicleState($vehicleID: String!) {
      vehicleState(id: $vehicleID) {
        ${fragment}
      }
    }`,
        variables: { vehicleID: vehicleId },
      };
    
      return (await gql(GRAPHQL_GATEWAY, body, authHeaders())).vehicleState;
    }
  • mcp-server.js:468-487 (registration)
    MCP tool registration for 'rivian_get_vehicle_state' with zod schema validation for vehicle_id and optional properties array, including the handler that calls rivian.getVehicleState and formats the output.
    server.tool(
      'rivian_get_vehicle_state',
      "Check your vehicle's current status — battery, range, doors, tires, location, climate, software, and more.",
      {
        vehicle_id: z.string().describe('Vehicle ID from your account info'),
        properties: z
          .array(z.string())
          .optional()
          .describe('Specific properties to check. Leave empty for a full status report.'),
      },
      async ({ vehicle_id, properties }) => {
        try {
          requireAuth();
          const props = properties ? new Set(properties) : undefined;
          return text(formatVehicleState(await rivian.getVehicleState(vehicle_id, props)));
        } catch (err) {
          return text(err.message);
        }
      },
    );
  • Input schema definition using zod: vehicle_id (required string) and properties (optional array of strings) for specifying which vehicle properties to query.
    {
      vehicle_id: z.string().describe('Vehicle ID from your account info'),
      properties: z
        .array(z.string())
        .optional()
        .describe('Specific properties to check. Leave empty for a full status report.'),
    },
  • formatVehicleState helper function that transforms raw vehicle state data into a human-readable text format organized by categories (Battery & Range, Charging, Doors, Closures, Windows, Climate, Tires, Software, Security, Drive, Connection, Location).
    function formatVehicleState(state) {
      const lines = [];
      const printed = new Set();
    
      function v(key) {
        return state[key]?.value ?? null;
      }
    
      function print(label, key, suffix = '') {
        if (!(key in state)) return;
        printed.add(key);
        const value = v(key);
        if (value === null || value === undefined) return;
        lines.push(`  ${label}: ${value}${suffix}`);
      }
    
      // Battery & Range
      if ('batteryLevel' in state || 'distanceToEmpty' in state) {
        lines.push('Battery & Range');
        print('Battery', 'batteryLevel', '%');
        print('Charge limit', 'batteryLimit', '%');
        print('Capacity', 'batteryCapacity');
        print('Range', 'distanceToEmpty', ' miles');
        print('Odometer', 'vehicleMileage', ' miles');
        print('Power', 'powerState');
        print('Time to full', 'timeToEndOfCharge', ' min');
        print('Remote charging', 'remoteChargingAvailable');
        lines.push('');
      }
    
      // Charging
      if ('chargerStatus' in state || 'chargerState' in state) {
        lines.push('Charging');
        print('Charger status', 'chargerStatus');
        print('Charger state', 'chargerState');
        print('Charge port', 'chargePortState');
        lines.push('');
      }
    
      // Doors — combine closed + locked per door
      const doorPositions = ['FrontLeft', 'FrontRight', 'RearLeft', 'RearRight'];
      const doorLines = [];
      for (const pos of doorPositions) {
        const closedKey = `door${pos}Closed`;
        const lockedKey = `door${pos}Locked`;
        if (closedKey in state || lockedKey in state) {
          printed.add(closedKey);
          printed.add(lockedKey);
          const parts = [v(closedKey), v(lockedKey)].filter(Boolean);
          const label = pos.replace(/([A-Z])/g, ' $1').trim().toLowerCase();
          if (parts.length) doorLines.push(`  ${label}: ${parts.join(', ')}`);
        }
      }
      if (doorLines.length) {
        lines.push('Doors');
        lines.push(...doorLines);
        lines.push('');
      }
    
      // Closures — frunk, liftgate, tailgate, tonneau
      const closures = ['Frunk', 'Liftgate', 'Tailgate', 'Tonneau'];
      const closureLines = [];
      for (const name of closures) {
        const closedKey = `closure${name}Closed`;
        const lockedKey = `closure${name}Locked`;
        if (closedKey in state || lockedKey in state) {
          printed.add(closedKey);
          printed.add(lockedKey);
          const parts = [v(closedKey), v(lockedKey)].filter(Boolean);
          if (parts.length) closureLines.push(`  ${name.toLowerCase()}: ${parts.join(', ')}`);
        }
      }
      if (closureLines.length) {
        lines.push('Closures');
        lines.push(...closureLines);
        lines.push('');
      }
    
      // Windows
      const windowLines = [];
      for (const pos of doorPositions) {
        const key = `window${pos}Closed`;
        if (key in state) {
          printed.add(key);
          const value = v(key);
          if (value) {
            const label = pos.replace(/([A-Z])/g, ' $1').trim().toLowerCase();
            windowLines.push(`  ${label}: ${value}`);
          }
        }
      }
      if (windowLines.length) {
        lines.push('Windows');
        lines.push(...windowLines);
        lines.push('');
      }
    
      // Climate
      if ('cabinClimateInteriorTemperature' in state || 'cabinPreconditioningStatus' in state) {
        lines.push('Climate');
        if ('cabinClimateInteriorTemperature' in state) {
          printed.add('cabinClimateInteriorTemperature');
          const temp = v('cabinClimateInteriorTemperature');
          if (temp) lines.push(`  Cabin temp: ${temp}°`);
        }
        print('Preconditioning', 'cabinPreconditioningStatus');
        print('Defrost/defog', 'defrostDefogStatus');
        print('Pet mode', 'petModeStatus');
        lines.push('');
      }
    
      // Tires
      const tirePositions = { FrontLeft: 'front left', FrontRight: 'front right', RearLeft: 'rear left', RearRight: 'rear right' };
      const tireLines = [];
      for (const [pos, label] of Object.entries(tirePositions)) {
        const key = `tirePressureStatus${pos}`;
        if (key in state) {
          printed.add(key);
          const value = v(key);
          if (value) tireLines.push(`  ${label}: ${value}`);
        }
      }
      if (tireLines.length) {
        lines.push('Tire Pressure');
        lines.push(...tireLines);
        lines.push('');
      }
    
      // Software (OTA)
      if ('otaCurrentVersion' in state || 'otaAvailableVersion' in state || 'otaStatus' in state) {
        lines.push('Software');
        print('Current version', 'otaCurrentVersion');
        print('Available update', 'otaAvailableVersion');
        print('Status', 'otaStatus');
        print('Install status', 'otaCurrentStatus');
        print('Install ready', 'otaInstallReady');
        print('Install progress', 'otaInstallProgress', '%');
        print('Download progress', 'otaDownloadProgress', '%');
        print('Install type', 'otaInstallType');
        print('Current hash', 'otaCurrentVersionGitHash');
        print('Available hash', 'otaAvailableVersionGitHash');
        lines.push('');
      }
    
      // Security
      if ('gearGuardLocked' in state) {
        lines.push('Security');
        print('Gear Guard', 'gearGuardLocked');
        print('Gear Guard video', 'gearGuardVideoStatus');
        lines.push('');
      }
    
      // Drive
      if ('driveMode' in state || 'gearStatus' in state) {
        lines.push('Drive');
        print('Drive mode', 'driveMode');
        print('Gear', 'gearStatus');
        lines.push('');
      }
    
      // Connection
      if ('cloudConnection' in state) {
        printed.add('cloudConnection');
        const cc = state.cloudConnection;
        const online = cc?.isOnline ? 'Online' : 'Offline';
        const sync = cc?.lastSync ? ` (last sync: ${cc.lastSync})` : '';
        lines.push('Connection');
        lines.push(`  Status: ${online}${sync}`);
        lines.push('');
      }
    
      // Location
      if ('gnssLocation' in state) {
        printed.add('gnssLocation');
        const loc = state.gnssLocation;
        if (loc?.latitude && loc?.longitude) {
          lines.push('Location');
          lines.push(`  ${loc.latitude}, ${loc.longitude}`);
          lines.push('');
        }
      }
    
      // Anything not already printed
      const remaining = [];
      for (const [key, entry] of Object.entries(state)) {
        if (printed.has(key)) continue;
        const value = entry?.value ?? entry;
        if (value !== null && value !== undefined) {
          remaining.push(`  ${key}: ${value}`);
        }
      }
      if (remaining.length) {
        lines.push('Other');
        lines.push(...remaining);
      }
    
      return lines.join('\n').trim();
    }
  • Vehicle state property templates including VALUE_TEMPLATE, TEMPLATE_MAP for special properties like cloudConnection and gnssLocation, and DEFAULT_VEHICLE_STATE_PROPERTIES containing all default properties to query when none are specified.
    // ── Vehicle state property templates ────────────────────────────────
    
    const VALUE_TEMPLATE = '{ timeStamp value }';
    
    const TEMPLATE_MAP = {
      cloudConnection: '{ lastSync isOnline }',
      gnssLocation: '{ latitude longitude timeStamp isAuthorized }',
      gnssError: '{ timeStamp positionVertical positionHorizontal speed bearing }',
    };
    
    const DEFAULT_VEHICLE_STATE_PROPERTIES = new Set([
      'cloudConnection',
      'gnssLocation',
      'batteryLevel',
      'batteryLimit',
      'batteryCapacity',
      'distanceToEmpty',
      'vehicleMileage',
      'powerState',
      'chargerStatus',
      'chargerState',
      'chargePortState',
      'otaAvailableVersion',
      'otaAvailableVersionGitHash',
      'otaCurrentVersion',
      'otaCurrentVersionGitHash',
      'otaStatus',
      'otaInstallReady',
      'otaInstallProgress',
      'otaCurrentStatus',
      'otaDownloadProgress',
      'otaInstallType',
      'driveMode',
      'gearStatus',
      'tirePressureStatusFrontLeft',
      'tirePressureStatusFrontRight',
      'tirePressureStatusRearLeft',
      'tirePressureStatusRearRight',
      'doorFrontLeftClosed',
      'doorFrontRightClosed',
      'doorRearLeftClosed',
      'doorRearRightClosed',
      'doorFrontLeftLocked',
      'doorFrontRightLocked',
      'doorRearLeftLocked',
      'doorRearRightLocked',
      'closureFrunkClosed',
      'closureFrunkLocked',
      'closureLiftgateClosed',
      'closureLiftgateLocked',
      'closureTailgateClosed',
      'closureTailgateLocked',
      'closureTonneauClosed',
      'closureTonneauLocked',
      'windowFrontLeftClosed',
      'windowFrontRightClosed',
      'windowRearLeftClosed',
      'windowRearRightClosed',
      'cabinClimateInteriorTemperature',
      'cabinPreconditioningStatus',
      'defrostDefogStatus',
      'petModeStatus',
      'gearGuardLocked',
      'gearGuardVideoStatus',
      'timeToEndOfCharge',
      'remoteChargingAvailable',
    ]);
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes what the tool does (check status) but lacks details on permissions needed, rate limits, whether it's a read-only operation, or what the response format looks like. For a tool with zero annotation coverage, this is a significant gap.

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

Conciseness5/5

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

The description is a single, efficient sentence that front-loads the core purpose ('Check your vehicle's current status') and provides relevant examples without unnecessary details. Every word earns its place.

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 checking vehicle state with multiple properties, no annotations, and no output schema, the description is incomplete. It lists examples of what can be checked but doesn't explain the return values, error handling, or how the 'properties' array interacts with the full report, leaving gaps for an AI agent.

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?

The schema description coverage is 100%, so the schema already documents both parameters (vehicle_id and properties). The description implies checking various status aspects but doesn't add syntax or format details beyond what the schema provides. The baseline is 3 when the schema does the heavy lifting.

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

Purpose4/5

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

The description clearly states the tool's purpose as checking a vehicle's current status with specific examples (battery, range, doors, etc.), which is a clear verb+resource combination. However, it doesn't explicitly differentiate from sibling tools like rivian_get_charging_session or rivian_get_ota_status, which might overlap in checking vehicle status aspects.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like rivian_get_charging_session for charging-specific status or rivian_get_ota_status for software updates. It mentions checking 'current status' but lacks explicit context or exclusions for usage.

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

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/PatrickHeneise/rivian-mcp'

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