Skip to main content

ctx

Learn how to add custom context to your MCP server and access request-specific information.

The ctx property on the server instance provides access to request-specific context information. This includes session details, client capabilities, authentication info, and custom data you define.

Context is especially useful when you need to pass application-specific data through your MCP server without using global variables, enabling proper request isolation in multi-session environments.

Basic API

Access the context through server.ctx within your handlers:

		server.tool(
	{
		name: 'get_info',
		description: 'Get session information',
	},
	async () => {
		const sessionId = server.ctx.sessionId;
		const clientName = server.ctx.sessionInfo?.clientInfo?.name;
		
		return tool.text(`Session: ${sessionId}, Client: ${clientName}`);
	},
);
	

The context object contains:

Property Description
sessionId Unique identifier for the current session
sessionInfo Object containing clientCapabilities, clientInfo, and logLevel
auth Authentication information if OAuth is enabled
custom Your custom context data

Custom Context

You can add your own context data to pass application-specific information through the server. First, define the context type using withContext:

		const server = new McpServer(
	{
		name: 'my-server',
		version: '1.0.0',
	},
	{
		adapter: new ValibotJsonSchemaAdapter(),
		capabilities: {
			tools: {},
		},
	},
).withContext<{
	userId: string;
	database: Database;
	config: AppConfig;
}>();
	

Providing Context

HTTP Transport

Pass custom context to the respond method:

		import { HttpTransport } from '@tmcp/transport-http';
 
const transport = new HttpTransport(server, {
	path: '/mcp',
});
 
serve({
	port: 3000,
	fetch: async (request) => {
		// Extract user info from request (e.g., from auth headers)
		const userId = request.headers.get('x-user-id');
		const database = await connectToDatabase();
		
		const response = await transport.respond(request, {
			userId: userId || 'anonymous',
			database,
			config: appConfig,
		});
		
		return response || new Response('Not Found', { status: 404 });
	},
});
	

Stdio Transport

Pass custom context to the listen method:

		import { StdioTransport } from '@tmcp/transport-stdio';
 
const transport = new StdioTransport(server);
 
const database = await connectToDatabase();
 
transport.listen({
	userId: 'local-user',
	database,
	config: appConfig,
});
	

Accessing Custom Context

Once you've provided custom context, access it through server.ctx.custom:

		server.tool(
	{
		name: 'query_database',
		description: 'Query the user database',
		schema: v.object({
			query: v.string(),
		}),
	},
	async ({ query }) => {
		// Access custom context
		const { database, userId } = server.ctx.custom!;
		
		// Use context in your logic
		const results = await database.query(query, { userId });
		
		return tool.text(JSON.stringify(results));
	},
);