#
tokens: 3769/50000 8/8 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── Dockerfile
├── index.ts
├── LICENSE
├── logo.png
├── package.json
├── README.md
├── screenshot.png
├── smithery.yaml
├── tsconfig.base.json
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
1 | dist/
2 | node_modules/
3 | *.lock
4 | package-lock.json
5 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/btwiuse-npm-search-mcp-server-badge.png)](https://mseep.ai/app/btwiuse-npm-search-mcp-server)
  2 | 
  3 | # npm-search MCP Server
  4 | [![smithery badge](https://smithery.ai/badge/npm-search-mcp-server)](https://smithery.ai/server/npm-search-mcp-server)
  5 | 
  6 | A Model Context Protocol server that allows you to search for npm packages by calling the `npm search` command.
  7 | 
  8 | <a href="https://glama.ai/mcp/servers/yeb3luefvf"><img width="380" height="200" src="https://glama.ai/mcp/servers/yeb3luefvf/badge" alt="npm-search-mcp-server MCP server" /></a>
  9 | 
 10 | ### Available Tools
 11 | 
 12 | - `search_npm_packages` - Search for npm packages.
 13 |   - Required arguments:
 14 |     - `query` (string): The search query.
 15 | 
 16 | ![Claude Screenshot](./screenshot.png)
 17 | 
 18 | ## Installation
 19 | 
 20 | ### Installing via Smithery
 21 | 
 22 | To install npm-search for Claude Desktop automatically via [Smithery](https://smithery.ai/server/npm-search-mcp-server):
 23 | 
 24 | ```bash
 25 | npx -y @smithery/cli install npm-search-mcp-server --client claude
 26 | ```
 27 | 
 28 | ### Using NPM (recommended)
 29 | 
 30 | Alternatively you can install `npm-search-mcp-server` via npm:
 31 | 
 32 | ```bash
 33 | npm install -g npm-search-mcp-server
 34 | ```
 35 | 
 36 | After installation, you can run it as a command using:
 37 | 
 38 | ```bash
 39 | npm-search-mcp-server
 40 | ```
 41 | 
 42 | ### Using uv
 43 | 
 44 | When using [`uv`](https://docs.astral.sh/uv/) no specific installation is needed. We will
 45 | use [`uvx`](https://docs.astral.sh/uv/guides/tools/) to directly run *npm-search-mcp-server*.
 46 | 
 47 | ## Configuration
 48 | 
 49 | ### Configure for Claude.app
 50 | 
 51 | Add to your Claude settings:
 52 | 
 53 | <details>
 54 | <summary>Using npm installation</summary>
 55 | 
 56 | ```json
 57 | "mcpServers": {
 58 |   "npm-search": {
 59 |     "command": "npx",
 60 |     "args": ["-y", "npm-search-mcp-server"]
 61 |   }
 62 | }
 63 | ```
 64 | </details>
 65 | 
 66 | <details>
 67 | <summary>Using uvx</summary>
 68 | 
 69 | ```json
 70 | "mcpServers": {
 71 |   "npm-search": {
 72 |     "command": "uvx",
 73 |     "args": ["npm-search-mcp-server"]
 74 |   }
 75 | }
 76 | ```
 77 | </details>
 78 | 
 79 | ### Configure for Zed
 80 | 
 81 | Add to your Zed settings.json:
 82 | 
 83 | <details>
 84 | <summary>Using npm installation</summary>
 85 | 
 86 | ```json
 87 | "context_servers": {
 88 |   "npm-search-mcp-server": {
 89 |     "command": "npx",
 90 |     "args": ["-y", "npm-search-mcp-server"]
 91 |   }
 92 | },
 93 | ```
 94 | </details>
 95 | 
 96 | <details>
 97 | <summary>Using uvx</summary>
 98 | 
 99 | ```json
100 | "context_servers": [
101 |   "npm-search-mcp-server": {
102 |     "command": "uvx",
103 |     "args": ["npm-search-mcp-server"]
104 |   }
105 | ],
106 | ```
107 | </details>
108 | 
109 | ## Example Interactions
110 | 
111 | 1. Search for npm packages:
112 | ```json
113 | {
114 |   "name": "search_npm_packages",
115 |   "arguments": {
116 |     "query": "express"
117 |   }
118 | }
119 | ```
120 | Response:
121 | ```json
122 | {
123 |   "results": [
124 |     {
125 |       "name": "express",
126 |       "description": "Fast, unopinionated, minimalist web framework",
127 |       "version": "4.17.1",
128 |       "author": "TJ Holowaychuk",
129 |       "license": "MIT"
130 |     },
131 |     ...
132 |   ]
133 | }
134 | ```
135 | 
136 | ## Debugging
137 | 
138 | You can use the MCP inspector to debug the server. For uvx installations:
139 | 
140 | ```bash
141 | npx @modelcontextprotocol/inspector npx -y npm-search-mcp-server
142 | ```
143 | 
144 | Or if you've installed the package in a specific directory or are developing on it:
145 | 
146 | ```bash
147 | cd path/to/servers/src/npm-search
148 | npx @modelcontextprotocol/inspector uv run npm-search-mcp-server
149 | ```
150 | 
151 | ## Examples of Questions for Claude
152 | 
153 | 1. "Search for express package on npm"
154 | 2. "Find packages related to react"
155 | 3. "Show me npm packages for web development"
156 | 
157 | ## Build
158 | 
159 | Docker build:
160 | 
161 | ```bash
162 | cd src/npm-search
163 | docker build -t mcp/npm-search .
164 | ```
165 | 
166 | ## Contributing
167 | 
168 | We encourage contributions to help expand and improve npm-search-mcp-server. Whether you want to add new npm-related tools, enhance existing functionality, or improve documentation, your input is valuable.
169 | 
170 | For examples of other MCP servers and implementation patterns, see:
171 | https://github.com/modelcontextprotocol/servers
172 | 
173 | Pull requests are welcome! Feel free to contribute new ideas, bug fixes, or enhancements to make npm-search-mcp-server even more powerful and useful.
174 | 
175 | ## License
176 | 
177 | npm-search-mcp-server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
178 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.base.json",
 3 |   "compilerOptions": {
 4 |     "outDir": "./dist",
 5 |     "rootDir": "."
 6 |   },
 7 |   "include": [
 8 |     "./**/*.ts"
 9 |   ]
10 | }
11 | 
```

--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "Node16",
 5 |     "moduleResolution": "Node16",
 6 |     "strict": true,
 7 |     "esModuleInterop": true,
 8 |     "skipLibCheck": true,
 9 |     "forceConsistentCasingInFileNames": true,
10 |     "resolveJsonModule": true
11 |   },
12 |   "include": ["src/**/*"],
13 |   "exclude": ["node_modules"]
14 | }
15 | 
```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
 2 | 
 3 | startCommand:
 4 |   type: stdio
 5 |   configSchema:
 6 |     # JSON Schema defining the configuration options for the MCP.
 7 |     type: object
 8 |     required: []
 9 |     properties: {}
10 |   commandFunction:
11 |     # A function that produces the CLI command to start the MCP on stdio.
12 |     |-
13 |     config => ({command:'node', args:['dist/index.js']})
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
 2 | # Stage 1: Build the application
 3 | FROM node:20 AS builder
 4 | 
 5 | # Set the working directory
 6 | WORKDIR /app
 7 | 
 8 | # Copy package.json and package-lock.json
 9 | COPY package.json tsconfig.json ./
10 | 
11 | # Install dependencies
12 | RUN npm install
13 | 
14 | # Copy the rest of the application
15 | COPY . .
16 | 
17 | # Build the application
18 | RUN npm run build
19 | 
20 | # Stage 2: Run the application
21 | FROM node:20-alpine
22 | 
23 | # Set the working directory
24 | WORKDIR /app
25 | 
26 | # Copy the build output and package files from the builder stage
27 | COPY --from=builder /app/dist /app/dist
28 | COPY --from=builder /app/package.json /app/package-lock.json /app/node_modules /app/
29 | 
30 | # Set the entrypoint
31 | ENTRYPOINT ["node", "dist/index.js"]
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "npm-search-mcp-server",
 3 |   "version": "0.1.1",
 4 |   "description": "MCP server for searching npm",
 5 |   "license": "MIT",
 6 |   "author": "Anthropic, PBC (https://anthropic.com)",
 7 |   "homepage": "https://modelcontextprotocol.io",
 8 |   "repository": "https://github.com/btwiuse/npm-search-mcp-server",
 9 |   "bugs": "https://github.com/modelcontextprotocol/servers/issues",
10 |   "type": "module",
11 |   "bin": {
12 |     "npm-search-mcp-server": "dist/index.js"
13 |   },
14 |   "files": [
15 |     "dist"
16 |   ],
17 |   "scripts": {
18 |     "build": "tsc && shx chmod +x dist/*.js",
19 |     "prepare": "npm run build",
20 |     "watch": "tsc --watch"
21 |   },
22 |   "dependencies": {
23 |     "@modelcontextprotocol/sdk": "1.0.1"
24 |   },
25 |   "devDependencies": {
26 |     "@types/node": "^22.10.5",
27 |     "shx": "^0.3.4",
28 |     "typescript": "^5.6.2"
29 |   }
30 | }
31 | 
```

--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js';
  3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
  4 | import {
  5 |   CallToolRequestSchema,
  6 |   ErrorCode,
  7 |   ListToolsRequestSchema,
  8 |   McpError,
  9 | } from '@modelcontextprotocol/sdk/types.js';
 10 | import { exec } from 'child_process';
 11 | import util from 'util';
 12 | 
 13 | const execPromise = util.promisify(exec);
 14 | 
 15 | const isValidSearchArgs = (args: any): args is { query: string } =>
 16 |   typeof args === 'object' && args !== null && typeof args.query === 'string';
 17 | 
 18 | class NpmSearchServer {
 19 |   private server: Server;
 20 | 
 21 |   constructor() {
 22 |     this.server = new Server(
 23 |       {
 24 |         name: 'npm-search-server',
 25 |         version: '0.1.0',
 26 |       },
 27 |       {
 28 |         capabilities: {
 29 |           tools: {},
 30 |         },
 31 |       }
 32 |     );
 33 | 
 34 |     this.setupToolHandlers();
 35 | 
 36 |     // Error handling
 37 |     this.server.onerror = (error) => console.error('[MCP Error]', error);
 38 |     process.on('SIGINT', async () => {
 39 |       await this.server.close();
 40 |       process.exit(0);
 41 |     });
 42 |   }
 43 | 
 44 |   private setupToolHandlers() {
 45 |     this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
 46 |       tools: [
 47 |         {
 48 |           name: 'search_npm_packages', // Unique identifier
 49 |           description: 'Search for npm packages', // Human-readable description
 50 |           inputSchema: {
 51 |             // JSON Schema for parameters
 52 |             type: 'object',
 53 |             properties: {
 54 |               query: {
 55 |                 type: 'string',
 56 |                 description: 'Search query',
 57 |               },
 58 |             },
 59 |             required: ['query'], // Array of required property names
 60 |           },
 61 |         },
 62 |       ],
 63 |     }));
 64 | 
 65 |     this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
 66 |       if (request.params.name !== 'search_npm_packages') {
 67 |         throw new McpError(
 68 |           ErrorCode.MethodNotFound,
 69 |           `Unknown tool: ${request.params.name}`
 70 |         );
 71 |       }
 72 | 
 73 |       if (!isValidSearchArgs(request.params.arguments)) {
 74 |         throw new McpError(
 75 |           ErrorCode.InvalidParams,
 76 |           'Invalid search arguments'
 77 |         );
 78 |       }
 79 | 
 80 |       const query = request.params.arguments.query;
 81 | 
 82 |       try {
 83 |         const { stdout, stderr } = await execPromise(`npm search ${query}`);
 84 |         if (stderr) {
 85 |           throw new McpError(
 86 |             ErrorCode.InternalError,
 87 |             `npm search error: ${stderr}`
 88 |           );
 89 |         }
 90 | 
 91 |         return {
 92 |           content: [
 93 |             {
 94 |               type: 'text',
 95 |               text: stdout,
 96 |             },
 97 |           ],
 98 |         };
 99 |       } catch (error) {
100 |         if (error instanceof McpError) {
101 |           throw error;
102 |         }
103 |         if (error instanceof Error) {
104 |           throw new McpError(
105 |             ErrorCode.InternalError,
106 |             `Unexpected error: ${error.message}`
107 |           );
108 |         }
109 |         throw new McpError(
110 |           ErrorCode.InternalError,
111 |           'Unexpected error occurred'
112 |         );
113 |       }
114 |     });
115 |   }
116 | 
117 |   async run() {
118 |     const transport = new StdioServerTransport();
119 |     await this.server.connect(transport);
120 |     console.error('Npm Search MCP server running on stdio');
121 |   }
122 | }
123 | 
124 | const server = new NpmSearchServer();
125 | server.run().catch(console.error);
126 | 
```