MCP Sampling AI Provider
The MCP Sampling AI Provider allows MCP servers to use AI models through the AI SDK by leveraging your existing client subscriptions (like VS Code Copilot). This transforms your MCP server into an agentic tool that can reason and make decisions, without requiring separate API keys or subscriptions.
The provider implements LanguageModelV2 by forwarding requests through MCP's sampling feature to the MCP client, offering unique advantages:
- Server-Side AI Integration: Enable MCP servers to call language models directly through AI SDK's standard interface
- No Direct Model Management: Forward AI requests to MCP clients, eliminating the need for multiple API keys
- Model Flexibility: Let MCP clients decide which model to use based on preferences (cost, speed, intelligence)
- Seamless AI SDK Compatibility: Support for
generateText,streamText,generateObject, and experimental tool calling - Client Sampling Support: Add sampling capability to any MCP client with built-in helpers
- Agentic Tools: Transform simple MCP tools into intelligent agents that can reason and make decisions
Learn more about MCP Sampling in the MCP Specification.
Prerequisites
Warning: This provider has specific requirements:
- Must run inside an MCP Server - This is not a standalone AI SDK provider. It works by forwarding requests to the MCP client.
- Client must support MCP Sampling - The connected MCP client must implement the sampling capability, or you can implement it yourself (see Client Sampling below).
Clients with Sampling Support
- VS Code (with GitHub Copilot) - Supported
- Claude Desktop - Tracking (Issue #1785)
- Cursor - Tracking (Issue #3023)
See the full list of MCP clients for more options.
Alternative: Use setupClientSampling() to add sampling to any MCP client (see example below).
Setup
The MCP Sampling AI Provider is available in the @mcpc-tech/mcp-sampling-ai-provider module. You can install it with:
pnpm add @mcpc-tech/mcp-sampling-ai-provider
Provider Instance
To create an MCP Sampling provider instance, use the createMCPSamplingProvider function with your MCP server instance:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';import { createMCPSamplingProvider } from '@mcpc-tech/mcp-sampling-ai-provider';
// Create an MCP server with sampling capabilityconst server = new Server( { name: 'my-agent', version: '1.0.0' }, { capabilities: { sampling: {}, tools: {} } },);
const provider = createMCPSamplingProvider({ server });Configuration
The provider accepts the following configuration:
-
server MCP Server instance
An MCP Server instance that has sampling capability enabled.
Language Models
Create a language model instance using the languageModel() method:
const model = provider.languageModel({ modelPreferences: { hints: [{ name: 'gpt-5-mini' }], costPriority: 0.5, speedPriority: 0.8, intelligencePriority: 0.9, },});Model Preferences
The languageModel() method accepts optional model preferences:
-
hints Array<{ name: string }>
Array of model name hints (e.g.,
[{ name: "gpt-5-mini" }]). These suggest preferred models to the MCP client. -
costPriority number (0-1)
Higher values prefer cheaper models. Default is 0.
-
speedPriority number (0-1)
Higher values prefer faster models. Default is 0.
-
intelligencePriority number (0-1)
Higher values prefer more capable models. Default is 0.
See MCP Model Preferences for more details.
Examples
generateText
Generate text using the MCP Sampling Provider in an MCP server tool:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import { CallToolRequestSchema, ListToolsRequestSchema,} from '@modelcontextprotocol/sdk/types.js';import { createMCPSamplingProvider } from '@mcpc-tech/mcp-sampling-ai-provider';import { generateText } from 'ai';
// Create MCP server with sampling capabilityconst server = new Server( { name: 'translator', version: '1.0.0' }, { capabilities: { sampling: {}, tools: {} } },);
// List available toolsserver.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'translate', description: 'Translate text to a target language using AI', inputSchema: { type: 'object', properties: { text: { type: 'string', description: 'The text to translate', }, target_lang: { type: 'string', description: 'The target language (e.g., "Spanish", "French")', }, }, required: ['text', 'target_lang'], }, }, ], };});
// Register a translation tool that uses AIserver.setRequestHandler(CallToolRequestSchema, async request => { if (request.params.name === 'translate') { // Create provider from the server const provider = createMCPSamplingProvider({ server });
// Use AI SDK to translate text const { text } = await generateText({ model: provider.languageModel({ modelPreferences: { hints: [{ name: 'gpt-5-mini' }] }, }), prompt: `Translate to ${request.params.arguments?.target_lang}: ${request.params.arguments?.text}`, });
return { content: [{ type: 'text', text }] }; }});
// Connect and startconst transport = new StdioServerTransport();await server.connect(transport);streamText
Stream text responses using the MCP Sampling Provider:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import { CallToolRequestSchema, ListToolsRequestSchema,} from '@modelcontextprotocol/sdk/types.js';import { createMCPSamplingProvider } from '@mcpc-tech/mcp-sampling-ai-provider';import { streamText } from 'ai';
const server = new Server( { name: 'ai-assistant', version: '1.0.0' }, { capabilities: { sampling: {}, tools: {} } },);
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'generate-story', description: 'Generate a story or poem using AI', inputSchema: { type: 'object', properties: {}, }, }, ], };});
server.setRequestHandler(CallToolRequestSchema, async request => { if (request.params.name === 'generate-story') { const provider = createMCPSamplingProvider({ server });
const result = streamText({ model: provider.languageModel({ modelPreferences: { hints: [{ name: 'gpt-5-mini' }], speedPriority: 0.9, }, }), prompt: 'Write a short poem about coding.', });
const text = await result.text;
return { content: [{ type: 'text', text }] }; }});
const transport = new StdioServerTransport();await server.connect(transport);generateObject
Generate structured objects using the MCP Sampling Provider:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import { CallToolRequestSchema, ListToolsRequestSchema,} from '@modelcontextprotocol/sdk/types.js';import { createMCPSamplingProvider } from '@mcpc-tech/mcp-sampling-ai-provider';import { generateObject } from 'ai';import { z } from 'zod';
const server = new Server( { name: 'recipe-generator', version: '1.0.0' }, { capabilities: { sampling: {}, tools: {} } },);
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'generate-recipe', description: 'Generate a recipe using AI', inputSchema: { type: 'object', properties: {}, }, }, ], };});
server.setRequestHandler(CallToolRequestSchema, async request => { if (request.params.name === 'generate-recipe') { const provider = createMCPSamplingProvider({ server });
const recipeSchema = z.object({ recipe: z.object({ name: z.string(), cuisine: z.string(), ingredients: z.array(z.string()), steps: z.array(z.string()), }), });
const { object } = await generateObject({ mode: 'json', model: provider.languageModel({ modelPreferences: { hints: [{ name: 'gpt-5-mini' }] }, }), schema: recipeSchema, prompt: 'Generate a delicious lasagna recipe.', });
return { content: [{ type: 'text', text: JSON.stringify(object, null, 2) }], }; }});
const transport = new StdioServerTransport();await server.connect(transport);Tool Calling (Experimental)
Use tools with the MCP Sampling Provider. Note: This is implemented via system prompt and may not be as reliable as native tool support:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import { CallToolRequestSchema, ListToolsRequestSchema,} from '@modelcontextprotocol/sdk/types.js';import { createMCPSamplingProvider } from '@mcpc-tech/mcp-sampling-ai-provider';import { generateText } from 'ai';import { z } from 'zod';
const server = new Server( { name: 'weather-agent', version: '1.0.0' }, { capabilities: { sampling: {}, tools: {} } },);
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'ask-weather', description: 'Ask a weather-related question', inputSchema: { type: 'object', properties: { question: { type: 'string', description: 'The weather question to ask', }, }, }, }, ], };});
server.setRequestHandler(CallToolRequestSchema, async request => { if (request.params.name === 'ask-weather') { const provider = createMCPSamplingProvider({ server });
const result = await generateText({ model: provider.languageModel({ modelPreferences: { hints: [{ name: 'gpt-5-mini' }] }, }), tools: { getWeather: { description: 'Get the weather for a location', parameters: z.object({ city: z.string().describe('The city name'), }), execute: async ({ city }) => { return `The weather in ${city} is sunny and 72°F`; }, }, }, prompt: request.params.arguments?.question || 'What is the weather in San Francisco?', maxSteps: 5, });
return { content: [{ type: 'text', text: result.text }] }; }});
const transport = new StdioServerTransport();await server.connect(transport);Additional Examples
See the examples directory for more complete working examples:
- generate_text_example.ts - Basic text generation
- stream_text_example.ts - Streaming responses
- generate_object_example.ts - Structured output
- client-sampling-example.ts - Client sampling implementation
Client Sampling (for clients without native support)
If your MCP client doesn't support sampling natively, you can add sampling capability using setupClientSampling with model preferences:
import { Client } from '@modelcontextprotocol/sdk/client/index.js';import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';import { convertAISDKFinishReasonToMCP, selectModelFromPreferences, setupClientSampling,} from '@mcpc-tech/mcp-sampling-ai-provider';import { generateText } from 'ai';
const client = new Client( { name: 'my-client', version: '1.0.0' }, { capabilities: { sampling: {} } },);
setupClientSampling(client, { handler: async params => { const modelId = selectModelFromPreferences(params.modelPreferences, { hints: { 'gpt-5': 'openai/gpt-5-mini', 'gpt-mini': 'openai/gpt-5-mini', }, priorities: { speed: 'openai/gpt-5-mini', intelligence: 'openai/gpt-5-mini', }, default: 'openai/gpt-5-mini', });
const result = await generateText({ model: modelId, messages: params.messages, });
return { model: modelId, role: 'assistant', content: { type: 'text', text: result.text }, stopReason: convertAISDKFinishReasonToMCP(result.finishReason), }; },});
const transport = new StdioClientTransport({ command: 'npx', args: ['-y', 'example_mcp_server.ts'],});
await client.connect(transport);See the complete example for more details.
How It Works
The request flow is straightforward:
- AI SDK calls the language model
- Provider converts to MCP
sampling/createMessageformat - MCP client handles the sampling request
- Provider converts response back to AI SDK format
The MCP client (e.g., VS Code, Claude Desktop) decides which actual model to use based on the provided modelPreferences.
Limitations
- No token counting: MCP doesn't provide token usage information (returns 0)
- No native streaming: MCP sampling doesn't support streaming - the provider calls
doGeneratefirst, then emits the complete response as stream events - Experimental tool/JSON support: Implemented via systemPrompt as MCP sampling doesn't natively support these features