TypeScript SDK:MCP服务端客户端开发利器,高效处理LLM上下文
TypeScript SDK:MCP服务端客户端开发利器,高效处理LLM上下文。作为Model Context Protocol官方实现工具,该SDK简化MCP服务端与客户端开发流程,助力开发者轻松管理LLM上下文,提升AI应用构建效率,是2025年处理MCP协议与LLM交互的实用技术方案。

Mastering the Model Context Protocol with TypeScript SDK: A Comprehensive Guide
In the rapidly evolving landscape of AI development, managing LLM context has become a critical challenge for developers building sophisticated AI applications. The Model Context Protocol (MCP) has emerged as a game-changing standard for separating context provision from LLM interaction, and the official typescript-sdk from modelcontextprotocol is leading the charge in implementing this protocol. With over 9,980 stars and 1,287 forks on GitHub, this SDK has quickly become an essential tool for TypeScript and Node.js developers working with large language models.
Understanding the Model Context Protocol (MCP)
The Model Context Protocol represents a significant shift in how developers approach LLM application architecture. Unlike traditional methods that tightly couple context management with LLM interaction, MCP introduces a standardized way to separate these concerns—similar to how REST transformed web API development.
At its core, MCP enables:
- Clear separation between context provision and LLM processing
- Standardized communication between MCP servers and clients
- Consistent handling of resources, tools, and prompts across applications
- Improved security and maintainability in LLM applications
Since its initial release in September 2024, the protocol has gained traction across the AI development community, with the typescript-sdk serving as the reference implementation for both MCP servers and clients.
Getting Started with the TypeScript SDK
Getting up and running with the MCP SDK is straightforward, requiring just a few steps:
bash
npm install @modelcontextprotocol/sdk
Note: The SDK requires Node.js v18.x or higher to function properly, ensuring access to modern JavaScript features and improved fetch API support.
Creating Your First MCP Server
The SDK simplifies building MCP servers that can expose resources, tools, and prompts to LLM applications. Here's a basic implementation:
typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Initialize server
const server = new McpServer({
name: "my-first-mcp-server",
version: "1.0.0"
});
// Register a calculator tool
server.registerTool("calculate",
{
title: "Simple Calculator",
description: "Perform basic arithmetic operations",
inputSchema: z.object({
operation: z.enum(["add", "subtract", "multiply", "divide"]),
a: z.number(),
b: z.number()
})
},
async ({ operation, a, b }) => {
let result;
switch(operation) {
case "add": result = a + b; break;
case "subtract": result = a - b; break;
case "multiply": result = a * b; break;
case "divide": result = a / b; break;
}
return { content: [{ type: "text", text: String(result) }] };
}
);
// Start server with stdio transport
const transport = new StdioServerTransport();
await server.connect(transport);
console.log("MCP server running...");
This simple server demonstrates the power of the typescript-sdk—with minimal code, you can create a functional MCP server exposing useful tools to LLM applications.
Core Concepts: Resources, Tools, and Prompts
The MCP SDK revolves around three fundamental concepts that enable rich LLM context management:
Resources: Providing Contextual Data
Resources in MCP are similar to REST API endpoints but optimized for LLM context delivery. They allow servers to expose structured data that LLMs can use to inform their responses:
typescript
// Register a dynamic user profile resource
server.registerResource(
"user-profile",
new ResourceTemplate("users://{userId}/profile", { list: undefined }),
{
title: "User Profile Information",
description: "Retrieve detailed profile information for a specific user"
},
async (uri, { userId }) => {
// Fetch user data from database or external API
const userData = await getUserFromDatabase(userId);
return {
contents: [{
uri: uri.href,
text: JSON.stringify(userData, null, 2)
}]
};
}
);
Tools: Extending LLM Capabilities
Tools enable LLMs to perform specific actions or computations, significantly extending their capabilities beyond text generation:
typescript
// Weather lookup tool example
server.registerTool(
"fetch-weather",
{
title: "Weather Information",
description: "Get current weather conditions for a specific location",
inputSchema: z.object({
city: z.string(),
countryCode: z.string().length(2)
})
},
async ({ city, countryCode }) => {
const response = await fetch(
`https://api.weatherapi.com/v1/current.json?key=${process.env.WEATHER_API_KEY}&q=${city},${countryCode}`
);
const weatherData = await response.json();
return {
content: [{
type: "text",
text: `Current weather in ${city}: ${weatherData.current.temp_c}°C, ${weatherData.current.condition.text}`
}]
};
}
);
Prompts: Standardizing LLM Interactions
Prompts provide reusable templates that help standardize how LLMs interact with your application:
typescript
// Customer support prompt example
server.registerPrompt(
"support-response",
{
title: "Customer Support Response Generator",
description: "Generate helpful responses to customer inquiries",
argsSchema: z.object({
customerIssue: z.string(),
product: z.string(),
tone: z.enum(["friendly", "professional", "technical"])
})
},
({ customerIssue, product, tone }) => ({
messages: [{
role: "system",
content: {
type: "text",
text: `You are a ${tone} customer support agent for ${product}. ` +
`Address the following customer issue thoroughly and helpfully: ${customerIssue}`
}
}]
})
);
Building MCP Clients with TypeScript
The SDK isn't just for server development—it also provides powerful tools for building MCP clients that can communicate with any MCP server:
typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function runClient() {
// Create transport and client
const transport = new StdioClientTransport({
command: "node",
args: ["path/to/server.js"]
});
const client = new Client({
name: "my-mcp-client",
version: "1.0.0"
});
// Connect to server
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log("Available tools:", tools);
// Call calculator tool
const result = await client.callTool({
name: "calculate",
arguments: {
operation: "add",
a: 25,
b: 37
}
});
console.log("Calculation result:", result.content[0].text);
// Read user profile resource
const userProfile = await client.readResource({
uri: "users://12345/profile"
});
console.log("User profile:", userProfile.contents[0].text);
}
runClient().catch(console.error);
Advanced Transport Options
The typescript-sdk supports multiple transport mechanisms to suit different deployment scenarios:
Streamable HTTP for Web Applications
For web-based deployments, Streamable HTTP provides efficient communication with session management:
typescript
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { randomUUID } from "node:crypto";
const app = express();
app.use(express.json());
const server = new McpServer({ name: "web-mcp-server", version: "1.0.0" });
const transports = {}; // Store active transports
// Configure CORS for browser clients
app.use(cors({
origin: ['https://your-app-domain.com'],
exposedHeaders: ['Mcp-Session-Id'],
allowedHeaders: ['Content-Type', 'mcp-session-id'],
}));
// HTTP transport endpoint
app.post('/mcp', async (req, res) => {
const sessionId = req.headers['mcp-session-id'] as string;
let transport;
if (sessionId && transports[sessionId]) {
transport = transports[sessionId];
} else {
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: (sessionId) => {
transports[sessionId] = transport;
},
enableDnsRebindingProtection: true,
allowedHosts: ['your-app-domain.com']
});
transport.onclose = () => {
if (transport.sessionId) delete transports[transport.sessionId];
};
await server.connect(transport);
}
await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => console.log("HTTP MCP server running on port 3000"));
STDIO for Command-Line Applications
STDIO transport is ideal for local development and command-line tool integration, providing a simple interface for inter-process communication.
Real-World Applications and Examples
The typescript-sdk enables a wide range of powerful applications. Let's explore some practical examples:
SQLite Database Explorer
typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import sqlite3 from "sqlite3";
import { promisify } from "util";
// Database connection helper
const getDb = () => {
const db = new sqlite3.Database("company-data.db");
return {
all: promisify(db.all.bind(db)),
close: promisify(db.close.bind(db))
};
};
const server = new McpServer({ name: "sqlite-explorer", version: "1.0.0" });
// Expose database schema as a resource
server.registerResource(
"database-schema",
"schema://main",
{
title: "Database Schema",
description: "Retrieve the complete database schema"
},
async () => {
const db = getDb();
try {
const tables = await db.all(
"SELECT name, sql FROM sqlite_master WHERE type='table'"
);
return {
contents: [{
uri: "schema://main",
text: tables.map(t => `${t.sql};\n`).join("\n")
}]
};
} finally {
await db.close();
}
}
);
// SQL query execution tool
server.registerTool(
"execute-sql",
{
title: "Execute SQL Query",
description: "Run SQL queries against the database",
inputSchema: z.object({ sql: z.string() })
},
async ({ sql }) => {
const db = getDb();
try {
const results = await db.all(sql);
return {
content: [{
type: "text",
text: JSON.stringify(results, null, 2)
}]
};
} catch (err) {
return {
content: [{ type: "text", text: `Error: ${err.message}` }],
isError: true
};
} finally {
await db.close();
}
}
);
// Start server with appropriate transport...
Dynamic Server Configuration
The SDK supports dynamic server configuration, allowing you to adapt to runtime conditions:
typescript
// Dynamic tool registration based on user authentication
server.registerTool(
"upgrade-auth",
{
title: "Upgrade Authentication",
description: "Upgrade user authentication level",
inputSchema: z.object({ permission: z.enum(["write", "admin"]) })
},
async ({ permission }) => {
// Perform authentication upgrade logic
const result = await upgradeUserPermissions(permission);
if (result.success && permission === "write") {
// Add additional tools when user gains write access
server.registerTool("create-document",
{ /* tool configuration */ },
documentCreationHandler
);
}
return {
content: [{ type: "text", text: result.message }]
};
}
);
Best Practices for MCP Development
When working with the typescript-sdk, consider these best practices:
-
Security First: Always validate inputs, implement proper authentication, and restrict resource access appropriately.
-
Performance Optimization: Use ResourceLinks for large data sets to avoid unnecessary data transfer:
typescript
// Efficient file listing with ResourceLinks
server.registerTool(
"list-project-files",
{
title: "Project File Lister",
description: "List files in the project directory",
inputSchema: z.object({ directory: z.string() })
},
async ({ directory }) => {
const files = await listFilesInDirectory(directory);
return {
content: [
{ type: "text", text: `Found ${files.length} files:` },
...files.map(file => ({
type: "resource_link",
uri: `file://${file.path}`,
name: file.name,
mimeType: file.mimeType,
description: file.size ? `${file.size} bytes` : undefined
}))
]
};
}
);
- Debounce Notifications: Improve efficiency when making multiple rapid changes:
typescript
// Enable notification debouncing
const server = new McpServer(
{ name: "efficient-server", version: "1.0.0" },
{
debouncedNotificationMethods: [
'notifications/tools/list_changed',
'notifications/resources/list_changed'
]
}
);
- Error Handling: Implement comprehensive error handling for robust applications:
typescript
// Robust error handling example
server.registerTool("data-processor",
{ /* configuration */ },
async (params) => {
try {
// Input validation beyond schema checking
if (params.date && new Date(params.date).toString() === "Invalid Date") {
return {
content: [{ type: "text", text: "Invalid date format. Please use YYYY-MM-DD." }],
isError: true
};
}
// Main processing logic
const result = await complexDataProcessing(params);
return { content: [{ type: "text", text: result }] };
} catch (error) {
console.error("Tool error:", error);
return {
content: [{
type: "text",
text: "An unexpected error occurred. Please try again later."
}],
isError: true
};
}
}
);
Conclusion: Transforming LLM Application Development
The model context protocol and its official typescript-sdk represent a significant advancement in LLM application development. By standardizing how context is provided to language models, the SDK addresses critical challenges in AI application development:
- Separation of Concerns: Cleanly separates context management from LLM interaction
- Standardization: Provides a consistent interface across different LLM providers and applications
- Extensibility: Enables rich tool integration and resource management
- Flexibility: Supports multiple transport mechanisms for diverse deployment scenarios
As AI application development continues to evolve, tools like the MCP TypeScript SDK will play an increasingly important role in creating robust, maintainable, and secure LLM-powered applications. Whether you're building simple utilities or complex AI systems, the SDK provides the foundation you need to create sophisticated LLM interactions with clean architecture and standardized protocols.
To get started with the typescript-sdk, visit the official GitHub repository at https://github.com/modelcontextprotocol/typescript-sdk and explore the extensive documentation and examples. Join the growing community of developers revolutionizing LLM application development with the Model Context Protocol.