---
title: Context
description: Per-request context and authenticated fetch for tools, resources, and providers
sidebarTitle: Context
slug: extensibility/request-context
icon: id-card
keywords: ['frontmcp', 'mcp', 'model context protocol', 'extensibility', 'extension', 'customization', 'request context', 'fetch', 'typescript']
---

FrontMcpContext provides per-request state that flows through the entire async execution chain. It enables distributed tracing, timing, request-scoped data storage, context-aware fetch, and transport access.

## Overview

Every HTTP request to your FrontMCP server creates a `FrontMcpContext` that:

- Propagates through all stages, tools, resources, and prompts via AsyncLocalStorage
- Provides W3C Trace Context for distributed tracing
- Stores authentication information after verification
- Tracks timing marks for performance monitoring
- Provides request-scoped key-value storage
- Offers context-aware fetch with auto-injection
- Enables transport access for elicit requests

## Accessing Context

### From Tools/Resources/Prompts

Use the `context` getter for convenient access:

```ts
import { Tool } from '@frontmcp/sdk';
import { z } from '@frontmcp/sdk';

@Tool({ name: 'my-tool', inputSchema: { query: z.string() } })
class MyTool {
  async execute({ query }) {
    const ctx = this.context;
    // or: const ctx = this.get(FRONTMCP_CONTEXT);

    console.log(`Request ${ctx.requestId} from session ${ctx.sessionId}`);
    return `Processed: ${query}`;
  }
}
```

### Safe Access

Use `tryGetContext()` when context may not be available (e.g., during initialization or in non-HTTP flows):

```ts
const ctx = this.tryGetContext();
if (ctx) {
  console.log(ctx.requestId);
} else {
  console.log('No context available');
}
```

### From CONTEXT-Scoped Providers

CONTEXT-scoped providers can receive FrontMcpContext via factory injection:

```ts
import { ProviderScope, FRONTMCP_CONTEXT, FrontMcpContext } from '@frontmcp/sdk';

const requestLoggerProvider = {
  provide: 'RequestLogger',
  scope: ProviderScope.CONTEXT,
  useFactory: (ctx: FrontMcpContext) => ({
    log: (msg: string) => console.log(`[${ctx.requestId}] ${msg}`),
  }),
  inject: [FRONTMCP_CONTEXT],
};
```

---

## Context-Aware Fetch

FrontMcpContext provides a `fetch()` method that automatically injects headers:

```ts
const ctx = this.context;

// Automatically injects:
// - Authorization: Bearer <token> (if authInfo.token is available)
// - traceparent: <W3C trace context>
// - x-request-id: <request ID>
// - Custom x-frontmcp-* headers from request metadata
const response = await ctx.fetch('https://api.example.com/data');
```

### Configuration

Configure fetch behavior via context config:

```ts
// In FrontMcpContextArgs
{
  config: {
    autoInjectAuthHeaders: true,       // Default: true
    autoInjectTracingHeaders: true,    // Default: true
    requestTimeout: 30000,             // Default: 30000ms
  }
}
```

### Custom Headers

Additional headers can be passed and will be merged:

```ts
const response = await ctx.fetch('https://api.example.com/data', {
  headers: {
    'X-Custom-Header': 'value',
  },
});
```

---

## Transport Access (Elicit)

Access the transport for interactive prompts:

```ts
const ctx = this.context;

if (ctx.transport?.supportsElicit) {
  const result = await ctx.transport.elicit('Please confirm your action', schema);

  switch (result.action) {
    case 'accept':
      console.log('User accepted:', result.content);
      break;
    case 'decline':
      console.log('User declined');
      break;
    case 'cancel':
      console.log('User cancelled');
      break;
  }
}
```

---

## Distributed Tracing

