#
tokens: 4226/50000 10/10 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .github
│   └── workflows
│       └── npm-publish.yml
├── .gitignore
├── .npmignore
├── build
│   ├── index.d.ts
│   └── index.js
├── build.sh
├── Dockerfile
├── docs
│   └── images
│       └── screenshot.png
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── smithery.yaml
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------

```
# Development files
.git
.github
.vscode
src/
test/
tests/
*.test.js
*.spec.js
tsconfig.json
.eslintrc
.prettierrc
.editorconfig
.gitignore
.travis.yml
.circleci/
jest.config.js

# Build scripts
build.sh
scripts/

# Documentation files that aren't needed in the package
docs/
test-instructions.md

# Node.js
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log

# macOS
.DS_Store

```

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

```
# Dependency directories
node_modules/

# Build artifacts
dist/

# dotenv environment variables file
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# OS-specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Yarn integrity file
.yarn-integrity

# Optional npm cache directory
.npm

# Editor directories and files
.idea
.vscode
*.swp
*.swo
```

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

```markdown
# MCP Easy Copy

[![MCP Server](https://badge.mcpx.dev?type=server)](https://modelcontextprotocol.io)
[![Platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20Windows-lightgrey)](https://claude.ai/download)
[![npm version](https://img.shields.io/npm/v/@fishes/mcp-easy-copy)](https://www.npmjs.com/package/@fishes/mcp-easy-copy)
[![Node.js](https://img.shields.io/badge/node-%3E%3D14.0.0-brightgreen)](https://nodejs.org)
[![smithery badge](https://smithery.ai/badge/@fisheepx/mcp-easy-copy)](https://smithery.ai/server/@fisheepx/mcp-easy-copy)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

A Model Context Protocol server that makes it easy to discover and copy available MCP services in Claude Desktop.

<img src="docs/images/screenshot.png" alt="MCP Easy Copy in action" width="400"/>

## Purpose

This MCP server is designed to be your first stop when working with Claude Desktop. It solves the problem of having to remember MCP service names or looking them up in configuration files by:

1. Automatically reading the Claude Desktop configuration file
2. Extracting the names of all configured MCP services
3. Presenting them in an easy-to-copy format at the top of the tools list

Although Claude can now automatically select the appropriate MCP services in most scenarios, there are still situations where users need to explicitly specify an MCP service name. These situations include:

- When you have many MCP services configured, making the tools list long and difficult to navigate
- When specific MCP services offer multiple callable actions, further increasing the list length
- When you need to direct Claude to use a specific service rather than relying on its automatic selection
- When troubleshooting or comparing results between different MCP services

This tool bridges that gap, making all available services easily accessible without having to search through configuration files.

## Features

- **Appears at the top of tools list**: Uses special name formatting to always appear first
- **Dynamic updates**: Always shows the latest available services
- **Copy-friendly format**: Numbered list for easy reference
- **Zero external dependencies**: Just needs Node.js

## Installation

### Option 1: Install via npm (Recommended)

```bash
npm install -g @fishes/mcp-easy-copy
```

Then add to your Claude Desktop configuration:

```json
{
  "mcpServers": {
    "mcp-easy-copy": {
      "command": "npx",
      "args": [
        "-y",
        "@fishes/mcp-easy-copy"
      ]
    }
  }
}
```

### Option 2: Installing via Smithery

To install Easy Copy for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@fisheepx/mcp-easy-copy):

```bash
npx -y @smithery/cli install @fisheepx/mcp-easy-copy --client claude
```

### Option 3: Manual Installation

1. Clone the repository:
   ```bash
   git clone https://github.com/f-is-h/mcp-easy-copy.git
   cd mcp-easy-copy
   ```

2. Install dependencies and build:
   ```bash
   npm install
   npm run build
   ```

3. Configure Claude Desktop:
   
   **For macOS:**
   Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
   
   **For Windows:**
   Edit `%APPDATA%\Claude\claude_desktop_config.json`
   
   Add the following configuration:
   ```json
   {
     "mcpServers": {
       "mcp-easy-copy": {
         "command": "node",
         "args": [
            "/ABSOLUTE/PATH/TO/mcp_easy_copy/build/index.js"
         ]
       }
     }
   }
   ```

4. Restart Claude Desktop



## Using the Tool

Once installed, you can use the service in two ways:

1. **Via the tools menu:** Click the hammer icon in Claude Desktop and select the service at the top of the list (it will show all available services in its description)

2. **Via a prompt:** Ask Claude something like:
   ```
   Please list all MCP services that are available to you
   ```
   or
   ```
   Please use _________mcp-easy-copy_________ to show me all available MCP services
   ```

## Development

MCP Easy Copy is built with TypeScript and uses the Model Context Protocol SDK.

```bash
# Install dependencies
npm install

