# How to Extend DesktopCommanderMCP with Plugins: A Complete Guide

> Extend DesktopCommanderMCP with plugins using its manifest-based system. Load custom tools and UI resources from the plugins directory easily.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: how-to-guide
- Published: 2026-07-16

---

**Yes, DesktopCommanderMCP supports plugin extension through a manifest-based discovery system that automatically loads custom tools and UI resources from the `plugins/` directory without requiring modifications to the core server.**

DesktopCommanderMCP is built as a Model Context Protocol (MCP) server that implements a flexible plugin architecture. According to the source code in `wonderwhy-er/DesktopCommanderMCP`, the server discovers extensions via a top-level [`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml) manifest (lines 5-61) and loads individual plugin descriptors from [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json) files located in subdirectories under `plugins/`. This design enables third-party developers to add new functionality by declaring tools, schemas, and resources in a standardized format.

## Understanding the Plugin Architecture

The extension system leverages the standard Agenium plugin schema to register capabilities dynamically. When the MCP server starts, the SDK scans the `plugins/` directory (or paths referenced in [`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml)) and automatically registers each discovered plugin's tools and resources.

The core extensibility points are implemented in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) (lines 13-30), which registers generic handlers for `ListResourcesRequestSchema` and `ReadResourceRequestSchema`. These handlers serve UI assets for any plugin that contributes resources, meaning the core server does not need code changes to support new plugins.

Key configuration files include:

- **[`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml)** (lines 5-61): Declares the server as a discoverable MCP plugin with runtime requirements (`runtime.language: typescript`, `transport: stdio`)
- **[`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts)**: Contains the generic resource and tool handlers that expose plugin capabilities via `ListResourcesRequestSchema` and `ReadResourceRequestSchema`
- **[`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts)**: Provides Zod schema templates for tool argument validation

## Creating a Custom DesktopCommanderMCP Plugin

Developing a plugin requires four main components: a directory structure, a plugin descriptor, tool implementation, and optional UI resources.

### Step 1: Define the Plugin Structure

Create a new directory under `plugins/` following this layout:

```

plugins/my-custom-tool/
├─ .my-custom-plugin/plugin.json    ← Plugin descriptor
├─ src/
│   └─ myTool.ts                     ← Tool implementation
└─ ui/
    └─ my-ui.html                    ← Optional UI resource

```

### Step 2: Configure the plugin.json Descriptor

The [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json) file declares your tool's metadata, input schemas, and runtime requirements. Based on the reference implementations in [`plugins/cursor/.cursor-plugin/plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugins/cursor/.cursor-plugin/plugin.json) and [`plugins/claude/.claude-plugin/plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugins/claude/.claude-plugin/plugin.json), a minimal descriptor looks like this:

```json
{
  "name": "my-custom-tool",
  "display_name": "My Custom Tool",
  "description": "A sample tool that echoes back user text.",
  "version": "0.1.0",
  "author": { 
    "name": "Your Name", 
    "url": "https://github.com/yourname" 
  },
  "runtime": { 
    "language": "typescript", 
    "min_node": "18" 
  },
  "tools": [
    {
      "name": "myEcho",
      "description": "Returns the supplied string.",
      "input_schema": {
        "type": "object",
        "properties": { 
          "text": { "type": "string" } 
        },
        "required": ["text"]
      },
      "handler": "./src/myTool.ts"
    }
  ],
  "resources": [
    { 
      "uri": "my-ui.html", 
      "path": "./ui/my-ui.html" 
    }
  ]
}

```

### Step 3: Implement Tool Logic

Create the tool implementation file referenced in the `handler` field. This file must export a function matching the expected signature:

```typescript
import { ToolResult } from "@modelcontextprotocol/sdk/types.js";

export async function myEcho(args: { text: string }): Promise<ToolResult> {
  return { result: `Echo: ${args.text}` };
}

```

Place your implementation in `src/tools/` or the path specified in your [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json). The function receives validated arguments based on your Zod schema (use [`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts) as a template for complex validation) and returns a `ToolResult`.

