MCP Entitlements
Entitlement checking is the gate between an AI agent requesting a tool call and the tool actually executing. This page covers how entitlement checking works for MCP, the denial reason codes, and best practices for handling failures.
The Entitlement Flow
Every MCP tool call should follow this three-step flow:
1. CHECK ──► 2. EXECUTE ──► 3. RECORD
│ │ │
│ Is this │ Run the │ Deduct credits
│ allowed? │ tool │ and log usage
│ │ │
▼ ▼ ▼
allowed: true Tool result credits_used: N
───or───
allowed: false
reason: "..."Never skip step 1. Executing a tool and then discovering the user cannot pay for it creates a poor experience and leaves your system in an inconsistent state.
What Gets Checked
When you call the check-entitlement endpoint, the platform evaluates:
- Deployment exists -- Does the deployment ID resolve to an active deployment?
- Tier allows MCP -- Is
mcp_enabledtrue for the deployment's tier? (Sandbox = no) - Credit cost lookup -- What does this tool cost based on the
TOOL_ACTION_MAP? - Credit balance -- Does the deployment have enough credits? (Zero-cost actions always pass)
Reason Codes
When allowed is false, the response includes a reason field:
| Reason Code | Meaning | Suggested Action |
|---|---|---|
sandbox_tier | Deployment is on the Sandbox tier, which does not include MCP | Prompt the user to upgrade to Trial or above |
insufficient_credits | The deployment has run out of credits | Prompt the user to purchase a credit pack or wait for monthly reset |
deployment_not_found | The deployment ID does not exist or is not active | Verify the deployment ID; the deployment may have been suspended or deleted |
no_deployment_found | No active deployment could be resolved for the user/org | Check that the user belongs to an organization with an active deployment |
mcp_disabled | MCP is explicitly disabled for this deployment | Contact support or check deployment configuration |
Handling Denials
Your MCP server should handle denials gracefully. The agent (Claude Code, your LLM pipeline, etc.) receives the denial and can take appropriate action.
Pattern: Inform the Agent
Return a structured error that the agent can interpret:
async def handle_tool_call(tool_name: str, args: dict) -> dict:
entitlement = await check_entitlement(tool_name)
if not entitlement["allowed"]:
reason = entitlement["reason"]
if reason == "sandbox_tier":
return {
"error": "This tool requires a paid plan. "
"Upgrade at https://app.hiveforge.dev/billing"
}
elif reason == "insufficient_credits":
return {
"error": f"Insufficient credits. "
f"This tool costs {entitlement.get('credit_cost', 'N')} credits. "
f"Purchase more at https://app.hiveforge.dev/billing/credits"
}
else:
return {"error": f"Tool access denied: {reason}"}
# Execute and record...Pattern: Graceful Degradation
For tools that have free alternatives, fall back to a limited version:
async def handle_rag_search(query: str) -> dict:
entitlement = await check_entitlement("hornethive_rag_search")
if not entitlement["allowed"]:
# Fall back to basic keyword search (no credit cost)
return await basic_keyword_search(query)
# Full RAG search with vector embeddings
result = await rag_search(query)
await record_usage("hornethive_rag_search")
return resultCaching Recommendations
| Data | Cache Duration | Reason |
|---|---|---|
| Deployment resolution | 5 minutes | Tier changes are infrequent |
| Entitlement check | 5 minutes | Balances tier responsiveness vs. API load |
| Credit costs | 1 hour | Costs change very rarely |
The HiveForge API caches deployment resolution results server-side for 5 minutes. Client-side caching on top of this is recommended but not required.
Edge Cases
Zero-Cost Tools
Some tool actions have a credit cost of zero. These always pass the entitlement check (assuming the tier allows MCP). You should still record usage for audit purposes.
Unknown Tool Names
If a tool_name is not found in the TOOL_ACTION_MAP, it defaults to the platform_basic credit action. This means unrecognized tools still get metered, just at the base rate.
Concurrent Tool Calls
If an agent fires multiple tool calls in parallel, each one independently checks entitlement and records usage. There is no batching mechanism -- credits are deducted atomically per call via a database function.
Subscription Changes Mid-Session
If a user's tier changes (e.g., they upgrade from Trial to Launch), the change takes effect within 5 minutes due to the deployment resolution cache. For immediate effect, the cache can be busted by restarting the MCP server session.