# Build the project
npm run build

# Test with the MCP Inspector
npm run inspector
```

## Troubleshooting

If the tool doesn't work as expected:

1. **Check logs**: Look at the log files
   - macOS: `~/Library/Logs/Claude/mcp-server-mcp-easy-copy.log`
   - Windows: `%APPDATA%\Claude\logs\mcp-server-mcp-easy-copy.log`

2. **Verify configuration**: Make sure your `claude_desktop_config.json` is valid JSON

3. **Check Node.js**: Ensure Node.js is properly installed (`node --version`)

4. **Restart Claude**: Always restart Claude Desktop after making configuration changes

5. **Use the Inspector**: Run `npm run inspector` to debug with the MCP Inspector

## Other Badges

### Glama
<a href="https://glama.ai/mcp/servers/@fisheepx/mcp-easy-copy">
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@f-is-h/mcp-easy-copy/badge" alt="Easy Copy MCP server" />
</a>

### MseeP.ai
[![MseeP.ai Security Assessment Badge](https://mseep.net/pr/f-is-h-mcp-easy-copy-badge.png)](https://mseep.ai/app/f-is-h-mcp-easy-copy)

## License

[MIT License](LICENSE)

## Future Vision

While we have no specific knowledge of Anthropic's roadmap, we imagine that future versions of Claude's client could potentially implement features like autocomplete when using the '@' symbol. Such a feature might display a dropdown list of available MCP services, making it much easier for users to explicitly instruct Claude to utilize specific services.

Even if such improvements eventually make this project obsolete, we'd be delighted to see Claude's interface evolve in ways that improve user experience. After all, the goal of this tool is to make MCP services more accessible, and having that functionality built directly into Claude would be the ultimate success.

```

--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------

```bash
#!/bin/bash

# Change to the directory where the script is located
cd "$(dirname "$0")"

# Build the project
npm run build

# Show success message
echo "Build completed successfully!"
echo "To use this MCP service, configure it in Claude Desktop."


```

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

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "outDir": "./build",
    "strict": true,
    "declaration": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "**/*.test.ts"]
}
```

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

```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
FROM node:lts-alpine

WORKDIR /app

# Copy package files and install dependencies
COPY package*.json ./
RUN npm install --ignore-scripts

# Copy the rest of the source code and build
COPY . .
RUN npm run build

# Expose any required ports (if applicable)
# EXPOSE 3000

CMD ["npm", "start"]

```

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

```yaml
# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml

startCommand:
  type: stdio
  configSchema:
    # JSON Schema defining the configuration options for the MCP.
    type: object
    properties: {}
  commandFunction:
    # A JS function that produces the CLI command based on the given config to start the MCP on stdio.
    |-
    (config) => ({
      command: 'node',
      args: ['build/index.js']
    })
  exampleConfig: {}

```

--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------

```yaml
name: Node.js Package

on:
  release:
    types: [created]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: 16
      - run: npm ci
      - run: npm test
      - run: npm run build

  publish-npm:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: 16
          registry-url: https://registry.npmjs.org/
      - run: npm ci
      - run: npm run build
      - run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

```

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

```json
{
  "name": "@fishes/mcp-easy-copy",
  "version": "1.0.1",
  "description": "A MCP server that lists all available MCP services for easy copying and usage",
  "main": "build/index.js",
  "type": "module",
  "bin": {
    "mcp-easy-copy": "build/index.js"
  },
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js",
    "inspector": "npx @modelcontextprotocol/inspector node build/index.js",
    "prepublishOnly": "npm run build"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/fisheepx/mcp-easy-copy.git"
  },
  "keywords": [
    "mcp",
    "claude",
    "service-list",
    "tools",
    "utility"
  ],
  "author": "fisheep",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.7.0"
  },
  "devDependencies": {
    "@types/node": "^20.8.0",
    "typescript": "^5.2.2"
  },
  "engines": {
    "node": ">=14.0.0"
  }
}
```

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

```typescript
#!/usr/bin/env node

/**
 * MCP Easy Copy Server
 * 
 * This MCP server lists all configured MCP services in the Claude Desktop application.
 * It makes it easy for users to copy service names for use in their prompts.
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import fs from "fs/promises";
import path from "path";
import os from "os";

// Create an MCP server that will appear at the top of the tools list
const server = new McpServer({
  name: "mcp-easy-copy", // Use hyphens consistently for npm naming convention
  version: "1.0.0"
});

// Configure logging to stderr (doesn't interfere with the MCP protocol)
const logDebug = (message: string) => {
  // Uncomment for debugging
  // console.error(`[DEBUG] ${message}`);
};

/**
 * Configuration file paths for different operating systems
 * - macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
 * - Linux: ~/.config/Claude/claude_desktop_config.json
 * - Windows: %APPDATA%/Claude/claude_desktop_config.json
 */