### Step 4: Add Optional UI Resources

If your plugin requires a user interface, place HTML or asset files in a `ui/` folder. The generic resource handlers in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) automatically serve these files via the MCP `resources/list` and `resources/read` methods. Clients can access these resources using URIs defined in the `resources` array of your [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json).

## How Plugin Discovery Works

The MCP server loads plugins through the following mechanism:

1. **Manifest Scanning**: On startup, the server reads [`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml) to confirm it is operating as a DesktopCommanderMCP instance with `transport: stdio`.
2. **Directory Scanning**: The SDK scans the `plugins/` directory for subdirectories containing `.[plugin-name]/plugin.json` descriptors (following the pattern seen in `.cursor-plugin/` and `.claude-plugin/`).
3. **Registration**: Tools are registered with the MCP framework using their declared names and schemas. Resources are indexed for the generic handlers.
4. **Runtime Execution**: When a client calls a tool via the `tools/call` JSON-RPC method, the server routes the request to the appropriate handler function defined in your plugin's TypeScript file.

## Examples from the Repository

The `plugins/` directory contains reference implementations demonstrating the extension pattern:

- **[`plugins/cursor/.cursor-plugin/plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugins/cursor/.cursor-plugin/plugin.json)**: Shows how Cursor-specific integrations declare tools and UI contracts
- **[`plugins/claude/.claude-plugin/plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugins/claude/.claude-plugin/plugin.json)**: Provides an example of Claude-specific plugin configuration  
- **[`src/ui/contracts.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/ui/contracts.ts)**: Defines URI patterns used by the resource handlers to serve plugin assets

These examples serve as templates for creating new extensions that integrate with specific AI clients while maintaining compatibility with the core MCP protocol.

## Summary

- **DesktopCommanderMCP** uses a manifest-based plugin system defined in [`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml) (lines 5-61) and individual [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json) descriptors
- Plugins reside in the `plugins/` directory and require no core server modifications to function
- The generic handlers in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) (lines 13-30) automatically expose tools and resources declared in [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json) files
- Tool implementations use TypeScript with Zod schemas for input validation, following patterns in [`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts)
- UI resources in `ui/` folders are served automatically via the MCP resources protocol through `resources/list` and `resources/read` handlers

## Frequently Asked Questions

### Do I need to modify the core server code to add a plugin?

No. DesktopCommanderMCP is designed so that **the core server never requires modification** for plugin installation. The generic `resources` and `tools` handlers in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) automatically discover and register capabilities from [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json) files found in the `plugins/` directory. You only need to add your plugin folder and restart the server.

### What is the difference between plugin.yaml and plugin.json?

**[`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml)** is the top-level manifest (lines 5-61) that declares the entire repository as an MCP plugin for the Agenium platform, specifying runtime language (`typescript`) and transport settings (`stdio`). **[`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json)** files exist inside individual plugin subdirectories (like `plugins/cursor/.cursor-plugin/`) and define specific tools, schemas, and resources for that particular extension. Think of [`plugin.yaml`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.yaml) as the server declaration and [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json) as individual feature modules.

### Can DesktopCommanderMCP plugins include custom user interfaces?

Yes. Plugins can bundle UI resources such as HTML files in a `ui/` folder, declared in the `resources` array of [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json). The MCP server serves these via the standard `resources/list` and `resources/read` handlers already implemented in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts). Clients can request these resources by URI (e.g., [`my-ui.html`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/my-ui.html)) to display plugin-specific interfaces within the chat context.

### How does the server discover new plugins?

The MCP SDK scans the `plugins/` directory at startup, looking for subdirectories containing plugin descriptors. Following the pattern of `plugins/cursor/` and `plugins/claude/`, each plugin should have a configuration folder (e.g., `.my-plugin/`) containing [`plugin.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/plugin.json). The server validates these descriptors against the schema and registers tools automatically, making them available via JSON-RPC `tools/call` requests without manual configuration.