Model README on the Python SDK's README
This commit is contained in:
parent
e60fb5e2b8
commit
0790890bf3
2 changed files with 334 additions and 95 deletions
433
README.md
433
README.md
|
|
@ -1,6 +1,26 @@
|
|||
# MCP TypeScript SDK 
|
||||
# MCP TypeScript SDK  
|
||||
|
||||
TypeScript implementation of the [Model Context Protocol](https://modelcontextprotocol.io) (MCP), providing both client and server capabilities for integrating with LLM surfaces.
|
||||
## Table of Contents
|
||||
- [Overview](#overview)
|
||||
- [Installation](#installation)
|
||||
- [Quickstart](#quickstart)
|
||||
- [What is MCP?](#what-is-mcp)
|
||||
- [Core Concepts](#core-concepts)
|
||||
- [Server](#server)
|
||||
- [Resources](#resources)
|
||||
- [Tools](#tools)
|
||||
- [Prompts](#prompts)
|
||||
- [Running Your Server](#running-your-server)
|
||||
- [Development Mode](#development-mode)
|
||||
- [Claude Desktop Integration](#claude-desktop-integration)
|
||||
- [Direct Execution](#direct-execution)
|
||||
- [Examples](#examples)
|
||||
- [Echo Server](#echo-server)
|
||||
- [SQLite Explorer](#sqlite-explorer)
|
||||
- [Advanced Usage](#advanced-usage)
|
||||
- [Low-Level Server](#low-level-server)
|
||||
- [Writing MCP Clients](#writing-mcp-clients)
|
||||
- [Server Capabilities](#server-capabilities)
|
||||
|
||||
## Overview
|
||||
|
||||
|
|
@ -19,158 +39,377 @@ npm install @modelcontextprotocol/sdk
|
|||
|
||||
## Quick Start
|
||||
|
||||
### Creating a Client
|
||||
Let's create a simple MCP server that exposes a calculator tool and some data:
|
||||
|
||||
```typescript
|
||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
||||
import {
|
||||
ListResourcesRequestSchema,
|
||||
ReadResourceRequestSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { z } from "zod";
|
||||
|
||||
const transport = new StdioClientTransport({
|
||||
command: "path/to/server",
|
||||
// Create an MCP server
|
||||
const server = new McpServer({
|
||||
name: "Demo",
|
||||
version: "1.0.0"
|
||||
});
|
||||
|
||||
const client = new Client({
|
||||
name: "example-client",
|
||||
version: "1.0.0",
|
||||
}, {
|
||||
capabilities: {}
|
||||
});
|
||||
|
||||
await client.connect(transport);
|
||||
|
||||
// List available resources
|
||||
const resources = await client.request(
|
||||
{ method: "resources/list" },
|
||||
ListResourcesResultSchema
|
||||
// Add an addition tool
|
||||
server.tool("add",
|
||||
{ a: z.number(), b: z.number() },
|
||||
async ({ a, b }) => ({
|
||||
content: [{ type: "text", text: String(a + b) }]
|
||||
})
|
||||
);
|
||||
|
||||
// Read a specific resource
|
||||
const resourceContent = await client.request(
|
||||
{
|
||||
method: "resources/read",
|
||||
params: {
|
||||
uri: "file:///example.txt"
|
||||
}
|
||||
},
|
||||
ReadResourceResultSchema
|
||||
// Add a dynamic greeting resource
|
||||
server.resource(
|
||||
"greeting",
|
||||
"greeting://{name}",
|
||||
async (uri, { name }) => ({
|
||||
contents: [{
|
||||
uri: uri.href,
|
||||
text: `Hello, ${name}!`
|
||||
}]
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
### Creating a Server
|
||||
## What is MCP?
|
||||
|
||||
The SDK provides two ways to create a server: using the low-level `Server` class or the simplified `McpServer` class with an Express-style API.
|
||||
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:
|
||||
|
||||
#### Using McpServer (Recommended)
|
||||
- Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
|
||||
- Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
|
||||
- Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
|
||||
- And more!
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Server
|
||||
|
||||
The McpServer is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
|
||||
|
||||
```typescript
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { z } from "zod";
|
||||
|
||||
const server = new McpServer({
|
||||
name: "example-server",
|
||||
version: "1.0.0",
|
||||
name: "My App",
|
||||
version: "1.0.0"
|
||||
});
|
||||
```
|
||||
|
||||
// Define a simple tool with no parameters
|
||||
server.tool("save", async () => {
|
||||
return {
|
||||
content: [{ type: "text", text: "Saved successfully." }]
|
||||
};
|
||||
});
|
||||
### Resources
|
||||
|
||||
// Define a tool with parameters
|
||||
server.tool("add", { a: z.number(), b: z.number() }, async ({ a, b }) => {
|
||||
return {
|
||||
content: [{ type: "text", text: String(a + b) }]
|
||||
};
|
||||
});
|
||||
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:
|
||||
|
||||
// Define a static resource
|
||||
```typescript
|
||||
// Static resource
|
||||
server.resource(
|
||||
"welcome-message",
|
||||
"file:///welcome.txt",
|
||||
"config",
|
||||
"config://app",
|
||||
async (uri) => ({
|
||||
contents: [{
|
||||
uri: uri.href,
|
||||
text: "Welcome to the server!"
|
||||
text: "App configuration here"
|
||||
}]
|
||||
})
|
||||
);
|
||||
|
||||
// Define a prompt with parameters
|
||||
// Dynamic resource with parameters
|
||||
server.resource(
|
||||
"user-profile",
|
||||
"users://{userId}/profile",
|
||||
async (uri, { userId }) => ({
|
||||
contents: [{
|
||||
uri: uri.href,
|
||||
text: `Profile data for user ${userId}`
|
||||
}]
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
### Tools
|
||||
|
||||
Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
|
||||
|
||||
```typescript
|
||||
// Simple tool with parameters
|
||||
server.tool(
|
||||
"calculate-bmi",
|
||||
{
|
||||
weightKg: z.number(),
|
||||
heightM: z.number()
|
||||
},
|
||||
async ({ weightKg, heightM }) => ({
|
||||
content: [{
|
||||
type: "text",
|
||||
text: String(weightKg / (heightM * heightM))
|
||||
}]
|
||||
})
|
||||
);
|
||||
|
||||
// Async tool with external API call
|
||||
server.tool(
|
||||
"fetch-weather",
|
||||
{ city: z.string() },
|
||||
async ({ city }) => {
|
||||
const response = await fetch(`https://api.weather.com/${city}`);
|
||||
const data = await response.text();
|
||||
return {
|
||||
content: [{ type: "text", text: data }]
|
||||
};
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Prompts
|
||||
|
||||
Prompts are reusable templates that help LLMs interact with your server effectively:
|
||||
|
||||
```typescript
|
||||
server.prompt(
|
||||
"greeting",
|
||||
{ name: z.string(), language: z.string().optional() },
|
||||
({ name, language }) => ({
|
||||
"review-code",
|
||||
{ code: z.string() },
|
||||
({ code }) => ({
|
||||
messages: [{
|
||||
role: "assistant",
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `${language === "es" ? "¡Hola" : "Hello"} ${name}!`
|
||||
text: `Please review this code:\n\n${code}`
|
||||
}
|
||||
}]
|
||||
})
|
||||
);
|
||||
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
```
|
||||
|
||||
#### Using Server (Low-level API)
|
||||
## Examples
|
||||
|
||||
### Echo Server
|
||||
|
||||
A simple server demonstrating resources, tools, and prompts:
|
||||
|
||||
```typescript
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { z } from "zod";
|
||||
|
||||
const server = new McpServer({
|
||||
name: "Echo",
|
||||
version: "1.0.0"
|
||||
});
|
||||
|
||||
server.resource(
|
||||
"echo",
|
||||
"echo://{message}",
|
||||
async (uri, { message }) => ({
|
||||
contents: [{
|
||||
uri: uri.href,
|
||||
text: `Resource echo: ${message}`
|
||||
}]
|
||||
})
|
||||
);
|
||||
|
||||
server.tool(
|
||||
"echo",
|
||||
{ message: z.string() },
|
||||
async ({ message }) => ({
|
||||
content: [{ type: "text", text: `Tool echo: ${message}` }]
|
||||
})
|
||||
);
|
||||
|
||||
server.prompt(
|
||||
"echo",
|
||||
{ message: z.string() },
|
||||
({ message }) => ({
|
||||
messages: [{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `Please process this message: ${message}`
|
||||
}
|
||||
}]
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
### SQLite Explorer
|
||||
|
||||
A more complex example showing database integration:
|
||||
|
||||
```typescript
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import sqlite3 from "sqlite3";
|
||||
import { promisify } from "util";
|
||||
import { z } from "zod";
|
||||
|
||||
const server = new McpServer({
|
||||
name: "SQLite Explorer",
|
||||
version: "1.0.0"
|
||||
});
|
||||
|
||||
// Helper to create DB connection
|
||||
const getDb = () => {
|
||||
const db = new sqlite3.Database("database.db");
|
||||
return {
|
||||
all: promisify<string, any[]>(db.all.bind(db)),
|
||||
close: promisify(db.close.bind(db))
|
||||
};
|
||||
};
|
||||
|
||||
server.resource(
|
||||
"schema",
|
||||
"schema://main",
|
||||
async (uri) => {
|
||||
const db = getDb();
|
||||
try {
|
||||
const tables = await db.all(
|
||||
"SELECT sql FROM sqlite_master WHERE type='table'"
|
||||
);
|
||||
return {
|
||||
contents: [{
|
||||
uri: uri.href,
|
||||
text: tables.map((t: {sql: string}) => t.sql).join("\n")
|
||||
}]
|
||||
};
|
||||
} finally {
|
||||
await db.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.tool(
|
||||
"query",
|
||||
{ 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: unknown) {
|
||||
const error = err as Error;
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: `Error: ${error.message}`
|
||||
}],
|
||||
isError: true
|
||||
};
|
||||
} finally {
|
||||
await db.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Low-Level Server
|
||||
|
||||
For more control, you can use the low-level Server class directly:
|
||||
|
||||
```typescript
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import {
|
||||
ListResourcesRequestSchema,
|
||||
ReadResourceRequestSchema,
|
||||
ListPromptsRequestSchema,
|
||||
GetPromptRequestSchema
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
const server = new Server({
|
||||
name: "example-server",
|
||||
version: "1.0.0",
|
||||
}, {
|
||||
capabilities: {
|
||||
resources: {}
|
||||
const server = new Server(
|
||||
{
|
||||
name: "example-server",
|
||||
version: "1.0.0"
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {}
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
||||
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
||||
return {
|
||||
resources: [
|
||||
{
|
||||
uri: "file:///example.txt",
|
||||
name: "Example Resource",
|
||||
},
|
||||
],
|
||||
prompts: [{
|
||||
name: "example-prompt",
|
||||
description: "An example prompt template",
|
||||
arguments: [{
|
||||
name: "arg1",
|
||||
description: "Example argument",
|
||||
required: true
|
||||
}]
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
||||
if (request.params.uri === "file:///example.txt") {
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri: "file:///example.txt",
|
||||
mimeType: "text/plain",
|
||||
text: "This is the content of the example resource.",
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
throw new Error("Resource not found");
|
||||
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
||||
if (request.params.name !== "example-prompt") {
|
||||
throw new Error("Unknown prompt");
|
||||
}
|
||||
return {
|
||||
description: "Example prompt",
|
||||
messages: [{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: "Example prompt text"
|
||||
}
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
```
|
||||
|
||||
### Writing MCP Clients
|
||||
|
||||
The SDK provides a high-level client interface:
|
||||
|
||||
```typescript
|
||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
||||
|
||||
const transport = new StdioClientTransport({
|
||||
command: "node",
|
||||
args: ["server.js"]
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "example-client",
|
||||
version: "1.0.0"
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
await client.connect(transport);
|
||||
|
||||
// List prompts
|
||||
const prompts = await client.listPrompts();
|
||||
|
||||
// Get a prompt
|
||||
const prompt = await client.getPrompt("example-prompt", {
|
||||
arg1: "value"
|
||||
});
|
||||
|
||||
// List resources
|
||||
const resources = await client.listResources();
|
||||
|
||||
// Read a resource
|
||||
const resource = await client.readResource("file:///example.txt");
|
||||
|
||||
// Call a tool
|
||||
const result = await client.callTool("example-tool", {
|
||||
arg1: "value"
|
||||
});
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Model Context Protocol documentation](https://modelcontextprotocol.io)
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/sdk",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@modelcontextprotocol/sdk",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"content-type": "^1.0.5",
|
||||
|
|
|
|||
Loading…
Reference in a new issue