vincemeshed
06/07/2025, 12:06 PMVapi Support Bot
06/07/2025, 12:07 PMjs
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)vincemeshed
06/07/2025, 12:37 PMVapi Support Bot
06/07/2025, 12:39 PMjson
{
"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)vincemeshed
06/07/2025, 3:06 PMVapi Support Bot
06/07/2025, 3:08 PMassistantOverride.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:
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)vincemeshed
06/07/2025, 3:19 PMKings_bigđź’«
06/07/2025, 4:05 PMvincemeshed
06/07/2025, 4:41 PMAniah
06/08/2025, 6:06 AMvincemeshed
06/08/2025, 11:44 AMAniah
06/10/2025, 6:25 AMvincemeshed
06/11/2025, 11:49 AMutvara
08/11/2025, 8:39 PMAniah
09/04/2025, 11:07 PM// 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"
}]
}
});
Aniah
09/04/2025, 11:07 PMconst 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();
};
Aniah
09/04/2025, 11:08 PM// 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();
});
}
Aniah
09/04/2025, 11:08 PM