A TypeScript CLI tool that automatically boots a local MCP server from a specific folder and exposes tools via a predefined API. Supports both JavaScript and TypeScript tools with no build step required.
Run directly with Bun (no installation required):
# Run directly
bunx @rmcp/cli
# Or install globally
bun install -g @rmcp/cli# Use default ./rmcp-tools folder
bunx @rmcp/cli
# Or specify a custom folder
bunx @rmcp/cli <folder>By default, rmcp looks for tools in the ./rmcp-tools directory in your current working directory. You can override this by providing a folder path as the first argument.
-n, --name <name>: Server name (default: "rmcp")-s, --server-version <version>: Server version (default: "1.0.0")-a, --addTool [toolName]: Generate a new tool file (default: "example-tool")-g, --globalToolsPath [path]: Use global tools directory (optional path overridesRMCP_GLOBAL_TOOLS_PATHenv var and default)
# Start server with tools from default ./rmcp-tools folder
bunx @rmcp/cli
# Start server with tools from ./my-tools folder
bunx @rmcp/cli ./my-tools
# Start with custom name and server version
bunx @rmcp/cli ./my-tools --name "my-server" --server-version "2.0.0"
# Use global tools (from ~/.rmcp-tools by default)
bunx @rmcp/cli -g
# Use custom global tools path
bunx @rmcp/cli -g ~/my-global-tools
# Development mode
bun run src/cli.tsTools must export a default object that implements this interface:
export interface Tool<S extends TSchema = TSchema, Ctx = unknown> {
readonly name: string;
readonly description?: string;
readonly inputSchema: S;
readonly run: (args: StaticDecode<S>, ctx: Ctx) => Promise<string>;
}const { Type } = require('@sinclair/typebox');
const myTool = {
name: 'echo',
description: 'Echoes back the input message',
inputSchema: Type.Object({
message: Type.String({ description: 'The message to echo back' })
}),
run: async (args, ctx) => {
return `Echo: ${args.message}`;
}
};
module.exports = { default: myTool };import { Type, StaticDecode } from '@sinclair/typebox';
import { Tool } from '../src/types.js';
const timestampSchema = Type.Object({
format: Type.Optional(
Type.Union(
[Type.Literal('iso'), Type.Literal('unix'), Type.Literal('readable')],
{ description: 'Format for the timestamp', default: 'iso' }
)
)
});
const timestampTool: Tool<typeof timestampSchema> = {
name: 'timestamp',
description: 'Returns the current timestamp in various formats',
inputSchema: timestampSchema,
run: async (args: StaticDecode<typeof timestampSchema>, _ctx) => {
const now = new Date();
switch (args.format) {
case 'unix':
return `Unix timestamp: ${Math.floor(now.getTime() / 1000)}`;
case 'readable':
return `Readable: ${now.toLocaleString()}`;
case 'iso':
default:
return `ISO timestamp: ${now.toISOString()}`;
}
}
};
export default timestampTool;Once running, add the server to your Claude/Cursor MCP configuration:
{
"mcpServers": {
"rmcp": {
"command": "bunx",
"args": ["@rmcp/cli"]
}
}
}{
"mcpServers": {
"rmcp-dev": {
"command": "bun",
"args": ["run", "/path/to/rmcp/src/cli.ts"]
}
}
}{
"mcpServers": {
"rmcp": {
"command": "bunx",
"args": ["@rmcp/cli", "/path/to/your/tools/folder"]
}
}
}{
"mcpServers": {
"rmcp": {
"command": "bunx",
"args": ["@rmcp/cli", "-g", "/path/to/your/global/tools/folder"]
}
}
}- ✅ No Build Step: TypeScript tools run directly with Bun
- ✅ Default Folder: Uses
./rmcp-toolsby default - ✅ Mixed Languages: Support for both JS and TS tools in the same folder
- ✅ Type Safety: Full TypeScript support with proper typing
- ✅ Auto Discovery: Automatically finds and loads all
.js,.ts, and.mjsfiles - ✅ Error Handling: Graceful error handling for malformed tools
The --addTool option provides an intelligent tool generator that creates new tool files based on your project setup. It automatically detects your project type and generates appropriate templates.
# Generate a local tool with default name "example-tool"
bunx @rmcp/cli --addTool
# Generate a tool with custom name
bunx @rmcp/cli --addTool my-custom-tool
# Generate a global tool
bunx @rmcp/cli --addTool my-global-tool -g
# Generate in specific folder
bunx @rmcp/cli ./my-tools --addTool my-toolThe generator automatically detects your project setup and creates appropriate files:
Generated when no package.json exists or TypeScript support is not detected:
- Creates a
.jsfile - No external dependencies
- Self-contained implementation
Generated when TypeScript support is detected (via tsconfig.json or TypeScript dependency):
- Creates a
.tsfile - Proper type imports
- Automatically installs
@rmcp/clidependency if needed
When running inside the rmcp repository itself:
- Uses relative imports to local type definitions
- No dependency installation needed
Tool names must follow these conventions:
- kebab-case format only:
my-tool,data-processor,api-client - Lowercase letters and hyphens only
- Cannot use reserved names:
index,cli,server,types,tool-discovery,mcp-server
The generator automatically detects and uses your preferred package manager:
- Bun: Detects
bun.lockb - pnpm: Detects
pnpm-lock.yaml - Yarn: Detects
yarn.lock - npm: Detects
package-lock.json(default fallback)
The generator prevents naming conflicts:
- Checks existing tool files in the target directory
- Compares names case-insensitively
- Provides clear error messages with suggestions
RMCP supports global tools that can be shared across all your projects. Global tools are automatically discovered and merged with local tools, with local tools taking precedence in case of name conflicts.
Option 1: Default Location
# Tools in ~/.rmcp-tools are automatically discovered
bunx @rmcp/cliOption 2: Environment Variable
# Set global tools path via environment variable
export RMCP_GLOBAL_TOOLS_PATH=~/my-global-tools
bunx @rmcp/cliOption 3: CLI Flag
# Specify global tools path directly (overrides env var and default)
bunx @rmcp/cli -g ~/custom-global-toolsRMCP always checks for global tools and gracefully falls back to local-only discovery:
- ✅ Global directory exists → Multi-source discovery (global + local tools)
- ✅ No global directory → Single-source discovery (local tools only)
- ✅ Local tools override global → Conflict resolution with local precedence
When global tools are found, RMCP shows detailed source information:
🔍 Discovering tools...
✅ Found 2 global + 3 local tools (5 total)
🌐 Global tools from: /Users/user/.rmcp-tools (default)
📋 Tool Details:
🌐 Global tools:
• auth-helper: Authentication utility tool
• data-formatter: Format data in various formats
📁 Local tools:
• project-deploy: Deploy this specific project (overrides global)
• test-runner: Run project tests
• build-tool: Build project assetsCreate tools directly in your global directory:
# Create global tool in default location (~/.rmcp-tools)
bunx @rmcp/cli --addTool my-global-tool -g
# Create global tool in custom location
bunx @rmcp/cli --addTool auth-helper -g ~/my-global-tools
# Create global tool using environment variable path
export RMCP_GLOBAL_TOOLS_PATH=~/shared-tools
bunx @rmcp/cli --addTool shared-utility -gThe first time you create a global tool, RMCP will:
- Create the global directory if it doesn't exist
- Interactively prompt you to choose between TypeScript or CommonJS setup
- Initialize it as a proper Node.js project (
package.json,tsconfig.jsonfor TypeScript) - Automatically install dependencies using your preferred package manager
RMCP follows this precedence order for determining the global tools path:
- CLI Flag:
-g ~/custom-path(highest priority) - Environment Variable:
RMCP_GLOBAL_TOOLS_PATH=~/env-path - Default:
~/.rmcp-tools(lowest priority)
# Install dependencies
bun install
# Run directly
bun run src/cli.ts
# Test with example tools
bun run src/cli.ts ./rmcp-tools# Install dependencies
npm install
# Build
npm run build
# Development mode (watch)
npm run dev
# Lint
npm run lint
# Type check
npm run typecheck