CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-modelcontextprotocol--sdk

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
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

client.mddocs/

Client API

Client connects to MCP servers and accesses their resources, tools, and prompts.

Creating a Client

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
}

Example

const client = new Client(
  { name: 'my-client', version: '1.0.0' },
  {
    capabilities: {
      sampling: {},
      roots: { listChanged: true }
    }
  }
);

Connecting

async connect(
  transport: Transport,
  options?: { timeout?: number; signal?: AbortSignal; }
): Promise<void>;

Examples

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);

Tools

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>;

Examples

// 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);
}

Resources

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>;

Examples

// 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 });
});

Prompts

async listPrompts(params?: { cursor?: string }, options?: RequestOptions): Promise<ListPromptsResult>;

async getPrompt(
  params: { name: string; arguments?: Record<string, string>; },
  options?: RequestOptions
): Promise<GetPromptResult>;

Examples

// 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}`); });

Argument Completion

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>;

Example

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']

Handling Server Requests

setRequestHandler<T extends ZodType<object>>(
  schema: T,
  handler: (request: z.infer<T>, extra: RequestHandlerExtra) => Promise<Result>
): void;

Examples

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 };
});

Server Information

getServerCapabilities(): ServerCapabilities | undefined;
getServerVersion(): Implementation | undefined;
getInstructions(): string | undefined;

Utility Methods

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;

Middleware

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;

Examples

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);

Types Reference

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';

docs

authentication.md

client.md

index.md

server-advanced.md

server-prompts.md

server-resources.md

server-tools.md

transports.md

types.md

tile.json