Skip to main content
Glama

rivian_login

Sends a verification code to your registered phone or email to initiate Rivian account login.

Instructions

Log in to your Rivian account. Rivian will send a verification code to your phone or email — use rivian_submit_otp to complete sign-in.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • mcp-server.js:68-97 (registration)
    The 'rivian_login' tool is registered via server.tool() on the McpServer instance. It reads RIVIAN_EMAIL and RIVIAN_PASSWORD from env, calls rivian.createCsrfToken() then rivian.login(), and saves the session.
    server.tool(
      'rivian_login',
      'Log in to your Rivian account. Rivian will send a verification code to your phone or email — use rivian_submit_otp to complete sign-in.',
      {},
      async () => {
        const email = process.env.RIVIAN_EMAIL
        const password = process.env.RIVIAN_PASSWORD
        if (!email || !password) {
          return text(
            'Rivian credentials are not configured. Set RIVIAN_EMAIL and RIVIAN_PASSWORD in your MCP server settings.',
          )
        }
    
        try {
          await rivian.createCsrfToken()
          const { mfa } = await rivian.login(email, password)
          saveSession(rivian)
    
          if (mfa) {
            return text(
              "A verification code has been sent to your phone or email. Tell me the code and I'll complete the sign-in.",
            )
          }
    
          return text('Signed in to Rivian successfully.')
        } catch (err) {
          return text(`Couldn't sign in: ${err.message}`)
        }
      },
    )
  • The async handler function that executes the rivian_login logic: checks env credentials, creates CSRF token, performs login via the Rivian API, and returns a text response indicating success or OTP requirement.
    server.tool(
      'rivian_login',
      'Log in to your Rivian account. Rivian will send a verification code to your phone or email — use rivian_submit_otp to complete sign-in.',
      {},
      async () => {
        const email = process.env.RIVIAN_EMAIL
        const password = process.env.RIVIAN_PASSWORD
        if (!email || !password) {
          return text(
            'Rivian credentials are not configured. Set RIVIAN_EMAIL and RIVIAN_PASSWORD in your MCP server settings.',
          )
        }
    
        try {
          await rivian.createCsrfToken()
          const { mfa } = await rivian.login(email, password)
          saveSession(rivian)
    
          if (mfa) {
            return text(
              "A verification code has been sent to your phone or email. Tell me the code and I'll complete the sign-in.",
            )
          }
    
          return text('Signed in to Rivian successfully.')
        } catch (err) {
          return text(`Couldn't sign in: ${err.message}`)
        }
      },
    )
  • The login() function called by rivian_login handler. Sends a Login GraphQL mutation, stores access/refresh tokens on success, or stores otpToken and returns {mfa: true} if MFA is needed.
    export async function login(email, password) {
      const data = await gql(
        GRAPHQL_GATEWAY,
        {
          operationName: 'Login',
          query: `mutation Login($email: String!, $password: String!) {
      login(email: $email, password: $password) {
        __typename
        ... on MobileLoginResponse {
          __typename
          accessToken
          refreshToken
          userSessionToken
        }
        ... on MobileMFALoginResponse {
          __typename
          otpToken
        }
      }
    }`,
          variables: { email, password },
        },
        { 'Csrf-Token': session.csrfToken, 'A-Sess': session.appSessionToken },
      )
    
      if (data.login.otpToken) {
        session.otpToken = data.login.otpToken
        return { mfa: true }
      }
    
      session.accessToken = data.login.accessToken
      session.refreshToken = data.login.refreshToken
      session.userSessionToken = data.login.userSessionToken
      return { mfa: false }
    }
  • The createCsrfToken() function called before login. Fetches a CSRF token and app session token needed for the subsequent login request.
    export async function createCsrfToken() {
      const data = await gql(GRAPHQL_GATEWAY, {
        operationName: 'CreateCSRFToken',
        query: `mutation CreateCSRFToken {
      createCsrfToken {
        __typename
        csrfToken
        appSessionToken
      }
    }`,
        variables: null,
      })
      session.csrfToken = data.createCsrfToken.csrfToken
      session.appSessionToken = data.createCsrfToken.appSessionToken
    }
  • The saveSession() function called after login to persist authentication tokens to disk (~/.rivian-mcp/session.json).
    export function saveSession(rivianApi) {
      mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 })
      chmodSync(CONFIG_DIR, 0o700)
      const session = { ...rivianApi.exportSession(), savedAt: Date.now() }
      writeFileSync(SESSION_FILE, JSON.stringify(session, null, 2), { mode: 0o600 })
      chmodSync(SESSION_FILE, 0o600)
    }
Behavior4/5

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

Given no annotations, the description discloses that Rivian will send a verification code to phone or email, a key side effect. This helps the agent model the tool's behavior beyond just 'login'.

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?

Two sentences, clean and front-loaded: first sentence states purpose, second provides guidance. No extraneous words.

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

Completeness4/5

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

For a simple tool with no parameters and no output schema, the description covers the essential context: what the tool does, what happens next, and the role of a sibling tool. It is complete enough.

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

Parameters4/5

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

With zero parameters, the baseline is 4 per guidelines. The description adds meaning by explaining the login process and the follow-up step, which is more than just restating the name.

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 it is for logging into a Rivian account, a specific verb-resource pair. It distinguishes itself from sibling tools by naming rivian_submit_otp as the follow-up step, leaving no ambiguity.

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

Usage Guidelines4/5

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

The description explicitly instructs the agent to use rivian_submit_otp after receiving the verification code, providing a clear workflow. It does not mention when not to use it, but for a login initiation tool this is sufficient.

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