Skip to main content
FrontMCP’s environment-awareness system lets you declaratively restrict when entries (tools, resources, prompts, skills, agents) are discoverable and executable, based on the runtime environment. Entries that don’t match the current environment are automatically filtered from discovery and blocked from execution.
This enables platform-specific tools (e.g., Apple Notes on macOS only), runtime-specific resources (e.g., Node.js file system), and environment-gated features (e.g., debug tools in development only).

The availableWhen Option

Add availableWhen to any entry’s metadata to constrain its availability:

Matching Semantics

  • AND across fields — all specified fields must match
  • OR within arrays — at least one value in an array must match
  • Omitted fields — unconstrained (matches everything)
  • Empty array — matches nothing (entry is never available)
  • No availableWhen — always available (default)

Available Fields

os (replaces platform)

Operating system, matching process.platform values. Renamed from platform in issue #417 — the old name still works as a deprecated alias.

runtime

JavaScript runtime:

deployment

Coarse deployment mode:

provider (issue #417)

Discriminated deploy provider. Lets @Tool({ availableWhen: { provider: ['vercel'] } }) express provider-specific rules where deployment: ['serverless'] is too coarse. Override the detection with FRONTMCP_PROVIDER=<name> (useful for tests, Docker images without a discriminating env var, etc.).

target (issue #417)

Build target produced by frontmcp build --target <x>. Always 'unknown' in dev (frontmcp dev). Resolution order: globalThis.FRONTMCP_BUILD_TARGET (inlined by the adapter) → process.env.FRONTMCP_BUILD_TARGET'unknown'.

surface (issue #417)

Per-call axis — set by the transport adapter / dispatcher on the request ctx to discriminate “who is calling this tool.” Unlike the other axes (which are constant for the process lifetime), surface varies per request. Example — block external MCP calls but allow agent dispatch:

env

NODE_ENV value:

Structured errors

When a tool exists but its availableWhen constraint fails at call time, FrontMCP throws EntryUnavailableError with a missingAxes array in data (issue #417). Clients can surface “this tool isn’t reachable because provider=vercel / surface=mcp / …” without parsing prose.

Supported Entry Types

availableWhen works on all five entry types:

Runtime Context API

Inside execute() methods, use runtime context helpers for imperative checks:

Available Methods

RuntimeContext exposes the operating system via the os property; platform remains as a deprecated alias for backward compatibility (issue #417) and resolves to the same value. New code should read this.runtimeContext.os directly. These methods are available on ToolContext, ResourceContext, PromptContext, and AgentContext.

Multi-Platform Pattern

When building tools that serve the same purpose across platforms, use separate files with availableWhen in each:
Register all variants — the SDK automatically exposes only the one matching the current platform:
The multi-platform file pattern (name.platform.tool.ts) is recommended when you have platform-specific implementations of the same logical capability. For simple cases where a single tool needs a platform check, use this.isPlatform() inside execute() instead.

Error Handling

When a client tries to call a tool that exists but is unavailable in the current environment, the SDK returns an EntryUnavailableError (HTTP 403) with both the constraint and the current context. The data payload includes a missingAxes array so clients can show a precise reason for the failure without parsing the message string:
This is distinct from a ToolNotFoundError (404), helping clients understand why a tool is inaccessible. See the Structured errors reference (if present) for the full schema.

How It Works: Registry-Level Filtering

availableWhen is not the same as authorization or rule-based filtering. It is evaluated at the registry level during server boot, not in HTTP request flows.
Key differences:
  • availableWhen is a hard constraint — filtered entries cannot be listed OR called
  • It runs at registry initialization, not in HTTP flows — no per-request overhead
  • The runtime context (OS, runtime, deployment, NODE_ENV) is detected once and cached
  • Results are logged at boot time for operational visibility

Boot-Time Logging

When entries have availableWhen constraints, the SDK logs a summary at startup:
Empty constraint arrays trigger a warning (likely a configuration bug):