# 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 | [](https://mseep.ai/app/btwiuse-npm-search-mcp-server)
2 |
3 | # npm-search MCP Server
4 | [](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 | 
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 |
```