#
tokens: 7762/50000 9/10 files (page 1/2)
lines: on (toggle) GitHub
raw markdown copy reset
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 ![NPM Version](https://img.shields.io/npm/v/%40modelcontextprotocol%2Fsdk) ![MIT licensed](https://img.shields.io/npm/l/%40modelcontextprotocol%2Fsdk)
  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.
```
Page 1/2FirstPrevNextLast