TypeScript SDK for implementing the Model Context Protocol, enabling developers to build MCP servers and clients with support for multiple transports, tools, resources, prompts, and authentication
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Client connects to MCP servers and accesses their resources, tools, and prompts.
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
constructor(
clientInfo: Implementation,
options?: {
capabilities?: ClientCapabilities;
debouncedNotificationMethods?: string[];
}
);
interface Implementation { name: string; version: string; }
interface ClientCapabilities {
sampling?: {}; // Handle LLM completion requests from server
elicitation?: {}; // Handle user input requests from server
roots?: { listChanged?: boolean; }; // Provide root directories/files
}const client = new Client(
{ name: 'my-client', version: '1.0.0' },
{
capabilities: {
sampling: {},
roots: { listChanged: true }
}
}
);async connect(
transport: Transport,
options?: { timeout?: number; signal?: AbortSignal; }
): Promise<void>;import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
// Connect via stdio
const stdioTransport = new StdioClientTransport({ command: 'node', args: ['server.js'] });
await client.connect(stdioTransport);
// Connect via HTTP
const httpTransport = new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp'));
await client.connect(httpTransport);async listTools(params?: { cursor?: string }, options?: RequestOptions): Promise<ListToolsResult>;
async callTool(
params: { name: string; arguments?: Record<string, unknown>; },
resultSchema?: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema,
options?: RequestOptions
): Promise<CallToolResult>;// List all tools
const { tools, nextCursor } = await client.listTools();
console.log(`Found ${tools.length} tools`);
tools.forEach(tool => { console.log(`- ${tool.name}: ${tool.description}`); });
// Call a tool
const result = await client.callTool({ name: 'add', arguments: { a: 5, b: 3 } });
console.log(result.structuredContent); // { result: 8 }
// Handle tool errors
if (result.isError) {
console.error('Tool failed:', result.content[0].text);
} else {
console.log('Success:', result.content[0].text);
}async listResources(params?: { cursor?: string }, options?: RequestOptions): Promise<ListResourcesResult>;
async listResourceTemplates(params?: { cursor?: string }, options?: RequestOptions): Promise<ListResourceTemplatesResult>;
async readResource(params: { uri: string }, options?: RequestOptions): Promise<ReadResourceResult>;
async subscribeResource(params: { uri: string }, options?: RequestOptions): Promise<void>;
async unsubscribeResource(params: { uri: string }, options?: RequestOptions): Promise<void>;// List resources
const { resources } = await client.listResources();
resources.forEach(resource => { console.log(`${resource.name} (${resource.uri})`); });
// Read a resource
const result = await client.readResource({ uri: 'config://app' });
const content = result.contents[0];
if ('text' in content) { console.log(content.text); }
// Subscribe to resource updates
await client.subscribeResource({ uri: 'config://app' });
// Handle resource updated notifications
client.setNotificationHandler(ResourceUpdatedNotificationSchema, async (notification) => {
console.log(`Resource updated: ${notification.params.uri}`);
const updated = await client.readResource({ uri: notification.params.uri });
});async listPrompts(params?: { cursor?: string }, options?: RequestOptions): Promise<ListPromptsResult>;
async getPrompt(
params: { name: string; arguments?: Record<string, string>; },
options?: RequestOptions
): Promise<GetPromptResult>;// List prompts
const { prompts } = await client.listPrompts();
prompts.forEach(prompt => { console.log(`${prompt.name}: ${prompt.description}`); });
// Get a prompt
const result = await client.getPrompt({
name: 'analyze-file',
arguments: { filePath: '/path/to/file.ts', analysisType: 'security' }
});
// Use prompt messages with LLM
result.messages.forEach(message => { console.log(`${message.role}: ${message.content.text}`); });async complete(
params: {
ref: { type: 'ref/prompt'; name: string } | { type: 'ref/resource'; uri: string };
argument: { name: string; value: string; };
context?: { arguments?: Record<string, unknown>; };
},
options?: RequestOptions
): Promise<CompleteResult>;const result = await client.complete({
ref: { type: 'ref/prompt', name: 'team-greeting' },
argument: { name: 'name', value: 'Al' },
context: { arguments: { department: 'engineering' } }
});
console.log(result.completion.values); // ['Alice']setRequestHandler<T extends ZodType<object>>(
schema: T,
handler: (request: z.infer<T>, extra: RequestHandlerExtra) => Promise<Result>
): void;import { CreateMessageRequestSchema, ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
// Handle sampling requests (server requesting LLM completion)
client.setRequestHandler(CreateMessageRequestSchema, async (request) => {
const completion = await myLLM.complete({
messages: request.params.messages,
maxTokens: request.params.maxTokens
});
return {
role: 'assistant',
content: { type: 'text', text: completion.text },
model: 'my-model',
stopReason: 'endTurn'
};
});
// Handle elicitation requests (server requesting user input)
client.setRequestHandler(ElicitRequestSchema, async (request) => {
const userInput = await showInputDialog(request.params.message, request.params.requestedSchema);
if (userInput.cancelled) {
return { action: 'cancel' };
}
return { action: 'accept', content: userInput.data };
});getServerCapabilities(): ServerCapabilities | undefined;
getServerVersion(): Implementation | undefined;
getInstructions(): string | undefined;async ping(options?: RequestOptions): Promise<void>;
async setLoggingLevel(level: LoggingLevel, options?: RequestOptions): Promise<void>;
async sendRootsListChanged(): Promise<void>;
async close(): Promise<void>;
registerCapabilities(capabilities: ClientCapabilities): void;import { Middleware, withOAuth, withLogging, applyMiddlewares, createMiddleware } from '@modelcontextprotocol/sdk/client/middleware.js';
type Middleware = (requestInfo: RequestInfo, next: (requestInfo: RequestInfo) => Promise<Response>) => Promise<Response>;
function withOAuth(provider: OAuthClientProvider, baseUrl?: string | URL): Middleware;
function withLogging(options: LoggingOptions): Middleware;
function applyMiddlewares(middlewares: Middleware[], fetch: FetchLike): FetchLike;
function createMiddleware(fn: (requestInfo: RequestInfo, next: () => Promise<Response>) => Promise<Response>): Middleware;
interface LoggingOptions {
logger: RequestLogger;
logRequests?: boolean;
logResponses?: boolean;
logErrors?: boolean;
}
type RequestLogger = (req: RequestInfo, res?: Response, error?: Error) => void;import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { withOAuth, withLogging, applyMiddlewares } from '@modelcontextprotocol/sdk/client/middleware.js';
// OAuth middleware (automatically applied when using authProvider)
const transport = new StreamableHTTPClientTransport(
new URL('http://localhost:3000/mcp'),
{ authProvider: myOAuthProvider }
);
// Custom logging middleware
const loggingMiddleware = withLogging({
logger: (req, res, error) => {
if (error) {
console.error('Request failed:', error);
} else {
console.log(`${req.method} ${req.url} -> ${res?.status}`);
}
},
logRequests: true,
logResponses: true,
logErrors: true
});
// Custom middleware
const customMiddleware = createMiddleware(async (req, next) => {
req.headers.set('X-Custom-Header', 'value');
const response = await next();
console.log('Response status:', response.status);
return response;
});
// Apply multiple middlewares
const enhancedFetch = applyMiddlewares([loggingMiddleware, customMiddleware], fetch);interface RequestOptions {
timeout?: number; // Default: 60000ms
onprogress?: (progress: Progress) => void;
signal?: AbortSignal;
}
interface Progress {
progress: number;
total?: number;
}
interface CallToolResult {
content: ContentBlock[];
isError?: boolean;
structuredContent?: Record<string, unknown>;
_meta?: Record<string, unknown>;
}
interface ReadResourceResult {
contents: ResourceContents[];
_meta?: Record<string, unknown>;
}
interface GetPromptResult {
description?: string;
messages: PromptMessage[];
_meta?: Record<string, unknown>;
}
interface CompleteResult {
completion: { values: string[]; total?: number; hasMore?: boolean; };
_meta?: Record<string, unknown>;
}
type LoggingLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency';