Skip to main content

API Reference

Complete API documentation for mcp-ts.

Server-Side API

createNextMcpHandler(options)

Creates handlers for Next.js App Router API routes.

import { createNextMcpHandler } from '@mcp-ts/sdk/server';

const { GET, POST } = createNextMcpHandler({
getIdentity: (request) => string,
getAuthToken?: (request) => string | null,
authenticate?: (identity, token) => Promise<boolean>,
heartbeatInterval?: number,
});

Options:

  • getIdentity - Function to extract identity from request (required)
  • getAuthToken - Function to extract auth token from request (optional)
  • authenticate - Custom authentication logic (optional)
  • heartbeatInterval - SSE heartbeat interval in ms (default: 30000)
  • clientDefaults - Static OAuth client metadata (optional)
  • getClientMetadata - Dynamic OAuth metadata getter (optional, overrides defaults)

Returns: { GET, POST } - HTTP method handlers


createSSEHandler(options)

Creates an SSE handler for standard Node.js/Express applications.

import { createSSEHandler } from '@mcp-ts/sdk/server';

const handler = createSSEHandler({
identity: string,
onAuth?: (identity) => Promise<boolean>,
heartbeatInterval?: number,
});

Options:

  • identity - User/Client identifier (required)
  • onAuth - Authentication callback (optional)
  • heartbeatInterval - Heartbeat interval in ms (default: 30000)
  • clientDefaults - Static OAuth client metadata (optional)
  • getClientMetadata - Dynamic OAuth metadata getter (optional)

Returns: Request handler function


MCPClient

Direct MCP client class for server-side operations.

import { MCPClient } from '@mcp-ts/sdk/server';

const client = new MCPClient({
identity: string,
sessionId: string,
serverId?: string,
serverUrl?: string,
callbackUrl?: string,
transportType?: 'sse' | 'streamable_http',
onRedirect?: (authUrl: string) => void,
// OAuth Metadata
clientName?: string,
clientUri?: string,
logoUri?: string,
policyUri?: string,
});

Methods

connect(): Promise<void>

Connect to the MCP server. May throw UnauthorizedError if OAuth is required.

await client.connect();

disconnect(): Promise<void>

Disconnect from the MCP server.

await client.disconnect();

listTools(): Promise<ListToolsResult>

List available tools from the MCP server.

const { tools } = await client.listTools();

callTool(name: string, args: object): Promise<CallToolResult>

Call a tool with arguments.

const result = await client.callTool('get_weather', {
location: 'San Francisco',
});

getAITools(): Promise<ToolSet>

Get all MCP tools and convert them to AI SDK compatible tools.

const tools = await client.getAITools();

listPrompts(): Promise<ListPromptsResult>

List available prompts.

const { prompts } = await client.listPrompts();

getPrompt(name: string, args?: object): Promise<GetPromptResult>

Get a prompt with optional arguments.

const prompt = await client.getPrompt('code-review', {
language: 'typescript',
});

listResources(): Promise<ListResourcesResult>

List available resources.

const { resources } = await client.listResources();

readResource(uri: string): Promise<ReadResourceResult>

Read a specific resource by URI.

const resource = await client.readResource('file:///path/to/file');

finishAuth(code: string): Promise<void>

Complete OAuth authorization with authorization code.

await client.finishAuth(authCode);

MultiSessionClient

Manages multiple MCP connections for a single user identity, allowing aggregation of tools from all connected servers.

import { MultiSessionClient } from '@mcp-ts/sdk/server';

const mcp = new MultiSessionClient(identity, {
timeout: 15000,
maxRetries: 2,
retryDelay: 1000,
});

Options:

  • timeout - Connection timeout in milliseconds (default: 15000)
  • maxRetries - Maximum number of retry attempts for each session (default: 2)
  • retryDelay - Delay between retries in milliseconds (default: 1000)

Methods

connect(): Promise<void>

Connects to all active sessions for the user. Skips sessions that fail to connect after retries, but logs errors.

await mcp.connect();

getClients(): MCPClient[]

Returns the array of currently connected clients.

