Skip to content

Conversation

@KKonstantinov
Copy link
Contributor

This is a PR which aims to introduce convenience / quality of life improvements to the Typescript SDK.

It adds a Context utility (with the aim to be backwards-compatible, so anyone using RequestHandlerExtra will not have breaking changes), which exposes extra convenience methods and could be extended further down the line.

Motivation and Context

It aims to explore the concept of a backwards-compatible Context utility class being passed in callbacks on the server-side. The Context utility class provides convenience methods and can be further extended in the future. It provides access to methods like logging, sampling, elicitation (and others could be added) and one can call them from the callbacks without having access to the Server or McpServer instances.

How Has This Been Tested?

Additional unit tests have been added.
Existing unit tests work with no changes.
Tests when callback is tied to RequestHandlerExtra.

Breaking Changes

No breaking changes.
The additions affect only server-side. Client-side should remain the same.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

The changes follow existing concepts of the PythonSDK, applied in a similar fashion (to the extent that the libraries differ or similar in various parts of them) to Typescript.

Notes:

  • If we can afford breaking changes, would definitely restructure/remove things out of Context, but currently it needs to implement RequestHandlerExtra to keep backward compatibility

Logging Utility methods

       // The .debug, .info, .warning, .error methods require a string message, and take optional extra data
       // The generic .log method follows the out of the box schema
        mcpServer.tool('ctx-log-test', { name: z.string() }, async (_args: { name: string }, extra) => {
            // Debug message with extra log data and a related session ID
            await extra.debug('Test message', { test: 'test' }, 'sample-session-id');
            // Info message with extra log data and a related session ID
            await extra.info('Test message', { test: 'test' }, 'sample-session-id');
            // Warning message with extra log data and a related session ID
            await extra.warning('Test message', { test: 'test' }, 'sample-session-id');
            // Error message with extra log data and a related session ID
            await extra.error('Test message', { test: 'test' }, 'sample-session-id');

            // Generic .log method which supports all levels, and "data" could be anything (not just a string)
            await extra.log({
                level,
                data: 'Test message',
                logger: 'test-logger-namespace'
            }, 'sample-session-id');

            return { content: [{ type: 'text', text: 'ok' }] };
        });

Elicit from Context

mcpServer.tool(
            'elicit-through-ctx-tool',
            {
                restaurant: z.string(),
                date: z.string(),
                partySize: z.number()
            },
            async ({ restaurant, date, partySize }, extra) => {
                // Check availability
                const available = await checkAvailability(restaurant, date, partySize);

                if (!available) {
                    // Ask user if they want to try alternative dates
                    const result = await extra.elicit({ // **Calling .elicit from Context here
                        message: `No tables available at ${restaurant} on ${date}. Would you like to check alternative dates?`,
                        requestedSchema: {
                            type: 'object',
                            properties: {
                                checkAlternatives: {
                                    type: 'boolean',
                                    title: 'Check alternative dates',
                                    description: 'Would you like me to check other dates?'
                                },
                                flexibleDates: {
                                    type: 'string',
                                    title: 'Date flexibility',
                                    description: 'How flexible are your dates?',
                                    enum: ['next_day', 'same_week', 'next_week'],
                                    enumNames: ['Next day', 'Same week', 'Next week']
                                }
                            },
                            required: ['checkAlternatives']
                        }
                    });
......

Sampling from Context

mcpServer.registerTool(
            'summarize',
            {
                title: 'Text Summarizer',
                description: 'Summarize any text using an LLM',
                inputSchema: {
                    text: z.string().describe('Text to summarize')
                },
                outputSchema: { summary: z.string() }
            },
            async ({ text }, extra) => {
                // Call the LLM through MCP sampling through Context
                const response = await extra.requestSampling({
                    messages: [
                        {
                            role: 'user',
                            content: {
                                type: 'text',
                                text: `Please summarize the following text concisely:\n\n${text}`
                            }
                        }
                    ],
                    maxTokens: 500
                });
        
                const summary = response.content.type === 'text' ? response.content.text : 'Unable to generate summary';

@KKonstantinov KKonstantinov requested a review from a team as a code owner December 7, 2025 08:26
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 7, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1241

commit: 96169b3

@KKonstantinov KKonstantinov linked an issue Dec 8, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ctx object inside the tool extra for transport/server controls

2 participants