diff --git a/docs/core/architecture.mdx b/docs/core/architecture.mdx new file mode 100644 index 0000000..c987d90 --- /dev/null +++ b/docs/core/architecture.mdx @@ -0,0 +1,282 @@ +--- +title: "Core Architecture" +description: "Understand how MCP connects clients, servers, and LLMs" +--- + +The Model Context Protocol (MCP) is built on a flexible, extensible architecture that enables seamless communication between LLM applications and external services. This document covers the core architectural components and concepts. + +## Overview + +MCP follows a client-server architecture where: + +- **Clients** are LLM applications (like claude.ai or IDEs) that initiate connections +- **Servers** provide context, tools, and prompts to clients +- **Hosts** are processes that run MCP clients + +```mermaid +flowchart LR + subgraph "Host (e.g., claude.ai)" + client[MCP Client] + end + subgraph "Server Process" + server[MCP Server] + end + + client <-->|Transport Layer| server +``` + +## Core components + +### Protocol Layer + +The protocol layer handles message framing, request/response linking, and high-level communication patterns. Key classes include: + +```typescript +class Protocol { + // Handle incoming requests + setRequestHandler(schema: T, handler: (request: T) => Result): void + + // Handle incoming notifications + setNotificationHandler(schema: T, handler: (notification: T) => void): void + + // Send requests and await responses + request(request: Request, schema: T): Promise + + // Send one-way notifications + notification(notification: Notification): Promise +} +``` + +### Transport layer + +The transport layer handles the actual communication between clients and servers. MCP supports multiple transport mechanisms: + +1. **stdio Transport** + - Uses standard input/output for communication + - Ideal for local processes + ```typescript + class StdioTransport implements Transport { + constructor(stdin: Readable, stdout: Writable) + send(message: JSONRPCMessage): Promise + } + ``` + +2. **WebSocket Transport** + - Enables real-time bidirectional communication + - Supports remote connections + ```typescript + class WebSocketTransport implements Transport { + constructor(url: URL) + send(message: JSONRPCMessage): Promise + } + ``` + +3. **SSE Transport** + - Uses Server-Sent Events for server-to-client messages + - HTTP POST for client-to-server messages + ```typescript + class SSETransport implements Transport { + constructor(url: URL) + send(message: JSONRPCMessage): Promise + } + ``` + +### Message types + +MCP uses JSON-RPC 2.0 as its message format with three main types: + +1. **Requests** + ```typescript + interface Request { + method: string + params?: { + _meta?: { + progressToken?: string | number + } + } + } + ``` + +2. **Notifications** + ```typescript + interface Notification { + method: string + params?: { + _meta?: Record + } + } + ``` + +3. **Results** + ```typescript + interface Result { + _meta?: Record + [key: string]: unknown + } + ``` + +## Connection lifecycle + +### 1. Initialization + +```mermaid +sequenceDiagram + participant Client + participant Server + + Client->>Server: initialize request + Server->>Client: initialize response + Client->>Server: initialized notification + + Note over Client,Server: Connection ready for use +``` + +1. Client sends `initialize` request with capabilities +2. Server responds with supported features +3. Client sends `initialized` notification +4. Normal message exchange begins + +### 2. Message Exchange + +After initialization, the following patterns are supported: + +- **Request-Response**: Client sends request, server responds +- **Notifications**: Either party sends one-way messages +- **Progress Updates**: Long-running operations can report progress +- **Resource Updates**: Servers notify about changed resources + +### 3. Termination + +Either party can terminate the connection: +- Clean shutdown via `close()` +- Transport disconnection +- Error conditions + +## Error handling + +MCP defines standard error codes and handling: + +```typescript +enum ErrorCode { + ConnectionClosed = -1, + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603 +} +``` + +Errors are propagated through: +- Error responses to requests +- Error events on transports +- Protocol-level error handlers + +## Implementation example + +Here's a basic example of implementing an MCP server: + +```typescript +import { Server } from "@modelcontextprotocol/sdk/server"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio"; + +const server = new Server({ + name: "example-server", + version: "1.0.0" +}); + +// Handle requests +server.setRequestHandler(ListResourcesRequestSchema, async () => { + return { + resources: [ + { + uri: "example://resource", + name: "Example Resource" + } + ] + }; +}); + +// Connect transport +const transport = new StdioServerTransport(); +await server.connect(transport); +``` + +## Best practices + +### Transport selection + +1. **Local Communication** + - Use stdio transport for local processes + - Efficient for same-machine communication + - Simple process management + +2. **Remote Communication** + - WebSocket for full-duplex communication + - SSE for scenarios requiring HTTP compatibility + - Consider security implications + +### Message Handling + +1. **Request Processing** + - Validate inputs thoroughly + - Use type-safe schemas + - Handle errors gracefully + - Implement timeouts + +2. **Progress Reporting** + - Use progress tokens for long operations + - Report progress incrementally + - Include total progress when known + +3. **Error Management** + - Use appropriate error codes + - Include helpful error messages + - Clean up resources on errors + +## Security considerations + +1. **Transport Security** + - Use TLS for remote connections + - Validate connection origins + - Implement authentication when needed + +2. **Message Validation** + - Validate all incoming messages + - Sanitize inputs + - Check message size limits + - Verify JSON-RPC format + +3. **Resource Protection** + - Implement access controls + - Validate resource paths + - Monitor resource usage + - Rate limit requests + +4. **Error Handling** + - Don't leak sensitive information + - Log security-relevant errors + - Implement proper cleanup + - Handle DoS scenarios + +## Debugging and monitoring + +1. **Logging** + - Log protocol events + - Track message flow + - Monitor performance + - Record errors + +2. **Diagnostics** + - Implement health checks + - Monitor connection state + - Track resource usage + - Profile performance + +3. **Testing** + - Test different transports + - Verify error handling + - Check edge cases + - Load test servers + +This architecture provides a robust foundation for building MCP integrations while maintaining flexibility for different use cases and deployment scenarios. \ No newline at end of file diff --git a/docs/core/prompts.mdx b/docs/core/prompts.mdx new file mode 100644 index 0000000..d553287 --- /dev/null +++ b/docs/core/prompts.mdx @@ -0,0 +1,393 @@ +--- +title: "Prompts" +description: "Create resuable prompt templates and workflows" +--- + +MCP Prompts enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs. They provide a powerful way to standardize and share common LLM interactions. + +## Overview + +Prompts in MCP are predefined templates that can: +- Accept dynamic arguments +- Include context from resources +- Chain multiple interactions +- Guide specific workflows +- Surface as UI elements (like slash commands) + +## Prompt structure + +Each prompt is defined with: + +```typescript +{ + name: string; // Unique identifier for the prompt + description?: string; // Human-readable description + arguments?: [ // Optional list of arguments + { + name: string; // Argument identifier + description?: string; // Argument description + required?: boolean; // Whether argument is required + } + ] +} +``` + +## Discovering prompts + +Clients can discover available prompts through the `prompts/list` endpoint: + +```typescript +// Request +{ + method: "prompts/list" +} + +// Response +{ + prompts: [ + { + name: "analyze-code", + description: "Analyze code for potential improvements", + arguments: [ + { + name: "language", + description: "Programming language", + required: true + } + ] + } + ] +} +``` + +## Using prompts + +To use a prompt, clients make a `prompts/get` request: + +```typescript +// Request +{ + method: "prompts/get", + params: { + name: "analyze-code", + arguments: { + language: "python" + } + } +} + +// Response +{ + description?: string, // Optional context about the prompt + messages: [ // Messages to send to the LLM + { + role: "user" | "assistant", + content: { + type: "text" | "image", + text?: string, + data?: string, // base64 for images + mimeType?: string + } + } + ] +} +``` + +## Dynamic prompts + +Prompts can be dynamic and include: + +### Context Integration + +```typescript +const analyzeLogsPrompt = { + name: "analyze-logs", + description: "Analyze recent system logs", + arguments: [ + { + name: "timeframe", + description: "Time period to analyze", + required: true + } + ] +}; + +server.setRequestHandler(GetPromptRequestSchema, async (request) => { + if (request.params.name === "analyze-logs") { + const logs = await getSystemLogs(request.params.arguments?.timeframe); + return { + messages: [ + { + role: "user", + content: { + type: "text", + text: `Analyze these system logs and identify any issues:\n\n${logs}` + } + } + ] + }; + } +}); +``` + +### Resource references + +```typescript +const codeReviewPrompt = { + name: "review-code", + async getMessages(fileUri: string) { + const code = await readResource(fileUri); + return [ + { + role: "user", + content: { + type: "text", + text: `Review this code for best practices:\n\n${code}` + } + } + ]; + } +}; +``` + +### Multi-step workflows + +```typescript +const debugWorkflow = { + name: "debug-error", + async getMessages(error: string) { + return [ + { + role: "user", + content: { + type: "text", + text: "Here's an error I'm seeing:" + } + }, + { + role: "assistant", + content: { + type: "text", + text: "I'll help analyze this error. What have you tried so far?" + } + }, + { + role: "user", + content: { + type: "text", + text: error + } + } + ]; + } +}; +``` + +## Example implementation + +Here's a complete example of implementing prompts in an MCP server: + +```typescript +import { Server } from "@modelcontextprotocol/sdk/server"; +import { + ListPromptsRequestSchema, + GetPromptRequestSchema +} from "@modelcontextprotocol/sdk/types"; + +const PROMPTS = { + "git-commit": { + name: "git-commit", + description: "Generate a Git commit message", + arguments: [ + { + name: "changes", + description: "Git diff or description of changes", + required: true + } + ] + }, + "explain-code": { + name: "explain-code", + description: "Explain how code works", + arguments: [ + { + name: "code", + description: "Code to explain", + required: true + }, + { + name: "language", + description: "Programming language", + required: false + } + ] + } +}; + +const server = new Server({ + name: "example-prompts-server", + version: "1.0.0" +}); + +// List available prompts +server.setRequestHandler(ListPromptsRequestSchema, async () => { + return { + prompts: Object.values(PROMPTS) + }; +}); + +// Get specific prompt +server.setRequestHandler(GetPromptRequestSchema, async (request) => { + const prompt = PROMPTS[request.params.name]; + if (!prompt) { + throw new Error(`Prompt not found: ${request.params.name}`); + } + + if (request.params.name === "git-commit") { + return { + messages: [ + { + role: "user", + content: { + type: "text", + text: `Generate a concise but descriptive commit message for these changes:\n\n${request.params.arguments?.changes}` + } + } + ] + }; + } + + if (request.params.name === "explain-code") { + const language = request.params.arguments?.language || "Unknown"; + return { + messages: [ + { + role: "user", + content: { + type: "text", + text: `Explain how this ${language} code works:\n\n${request.params.arguments?.code}` + } + } + ] + }; + } + + throw new Error("Prompt implementation not found"); +}); +``` + +## Best practices + +When implementing prompts: + +1. Use clear, descriptive prompt names +2. Provide detailed descriptions for prompts and arguments +3. Validate all required arguments +4. Handle missing arguments gracefully +5. Consider versioning for prompt templates +6. Cache dynamic content when appropriate +7. Implement error handling +8. Document expected argument formats +9. Consider prompt composability +10. Test prompts with various inputs + +## UI integration + +Prompts can be surfaced in client UIs as: + +- Slash commands +- Quick actions +- Context menu items +- Command palette entries +- Guided workflows +- Interactive forms + +## Updates and changes + +Servers can notify clients about prompt changes: + +1. Server capability: `prompts.listChanged` +2. Notification: `notifications/prompts/list_changed` +3. Client re-fetches prompt list + +## Security considerations + +When implementing prompts: + +- Validate all arguments +- Sanitize user input +- Consider rate limiting +- Implement access controls +- Audit prompt usage +- Handle sensitive data appropriately +- Validate generated content +- Implement timeouts +- Consider prompt injection risks +- Document security requirements + +## Advanced features + +### Prompt chaining + +```typescript +const analyzePRPrompt = { + async getMessages(prId: string) { + // Chain multiple prompts + const diffPrompt = await getPrompt("analyze-diff"); + const testsPrompt = await getPrompt("review-tests"); + const securityPrompt = await getPrompt("security-review"); + + return [ + ...diffPrompt.messages, + ...testsPrompt.messages, + ...securityPrompt.messages + ]; + } +}; +``` + +### Context enrichment + +```typescript +const troubleshootPrompt = { + async getMessages(error: string) { + // Enrich with system context + const systemInfo = await getSystemInfo(); + const recentLogs = await getRecentLogs(); + const stackTrace = await parseError(error); + + return [ + { + role: "user", + content: { + type: "text", + text: `Help troubleshoot this error: +Error: ${error} +System: ${systemInfo} +Logs: ${recentLogs} +Stack: ${stackTrace}` + } + } + ]; + } +}; +``` + +### Interactive workflows + +```typescript +const debugWorkflow = { + async getMessages(stage: string, context: any) { + switch (stage) { + case "initial": + return promptForError(); + case "analysis": + return analyzeError(context.error); + case "solution": + return suggestFixes(context.analysis); + case "verification": + return verifyFix(context.solution); + } + } +}; +``` \ No newline at end of file diff --git a/docs/core/resources.mdx b/docs/core/resources.mdx new file mode 100644 index 0000000..517d629 --- /dev/null +++ b/docs/core/resources.mdx @@ -0,0 +1,197 @@ +--- +title: "Resources" +description: "Expose data and content from your servers to LLMs" +--- + +Resources are a core primitive in the Model Context Protocol (MCP) that allow servers to expose data and content that can be read by clients and used as context for LLM interactions. + +## Overview + +Resources represent any kind of data that an MCP server wants to make available to clients. This can include: + +- File contents +- Database records +- API responses +- Live system data +- Screenshots and images +- Log files +- And more + +Each resource is identified by a unique URI and can contain either text or binary data. + +## Resource URIs + +Resources are identified using URIs that follow this format: + +``` +[protocol]://[path] +``` + +For example: +- `file:///home/user/documents/report.pdf` +- `postgres://database/customers/schema` +- `screen://localhost/display1` + +The protocol and path structure is defined by the MCP server implementation. Servers can define their own custom URI schemes. + +## Resource types + +Resources can contain two types of content: + +### Text Resources + +Text resources contain UTF-8 encoded text data. These are suitable for: +- Source code +- Configuration files +- Log files +- JSON/XML data +- Plain text + +### Binary resources + +Binary resources contain raw binary data encoded in base64. These are suitable for: +- Images +- PDFs +- Audio files +- Video files +- Other non-text formats + +## Resource discovery + +Clients can discover available resources through two main methods: + +### Direct resources + +Servers expose a list of concrete resources via the `resources/list` endpoint. Each resource includes: + +```typescript +{ + uri: string; // Unique identifier for the resource + name: string; // Human-readable name + description?: string; // Optional description + mimeType?: string; // Optional MIME type +} +``` + +### Resource templates + +For dynamic resources, servers can expose URI templates that clients can use to construct valid resource URIs: + +```typescript +{ + uriTemplate: string; // URI template following RFC 6570 + name: string; // Human-readable name for this type + description?: string; // Optional description + mimeType?: string; // Optional MIME type for all matching resources +} +``` + +## Reading resources + +To read a resource, clients make a `resources/read` request with the resource URI. The server responds with: + +```typescript +{ + contents: [ + { + uri: string; // The requested URI + mimeType?: string; // Optional MIME type + + // One of: + text?: string; // For text resources + blob?: string; // For binary resources (base64 encoded) + } + ] +} +``` + +## Resource updates + +MCP supports real-time updates for resources through two mechanisms: + +### List changes + +Servers can notify clients when their list of available resources changes via the `notifications/resources/list_changed` notification. + +### Content changes + +Clients can subscribe to updates for specific resources: + +1. Client sends `resources/subscribe` with resource URI +2. Server sends `notifications/resources/updated` when the resource changes +3. Client can fetch latest content with `resources/read` +4. Client can unsubscribe with `resources/unsubscribe` + +## Example implementation + +Here's a simple example of implementing resource support in an MCP server: + +```typescript +const server = new Server({ + name: "example-server", + version: "1.0.0" +}); + +// List available resources +server.setRequestHandler(ListResourcesRequestSchema, async () => { + return { + resources: [ + { + uri: "file:///logs/app.log", + name: "Application Logs", + mimeType: "text/plain" + } + ] + }; +}); + +// Read resource contents +server.setRequestHandler(ReadResourceRequestSchema, async (request) => { + const uri = request.params.uri; + + if (uri === "file:///logs/app.log") { + const logContents = await readLogFile(); + return { + contents: [ + { + uri, + mimeType: "text/plain", + text: logContents + } + ] + }; + } + + throw new Error("Resource not found"); +}); +``` + +## Best practices + +When implementing resource support: + +1. Use clear, descriptive resource names and URIs +2. Include helpful descriptions to guide LLM understanding +3. Set appropriate MIME types when known +4. Implement resource templates for dynamic content +5. Use subscriptions for frequently changing resources +6. Handle errors gracefully with clear error messages +7. Consider pagination for large resource lists +8. Cache resource contents when appropriate +9. Validate URIs before processing +10. Document your custom URI schemes + +## Security considerations + +When exposing resources: + +- Validate all resource URIs +- Implement appropriate access controls +- Sanitize file paths to prevent directory traversal +- Be cautious with binary data handling +- Consider rate limiting for resource reads +- Audit resource access +- Encrypt sensitive data in transit +- Validate MIME types +- Implement timeouts for long-running reads +- Handle resource cleanup appropriately \ No newline at end of file diff --git a/docs/core/sampling.mdx b/docs/core/sampling.mdx new file mode 100644 index 0000000..21f9dbd --- /dev/null +++ b/docs/core/sampling.mdx @@ -0,0 +1,221 @@ +--- +title: "Sampling" +description: "Let your servers request completions from LLMs" +--- + +Sampling is a powerful MCP feature that allows servers to request LLM completions through the client, enabling sophisticated agentic behaviors while maintaining security and privacy. + +## How sampling works + +The sampling flow follows these steps: + +1. Server sends a `sampling/createMessage` request to the client +2. Client reviews the request and can modify it +3. Client samples from an LLM +4. Client reviews the completion +5. Client returns the result to the server + +This human-in-the-loop design ensures users maintain control over what the LLM sees and generates. + +## Message format + +Sampling requests use a standardized message format: + +```typescript +{ + messages: [ + { + role: "user" | "assistant", + content: { + type: "text" | "image", + // For text: + text?: string, + // For images: + data?: string, // base64 encoded + mimeType?: string + } + } + ], + systemPrompt?: string, + includeContext?: "none" | "thisServer" | "allServers", + temperature?: number, + maxTokens: number, + stopSequences?: string[], + metadata?: Record +} +``` + +## Request parameters + +### Messages + +The `messages` array contains the conversation history to send to the LLM. Each message has: + +- `role`: Either "user" or "assistant" +- `content`: The message content, which can be: + - Text content with a `text` field + - Image content with `data` (base64) and `mimeType` fields + +### System prompt + +An optional `systemPrompt` field allows servers to request a specific system prompt. The client may modify or ignore this. + +### Context inclusion + +The `includeContext` parameter specifies what MCP context to include: + +- `"none"`: No additional context +- `"thisServer"`: Include context from the requesting server +- `"allServers"`: Include context from all connected MCP servers + +The client controls what context is actually included. + +### Sampling parameters + +Fine-tune the LLM sampling with: + +- `temperature`: Controls randomness (0.0 to 1.0) +- `maxTokens`: Maximum tokens to generate +- `stopSequences`: Array of sequences that stop generation +- `metadata`: Additional provider-specific parameters + +## Response format + +The client returns a completion result: + +```typescript +{ + model: string, // Name of the model used + stopReason: "endTurn" | "stopSequence" | "maxTokens", + role: "user" | "assistant", + content: { + type: "text" | "image", + text?: string, + data?: string, + mimeType?: string + } +} +``` + +## Example implementation + +Here's an example of requesting sampling from a client: + +```typescript +// Server-side code +const response = await server.request({ + method: "sampling/createMessage", + params: { + messages: [ + { + role: "user", + content: { + type: "text", + text: "What files are in the current directory?" + } + } + ], + systemPrompt: "You are a helpful file system assistant.", + includeContext: "thisServer", + maxTokens: 100, + temperature: 0.7 + } +}, CreateMessageResultSchema); + +// Handle the completion +console.log(response.content.text); +``` + +## Best practices + +When implementing sampling: + +1. Always provide clear, well-structured prompts +2. Handle both text and image content appropriately +3. Set reasonable token limits +4. Include relevant context through `includeContext` +5. Validate responses before using them +6. Handle errors gracefully +7. Consider rate limiting sampling requests +8. Document expected sampling behavior +9. Test with various model parameters +10. Monitor sampling costs + +## Human-in-the-loop controls + +Sampling is designed with human oversight in mind: + +### For prompts + +- Clients should show users the proposed prompt +- Users should be able to modify or reject prompts +- System prompts can be filtered or modified +- Context inclusion is controlled by the client + +### For completions + +- Clients should show users the completion +- Users should be able to modify or reject completions +- Clients can filter or modify completions +- Users control which model is used + +## Security considerations + +When implementing sampling: + +- Validate all message content +- Sanitize sensitive information +- Implement appropriate rate limits +- Monitor sampling usage +- Encrypt data in transit +- Handle user data privacy +- Audit sampling requests +- Control cost exposure +- Implement timeouts +- Handle model errors gracefully + +## Common patterns + +### Agentic workflows + +Sampling enables agentic patterns like: + +- Reading and analyzing resources +- Making decisions based on context +- Generating structured data +- Handling multi-step tasks +- Providing interactive assistance + +### Context management + +Best practices for context: + +- Request minimal necessary context +- Structure context clearly +- Handle context size limits +- Update context as needed +- Clean up stale context + +### Error handling + +Robust error handling should: + +- Catch sampling failures +- Handle timeout errors +- Manage rate limits +- Validate responses +- Provide fallback behaviors +- Log errors appropriately + +## Limitations + +Be aware of these limitations: + +- Sampling depends on client capabilities +- Users control sampling behavior +- Context size has limits +- Rate limits may apply +- Costs should be considered +- Model availability varies +- Response times vary +- Not all content types supported \ No newline at end of file diff --git a/docs/core/tools.mdx b/docs/core/tools.mdx new file mode 100644 index 0000000..2697e84 --- /dev/null +++ b/docs/core/tools.mdx @@ -0,0 +1,286 @@ +--- +title: "Tools" +description: "Enable LLMs to perform actions through your server" +--- + +Tools are a powerful primitive in the Model Context Protocol (MCP) that enable servers to expose executable functionality to clients. Through tools, LLMs can interact with external systems, perform computations, and take actions in the real world. + +## How tools work + +Tools in MCP follow a request-response pattern where: + +1. Clients discover available tools through the `tools/list` endpoint +2. Clients can invoke tools using the `tools/call` endpoint +3. Servers execute the requested operation and return results +4. Progress updates can be sent during long-running operations + +## Tool definition structure + +Each tool is defined with the following structure: + +```typescript +{ + name: string; // Unique identifier for the tool + description?: string; // Human-readable description + inputSchema: { // JSON Schema for the tool's parameters + type: "object", + properties: { + // Tool-specific parameters + } + } +} +``` + +The `inputSchema` uses JSON Schema to define the expected parameters and their types. This enables: + +- Parameter validation +- Type checking +- Documentation of required vs optional parameters +- Complex nested parameter structures + +## Implementing tools + +Here's an example of implementing a basic tool in an MCP server: + +```typescript +const server = new Server({ + name: "example-server", + version: "1.0.0" +}); + +// Define available tools +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { + tools: [{ + name: "calculate_sum", + description: "Add two numbers together", + inputSchema: { + type: "object", + properties: { + a: { type: "number" }, + b: { type: "number" } + }, + required: ["a", "b"] + } + }] + }; +}); + +// Handle tool execution +server.setRequestHandler(CallToolRequestSchema, async (request) => { + if (request.params.name === "calculate_sum") { + const { a, b } = request.params.arguments; + return { + toolResult: a + b + }; + } + throw new Error("Tool not found"); +}); +``` + +## Progress reporting + +For long-running operations, tools can report progress using the progress notification system: + +```typescript +server.setRequestHandler(CallToolRequestSchema, async (request) => { + if (request.params.name === "long_process") { + const progressToken = request.params._meta?.progressToken; + + for (let i = 0; i < total; i++) { + await doWork(); + + // Send progress update + await server.notification({ + method: "notifications/progress", + params: { + progress: i, + total: total, + progressToken + } + }); + } + + return { toolResult: "Complete" }; + } +}); +``` + +## Common tool patterns + +Here are some common patterns for implementing tools: + +### System operations + +Tools that interact with the local system: + +```typescript +{ + name: "execute_command", + description: "Run a shell command", + inputSchema: { + type: "object", + properties: { + command: { type: "string" }, + args: { type: "array", items: { type: "string" } } + } + } +} +``` + +### API integrations + +Tools that wrap external APIs: + +```typescript +{ + name: "github_create_issue", + description: "Create a GitHub issue", + inputSchema: { + type: "object", + properties: { + title: { type: "string" }, + body: { type: "string" }, + labels: { type: "array", items: { type: "string" } } + } + } +} +``` + +### Data processing + +Tools that transform or analyze data: + +```typescript +{ + name: "analyze_csv", + description: "Analyze a CSV file", + inputSchema: { + type: "object", + properties: { + filepath: { type: "string" }, + operations: { + type: "array", + items: { + enum: ["sum", "average", "count"] + } + } + } + } +} +``` + +## Best practices + +When implementing tools: + +1. Provide clear, descriptive names and descriptions +2. Use detailed JSON Schema definitions for parameters +3. Include examples in tool descriptions when helpful +4. Implement proper error handling and validation +5. Use progress reporting for long operations +6. Keep tool operations focused and atomic +7. Document expected return value structures +8. Implement proper timeouts +9. Consider rate limiting for resource-intensive operations +10. Log tool usage for debugging and monitoring + +## Security considerations + +When exposing tools: + +### Input validation + +- Validate all parameters against the schema +- Sanitize file paths and system commands +- Validate URLs and external identifiers +- Check parameter sizes and ranges +- Prevent command injection + +### Access control + +- Implement authentication where needed +- Use appropriate authorization checks +- Audit tool usage +- Rate limit requests +- Monitor for abuse + +### Error handling + +- Don't expose internal errors to clients +- Log security-relevant errors +- Handle timeouts appropriately +- Clean up resources after errors +- Validate return values + +## Tool discovery and updates + +MCP supports dynamic tool discovery: + +1. Clients can list available tools at any time +2. Servers can notify clients when tools change using `notifications/tools/list_changed` +3. Tools can be added or removed during runtime +4. Tool definitions can be updated (though this should be done carefully) + +## Common tool categories + +Tools typically fall into these categories: + +### System integration +- File operations +- Process management +- System information +- Network operations + +### External services +- API calls +- Database operations +- Authentication services +- Cloud services + +### Data processing +- Format conversion +- Data analysis +- Content generation +- Media processing + +### Device control +- Hardware interaction +- Device configuration +- Sensor reading +- Output control + +## Error handling + +Tools should return clear error information: + +```typescript +try { + // Tool operation +} catch (error) { + return { + toolResult: { + error: { + code: "OPERATION_FAILED", + message: "Failed to process request", + details: error.message + } + } + }; +} +``` + +## Testing tools + +Consider these testing approaches: + +1. Unit test parameter validation +2. Mock external dependencies +3. Test progress reporting +4. Verify error handling +5. Test concurrent execution +6. Validate return values +7. Test rate limiting +8. Check resource cleanup +9. Test timeout handling +10. Verify security constraints \ No newline at end of file diff --git a/docs/core/transport.mdx b/docs/core/transport.mdx new file mode 100644 index 0000000..e9e117c --- /dev/null +++ b/docs/core/transport.mdx @@ -0,0 +1,278 @@ +--- +title: "Transport" +description: "Learn about MCP's communication mechanisms" +--- + +Transport in the Model Context Protocol (MCP) provides the foundation for communication between clients and servers. It handles the underlying mechanics of how messages are sent and received. + +## How transport works + +MCP transport is built on a simple message-passing architecture where both clients and servers can send messages to each other. The transport layer is responsible for: + +- Establishing connections +- Sending messages +- Receiving messages +- Handling connection lifecycles +- Managing errors +- Ensuring reliable delivery + +## Available transport types + +MCP supports three main transport types: + +### Standard input/output (stdio) + +The stdio transport enables communication through standard input and output streams. This is particularly useful for local integrations and command-line tools. + +```typescript +// Server implementation +const server = new Server({ + name: "example-server", + version: "1.0.0" +}); + +const transport = new StdioServerTransport(); +await server.connect(transport); + +// Client implementation +const client = new Client({ + name: "example-client", + version: "1.0.0" +}); + +const transport = new StdioClientTransport({ + command: "./server", + args: ["--option", "value"] +}); +await client.connect(transport); +``` + +### WebSocket + +WebSocket transport provides real-time, bidirectional communication over a persistent connection. This is ideal for web-based applications that need low-latency messaging. + +```typescript +// Server implementation +const server = new Server({ + name: "example-server", + version: "1.0.0" +}); + +const transport = new WebSocketServerTransport(); +await server.connect(transport); + +// Client implementation +const client = new Client({ + name: "example-client", + version: "1.0.0" +}); + +const transport = new WebSocketClientTransport( + new URL("ws://localhost:3000") +); +await client.connect(transport); +``` + +### Server-sent events (SSE) + +SSE transport enables server-to-client streaming with HTTP POST requests for client-to-server communication. This is useful when WebSocket support isn't available. + +```typescript +// Server implementation +const server = new Server({ + name: "example-server", + version: "1.0.0" +}); + +const transport = new SSEServerTransport("/message", response); +await server.connect(transport); + +// Client implementation +const client = new Client({ + name: "example-client", + version: "1.0.0" +}); + +const transport = new SSEClientTransport( + new URL("http://localhost:3000/sse") +); +await client.connect(transport); +``` + +## Transport interface + +All transport implementations must conform to the Transport interface: + +```typescript +interface Transport { + // Start processing messages + start(): Promise; + + // Send a JSON-RPC message + send(message: JSONRPCMessage): Promise; + + // Close the connection + close(): Promise; + + // Callbacks + onclose?: () => void; + onerror?: (error: Error) => void; + onmessage?: (message: JSONRPCMessage) => void; +} +``` + +## Message format + +Messages sent over MCP transport follow the JSON-RPC 2.0 specification. There are three types of messages: + +### Requests + +```typescript +{ + jsonrpc: "2.0", + id: number | string, + method: string, + params?: object +} +``` + +### Responses + +```typescript +{ + jsonrpc: "2.0", + id: number | string, + result?: object, + error?: { + code: number, + message: string, + data?: unknown + } +} +``` + +### Notifications + +```typescript +{ + jsonrpc: "2.0", + method: string, + params?: object +} +``` + +## Error handling + +Transport implementations should handle various error scenarios: + +1. Connection errors +2. Message parsing errors +3. Protocol errors +4. Network timeouts +5. Resource cleanup + +Example error handling: + +```typescript +class ExampleTransport implements Transport { + async start() { + try { + // Connection logic + } catch (error) { + this.onerror?.(new Error(`Failed to connect: ${error}`)); + throw error; + } + } + + async send(message: JSONRPCMessage) { + try { + // Sending logic + } catch (error) { + this.onerror?.(new Error(`Failed to send message: ${error}`)); + throw error; + } + } +} +``` + +## Best practices + +When implementing or using MCP transport: + +1. Handle connection lifecycle properly +2. Implement proper error handling +3. Clean up resources on connection close +4. Use appropriate timeouts +5. Validate messages before sending +6. Log transport events for debugging +7. Implement reconnection logic when appropriate +8. Handle backpressure in message queues +9. Monitor connection health +10. Implement proper security measures + +## Security considerations + +When implementing transport: + +### Authentication and authorization + +- Implement proper authentication mechanisms +- Validate client credentials +- Use secure token handling +- Implement authorization checks + +### Data security + +- Use TLS for network transport +- Encrypt sensitive data +- Validate message integrity +- Implement message size limits +- Sanitize input data + +### Network security + +- Implement rate limiting +- Use appropriate timeouts +- Handle denial of service scenarios +- Monitor for unusual patterns +- Implement proper firewall rules + +## Debugging transport + +Tips for debugging transport issues: + +1. Enable debug logging +2. Monitor message flow +3. Check connection states +4. Validate message formats +5. Test error scenarios +6. Use network analysis tools +7. Implement health checks +8. Monitor resource usage +9. Test edge cases +10. Use proper error tracking + +## Transport selection guide + +Choose the appropriate transport based on your needs: + +### Use stdio when: + +- Building command-line tools +- Implementing local integrations +- Needing simple process communication +- Working with shell scripts + +### Use WebSocket when: + +- Real-time updates are needed +- Low latency is required +- Bidirectional communication is necessary +- Working with web applications + +### Use SSE when: + +- Only server-to-client streaming is needed +- WebSocket support is limited +- Working with restricted networks +- Implementing simple updates \ No newline at end of file diff --git a/docs/guides/first-server-python.mdx b/docs/guides/first-server-python.mdx index da5be94..7c512a2 100644 --- a/docs/guides/first-server-python.mdx +++ b/docs/guides/first-server-python.mdx @@ -45,7 +45,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Create Your Server +## Create your server @@ -269,7 +269,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Try It Out! +## Try it out! @@ -297,7 +297,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Understanding the Code +## Understanding the code Let's break down the key MCP concepts used in this server: @@ -346,7 +346,7 @@ Let's break down the key MCP concepts used in this server: -## Next Steps +## Next steps Now that you've built your first MCP server, try these enhancements: diff --git a/docs/guides/first-server-ts.mdx b/docs/guides/first-server-ts.mdx index c94021f..d3e0656 100644 --- a/docs/guides/first-server-ts.mdx +++ b/docs/guides/first-server-ts.mdx @@ -62,7 +62,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Create Your Server +## Create your server @@ -311,7 +311,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Try It Out! +## Try it out! @@ -336,7 +336,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Understanding the Code +## Understanding the code @@ -386,7 +386,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea -## Best Practices +## Best practices -## Next Steps +## Next steps - This guide provides a high-level overview of MCP's core concepts. For detailed implementation guides, check out our tutorials section. - - -The Model Context Protocol (MCP) enables seamless integration between LLM applications and external data sources or tools. Let's break down the key concepts: - - diff --git a/introduction.mdx b/introduction.mdx index e9a1f4f..ec9c2f4 100644 --- a/introduction.mdx +++ b/introduction.mdx @@ -55,42 +55,42 @@ Dive deeper into MCP's core concepts and capabilities: Understand how MCP connects clients, servers, and LLMs Expose data and content from your servers to LLMs Create reusable prompt templates and workflows Enable LLMs to perform actions through your server Let your servers request completions from LLMs Learn about MCP's communication mechanisms diff --git a/mint.json b/mint.json index cf87c99..6fce8e4 100644 --- a/mint.json +++ b/mint.json @@ -57,6 +57,17 @@ "docs/guides/integrate-ts" ] }, + { + "group": "Concepts", + "pages": [ + "docs/core/architecture", + "docs/core/resources", + "docs/core/prompts", + "docs/core/tools", + "docs/core/sampling", + "docs/core/transport" + ] + }, { "group": "API Reference", "pages": [