> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcp-use.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tool context (ctx)

> The context object passed to every tool, resource, and prompt callback API Documentation

<Callout type="info" title="Source Code">
  View the source code for this module on GitHub:{" "}

  <a href="https://github.com/mcp-use/mcp-use/blob/main/libraries/typescript/packages/server/src/context.ts" target="_blank" rel="noopener noreferrer">
    [https://github.com/mcp-use/mcp-use/blob/main/libraries/typescript/packages/server/src/context.ts](https://github.com/mcp-use/mcp-use/blob/main/libraries/typescript/packages/server/src/context.ts)
  </a>
</Callout>

`RequestContext` is the second argument (`ctx`) passed to tool, resource, and prompt callbacks. It exposes request cancellation, the current HTTP request, OAuth identity when configured, stateless elicitation, request-scoped notifications, progress and logging helpers, and the client metadata declared in the current request.

```ts wrap theme={null}
import { MCPServer } from "mcp-use";

const server = new MCPServer({
  name: "client-context-example",
  version: "1.0.0",
});

server.tool(
  {
    name: "report-client",
    description: "Report the client metadata declared for this request.",
  },
  async (_params, ctx) => {
    const info = ctx.client.info();
    const capabilities = ctx.client.capabilities();
    const user = ctx.client.user();
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify({ info, capabilities, user }),
        },
      ],
    };
  },
);

await server.listen();
```

<Note>
  Client info and capabilities are self-reported, request-scoped hints. Never
  use `ctx.client.info()`, `capabilities()`, `can()`, `extension()`, or `user()`
  for authentication or authorization; use verified `ctx.auth` data instead.
</Note>

## RequestContext

Context object passed to tool, resource, and prompt callbacks. It augments the active Hono context with request-scoped MCP helpers and metadata.

```ts theme={null}
import type { RequestContext } from "mcp-use";
```

### sendNotification

Sends a custom one-way notification related to the active MCP request. The
notification travels on the originating request's response stream and must be
awaited before the callback returns. It does not create a session or a
post-response push channel.

For cross-request tool, prompt, and resource changes, use the corresponding
`server.notify*` helper instead.

**Signature**

```ts wrap theme={null}
sendNotification: (method: string, params?: Record<string, unknown>) =>
  Promise<void>;
```

**Example**

```ts wrap theme={null}
await ctx.sendNotification("com.example/import-status", {
  status: "started",
});
```

**Parameters**

> <ParamField body="method" type="string" required="true">
>   Application-defined notification method. Use a namespace you control.
> </ParamField>
>
> <ParamField body="params" type="Record<string, unknown>" default="undefined">
>   Optional JSON-serializable notification parameters.
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<void>" />

### sample

Requests sampling from the client's LLM, with automatic progress notifications sent every `progressIntervalMs` (default 5000 ms) while waiting. This keeps clients that set `resetTimeoutOnProgress: true` from timing out. There is no timeout by default (the call waits indefinitely); set `options.timeout` to bound the wait. Has two overloads: a simplified string-prompt form and a full-control form that takes complete `CreateMessageRequest["params"]`.

When called with a string prompt, the prompt is wrapped into a single user message and `maxTokens` defaults to `1000`. Only available if the client advertised the `sampling` capability, check with `ctx.client.can("sampling")` first.

**Signature**

```ts wrap theme={null}
sample: {
  // Overload 1: Simplified string API
  (prompt: string, options?: SampleOptions): Promise<CreateMessageResult>;
  // Overload 2: Full control API
  (params: CreateMessageRequest["params"], options?: SampleOptions): Promise<CreateMessageResult>;
};
```

**Parameters**

> <ParamField body="prompt | params" type="string | CreateMessageRequest['params']" required="true">
>   {" "}
>
>   Either a prompt string (simplified API) or a complete sampling params object
>   (full control API).{" "}
> </ParamField>
>
> <ParamField body="options" type="SampleOptions" default="undefined">
>   {" "}
>
>   Optional timeout, progress interval, max tokens, model preferences, and
>   other sampling options. See `SampleOptions`.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<CreateMessageResult>" />

### elicit

Requests user input via the client through elicitation. Supports three overloads with automatic mode detection: a Zod schema for form mode (type-safe, returns `result.data` typed via `z.infer<T>`), a URL string for URL mode (use for sensitive interactions such as OAuth), and the verbose params form for backward compatibility. There is no timeout by default; set `options.timeout` to bound the wait.

In form mode, accepted responses are validated against the Zod schema. If validation fails, an `ElicitationValidationError` is thrown. The returned object always carries the SDK `action` (`"accept"`, `"decline"`, or `"cancel"`), and for accepted responses the input is exposed on `result.data` (validated against the Zod schema in form mode). Only available if the client advertised the `elicitation` capability.

**Signature**

```ts wrap theme={null}
elicit: {
  // Overload 1: Form mode with a Zod schema (type-safe)
  <T extends z.ZodObject<any>>(message: string, schema: T, options?: ElicitOptions): Promise<ElicitResult & { data: z.infer<T> }>;
  // Overload 2: URL mode with a URL string
  (message: string, url: string, options?: ElicitOptions): Promise<ElicitResult>;
  // Overload 3: Verbose params form (backward compatible)
  (params: ElicitFormParams | ElicitUrlParams, options?: ElicitOptions): Promise<ElicitResult>;
};
```

**Parameters**

> <ParamField body="message" type="string" required="true">
>   {" "}
>
>   Human-readable message explaining why the input is needed (overloads 1 and
>   2\).{" "}
> </ParamField>
>
> <ParamField body="schema" type="z.ZodObject<any>" required="true">
>   {" "}
>
>   Zod object schema describing the requested fields (form mode, overload
>   1\).{" "}
> </ParamField>
>
> <ParamField body="url" type="string" required="true">
>   {" "}
>
>   URL the user should navigate to (URL mode, overload 2).{" "}
> </ParamField>
>
> <ParamField body="params" type="ElicitFormParams | ElicitUrlParams" required="true">
>   {" "}
>
>   Verbose params object (overload 3). See `ElicitFormParams` and
>   `ElicitUrlParams`.{" "}
> </ParamField>
>
> <ParamField body="options" type="ElicitOptions" default="undefined">
>   {" "}
>
>   Optional timeout. See `ElicitOptions`.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<ElicitResult & { data: z.infer<T> }> | Promise<ElicitResult>" />

### reportProgress

Sends a progress notification to the client when the request includes a
`progressToken`. Returns `false` without sending when the caller did not
request progress updates.

**Signature**

```ts wrap theme={null}
reportProgress: (progress: number, total?: number, message?: string) =>
  Promise<boolean>;
```

**Parameters**

> <ParamField body="progress" type="number" required="true">
>   {" "}
>
>   Current progress value. Should increase with each call.{" "}
> </ParamField>
>
> <ParamField body="total" type="number" default="undefined">
>   {" "}
>
>   Total progress value, if known.{" "}
> </ParamField>
>
> <ParamField body="message" type="string" default="undefined">
>   {" "}
>
>   Optional message describing current progress.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<boolean>" />

### sendLog

Sends a log notification to the client. Always present on `ctx`, and sends notifications when the client supports them. Levels follow RFC 5424; if the client set a minimum log level, messages below that threshold are dropped silently.

**Signature**

```ts wrap theme={null}
sendLog: (
  level:
    | "debug"
    | "info"
    | "notice"
    | "warning"
    | "error"
    | "critical"
    | "alert"
    | "emergency",
  data: unknown,
  logger?: string,
) => Promise<void>;
```

**Parameters**

> <ParamField body="level" type="&#x22;debug&#x22; | &#x22;info&#x22; | &#x22;notice&#x22; | &#x22;warning&#x22; | &#x22;error&#x22; | &#x22;critical&#x22; | &#x22;alert&#x22; | &#x22;emergency&#x22;" required="true">
>   {" "}
>
>   RFC 5424 log level.{" "}
> </ParamField>
>
> <ParamField body="data" type="unknown" required="true">
>   {" "}
>
>   JSON-serializable log data.{" "}
> </ParamField>
>
> <ParamField body="logger" type="string" default="&#x22;tool&#x22;">
>   {" "}
>
>   Optional logger name. Defaults to `"tool"`.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<void>" />

### client

The request-scoped client metadata interface. Modern v2 clients declare their implementation and capabilities on every request; no value is inferred from a previous request or session. Always present on `ctx`. See the [client object](#client-object) section for each method.

**Signature**

```ts wrap theme={null}
client: {
  can(capability: string): boolean;
  capabilities(): ClientCapabilities;
  info(): Partial<Implementation>;
  extension(id: string): NonNullable<ClientCapabilities["extensions"]>[string] | undefined;
  user(): UserContext | undefined;
  supportsViews(): boolean;
};
```

### session

Session information for the current tool execution. Exposes the unique session ID, which can be passed to `ctx.sendNotificationToSession()` to target this session from another tool.

**Signature**

```ts wrap theme={null}
session: {
  sessionId: string;
}
```

**Properties**

> <ParamField body="sessionId" type="string" required="true">
>   {" "}
>
>   Unique identifier for the current session.{" "}
> </ParamField>

### sendNotification

Sends a notification to the current session (the client that called this tool). A convenience over `server.sendNotification()`, which broadcasts to all sessions. If the session has no `sendNotification` function, a warning is logged and the call resolves without sending.

**Signature**

```ts wrap theme={null}
sendNotification: (method: string, params?: Record<string, unknown>) =>
  Promise<void>;
```

**Parameters**

> <ParamField body="method" type="string" required="true">
>   {" "}
>
>   The notification method name (e.g. `"custom/my-notification"`).{" "}
> </ParamField>
>
> <ParamField body="params" type="Record<string, unknown>" default="undefined">
>   {" "}
>
>   Optional parameters to include in the notification.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<void>" />

### sendNotificationToSession

Sends a notification to a specific session by ID. Unlike `sendNotification`, this can target any connected session, useful for cross-session coordination. Resolves to `false` if the target session is not found or has no notification channel, otherwise `true`.

**Signature**

```ts wrap theme={null}
sendNotificationToSession: (
  sessionId: string,
  method: string,
  params?: Record<string, unknown>,
) => Promise<boolean>;
```

**Parameters**

> <ParamField body="sessionId" type="string" required="true">
>   {" "}
>
>   The target session ID (from `ctx.session.sessionId` or
>   `server.getActiveSessions()`).{" "}
> </ParamField>
>
> <ParamField body="method" type="string" required="true">
>   {" "}
>
>   The notification method name.{" "}
> </ParamField>
>
> <ParamField body="params" type="Record<string, unknown>" default="undefined">
>   {" "}
>
>   Optional parameters to include in the notification.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<boolean>" /> `true` if the
> notification was sent, `false` if the session was not found.

## client object

The `ctx.client` object reflects metadata declared for the current request. `can`, `capabilities`, `info`, `extension`, and `supportsViews` read one snapshot of MCP's modern metadata envelope. `user` separately normalizes ordinary OpenAI-specific request `_meta`. No accessor consults session state or reuses an earlier request. Object accessors return defensive copies, and missing metadata uses empty or absent fallbacks.

All values are client-declared and unverified. Use them to select compatible response behavior, never to grant access; verified identity is available through `ctx.auth` when OAuth is configured.

```ts wrap theme={null}
server.tool(
  {
    name: "who-is-connected",
    description: "Summarize metadata declared by the current client request.",
  },
  async (_params, ctx) => {
    const { name, version } = ctx.client.info();
    const caps = ctx.client.capabilities();
    const ui = ctx.client.extension("io.modelcontextprotocol/ui");
    const user = ctx.client.user();
    console.log(name, version, Object.keys(caps), ui, user?.locale);
    return { content: [{ type: "text", text: "ok" }] };
  },
);
```

### client.can

Checks whether the current request advertises a specific top-level capability. It reports own-property presence, not a truthy value.

**Signature**

```ts wrap theme={null}
can(capability: string): boolean;
```

**Parameters**

> <ParamField body="capability" type="string" required="true">
>   {" "}
>
>   Capability name (e.g. `"sampling"`, `"elicitation"`, `"roots"`).{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="boolean" /> `true` if the client
> advertised this capability.

### client.capabilities

Returns a shallow copy of the official `ClientCapabilities` declared by the current request, or an empty object when no modern envelope is available. Calls do not reuse capabilities from earlier requests.

**Signature**

```ts wrap theme={null}
capabilities(): ClientCapabilities;
```

**Returns**

> <ResponseField name="returns" type="ClientCapabilities" />

### client.info

Returns a shallow copy of the official `Implementation` metadata declared by the current request. Valid modern requests include `name` and `version`; the partial type and empty-object fallback preserve v1 ergonomics for legacy requests without an envelope.

**Signature**

```ts wrap theme={null}
info(): Partial<Implementation>;
```

**Returns**

> <ResponseField name="returns" type="Partial<Implementation>" />

### client.extension

Returns a shallow copy of one extension settings object declared by the current request, or `undefined` if that request did not advertise the extension.

**Signature**

```ts wrap theme={null}
extension(id: string): NonNullable<ClientCapabilities["extensions"]>[string] | undefined;
```

**Parameters**

> <ParamField body="id" type="string" required="true">
>   {" "}
>
>   Extension identifier (e.g. `"io.modelcontextprotocol/ui"`).{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="NonNullable<ClientCapabilities['extensions']>[string] | undefined" />

### client.user

Returns normalized OpenAI-specific caller hints from the current request's ordinary `_meta`, or `undefined` when no recognized valid field is present. It does not require the modern MCP client envelope. Every call returns a fresh object and, when present, a fresh nested location object.

Recognized keys are `openai/locale` (with legacy `webplus/i18n` fallback), `openai/userAgent`, `openai/userLocation`, `openai/subject`, `openai/session`, and `openai/organization`. Malformed values and the no-longer-documented `timezone_offset_minutes` key are ignored.

**Signature**

```ts wrap theme={null}
user(): UserContext | undefined;
```

**Returns**

> <ResponseField name="returns" type="UserContext | undefined" />

<Warning>
  Every field is supplied by the client. A subject, conversation ID, or
  organization ID is not proof of identity or membership. Use `ctx.auth` for
  authentication and authorization.
</Warning>

### client.supportsViews

Returns `true` if the current request advertises MCP Apps support: the `io.modelcontextprotocol/ui` extension whose `mimeTypes` includes `text/html;profile=mcp-app`. Use it to conditionally shape a result for view-capable clients.

**Signature**

```ts wrap theme={null}
supportsViews(): boolean;
```

**Returns**

> <ResponseField name="returns" type="boolean" />

## Functions

### getRequestContext()

Returns the current Hono `Context` from `AsyncLocalStorage`, or `undefined` when called outside a request context. Lets deeply nested code (tool callbacks, dynamically imported resource or prompt handlers) read request headers, middleware-set variables such as `auth`, and env without explicit parameter passing.

```ts theme={null}
import { getRequestContext } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
function getRequestContext(): Context | undefined;
```

**Returns**

> <ResponseField name="returns" type="Context | undefined" /> The Hono `Context`
> for the current async operation, or `undefined` if not in a request context.

### hasRequestContext()

Returns `true` when the current async operation is executing within a request context (an `AsyncLocalStorage` store is set). Use it to branch before calling `getRequestContext()` when a `Context` may or may not be present.

```ts theme={null}
import { hasRequestContext } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
function hasRequestContext(): boolean;
```

**Returns**

> <ResponseField name="returns" type="boolean" /> `true` if a request context is
> available.

### runWithContext()

Runs an async function with a Hono `Context` (and optional session ID) stored in `AsyncLocalStorage`, so that any async operation inside `fn` can retrieve it via `getRequestContext()`. The framework wraps MCP request handling in this for you; you typically only call it directly when integrating custom request handling.

```ts theme={null}
import { runWithContext } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
function runWithContext<T>(
  context: Context,
  fn: () => Promise<T>,
  sessionId?: string,
): Promise<T>;
```

**Parameters**

> <ParamField body="context" type="Context" required="true">
>   {" "}
>
>   Hono `Context` object to store for the duration of `fn`.{" "}
> </ParamField>
>
> <ParamField body="fn" type="() => Promise<T>" required="true">
>   {" "}
>
>   Function to execute within the context.{" "}
> </ParamField>
>
> <ParamField body="sessionId" type="string" default="undefined">
>   {" "}
>
>   Optional session ID to store alongside the context.{" "}
> </ParamField>

**Returns**

> <ResponseField name="returns" type="Promise<T>" /> Resolves to the return
> value of `fn`.

## Types

### SampleOptions

Options for the `sample()` method on `ToolContext`. All fields are optional.

```ts theme={null}
import type { SampleOptions } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
interface SampleOptions {
  timeout?: number;
  progressIntervalMs?: number;
  onProgress?: (progress: {
    progress: number;
    total?: number;
    message: string;
  }) => void;
  maxTokens?: number;
  modelPreferences?: {
    hints?: Array<{ name?: string }>;
    costPriority?: number;
    speedPriority?: number;
    intelligencePriority?: number;
  };
  systemPrompt?: string;
  temperature?: number;
  stopSequences?: string[];
  metadata?: Record<string, unknown>;
}
```

**Properties**

> <ParamField body="timeout" type="number" default="Infinity (no timeout)">
>   {" "}
>
>   Timeout in milliseconds for the sampling request. Defaults to no timeout
>   (waits indefinitely).{" "}
> </ParamField>
>
> <ParamField body="progressIntervalMs" type="number" default="5000">
>   {" "}
>
>   Interval in milliseconds between progress notifications, sent to prevent
>   client timeout when `resetTimeoutOnProgress` is enabled.{" "}
> </ParamField>
>
> <ParamField body="onProgress" type="(progress: { progress: number; total?: number; message: string }) => void" default="undefined">
>   {" "}
>
>   Callback invoked each time a progress notification is sent. Useful for
>   logging.{" "}
> </ParamField>
>
> <ParamField body="maxTokens" type="number" default="1000">
>   {" "}
>
>   Maximum number of tokens to generate. Only used with the string-prompt
>   shorthand.{" "}
> </ParamField>
>
> <ParamField body="modelPreferences" type="{ hints?: Array<{ name?: string }>; costPriority?: number; speedPriority?: number; intelligencePriority?: number }" default="undefined">
>   {" "}
>
>   Model preferences, including hints by name and cost / speed / intelligence
>   priorities.{" "}
> </ParamField>
>
> <ParamField body="systemPrompt" type="string" default="undefined">
>   {" "}
>
>   System prompt to prepend to the conversation.{" "}
> </ParamField>
>
> <ParamField body="temperature" type="number" default="undefined">
>   {" "}
>
>   Temperature for sampling (0.0 to 1.0). Controls randomness.{" "}
> </ParamField>
>
> <ParamField body="stopSequences" type="string[]" default="undefined">
>   {" "}
>
>   Stop sequences that end generation.{" "}
> </ParamField>
>
> <ParamField body="metadata" type="Record<string, unknown>" default="undefined">
>   {" "}
>
>   Additional metadata to pass with the request.{" "}
> </ParamField>

### ElicitOptions

Options for the `elicit()` method on `ToolContext`.

```ts theme={null}
import type { ElicitOptions } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
interface ElicitOptions {
  timeout?: number;
}
```

**Properties**

> <ParamField body="timeout" type="number" default="Infinity (no timeout)">
>   {" "}
>
>   Timeout in milliseconds for the elicitation request. Defaults to no timeout
>   (waits indefinitely for the user response).{" "}
> </ParamField>

### ElicitFormParams

Parameters for form mode elicitation, used with the verbose `elicit()` overload to request structured data with optional JSON Schema validation.

```ts theme={null}
import type { ElicitFormParams } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
interface ElicitFormParams {
  message: string;
  requestedSchema: Record<string, any>;
  mode?: "form";
}
```

**Properties**

> <ParamField body="message" type="string" required="true">
>   {" "}
>
>   Human-readable message explaining why the information is needed.{" "}
> </ParamField>
>
> <ParamField body="requestedSchema" type="Record<string, any>" required="true">
>   {" "}
>
>   JSON Schema defining the structure of the expected response.{" "}
> </ParamField>
>
> <ParamField body="mode" type="&#x22;form&#x22;" default="&#x22;form&#x22;">
>   {" "}
>
>   Mode specifier. Optional for backward compatibility, defaults to form
>   mode.{" "}
> </ParamField>

### ElicitUrlParams

Parameters for URL mode elicitation, used with the verbose `elicit()` overload to direct users to an external URL. Must be used for interactions involving sensitive information such as credentials.

```ts theme={null}
import type { ElicitUrlParams } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
interface ElicitUrlParams {
  message: string;
  url: string;
  mode: "url";
}
```

**Properties**

> <ParamField body="message" type="string" required="true">
>   {" "}
>
>   Human-readable message explaining why the interaction is needed.{" "}
> </ParamField>
>
> <ParamField body="url" type="string" required="true">
>   {" "}
>
>   URL for the user to navigate to.{" "}
> </ParamField>
>
> <ParamField body="mode" type="&#x22;url&#x22;" required="true">
>   {" "}
>
>   Mode specifier. Required for URL mode.{" "}
> </ParamField>

### UserContext

Normalized caller hints returned by `ctx.client.user()`, extracted from per-request `_meta` using OpenAI's documented key convention. All fields are optional, and the whole object is `undefined` when no recognized valid field is present. This data is client-reported and unverified; do not treat it as identity or authorization data.

```ts theme={null}
import type { UserContext } from "mcp-use";
```

**Signature**

```ts wrap theme={null}
interface UserContext {
  locale?: string;
  userAgent?: string;
  location?: {
    city?: string;
    region?: string;
    country?: string;
    timezone?: string;
    latitude?: string | number;
    longitude?: string | number;
  };
  subject?: string;
  conversationId?: string;
  organizationId?: string;
}
```

**Properties**

> <ParamField body="userAgent" type="string" default="undefined">
>   {" "}
>
>   Browser or host user-agent string (from `openai/userAgent`).{" "}
> </ParamField>
>
> <ParamField body="locale" type="string" default="undefined">
>   {" "}
>
>   BCP-47 locale tag, e.g. `"it-IT"` (from `openai/locale`).{" "}
> </ParamField>
>
> <ParamField body="location" type="{ city?: string; region?: string; country?: string; timezone?: string; latitude?: string | number; longitude?: string | number }" default="undefined">
>   {" "}
>
>   Approximate geographic location of the end user (from
>   `openai/userLocation`).{" "}
> </ParamField>
>
> <ParamField body="subject" type="string" default="undefined">
>   {" "}
>
>   Client-reported opaque subject hint (from `openai/subject`).{" "}
> </ParamField>
>
> <ParamField body="conversationId" type="string" default="undefined">
>   {" "}
>
>   Identifier for the current chat or conversation thread (from
>   `openai/session`). It is application metadata, not MCP transport state.{" "}
> </ParamField>
>
> <ParamField body="organizationId" type="string" default="undefined">
>   {" "}
>
>   Client-reported organization hint (from `openai/organization`).{" "}
> </ParamField>

### McpContext

Conditional Hono context type used as the base for MCP callbacks. The `HasOAuth` type parameter selects whether `auth` is guaranteed present. With `HasOAuth = true` (`McpContextWithAuth`), `auth: AuthInfo` is non-optional because tools are protected by default when OAuth is configured. With the default `HasOAuth = false` (`McpContextBase`), `auth?: AuthInfo` is optional so you can null-check, for example `if (!ctx.auth) return error("Not authenticated")`.

```ts theme={null}
import type { McpContext } from "mcp-use/server";
```

**Signature**

```ts wrap theme={null}
type McpContext<HasOAuth extends boolean = false> = HasOAuth extends true
  ? McpContextWithAuth
  : McpContextBase;
```

**Type Parameters**

> <ParamField body="HasOAuth" type="boolean" default="false">
>   {" "}
>
>   When `true`, `auth: AuthInfo` is guaranteed present. When `false`, `auth?:
>       AuthInfo` is optional.{" "}
> </ParamField>

**Resolved shapes**

> <ResponseField name="McpContextBase" type="HonoContext & { auth?: AuthInfo }">
>   {" "}
>
>   Base context without OAuth. `auth` is optional.{" "}
> </ResponseField>
>
> <ResponseField name="McpContextWithAuth" type="HonoContext & { auth: AuthInfo; readonly __hasOAuth?: true }">
>   {" "}
>
>   Context with OAuth configured. `auth` is guaranteed present.{" "}
> </ResponseField>