FrontMcpContext automatically parses [W3C Trace Context](https://www.w3.org/TR/trace-context/) headers for distributed tracing compatibility.

### Supported Headers

| Header                | Description                                              |
| --------------------- | -------------------------------------------------------- |
| `traceparent`         | W3C standard: `{version}-{trace-id}-{parent-id}-{flags}` |
| `tracestate`          | Vendor-specific trace data                               |
| `x-frontmcp-trace-id` | Fallback for non-W3C clients                             |

### Using Trace Context

```ts
const ctx = this.context;

// Access trace identifiers
const { traceId, parentId, traceFlags, traceState } = ctx.traceContext;

console.log(`Trace: ${traceId}, Parent: ${parentId}, Flags: ${traceFlags}`);

// Use ctx.fetch() for automatic trace propagation
const response = await ctx.fetch('https://api.example.com/data');
```

### Integration with Observability Tools

FrontMCP's trace context is compatible with:

- OpenTelemetry
- Datadog APM
- AWS X-Ray
- Jaeger
- Zipkin

---

## Timing & Performance

Track execution timing with marks for performance monitoring:

```ts
const ctx = this.context;

// Mark stages
ctx.mark('validation-start');
await this.validateInput();
ctx.mark('validation-end');

ctx.mark('db-query-start');
await this.queryDatabase();
ctx.mark('db-query-end');

// Measure elapsed time
console.log(`Validation: ${ctx.elapsed('validation-start', 'validation-end')}ms`);
console.log(`DB Query: ${ctx.elapsed('db-query-start', 'db-query-end')}ms`);
console.log(`Total: ${ctx.elapsed()}ms`); // From request start to now
```

### Performance Logging

```ts
// Log all timing marks at the end of request
const marks = ctx.getMarks();
for (const [name, timestamp] of marks) {
  console.log(`${name}: ${timestamp - ctx.timestamp}ms from start`);
}
```

---

## Context-Scoped Storage

Store and retrieve data that lives only for the duration of the request:

```ts
const ctx = this.context;

// Store data
ctx.set('correlation-id', crypto.randomUUID());
ctx.set('feature-flags', { newUI: true, betaFeatures: false });

// Retrieve data (later in the same request)
const correlationId = ctx.get<string>('correlation-id');
const flags = ctx.get<{ newUI: boolean }>('feature-flags');

// Check existence
if (ctx.has('correlation-id')) {
  // ...
}

// Delete data
ctx.delete('feature-flags');
```

---

## Request Metadata

Access HTTP request metadata:

```ts
const ctx = this.context;
const { metadata } = ctx;

console.log(`User-Agent: ${metadata.userAgent}`);
console.log(`Client IP: ${metadata.clientIp}`);
console.log(`Content-Type: ${metadata.contentType}`);
console.log(`Accept: ${metadata.accept}`);

// Custom x-frontmcp-* headers
console.log(`Custom headers:`, metadata.customHeaders);
```

---

## Authentication

Access authentication information via the context:

```ts
const ctx = this.context;
const { authInfo } = ctx;

// JWT token
if (authInfo.token) {
  console.log(`Token present, expires: ${authInfo.expiresAt}`);
}

// User information
if (authInfo.user) {
  console.log(`User: ${authInfo.user.email}`);
  console.log(`Tenant: ${authInfo.user.tenantId}`);
}

// Session information
console.log(`Session: ${authInfo.sessionId}`);
```

<Warning>
  `authInfo` is `Partial<AuthInfo>` because authentication information is progressively populated during the request lifecycle. Fields are fully populated after the authorization stage completes.
</Warning>

---

## Logging

Get a child logger with context attached:

```ts
const ctx = this.context;
const logger = ctx.getLogger(this.logger);

// Logger includes requestId and traceId prefix
logger.info('Processing request'); // [abc12345:def67890] Processing request

// Get summary for structured logging
const logContext = ctx.toLogContext();
// {
//   requestId: 'abc12345-...',
//   traceId: 'def67890...',
//   sessionIdHash: 'a1b2c3d4e5f6', // Hashed for privacy
//   scopeId: 'main',
//   flowName: 'tools/call',
//   elapsed: 123,
// }
```

---

## API Reference

### FrontMcpContext Class

| Property          | Type                             | Description                              |
| ----------------- | -------------------------------- | ---------------------------------------- |
| `requestId`       | `string`                         | Unique request identifier (UUID v4)      |
| `traceContext`    | `TraceContext`                   | W3C Trace Context data                   |
| `sessionId`       | `string`                         | MCP session identifier                   |
| `authInfo`        | `Partial<AuthInfo>`              | Authentication information               |
| `scopeId`         | `string`                         | Current scope identifier                 |
| `timestamp`       | `number`                         | Request start timestamp (ms since epoch) |
| `metadata`        | `RequestMetadata`                | HTTP request metadata                    |
| `config`          | `FrontMcpContextConfig`          | Context configuration                    |
| `transport`       | `TransportAccessor \| undefined` | Transport for elicit requests            |
| `flow`            | `FlowBaseRef \| undefined`       | Current flow reference                   |
| `scope`           | `ScopeRef \| undefined`          | Current scope reference                  |
| `sessionMetadata` | `SessionIdPayload \| undefined`  | Session metadata (protocol, platform)    |

| Method                  | Signature                                                                 | Description                        |
| ----------------------- | ------------------------------------------------------------------------- | ---------------------------------- |
| `mark`                  | `mark(name: string): void`                                                | Record a timing mark               |
| `elapsed`               | `elapsed(from?: string, to?: string): number`                             | Get elapsed time in ms             |
| `getMarks`              | `getMarks(): ReadonlyMap<string, number>`                                 | Get all timing marks               |
| `set`                   | `set<T>(key: string \| symbol, value: T): void`                           | Store context-scoped data          |
| `get`                   | `get<T>(key: string \| symbol): T \| undefined`                           | Retrieve context-scoped data       |
| `has`                   | `has(key: string \| symbol): boolean`                                     | Check if key exists                |
| `delete`                | `delete(key: string \| symbol): boolean`                                  | Delete a key                       |
| `getLogger`             | `getLogger(parent: FrontMcpLogger): FrontMcpLogger`                       | Get child logger with context      |
| `toLogContext`          | `toLogContext(): Record<string, unknown>`                                 | Get summary for logging            |
| `fetch`                 | `fetch(input: RequestInfo \| URL, init?: RequestInit): Promise<Response>` | Context-aware fetch                |
| `updateAuthInfo`        | `updateAuthInfo(authInfo: Partial<AuthInfo>): void`                       | Update auth info (internal)        |
| `updateSessionMetadata` | `updateSessionMetadata(metadata: SessionIdPayload): void`                 | Update session metadata (internal) |

### TraceContext Interface

| Property     | Type                  | Description                       |
| ------------ | --------------------- | --------------------------------- |
| `traceId`    | `string`              | 32-character hex trace identifier |
| `parentId`   | `string \| undefined` | 16-character hex parent span ID   |
| `traceFlags` | `number`              | Trace flags (e.g., 1 for sampled) |
| `traceState` | `string \| undefined` | Vendor-specific trace state       |
| `raw`        | `string`              | Raw traceparent header value      |

### RequestMetadata Interface

| Property        | Type                     | Description                     |
| --------------- | ------------------------ | ------------------------------- |
| `userAgent`     | `string \| undefined`    | User-Agent header               |
| `contentType`   | `string \| undefined`    | Content-Type header             |
| `accept`        | `string \| undefined`    | Accept header                   |
| `clientIp`      | `string \| undefined`    | Client IP address               |
| `customHeaders` | `Record<string, string>` | Headers matching `x-frontmcp-*` |

### TransportAccessor Interface

| Property/Method  | Type                                                     | Description                       |
| ---------------- | -------------------------------------------------------- | --------------------------------- |
| `supportsElicit` | `boolean`                                                | Whether transport supports elicit |
| `elicit`         | `<T>(message: string, schema: T): Promise<ElicitResult>` | Send elicit request               |

---

## Key Features

1. **Unified Context**: All request-scoped data in one place
2. **Better Tracing**: Access trace IDs alongside auth info
3. **Context-Aware Fetch**: Auto-inject headers in outgoing requests
4. **Transport Access**: Use elicit directly from context
5. **Timing Integration**: Correlate auth with performance metrics
6. **Future-Proof**: New features will be added to FrontMcpContext
