This is page 1 of 2. Use http://codebase.md/lorrylockie/lark-mcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .gitignore
├── build
│ ├── config.js
│ ├── lark-client.js
│ └── server.js
├── index.ts
├── llm-full.txt
├── package-lock.json
├── package.json
├── README.md
├── src
│ ├── config.ts
│ ├── lark-client.ts
│ └── server.ts
├── tsconfig.json
└── typescript-sdk.txt
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Nuxt.js build / generate output
91 | .nuxt
92 | dist
93 |
94 | # Gatsby files
95 | .cache/
96 | # Comment in the public line in if your project uses Gatsby and not Next.js
97 | # https://nextjs.org/blog/next-9-1#public-directory-support
98 | # public
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # vuepress v2.x temp and cache directory
104 | .temp
105 | .cache
106 |
107 | # vitepress build output
108 | **/.vitepress/dist
109 |
110 | # vitepress cache directory
111 | **/.vitepress/cache
112 |
113 | # Docusaurus cache and generated files
114 | .docusaurus
115 |
116 | # Serverless directories
117 | .serverless/
118 |
119 | # FuseBox cache
120 | .fusebox/
121 |
122 | # DynamoDB Local files
123 | .dynamodb/
124 |
125 | # TernJS port file
126 | .tern-port
127 |
128 | # Stores VSCode versions used for testing VSCode extensions
129 | .vscode-test
130 |
131 | # yarn v2
132 | .yarn/cache
133 | .yarn/unplugged
134 | .yarn/build-state.yml
135 | .yarn/install-state.gz
136 | .pnp.*
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Lark MCP Server
2 |
3 | A Model Context Protocol (MCP) server that integrates with Lark/Feishu APIs, allowing LLMs to interact with Lark services.
4 |
5 | ## Features
6 |
7 | - Query employee information using Lark's Contact API
8 | - More features coming soon...
9 |
10 | ## Prerequisites
11 |
12 | - Node.js 16 or higher
13 | - A Lark/Feishu application with App ID and App Secret
14 | - [Claude for Desktop](https://claude.ai/download) or another MCP client
15 |
16 | ## Installation
17 |
18 | ```bash
19 | npm install
20 | npm run build
21 | ```
22 |
23 | ## Usage
24 |
25 | You can run the server in two ways:
26 |
27 | ### 1. Using Command Line Arguments (Recommended)
28 |
29 | ```bash
30 | npx lark-mcp <app_id> <app_secret>
31 | ```
32 |
33 | Replace `<app_id>` and `<app_secret>` with your Lark application credentials.
34 |
35 | ### 2. Using Environment Variables
36 |
37 | ```bash
38 | export LARK_APP_ID=your_app_id
39 | export LARK_APP_SECRET=your_app_secret
40 | npx lark-mcp
41 | ```
42 |
43 | ## Available Tools
44 |
45 | ### get-user-info
46 |
47 | Retrieves employee information using their ID.
48 |
49 | Example usage in Claude:
50 | ```
51 | Please look up employee information for ID 12345
52 | ```
53 |
54 | ## Development
55 |
56 | 1. Clone the repository
57 | 2. Install dependencies:
58 | ```bash
59 | npm install
60 | ```
61 | 3. Build the project:
62 | ```bash
63 | npm run build
64 | ```
65 | 4. Start the server in development mode:
66 | ```bash
67 | npm run dev
68 | ```
69 |
70 | ## Configuration
71 |
72 | The server prioritizes credentials in the following order:
73 | 1. Command line arguments
74 | 2. Environment variables
75 | 3. Default values (if any)
76 |
77 | ## Error Handling
78 |
79 | - The server will validate credentials before starting
80 | - API errors are properly handled and returned to the client
81 | - Detailed error messages help with troubleshooting
82 |
83 | ## License
84 |
85 | MIT
86 |
87 | ## Contributing
88 |
89 | 1. Fork the repository
90 | 2. Create your feature branch
91 | 3. Commit your changes
92 | 4. Push to the branch
93 | 5. Create a new Pull Request
```
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
```typescript
1 |
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "Node16",
5 | "moduleResolution": "Node16",
6 | "outDir": "./build",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true
12 | },
13 | "include": ["src/**/*"],
14 | "exclude": ["node_modules"]
15 | }
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "lark-mcp",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "description": "Lark MCP Server",
6 | "main": "build/server.js",
7 | "scripts": {
8 | "build": "tsc",
9 | "start": "node build/server.js",
10 | "dev": "tsc && node build/server.js"
11 | },
12 | "dependencies": {
13 | "@larksuiteoapi/node-sdk": "^1.43.0",
14 | "@modelcontextprotocol/sdk": "^1.6.1"
15 | },
16 | "devDependencies": {
17 | "@types/node": "^20.0.0",
18 | "typescript": "^5.0.0"
19 | }
20 | }
21 |
```
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
```typescript
1 | export interface LarkConfig {
2 | appId: string;
3 | appSecret: string;
4 | }
5 |
6 | function parseArgs(): Partial<LarkConfig> {
7 | const args = process.argv.slice(2);
8 | const config: Partial<LarkConfig> = {};
9 |
10 | // Use positional arguments - first is appId, second is appSecret
11 | if (args.length >= 1) config.appId = args[0];
12 | if (args.length >= 2) config.appSecret = args[1];
13 |
14 | return config;
15 | }
16 |
17 | // Get config from command line args first, then fall back to environment variables
18 | const argsConfig = parseArgs();
19 | export const config: LarkConfig = {
20 | appId: argsConfig.appId || process.env.LARK_APP_ID || '',
21 | appSecret: argsConfig.appSecret || process.env.LARK_APP_SECRET || ''
22 | };
23 |
24 | // Validate config
25 | if (!config.appId || !config.appSecret) {
26 | console.error(`
27 | Error: Missing required credentials
28 | Please provide credentials either through:
29 | 1. Command line arguments (recommended):
30 | npx command <app_id> <app_secret>
31 | 2. Environment variables:
32 | LARK_APP_ID=xxx LARK_APP_SECRET=xxx npx command
33 | `);
34 | process.exit(1);
35 | }
```
--------------------------------------------------------------------------------
/src/lark-client.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { Client } from "@larksuiteoapi/node-sdk";
2 | import { config } from "./config.js";
3 |
4 | export class LarkClient {
5 | private client: Client;
6 |
7 | constructor() {
8 | this.client = new Client({
9 | appId: config.appId,
10 | appSecret: config.appSecret,
11 | disableTokenCache: false // Enable SDK's automatic token management
12 | });
13 | }
14 |
15 | // Get user information by employee ID
16 | async getUserInfo(employeeId: string) {
17 | try {
18 | const response = await this.client.contact.v3.user.get({
19 | path: {
20 | user_id: employeeId,
21 | },
22 | params: {
23 | user_id_type: 'user_id', // Using open_id as the lookup type
24 | department_id_type: 'open_department_id',
25 | }
26 | });
27 |
28 | return response.data;
29 | } catch (error) {
30 | console.error('Error fetching user info:', error);
31 | throw error;
32 | }
33 | }
34 |
35 | // This method will be used to get the client instance
36 | getClient(): Client {
37 | return this.client;
38 | }
39 |
40 | // Add helper methods for common Lark API operations
41 | // These will be implemented based on the specific tools we need
42 | }
```
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3 | import { z } from "zod";
4 | import { LarkClient } from "./lark-client.js";
5 |
6 | // Initialize Lark client
7 | const larkClient = new LarkClient();
8 |
9 | // Create MCP server
10 | const server = new McpServer({
11 | name: "lark-mcp",
12 | version: "1.0.0"
13 | });
14 |
15 | // Tool for getting user information
16 | server.tool(
17 | "get-user-info",
18 | {
19 | employee_id: z.string().describe("Employee ID to look up")
20 | },
21 | async ({ employee_id }) => {
22 | try {
23 | const userData = await larkClient.getUserInfo(employee_id);
24 | return {
25 | content: [{
26 | type: "text",
27 | text: JSON.stringify(userData, null, 2)
28 | }]
29 | };
30 | } catch (error) {
31 | return {
32 | content: [{
33 | type: "text",
34 | text: `Error fetching user info: ${error instanceof Error ? error.message : 'Unknown error'}`
35 | }],
36 | isError: true
37 | };
38 | }
39 | }
40 | );
41 |
42 | // Example tool structure - will be replaced with actual implementations
43 | server.tool(
44 | "send-message",
45 | {
46 | receive_id: z.string().describe("Receiver's ID"),
47 | msg_type: z.string().describe("Message type (text, post, image, etc.)"),
48 | content: z.string().describe("Message content")
49 | },
50 | async ({ receive_id, msg_type, content }) => {
51 | try {
52 | // Placeholder for actual implementation
53 | return {
54 | content: [{
55 | type: "text",
56 | text: "Message sent successfully"
57 | }]
58 | };
59 | } catch (error) {
60 | return {
61 | content: [{
62 | type: "text",
63 | text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`
64 | }],
65 | isError: true
66 | };
67 | }
68 | }
69 | );
70 |
71 | // Main function to start the server
72 | async function main() {
73 | try {
74 | const transport = new StdioServerTransport();
75 | await server.connect(transport);
76 | console.error("Lark MCP Server running on stdio");
77 | } catch (error) {
78 | console.error("Fatal error:", error);
79 | process.exit(1);
80 | }
81 | }
82 |
83 | // Start the server
84 | main().catch((error) => {
85 | console.error("Unhandled error:", error);
86 | process.exit(1);
87 | });
```
--------------------------------------------------------------------------------
/typescript-sdk.txt:
--------------------------------------------------------------------------------
```
1 | # MCP TypeScript SDK  
2 |
3 | ## Table of Contents
4 | - [Overview](#overview)
5 | - [Installation](#installation)
6 | - [Quickstart](#quickstart)
7 | - [What is MCP?](#what-is-mcp)
8 | - [Core Concepts](#core-concepts)
9 | - [Server](#server)
10 | - [Resources](#resources)
11 | - [Tools](#tools)
12 | - [Prompts](#prompts)
13 | - [Running Your Server](#running-your-server)
14 | - [stdio](#stdio)
15 | - [HTTP with SSE](#http-with-sse)
16 | - [Testing and Debugging](#testing-and-debugging)
17 | - [Examples](#examples)
18 | - [Echo Server](#echo-server)
19 | - [SQLite Explorer](#sqlite-explorer)
20 | - [Advanced Usage](#advanced-usage)
21 | - [Low-Level Server](#low-level-server)
22 | - [Writing MCP Clients](#writing-mcp-clients)
23 | - [Server Capabilities](#server-capabilities)
24 |
25 | ## Overview
26 |
27 | The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. This TypeScript SDK implements the full MCP specification, making it easy to:
28 |
29 | - Build MCP clients that can connect to any MCP server
30 | - Create MCP servers that expose resources, prompts and tools
31 | - Use standard transports like stdio and SSE
32 | - Handle all MCP protocol messages and lifecycle events
33 |
34 | ## Installation
35 |
36 | ```bash
37 | npm install @modelcontextprotocol/sdk
38 | ```
39 |
40 | ## Quick Start
41 |
42 | Let's create a simple MCP server that exposes a calculator tool and some data:
43 |
44 | ```typescript
45 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
46 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
47 | import { z } from "zod";
48 |
49 | // Create an MCP server
50 | const server = new McpServer({
51 | name: "Demo",
52 | version: "1.0.0"
53 | });
54 |
55 | // Add an addition tool
56 | server.tool("add",
57 | { a: z.number(), b: z.number() },
58 | async ({ a, b }) => ({
59 | content: [{ type: "text", text: String(a + b) }]
60 | })
61 | );
62 |
63 | // Add a dynamic greeting resource
64 | server.resource(
65 | "greeting",
66 | new ResourceTemplate("greeting://{name}", { list: undefined }),
67 | async (uri, { name }) => ({
68 | contents: [{
69 | uri: uri.href,
70 | text: `Hello, ${name}!`
71 | }]
72 | })
73 | );
74 |
75 | // Start receiving messages on stdin and sending messages on stdout
76 | const transport = new StdioServerTransport();
77 | await server.connect(transport);
78 | ```
79 |
80 | ## What is MCP?
81 |
82 | The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions. MCP servers can:
83 |
84 | - Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
85 | - Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
86 | - Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
87 | - And more!
88 |
89 | ## Core Concepts
90 |
91 | ### Server
92 |
93 | The McpServer is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
94 |
95 | ```typescript
96 | const server = new McpServer({
97 | name: "My App",
98 | version: "1.0.0"
99 | });
100 | ```
101 |
102 | ### Resources
103 |
104 | Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:
105 |
106 | ```typescript
107 | // Static resource
108 | server.resource(
109 | "config",
110 | "config://app",
111 | async (uri) => ({
112 | contents: [{
113 | uri: uri.href,
114 | text: "App configuration here"
115 | }]
116 | })
117 | );
118 |
119 | // Dynamic resource with parameters
120 | server.resource(
121 | "user-profile",
122 | new ResourceTemplate("users://{userId}/profile", { list: undefined }),
123 | async (uri, { userId }) => ({
124 | contents: [{
125 | uri: uri.href,
126 | text: `Profile data for user ${userId}`
127 | }]
128 | })
129 | );
130 | ```
131 |
132 | ### Tools
133 |
134 | Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
135 |
136 | ```typescript
137 | // Simple tool with parameters
138 | server.tool(
139 | "calculate-bmi",
140 | {
141 | weightKg: z.number(),
142 | heightM: z.number()
143 | },
144 | async ({ weightKg, heightM }) => ({
145 | content: [{
146 | type: "text",
147 | text: String(weightKg / (heightM * heightM))
148 | }]
149 | })
150 | );
151 |
152 | // Async tool with external API call
153 | server.tool(
154 | "fetch-weather",
155 | { city: z.string() },
156 | async ({ city }) => {
157 | const response = await fetch(`https://api.weather.com/${city}`);
158 | const data = await response.text();
159 | return {
160 | content: [{ type: "text", text: data }]
161 | };
162 | }
163 | );
164 | ```
165 |
166 | ### Prompts
167 |
168 | Prompts are reusable templates that help LLMs interact with your server effectively:
169 |
170 | ```typescript
171 | server.prompt(
172 | "review-code",
173 | { code: z.string() },
174 | ({ code }) => ({
175 | messages: [{
176 | role: "user",
177 | content: {
178 | type: "text",
179 | text: `Please review this code:\n\n${code}`
180 | }
181 | }]
182 | })
183 | );
184 | ```
185 |
186 | ## Running Your Server
187 |
188 | MCP servers in TypeScript need to be connected to a transport to communicate with clients. How you start the server depends on the choice of transport:
189 |
190 | ### stdio
191 |
192 | For command-line tools and direct integrations:
193 |
194 | ```typescript
195 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
196 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
197 |
198 | const server = new McpServer({
199 | name: "example-server",
200 | version: "1.0.0"
201 | });
202 |
203 | // ... set up server resources, tools, and prompts ...
204 |
205 | const transport = new StdioServerTransport();
206 | await server.connect(transport);
207 | ```
208 |
209 | ### HTTP with SSE
210 |
211 | For remote servers, start a web server with a Server-Sent Events (SSE) endpoint, and a separate endpoint for the client to send its messages to:
212 |
213 | ```typescript
214 | import express from "express";
215 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
216 | import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
217 |
218 | const server = new McpServer({
219 | name: "example-server",
220 | version: "1.0.0"
221 | });
222 |
223 | // ... set up server resources, tools, and prompts ...
224 |
225 | const app = express();
226 |
227 | app.get("/sse", async (req, res) => {
228 | const transport = new SSEServerTransport("/messages", res);
229 | await server.connect(transport);
230 | });
231 |
232 | app.post("/messages", async (req, res) => {
233 | // Note: to support multiple simultaneous connections, these messages will
234 | // need to be routed to a specific matching transport. (This logic isn't
235 | // implemented here, for simplicity.)
236 | await transport.handlePostMessage(req, res);
237 | });
238 |
239 | app.listen(3001);
240 | ```
241 |
242 | ### Testing and Debugging
243 |
244 | To test your server, you can use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector). See its README for more information.
245 |
246 | ## Examples
247 |
248 | ### Echo Server
249 |
250 | A simple server demonstrating resources, tools, and prompts:
251 |
252 | ```typescript
253 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
254 | import { z } from "zod";
255 |
256 | const server = new McpServer({
257 | name: "Echo",
258 | version: "1.0.0"
259 | });
260 |
261 | server.resource(
262 | "echo",
263 | new ResourceTemplate("echo://{message}", { list: undefined }),
264 | async (uri, { message }) => ({
265 | contents: [{
266 | uri: uri.href,
267 | text: `Resource echo: ${message}`
268 | }]
269 | })
270 | );
271 |
272 | server.tool(
273 | "echo",
274 | { message: z.string() },
275 | async ({ message }) => ({
276 | content: [{ type: "text", text: `Tool echo: ${message}` }]
277 | })
278 | );
279 |
280 | server.prompt(
281 | "echo",
282 | { message: z.string() },
283 | ({ message }) => ({
284 | messages: [{
285 | role: "user",
286 | content: {
287 | type: "text",
288 | text: `Please process this message: ${message}`
289 | }
290 | }]
291 | })
292 | );
293 | ```
294 |
295 | ### SQLite Explorer
296 |
297 | A more complex example showing database integration:
298 |
299 | ```typescript
300 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
301 | import sqlite3 from "sqlite3";
302 | import { promisify } from "util";
303 | import { z } from "zod";
304 |
305 | const server = new McpServer({
306 | name: "SQLite Explorer",
307 | version: "1.0.0"
308 | });
309 |
310 | // Helper to create DB connection
311 | const getDb = () => {
312 | const db = new sqlite3.Database("database.db");
313 | return {
314 | all: promisify<string, any[]>(db.all.bind(db)),
315 | close: promisify(db.close.bind(db))
316 | };
317 | };
318 |
319 | server.resource(
320 | "schema",
321 | "schema://main",
322 | async (uri) => {
323 | const db = getDb();
324 | try {
325 | const tables = await db.all(
326 | "SELECT sql FROM sqlite_master WHERE type='table'"
327 | );
328 | return {
329 | contents: [{
330 | uri: uri.href,
331 | text: tables.map((t: {sql: string}) => t.sql).join("\n")
332 | }]
333 | };
334 | } finally {
335 | await db.close();
336 | }
337 | }
338 | );
339 |
340 | server.tool(
341 | "query",
342 | { sql: z.string() },
343 | async ({ sql }) => {
344 | const db = getDb();
345 | try {
346 | const results = await db.all(sql);
347 | return {
348 | content: [{
349 | type: "text",
350 | text: JSON.stringify(results, null, 2)
351 | }]
352 | };
353 | } catch (err: unknown) {
354 | const error = err as Error;
355 | return {
356 | content: [{
357 | type: "text",
358 | text: `Error: ${error.message}`
359 | }],
360 | isError: true
361 | };
362 | } finally {
363 | await db.close();
364 | }
365 | }
366 | );
367 | ```
368 |
369 | ## Advanced Usage
370 |
371 | ### Low-Level Server
372 |
373 | For more control, you can use the low-level Server class directly:
374 |
375 | ```typescript
376 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
377 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
378 | import {
379 | ListPromptsRequestSchema,
380 | GetPromptRequestSchema
381 | } from "@modelcontextprotocol/sdk/types.js";
382 |
383 | const server = new Server(
384 | {
385 | name: "example-server",
386 | version: "1.0.0"
387 | },
388 | {
389 | capabilities: {
390 | prompts: {}
391 | }
392 | }
393 | );
394 |
395 | server.setRequestHandler(ListPromptsRequestSchema, async () => {
396 | return {
397 | prompts: [{
398 | name: "example-prompt",
399 | description: "An example prompt template",
400 | arguments: [{
401 | name: "arg1",
402 | description: "Example argument",
403 | required: true
404 | }]
405 | }]
406 | };
407 | });
408 |
409 | server.setRequestHandler(GetPromptRequestSchema, async (request) => {
410 | if (request.params.name !== "example-prompt") {
411 | throw new Error("Unknown prompt");
412 | }
413 | return {
414 | description: "Example prompt",
415 | messages: [{
416 | role: "user",
417 | content: {
418 | type: "text",
419 | text: "Example prompt text"
420 | }
421 | }]
422 | };
423 | });
424 |
425 | const transport = new StdioServerTransport();
426 | await server.connect(transport);
427 | ```
428 |
429 | ### Writing MCP Clients
430 |
431 | The SDK provides a high-level client interface:
432 |
433 | ```typescript
434 | import { Client } from "@modelcontextprotocol/sdk/client/index.js";
435 | import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
436 |
437 | const transport = new StdioClientTransport({
438 | command: "node",
439 | args: ["server.js"]
440 | });
441 |
442 | const client = new Client(
443 | {
444 | name: "example-client",
445 | version: "1.0.0"
446 | },
447 | {
448 | capabilities: {
449 | prompts: {},
450 | resources: {},
451 | tools: {}
452 | }
453 | }
454 | );
455 |
456 | await client.connect(transport);
457 |
458 | // List prompts
459 | const prompts = await client.listPrompts();
460 |
461 | // Get a prompt
462 | const prompt = await client.getPrompt("example-prompt", {
463 | arg1: "value"
464 | });
465 |
466 | // List resources
467 | const resources = await client.listResources();
468 |
469 | // Read a resource
470 | const resource = await client.readResource("file:///example.txt");
471 |
472 | // Call a tool
473 | const result = await client.callTool({
474 | name: "example-tool",
475 | arguments: {
476 | arg1: "value"
477 | }
478 | });
479 | ```
480 |
481 | ## Documentation
482 |
483 | - [Model Context Protocol documentation](https://modelcontextprotocol.io)
484 | - [MCP Specification](https://spec.modelcontextprotocol.io)
485 | - [Example Servers](https://github.com/modelcontextprotocol/servers)
486 |
487 | ## Contributing
488 |
489 | Issues and pull requests are welcome on GitHub at https://github.com/modelcontextprotocol/typescript-sdk.
490 |
491 | ## License
492 |
493 | This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details.
```