cursor-command-publisher
v1.0.4
Published
Dynamic MCP server that loads command templates from markdown files with variable substitution. Designed for Cursor and Claude.
Downloads
13
Maintainers
Readme
Command Publisher
A lightweight MCP (Model Context Protocol) server that dynamically loads and executes command templates from markdown files. Templates use YAML frontmatter for variable definitions and #{variable} placeholders for parameterized commands.
Searches ~/.cursor/published for .md files and parses front matter for interactive variable fillout.
https://github.com/user-attachments/assets/50efd387-6a83-4972-8028-7a777a3d1808
Closer view of interactive modal:
Getting Started
Quick Install
Click the Add to Cursor button above. Then, create ~/.cursor/published, or specify a different directory
Manual Installation
MCP Configuration
{
"mcpServers": {
"cmdpublisher": {
"command": "npx",
"args": ["-y", "cursor-command-publisher"],
}
}
}Or specify a custom directory:
{
"mcpServers": {
"cmdpublisher": {
"command": "node",
"args": ["/path/to/cursor-command-publisher/build/index.js"],
"env": {
"COMMANDS_DIR": ["/custom/path"]
}
}
}
}Note that COMMANDS_DIR must be an Array.
Manual Installation
Go to Cursor Settings -> MCP -> Add new MCP Server. Name to your liking, use command type with the command from the standard config above. You can also verify config or add command like arguments via clicking Edit.
Configuration Details
- Server Name:
cmdpublisher - Type: NPX Package
- Package:
emmahyde/cursor-command-publisher
Features
- Dynamic Command Loading: Watch a directory for
.mdfiles and automatically register them as MCP tools and prompts - Live Reloading: Changes to template files are detected instantly
- YAML Frontmatter: Clean variable definitions with descriptions in one place
- Simple Template Syntax: Use
#{varName}for placeholders - Optional Parameters: Use
variable?: "description"in frontmatter and#{variable?}in templates for conditional content - Conditional Blocks: Use
#{?variable}...#{/variable}to conditionally include entire sections based on variable values - Dual Registration: Each template is exposed as both a tool and a prompt
- Minimal Dependencies: Only uses
@modelcontextprotocol/sdk,chokidar, andyaml - Local Only: No network ports or API keys required
Usage
Create Command Templates
Create a .cursor/published/ directory and add markdown files with templates:
mkdir -p .cursor/publishedExample: .cursor/published/summarize.md
---
format: "output format (bullet points, paragraph, etc)"
text: "the text to summarize"
---
Summarize the following text in #{format} format:
#{text}Example: .cursor/published/translate.md
---
language: "target language"
text: "the text to translate"
---
Translate the following text to #{language} language:
#{text}Template Syntax
Templates use YAML frontmatter for variable definitions and #{variableName} for placeholders:
---
variableName: "human-readable description"
anotherVar: "another description"
---
Template content with #{variableName} and #{anotherVar} placeholders.Examples
Simple variables
---
command: "shell command to run"
---
Run: #{command}Multiple variables
---
host: "hostname or IP"
port: "port number"
user: "login username"
---
Connect to #{host} on port #{port} using username #{user}Optional variables:
Use the ? suffix in both YAML frontmatter and template placeholders to make parameters optional. Optional parameters can be left empty or omitted, and will be replaced with an empty string when not provided.
---
host: "hostname or IP"
port: "port number"
user?: "login username"
---
Connect to #{host} on port #{port}#{user? using username }#{user?}When user is provided: Connect to 192.168.1.1 on port 22 using username admin
When user is empty: Connect to 192.168.1.1 on port 22
Advanced optional usage with conditional text:
---
topic: "main topic"
author?: "author name"
date?: "publication date"
---
# #{topic}
Written by #{author?}#{date? on }#{date?}When all fields provided: # Testing\n\nWritten by Emma Hyde on 2025-10-17
When optional fields empty: # Testing\n\nWritten by
Conditional blocks:
Use #{?variable} to start a conditional block and #{/variable} or #{/} to end it. The entire block is only rendered if the variable has a non-empty value.
---
title: "document title"
author?: "author name"
version?: "version number"
---
# #{title}
#{?author}
## Author Information
Written by: #{author}
#{/author}
#{?version}
## Version
Version: #{version}
#{/}
## Content
Main documentation here.When all fields provided:
# API Documentation
## Author Information
Written by: Emma Hyde
## Version
Version: 1.0.0
## Content
Main documentation here.When optional fields empty:
# API Documentation
## Content
Main documentation here.This is much cleaner than using multiple optional placeholders with conditional text!
Drop code into your Prompt
---
code: "the path/to/code.file:X-Y range"
audience: "who needs the explanation"
---
# Code Explanation
Explain the following code for #{audience}:
\```
#{code}
\```
Focus on what it does and why.How It Works
- Startup: Server scans
.cursor/published/for.mdfiles and parses them - Registration: Each template is registered as both an MCP tool and prompt with variables as parameters
- Watching: File changes are detected via
chokidarand tools/prompts are updated in real-time - Execution: When a tool/prompt is called, variables are substituted and the result is returned
Architecture
src/
├── index.ts # Entry point with STDIO transport
├── server.ts # MCP server with tool registration
├── parser.ts # Template tokenizer and AST builder
└── watcher.ts # File watcher using chokidarKey Components
- Parser: YAML frontmatter parser with
#{}placeholder extraction, automatically skips fenced code blocks - Watcher: Monitors directory and notifies of changes
- Server: Registers tools and prompts dynamically, executes template rendering
Environment Variables
COMMANDS_DIR: Directory to watch for template files (default:~/.cursor/command-publisherand./.cursor/command-publisher)
File Watching Behavior
- Initial scan loads all existing
.mdfiles - File changes are detected with a 300ms stability threshold (waits for write to complete)
- Supports: add, modify, and delete operations
- Only
.mdfiles are processed
Error Handling
- Invalid template syntax is logged to stderr but doesn't crash the server
- Missing required arguments are reported as MCP errors
- File read errors are caught and logged
- Graceful shutdown on SIGINT (Ctrl+C)
Performance Characteristics
- Startup: O(n) where n = number of template files
- File Change: O(1) to re-register affected tool
- Tool Execution: O(1) template substitution
- Memory: Minimal, stores only parsed templates
Limitations
- Templates are text-based and returned as plain strings
- No built-in validation of substituted values
- Variable names are case-sensitive
- No template inheritance or includes (by design, keep it lean)
Future Enhancements
- Template validation schemas
- Nested templates or includes
- Multiple output formats (JSON, XML, etc.)
- Pre/post-processing hooks
- Template caching and optimization
- Conditional blocks based on the value of the param
License
MIT