const possibleConfigPaths = [
  path.join(os.homedir(), "Library/Application Support/Claude/claude_desktop_config.json"),
  path.join(os.homedir(), ".config/Claude/claude_desktop_config.json"),
  path.join(os.homedir(), "AppData/Roaming/Claude/claude_desktop_config.json")
];

/**
 * Finds the Claude Desktop configuration file
 * @returns The path to the config file if found, null otherwise
 */
async function findConfigFile(): Promise<string | null> {
  for (const configPath of possibleConfigPaths) {
    try {
      await fs.access(configPath);
      logDebug(`Found config file at: ${configPath}`);
      return configPath;
    } catch (error) {
      logDebug(`Config file not found at: ${configPath}`);
    }
  }
  return null;
}

/**
 * Retrieves all MCP service names from the Claude Desktop configuration file
 * @returns Array of MCP service names
 */
async function getMcpServices(): Promise<string[]> {
  try {
    // Find the config file
    const configPath = await findConfigFile();
    if (!configPath) {
      return [];
    }
    
    // Read and parse the config file
    const configContent = await fs.readFile(configPath, 'utf-8');
    const config = JSON.parse(configContent);
    
    // Extract and return MCP service names
    return config.mcpServers ? Object.keys(config.mcpServers) : [];
  } catch (error) {
    logDebug(`Error getting MCP services: ${error}`);
    return [];
  }
}

/**
 * Resource that returns the list of configured MCP services
 * This resource is exposed through URI: mcp-services://list
 */
server.resource(
  "mcp-services-list",
  "mcp-services://list",
  async (uri) => {
    try {
      // Find the config file
      const configPath = await findConfigFile();
      if (!configPath) {
        return {
          contents: [{
            uri: uri.href,
            text: "Error: Claude Desktop configuration file not found."
          }]
        };
      }
      
      // Read and parse the config file
      const configContent = await fs.readFile(configPath, 'utf-8');
      const config = JSON.parse(configContent);
      
      // Extract MCP service names
      const services = config.mcpServers ? Object.keys(config.mcpServers) : [];
      
      // Format the output in a user-friendly way
      const formattedList = services.length > 0 
        ? "📋 AVAILABLE MCP SERVICES:\n" + services.map((name) => `- ${name}`).join("\n") + "\n\nCopy a service name to use in prompts like:\n" +
          "• Can you use [service name] to...\n" +
          "• Please call [service name] to..."
        : "No MCP services configured.";
      
      return {
        contents: [{
          uri: uri.href,
          text: formattedList
        }]
      };
    } catch (error) {
      console.error("Error reading MCP config:", error);
      return {
        contents: [{
          uri: uri.href,
          text: `Error reading MCP configuration: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

/**
 * Initializes and starts the MCP server
 */
async function main() {
  try {
    // Get initial MCP services to include in the tool description
    let toolDescription = "List all MCP services available in this Claude instance";
    const services = await getMcpServices();
    
    if (services.length > 0) {
      // Format service names with separators for better visibility in the UI
      // (newlines don't work well in Claude's tool descriptions)
      const servicesList = services.map(name => `${name}`).join(" │ ");
      toolDescription = `│ ${servicesList} │`;
    }
    
    // Register the tool with underscores to appear at the top of tool listings
    server.tool(
      "_________available_mcp_services_for_easy_copy_________",
      toolDescription,
      {}, // No parameters needed
      async () => {
        // Always fetch the latest services when the tool is called
        const currentServices = await getMcpServices();
        
        if (currentServices.length === 0) {
          return {
            content: [{ 
              type: "text", 
              text: "No MCP services configured." 
            }]
          };
        }
        
        // Format the output with numbered list and usage instructions
        const formattedList = "📋 AVAILABLE MCP SERVICES:\n" + 
          currentServices.map((name, index) => `${index + 1}. ${name}`).join("\n") + 
          "\n\nCopy a service name to use in prompts like:\n" +
          "• Can you use [service name] to...\n" +
          "• Please call [service name] to...";
        
        return {
          content: [{ 
            type: "text", 
            text: formattedList 
          }]
        };
      }
    );
    
    // Connect the server using stdio transport (standard for MCP)
    const transport = new StdioServerTransport();
    await server.connect(transport);
    console.error("MCP Easy Copy server running...");
  } catch (error) {
    console.error("Failed to start server:", error);
    process.exit(1);
  }
}

// Start the server
main();
```