├── .gitignore ├── package.json ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directories 2 | node_modules/ 3 | npm-debug.log 4 | yarn-debug.log 5 | yarn-error.log 6 | package-lock.json 7 | 8 | # Environment variables 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Build outputs 16 | dist/ 17 | build/ 18 | 19 | # IDE and editor files 20 | .idea/ 21 | .vscode/ 22 | *.swp 23 | *.swo 24 | .DS_Store 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcp-rust-docs", 3 | "version": "1.0.0", 4 | "description": "MCP server for fetching Rust crate documentation", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "build-ts": "tsc" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@modelcontextprotocol/sdk": "^1.6.1", 15 | "axios": "^1.6.0", 16 | "html-to-text": "^9.0.5" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MCP Rust Documentation Server 2 | 3 | This is a Model Context Protocol (MCP) server that fetches and returns documentation for Rust crates providing essential context for LLM's when working with Rust code. 4 | 5 | ## Features 6 | 7 | - Fetches documentation for any Rust crate available on docs.rs 8 | - Strips HTML and formats the content for readability 9 | - Limits response size to prevent overwhelming the client 10 | - Uses the latest MCP SDK (v1.6.1) 11 | 12 | ## Installation 13 | 14 | ```bash 15 | # Clone the repository 16 | git https://github.com/0xKoda/mcp-rust-docs.git 17 | cd mcp-rust-docs 18 | 19 | # Install dependencies 20 | npm install 21 | ``` 22 | 23 | ### Prerequisites 24 | 25 | - Node.js 26 | - npm 27 | 28 | ## Usage 29 | 30 | ```bash 31 | # Start the server directly 32 | npm start 33 | ``` 34 | 35 | ## Integrating with AI Assistants 36 | 37 | ### Claude Desktop 38 | 39 | Add the following to your Claude Desktop configuration file (`claude_desktop_config.json`): 40 | 41 | ```json 42 | { 43 | "mcpServers": { 44 | "rust-docs": { 45 | "command": "node", 46 | "args": ["/absolute/path/to/index.js"] 47 | } 48 | } 49 | } 50 | ``` 51 | 52 | Replace `/absolute/path/to/index.js` with the absolute path to the index.js file in this repository. 53 | 54 | ## Example Usage 55 | 56 | Once the server is running and configured with your AI assistant, you can ask questions like: 57 | 58 | - "Look up the documentation for the 'tokio' crate" 59 | - "What features does the 'serde' crate provide?" 60 | - "Show me the documentation for 'ratatui'" 61 | - "Can you explain the main modules in the 'axum' crate?" 62 | 63 | The AI will use the `lookup_crate_docs` tool to fetch and display the relevant documentation. 64 | 65 | ## Testing with MCP Inspector 66 | 67 | You can test this server using the MCP Inspector: 68 | 69 | ```bash 70 | npx @modelcontextprotocol/inspector 71 | ``` 72 | 73 | Then select the "Connect to a local server" option and follow the prompts. 74 | 75 | ## How It Works 76 | 77 | This server implements a single MCP tool called `lookup_crate_docs` that: 78 | 79 | 1. Takes a Rust crate name as input (optional, defaults to 'tokio' if not provided) 80 | 2. Fetches the documentation from docs.rs 81 | 3. Converts the HTML to plain text using the html-to-text library 82 | 4. Truncates the content if it exceeds 8000 characters 83 | 5. Returns the formatted documentation in the proper MCP response format 84 | 85 | ## SDK Implementation Notes 86 | 87 | This server uses the MCP SDK with carefully structured import paths. If you're modifying the code, be aware that: 88 | 89 | 1. The SDK requires importing from specific paths (e.g., `@modelcontextprotocol/sdk/server/mcp.js`) 90 | 2. We use the high-level McpServer API rather than the low-level tools 91 | 3. The tool definition uses Zod for parameter validation 92 | 4. Console output is redirected to stderr to avoid breaking the MCP protocol 93 | 5. The tool returns properly formatted MCP response objects 94 | 95 | ## Contributing 96 | 97 | Contributions are welcome! Please feel free to submit a Pull Request. 98 | 99 | ## License 100 | 101 | MIT -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // index.js - Plain JavaScript version 2 | const axios = require('axios'); 3 | const { convert: htmlToText } = require('html-to-text'); 4 | 5 | // Import specific modules from the SDK with corrected paths 6 | const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js'); 7 | const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js'); 8 | const { z } = require('zod'); 9 | 10 | // Redirect console.log to stderr to avoid breaking the MCP protocol 11 | const originalConsoleLog = console.log; 12 | console.log = function() { 13 | console.error.apply(console, arguments); 14 | }; 15 | 16 | // Initialize the MCP server 17 | const server = new McpServer({ 18 | name: 'rust-docs', 19 | version: '1.0.0' 20 | }); 21 | 22 | // Define tool with proper Zod schema for parameters 23 | server.tool( 24 | 'lookup_crate_docs', 25 | 'Lookup documentation for a Rust crate from docs.rs', 26 | { crateName: z.string().optional().describe('Name of the Rust crate to lookup documentation for') }, 27 | async (args) => { 28 | try { 29 | // Extract crateName from args or use default 30 | const crateName = args.crateName || "tokio"; 31 | 32 | console.error(`Fetching documentation for default crate: ${crateName}`); 33 | 34 | // Construct the docs.rs URL for the crate 35 | const url = `https://docs.rs/${crateName}/latest/${crateName}/index.html`; 36 | console.error(`Making request to: ${url}`); 37 | 38 | // Fetch the HTML content 39 | const response = await axios.get(url); 40 | console.error(`Received response with status: ${response.status}`); 41 | 42 | // Convert HTML to text 43 | const text = htmlToText(response.data, { 44 | wordwrap: 130, 45 | selectors: [ 46 | { selector: 'a', options: { ignoreHref: true } }, 47 | { selector: 'img', format: 'skip' } 48 | ] 49 | }); 50 | 51 | // Truncate if necessary 52 | const maxLength = 8000; 53 | const truncatedText = text.length > maxLength 54 | ? text.substring(0, maxLength) + `\n\n[Content truncated. Full documentation available at ${url}]` 55 | : text; 56 | 57 | console.error(`Successfully processed docs for ${crateName}`); 58 | return { 59 | content: [{ type: "text", text: truncatedText }] 60 | }; 61 | } catch (error) { 62 | console.error(`Error fetching documentation:`, error.message); 63 | return { 64 | content: [{ type: "text", text: `Error: Could not fetch documentation. ${error.message}` }], 65 | isError: true 66 | }; 67 | } 68 | } 69 | ); 70 | 71 | // Define prompts for tools 72 | server.prompt( 73 | 'lookup_crate_docs', 74 | { crateName: z.string().describe('Name of the Rust crate to lookup documentation for') }, 75 | ({ crateName }) => ({ 76 | messages: [ 77 | { 78 | role: "user", 79 | content: { 80 | type: "text", 81 | text: `Please analyze and summarize the documentation for the Rust crate '${crateName}'. Focus on: 82 | 1. The main purpose and features of the crate 83 | 2. Key types and functions 84 | 3. Common usage patterns 85 | 4. Any important notes or warnings 86 | 5. VERY IMPORTANT: Latest Version 87 | 88 | Documentation content will follow.` 89 | } 90 | } 91 | ] 92 | }) 93 | ); 94 | 95 | // Connect to the stdio transport and start the server 96 | server.connect(new StdioServerTransport()) 97 | .then(() => { 98 | console.error('MCP Crate Docs Server is running...'); 99 | }) 100 | .catch((err) => { 101 | console.error('Failed to start MCP server:', err); 102 | process.exit(1); 103 | }); --------------------------------------------------------------------------------