how do I pass cookies into custom tool call?
# support
v
I want to be able to identify user from cookies token to make sure I'm only retrieving data for a particular user when custom tool is called
v
To securely identify users in your custom tool call, pass the user token as an argument in the tool call payload or as a custom header. On your server, extract the token from the request and use it for user validation. For example, in your Express endpoint:
Copy code
js
app.post("/chat/completions/custom-tool", (req, res) => {
  const userToken = req.headers['authorization']; // or req.body.message.userToken
  // Use userToken to identify and authorize the user
});
Set the header in your tool's server config as shown in the [Vapi docs](https://docs.vapi.ai/server-url/server-authentication#custom-headers-authentication). Sources: - [Server Authentication](https://docs.vapi.ai/server-url/server-authentication#custom-headers-authentication) - [Custom Tool Calling Integration](https://docs.vapi.ai/customization/tool-calling-integration#c-custom-tools)
v
@Vapi Support Bot how do I pass custom header in from react typescript
v
You cannot set custom headers (like Authorization) dynamically from React/TypeScript using the Vapi Web SDK. Custom headers for tool calls must be configured in your assistant or tool's server config, for example:
Copy code
json
{
  "server": {
    "url": "https://your-server.com/webhook",
    "headers": {
      "Authorization": "Bearer your-api-key"
    }
  }
}
If you need to identify the user, pass the token as an argument in the tool call payload instead, and extract it on your backend. [See Vapi docs for details.](https://docs.vapi.ai/server-url/server-authentication#custom-headers-authentication) Sources: - [Server Authentication](https://docs.vapi.ai/server-url/server-authentication#custom-headers-authentication) - [Custom Tool Calling Integration](https://docs.vapi.ai/customization/tool-calling-integration#c-custom-tools)
v
@Vapi Support Bot I've tried using assistantOverride.variableValues to pass user token in but its not replacing the value in header field? { "variableValues": { "usertoken": "super_secret_token" } } This is the value of header in the tool setup config Bearer {{usertoken}}
v
Dynamic header value replacement using
assistantOverride.variableValues
is not supported in Vapi.
Instead, pass the user token as an argument in your tool call payload and extract it on your backend:
Copy code
js
// Example Express endpoint
app.post("/chat/completions/custom-tool", (req, res) => {
  const userToken = req.body.message.toolCallList[0].function.arguments.usertoken;
  // Use userToken to identify and authorize the user
});
Set static headers in your tool config, but use payload arguments for dynamic user data. [See Vapi docs for details.](https://docs.vapi.ai/customization/tool-calling-integration#c-custom-tools) Sources: - [Server Authentication](https://docs.vapi.ai/server-url/server-authentication#custom-headers-authentication) - [Custom Tool Calling Integration](https://docs.vapi.ai/customization/tool-calling-integration#c-custom-tools)
v
@Kings_bigđź’« any idea?
k
Pass the user’s token from cookies into assistantOverrides.toolOverrides as an Authorization header when starting a session, so your custom tool can securely identify and return data only for that authenticated user..
v
is there documentation/example for this? I'm getting 400 on assistantOverrides.property toolOverrides should not exist
a
You can pass the user’s token as an Authorization header via assistantOverrides.credentials not toolOverrides, since toolOverrides isn’t valid. Use assistantOverrides: { credentials: { Authorization: "Bearer <token>" } } when starting a session..
v
are u sure? this isn't valid either
a
Could you provide an overview of the implementation and specifically how you are going to pass these cookies to the request? With this context it will give us a better understanding of the data flow and possible solutions
v
I'm using the nextjs an starting the session with vapi.start. I'm getting the cookies from browser session and trying to pass that into vapi session so every tool call(specifically our own MCP server) would use this token to identify user and apply row level access
a
If your MCP server uses OAuth2, you could potentially use the webhook integration with assistantOverrides.credentials and pass the dynamic variable into there:
u
Do you have an example somewhere how this can be achived? I also need to sign the MCP requests with Bearer token
a
1. Client-Side Setup (Next.js)
Copy code
// Get user's OAuth token from browser session
const userOAuthToken = getCookieValue('oauth_token'); // Your method to get the token
const userId = getCookieValue('user_id');

// Start Vapi session with user credentials
vapi.start({
  assistant: {
    // Your assistant configuration
    server: {
      url: "https://your-mcp-server.com/mcp-endpoint",
      // Pass user-specific data in server headers or body
      headers: {
        "X-User-ID": userId,
        "X-Session-Token": userOAuthToken
      }
    },
    // Alternative: Pass via webhookCredential for OAuth2 flow
    credentials: [{
      provider: "webhook",
      authenticationPlan: {
        type: "oauth2",
        url: "https://your-mcp-server.com/oauth/token",
        clientId: "your-client-id",
        clientSecret: "your-client-secret",
        scope: "user:read user:write"
      },
      name: "mcp-oauth-credential"
    }]
  }
});
2. API Call Example for Creating a Call
Copy code
const createCall = async () => {
  const response = await fetch('https://api.vapi.ai/call', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_VAPI_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      type: 'webCall',
      assistantId: 'your-assistant-id',
      assistantOverrides: {
        server: {
          url: "https://your-mcp-server.com/mcp-endpoint",
          headers: {
            "X-User-ID": userId,
            "X-Session-Token": userOAuthToken
          }
        },
        // Configure OAuth2 credential for MCP server
        credentials: [{
          provider: "webhook",
          authenticationPlan: {
            type: "oauth2",
            url: "https://your-mcp-server.com/oauth/token",
            clientId: process.env.MCP_CLIENT_ID,
            clientSecret: process.env.MCP_CLIENT_SECRET,
            scope: "mcp:tools:execute user:identify",
            // Additional parameters for user context
            additionalBodyParameters: {
              user_id: userId,
              session_token: userOAuthToken
            }
          },
          name: "mcp-user-credential"
        }],
        // Pass user context via variable values
        variableValues: {
          userId: userId,
          userToken: userOAuthToken,
          orgId: userOrgId
        }
      }
    })
  });

  return response.json();
};
Your MCP server should be configured to handle OAuth2 authentication and user identification:
Copy code
// MCP Server (Node.js/Express example)
app.post('/oauth/token', (req, res) => {
  const { client_id, client_secret, user_id, session_token } = req.body;
  
  // Validate client credentials
  if (client_id !== process.env.EXPECTED_CLIENT_ID || 
      client_secret !== process.env.EXPECTED_CLIENT_SECRET) {
    return res.status(401).json({ error: 'Invalid client credentials' });
  }

  // Validate user session token
  const userContext = validateUserSession(session_token, user_id);
  if (!userContext) {
    return res.status(401).json({ error: 'Invalid user session' });
  }

  // Generate access token with user context
  const accessToken = jwt.sign({
    client_id,
    user_id,
    org_id: userContext.orgId,
    permissions: userContext.permissions
  }, process.env.JWT_SECRET, { expiresIn: '1h' });

  res.json({
    access_token: accessToken,
    token_type: 'Bearer',
    expires_in: 3600
  });
});

// MCP tool endpoint with user access control
app.post('/mcp-endpoint', authenticateToken, (req, res) => {
  const { user_id, org_id, permissions } = req.user; // From JWT token
  
  // Apply row-level security based on user context
  const toolCall = req.body;
  
  // Example: Filter data based on user's organization
  if (toolCall.function.name === 'get_user_data') {
    const userData = getUserData({
      userId: user_id,
      orgId: org_id,
      permissions: permissions
    });
    
    res.json({
      result: userData,
      user_context: {
        user_id,
        org_id
      }
    });
  }
});

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.sendStatus(401);
  }

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}
Key Points: 1. **OAuth2 Flow**: Use webhookCredential with oauth2 type for proper authentication flow 2. **User Context**: Pass user identifiers through headers, body parameters, or variable values 3. **Row-Level Security**: Implement access control in your MCP server based on the authenticated user 4. **Token Validation**: Always validate tokens and user permissions on your MCP server 5. **Dynamic Headers**: Use variable substitution for dynamic user-specific values This setup ensures that every tool call to your MCP server includes the necessary user context for proper identification and access control.