ruvnet/ruflo · error
mcp-caller-auth-enabled-but-no-token
mcp-caller-auth-enabled-but-no-token
Error message
mcp-caller-auth-enabled-but-no-token
What it means
When MCP caller authentication is enabled, resolveMcpCallerIdentity requires both CLAUDE_FLOW_MCP_INVOCATION_TOKEN and CLAUDE_FLOW_MCP_CALLER_PUBKEY to be set. It throws this coded error when either variable is missing or empty, refusing to authorize the tool call rather than falling back to unauthenticated access.
Solutions
- Set both CLAUDE_FLOW_MCP_INVOCATION_TOKEN and CLAUDE_FLOW_MCP_CALLER_PUBKEY in the server environment
- Check the service/launch configuration actually exports the vars (systemd Environment=, docker -e, etc.)
- If auth was enabled unintentionally, disable MCP caller auth in policy config
Example fix
// before # token not exported // after export CLAUDE_FLOW_MCP_INVOCATION_TOKEN=<token-envelope> export CLAUDE_FLOW_MCP_CALLER_PUBKEY=<64-hex-pubkey>
Defensive patterns
Strategy: validation
Validate before calling
if (!process.env.CLAUDE_FLOW_MCP_INVOCATION_TOKEN || !process.env.CLAUDE_FLOW_MCP_CALLER_PUBKEY) { throw new Error('MCP caller auth enabled but token/pubkey env vars missing'); } Type guard
const hasMcpAuthEnv = (): boolean => Boolean(process.env.CLAUDE_FLOW_MCP_INVOCATION_TOKEN && process.env.CLAUDE_FLOW_MCP_CALLER_PUBKEY);
Try / catch
try { await callMcpTool(tool, args); } catch (e) { if (e.message === 'mcp-caller-auth-enabled-but-no-token') { /* set env vars or disable caller auth */ } throw e; } Prevention
- Enable MCP caller auth only after provisioning both env vars
- Verify env vars in startup health checks
- Document the required env vars in deployment configs
When it happens
Trigger: authorizeMcpTool runs with auth enabled but process.env.CLAUDE_FLOW_MCP_INVOCATION_TOKEN or CLAUDE_FLOW_MCP_CALLER_PUBKEY is unset/empty.
Common situations: Enabling mcp caller auth in config without provisioning the corresponding env vars; running the server under a service manager that strips the operator's env; forgetting to pass the token to a child process.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- mcp-caller-auth-verification-failed
- policy administration requires an authenticated user context
- RUFLO_X_ADMIN_TOKEN is not set (admission is admin-gated)
- policy- : ; receipt=
- approval issuance requires an authenticated human identity…
AI-assisted analysis of ruvnet/ruflo@2602b642d9 (2026-09-15).
Data as JSON: /api/errors/8f9941f0907bf728.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/services/policy-runtime.ts:353
* `verifyInvocationToken` here, and the tool-mismatch check is not exercised
* for this use case. What this retains: a process that never received the
* signed token cannot forge one, so it cannot impersonate `agent:<workerId>`.
* What it does NOT retain: a compromised worker process can still use its
* own valid token for every MCP call for the rest of its lifetime — the
* token does not limit blast radius to a single call.
*/
function resolveMcpCallerIdentity(): { id: string; type: 'agent' | 'legacy' } {
if (!isMcpCallerAuthEnabled()) {
return {
id: process.env.CLAUDE_FLOW_PRINCIPAL_ID ?? 'legacy-cli',
type: process.env.CLAUDE_FLOW_PRINCIPAL_ID ? 'agent' : 'legacy',
};
}
const encodedToken = process.env.CLAUDE_FLOW_MCP_INVOCATION_TOKEN;
const publicKeyHex = process.env.CLAUDE_FLOW_MCP_CALLER_PUBKEY;
if (!encodedToken || !publicKeyHex) {
throw new Error('mcp-caller-auth-enabled-but-no-token');
}
const token = decodeTokenEnvelope(encodedToken);
if (!token) {
throw new Error('mcp-caller-auth-enabled-but-no-token');
}
let publicKey;
try {
publicKey = publicKeyFromHex(publicKeyHex);
} catch {
throw new Error('mcp-caller-auth-enabled-but-no-token');
}
const result = verifyInvocationToken(token, publicKey, {});
if (!result.valid) {
throw new Error(`mcp-caller-auth-verification-failed:${result.reason}`);
}View on GitHub (pinned to 2602b642d9)