const clients = mcp.getClients();

disconnect(): void

Disconnects all active clients and clears the internal client list.

mcp.disconnect();

Adapters

Adapters convert MCP tools into framework-specific formats for seamless integration with AI frameworks.

AIAdapter

Convert MCP tools to Vercel AI SDK format.

import { AIAdapter } from '@mcp-ts/sdk/adapters/ai';

const adapter = new AIAdapter(client: MCPClient | MultiSessionClient, options?: {
prefix?: string // Tool name prefix (default: serverId)
});

const tools = await adapter.getTools(); // Returns ToolSet

LangChainAdapter

Convert MCP tools to LangChain DynamicStructuredTool format.

import { LangChainAdapter } from '@mcp-ts/sdk/adapters/langchain';

const adapter = new LangChainAdapter(client: MCPClient | MultiSessionClient, options?: {
prefix?: string // Tool name prefix
simplifyErrors?: boolean // Return simple error strings (default: false)
});

const tools = await adapter.getTools(); // Returns DynamicStructuredTool[]

MastraAdapter

Convert MCP tools to Mastra tool format.

import { MastraAdapter } from '@mcp-ts/sdk/adapters/mastra';

const adapter = new MastraAdapter(client: MCPClient | MultiSessionClient, options?: {
prefix?: string // Tool name prefix
});

const tools = await adapter.getTools(); // Returns MastraTool[]

AguiAdapter

Convert MCP tools to AG-UI protocol format.

import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';

const adapter = new AguiAdapter(client: MCPClient | MultiSessionClient, options?: {
prefix?: string // Tool name prefix (default: serverId)
});

// Get tools with handlers for server-side execution
const tools = await adapter.getTools(); // Returns AguiTool[]

// Get tool definitions (JSON Schema) for remote agents
const definitions = await adapter.getToolDefinitions(); // Returns AguiToolDefinition[]

Types:

interface AguiTool {
name: string;
description: string;
parameters?: Record<string, any>;
handler?: (args: any) => any | Promise<any>;
}

interface AguiToolDefinition {
name: string;
description: string;
parameters: Record<string, any>;
}

createMcpMiddleware

Create AG-UI middleware for server-side MCP tool execution.

import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';
import { HttpAgent } from '@ag-ui/client';

const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });

agent.use(createMcpMiddleware(client: MCPClient | MultiSessionClient, options?: {
toolPrefix?: string // Prefix to identify MCP tools (default: 'server-')
tools?: AguiTool[] // Pre-loaded tools with handlers
}));

Parameters:

  • client - MCP client or MultiSessionClient for executing tools
  • options.toolPrefix - Prefix to identify MCP tools in the event stream (default: 'server-')
  • options.tools - Pre-loaded tools with handlers. If not provided, tools will be loaded from the client on first use.

Returns: Middleware function compatible with AG-UI agent.use()

Example:

import { HttpAgent } from '@ag-ui/client';
import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';
import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';

// Setup
const client = new MultiSessionClient('user_123');
await client.connect();

const adapter = new AguiAdapter(client);
const mcpTools = await adapter.getTools();

// Create agent with middleware
const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });
agent.use(createMcpMiddleware(client, {
toolPrefix: 'server-',
tools: mcpTools,
}));

Storage Backend API

storage

Global storage instance that automatically selects the appropriate backend based on environment configuration.

import { storage } from '@mcp-ts/sdk/server';

Configuration

The storage backend is selected automatically:

# Redis (Production)
MCP_TS_STORAGE_TYPE=redis
REDIS_URL=redis://localhost:6379

# File System (Development)
MCP_TS_STORAGE_TYPE=file
MCP_TS_STORAGE_FILE=./sessions.json

# In-Memory (Testing - Default)
MCP_TS_STORAGE_TYPE=memory

Storage Methods

generateSessionId(): string

Generate a unique session ID.

const sessionId = storage.generateSessionId();

createSession(session: SessionData): Promise<void>

Create a new session. Throws if session already exists.

await storage.createSession({
sessionId: 'abc123',
identity: 'user-123',
serverId: 'server-id',
serverName: 'My Server',
serverUrl: 'https://mcp.example.com',
callbackUrl: 'https://myapp.com/callback',
transportType: 'sse',
active: true,
createdAt: Date.now(),
});

updateSession(identity: string, sessionId: string, data: Partial<SessionData>): Promise<void>

Update an existing session with partial data. Throws if session doesn't exist.

await storage.updateSession('user-123', 'abc123', {
active: false,
tokens: {
access_token: 'new-token',
token_type: 'Bearer',
},
});

getSession(identity: string, sessionId: string): Promise<SessionData | null>

Retrieve session data.

const session = await storage.getSession('user-123', 'abc123');

getIdentitySessionsData(identity: string): Promise<SessionData[]>

Get all session data for an identity.

const sessions = await storage.getIdentitySessionsData('user-123');

getIdentityMcpSessions(identity: string): Promise<string[]>

Get all session IDs for an identity.

const sessionIds = await storage.getIdentityMcpSessions('user-123');

removeSession(identity: string, sessionId: string): Promise<void>

Delete a session.

await storage.removeSession('user-123', 'abc123');

getAllSessionIds(): Promise<string[]>

Get all session IDs across all users (admin operation).

const allSessions = await storage.getAllSessionIds();

clearAll(): Promise<void>

Clear all sessions (admin operation).

await storage.clearAll();

cleanupExpiredSessions(): Promise<void>

Clean up expired sessions (Redis only, no-op for others).

await storage.cleanupExpiredSessions();

disconnect(): Promise<void>

Disconnect from storage backend.

await storage.disconnect();

Custom Storage Backends

You can also use specific storage backends directly:

import { 
RedisStorageBackend,
MemoryStorageBackend,
FileStorageBackend
} from '@mcp-ts/sdk/server';
import { Redis } from 'ioredis';

// Redis
const redis = new Redis(process.env.REDIS_URL);
const redisStorage = new RedisStorageBackend(redis);

// File System
const fileStorage = new FileStorageBackend({ path: './sessions.json' });
await fileStorage.init();

// In-Memory
const memoryStorage = new MemoryStorageBackend();

Client-Side API

useMcp(options)

React hook for managing MCP connections.

import { useMcp } from '@mcp-ts/sdk/client';

const {
connections,
status,
isInitializing,
connect,
disconnect,
refresh,
connectSSE,
disconnectSSE,
finishAuth,
callTool,
listTools,
listPrompts,
getPrompt,
listResources,
readResource,
getConnection,
getConnectionByServerId,
isServerConnected,
getTools,
} = useMcp({
url: string,
identity: string,
authToken?: string,
autoConnect?: boolean,
autoInitialize?: boolean,
onConnectionEvent?: (event) => void,
onLog?: (level, message, metadata) => void,
});

Options:

  • url - SSE endpoint URL (required)
  • identity - User/Client identifier (required)
  • authToken - Authentication token (optional)
  • autoConnect - Auto-connect SSE on mount (default: true)
  • autoInitialize - Auto-load sessions on mount (default: true)
  • onConnectionEvent - Connection event handler (optional)
  • onLog - Debug log handler (optional)

Returns: Object with state and methods


useMcpApps(mcpClient)

React hook for rendering MCP Apps (interactive tool UIs in a sandboxed iframe via AppBridge).

import { useMcpApps } from '@mcp-ts/sdk/client/react';

const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);

Parameters:

  • mcpClient — Object shaped like useMcp()’s return (at minimum connections with tools and optional sseClient for forwarding). May be null when disconnected.

Returns:

  • getAppMetadata(toolName: string) — Resolves UI metadata for a tool (strips tool_<id>_ prefixes).
  • McpAppRenderer — Stable, memoized component; pass per-tool-call props.

getAppMetadata(toolName: string)

Returns: McpAppMetadata | undefined

interface McpAppMetadata {
toolName: string;
resourceUri: string;
sessionId: string;
}

URI resolution uses tool.mcpApp.resourceUri, then tool._meta?.ui?.resourceUri, then tool._meta?.['ui/resourceUri'].

McpAppRenderer Component

The hook closes over mcpClient. Each renderer needs the active tool identity and call state. For ui:// / mcp-app:// HTML (and any injected HTML path), you must pass sandbox with your hosted proxy page (see MCP Apps).

Props (McpAppRendererProps):

interface McpAppRendererProps {
name: string;
input?: Record<string, unknown>;
result?: unknown;
status?: 'executing' | 'inProgress' | 'complete' | 'idle';

toolResourceUri?: string;
html?: string;

sandbox?: SandboxConfig;
hostContext?: Record<string, unknown>;

toolInputPartial?: unknown;
toolCancelled?: boolean;

onCallTool?: (params: { name: string; arguments?: Record<string, unknown> }) => Promise<unknown>;
onReadResource?: (uri: string) => Promise<{ contents: Array<{ text?: string; blob?: string }> }>;
onFallbackRequest?: (request: unknown) => Promise<unknown>;
onMessage?: /* AppBridge */ (params, extra) => Promise<unknown>;
onOpenLink?: (params, extra) => Promise<unknown>;
onLoggingMessage?: (params: { level?: string; data?: string }) => void;
onSizeChanged?: (params: { width?: number; height?: number }) => void;
onError?: (error: Error) => void;

className?: string;
loader?: React.ReactNode;
}

interface SandboxConfig {
url: URL | string;
permissions?: string;
csp?: Record<string, string>;
}

Example (recommended: sandbox + default CSP):

import { useMcpApps, DEFAULT_MCP_APP_CSP } from '@mcp-ts/sdk/client/react';

function ToolCallRenderer({ name, args, result, status }) {
const { mcpClient } = useMcpContext();
const { McpAppRenderer } = useMcpApps(mcpClient);

return (
<McpAppRenderer
name={name}
input={args}
result={result}
status={status}
sandbox={{
url: '/sandbox.html',
csp: DEFAULT_MCP_APP_CSP,
}}
className="my-custom-class"
/>
);
}

useAppHost(client, iframeRef, options?)

Lower-level React helper that constructs an AppHost for a given HTMLIFrameElement ref. Accepts the same options as AppHostOptions (sandbox, callbacks, hostContext, etc.). The hook currently initializes only when client is non-null; prefer McpAppRenderer for the usual useMcp integration.

import { useAppHost } from '@mcp-ts/sdk/client/react';

// sseClient: SSEClient | null from useMcp() / mcpClient.sseClient
const { host, error } = useAppHost(sseClient, iframeRef, { sandbox: { ... } });

AppHost class

Core MCP App host: AppBridge setup, sandbox proxy launch, resource fetch/cache, and tool I/O. Import from @mcp-ts/sdk/client.

import {
AppHost,
DEFAULT_MCP_APP_CSP,
APP_HOST_DEFAULTS,
} from '@mcp-ts/sdk/client';
import {
SANDBOX_PROXY_READY_METHOD,
SANDBOX_RESOURCE_READY_METHOD,
} from '@modelcontextprotocol/ext-apps';

Constructor

new AppHost(client: AppHostClient | null, iframe: HTMLIFrameElement, options?: AppHostOptions);
  • client — Usually SSEClient. If null, you must implement onCallTool / onReadResource (and any other paths your app uses) yourself.
  • options — See below.

AppHostOptions (selected fields)

  • debug?: boolean
  • sandbox?: SandboxConfigRequired when launching with HTML to inject (fetched ui:// HTML or html string).
  • hostContext?: Record<string, unknown> — Theme, locale, dimensions, etc.; synced to the guest via AppBridge.
  • onCallTool, onReadResource, onFallbackRequest, onMessage, onOpenLink, onLoggingMessage, onSizeChanged, onError, onRequestDisplayMode — Optional; override defaults (forwarding to client when provided and connected).

Methods

MethodDescription
start(): Promise<void>Prepares handlers; bridge connects during launch().
preload(tools: Array<{ _meta?: unknown }>): voidWarms resource cache for tools with UI metadata.
launch(source: { uri?: string; html?: string }, sessionId?: string): Promise<void>Loads UI (fetch uri or use html), runs sandbox proxy when needed, connects AppBridge.
sendToolInput(args: Record<string, unknown>): voidSends tool arguments to the guest.
sendToolResult(result: unknown): voidSends final tool result.
sendToolCancelled(reason: string): voidNotifies cancellation.
sendToolInputPartial(params: unknown): voidStreaming partial input.
setHostContext(context: Record<string, unknown>): voidUpdates host context on the bridge.

Constants

  • DEFAULT_MCP_APP_CSP — Sensible baseline CSP object for sandbox.csp (extend or narrow per app).
  • APP_HOST_DEFAULTS — Default timeout, host info label, URI schemes, theme/platform hints.
  • SANDBOX_PROXY_READY_METHOD / SANDBOX_RESOURCE_READY_METHOD — Re-exported from @modelcontextprotocol/ext-apps for custom sandbox pages (same as importing from that package directly).

SSEClient

Lower-level SSE client for custom implementations.

import { SSEClient } from '@mcp-ts/sdk/client';

const client = new SSEClient({
url: string,
identity: string,
authToken?: string,
onConnectionEvent?: (event) => void,
onStatusChange?: (status) => void,
onLog?: (level, message, metadata) => void,
});

Methods

connect(): void

Connect to the SSE endpoint.

client.connect();

disconnect(): void

Disconnect from the SSE endpoint.

client.disconnect();

getSessions(): Promise<Session[]>

Get all user sessions.

const sessions = await client.getSessions();

connectToServer(config): Promise<{ sessionId: string }>

Connect to an MCP server.

const { sessionId } = await client.connectToServer({
serverId: 'server-id',
serverName: 'My Server',
serverUrl: 'https://mcp.example.com',
callbackUrl: window.location.origin + '/callback',
});

disconnectFromServer(sessionId: string): Promise<void>

Disconnect from an MCP server.

await client.disconnectFromServer(sessionId);

callTool(sessionId, name, args): Promise<any>

Call a tool on a connected server.

const result = await client.callTool(sessionId, 'tool_name', {
arg1: 'value',
});

listTools(sessionId): Promise<Tool[]>

List tools for a session.

const tools = await client.listTools(sessionId);

Types

Connection Types

import type {
McpConnectionState,
McpConnectionEvent,
} from '@mcp-ts/sdk/shared';

type McpConnectionState =
| 'DISCONNECTED'
| 'CONNECTING'
| 'AUTHENTICATING'
| 'AUTHENTICATED'
| 'DISCOVERING'
| 'CONNECTED'
| 'VALIDATING'
| 'RECONNECTING'
| 'FAILED';

type McpConnectionEvent =
| { type: 'state_changed'; sessionId: string; state: McpConnectionState; ... }
| { type: 'tools_discovered'; sessionId: string; tools: Tool[]; ... }
| { type: 'auth_required'; sessionId: string; authUrl: string; ... }
| { type: 'error'; sessionId: string; error: string; ... }
| { type: 'disconnected'; sessionId: string; reason?: string; ... }
| { type: 'progress'; sessionId: string; message: string; ... };

Tool Types

import type { ToolInfo } from '@mcp-ts/sdk/shared';

interface ToolInfo {
name: string;
description?: string;
inputSchema: {
type: 'object';
properties?: Record<string, any>;
required?: string[];
};
}

Session Types

interface SessionData {
sessionId: string;
identity?: string;
serverId?: string;
serverName?: string;
serverUrl: string;
callbackUrl: string;
transportType: 'sse' | 'streamable_http';
active: boolean;
createdAt: number;
headers?: Record<string, string>;
// OAuth data
tokens?: OAuthTokens;
clientInformation?: OAuthClientInformation;
codeVerifier?: string;
clientId?: string;
}

Error Handling

UnauthorizedError

Thrown when OAuth authorization is required.

import { UnauthorizedError } from '@mcp-ts/sdk/server';

try {
await client.connect();
} catch (error) {
if (error instanceof UnauthorizedError) {
console.log('Redirect to:', error.authUrl);
}
}

Next Steps