0brym/mcp
If you are the rightful owner of mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
A config-driven, modular MCP (Model Context Protocol) server with zero dependencies, designed for easy tool and plugin management through a JSON configuration file.
Modular MCP Server
A config-driven, modular MCP (Model Context Protocol) server with zero dependencies. Just edit a JSON config file to enable/disable tools and plugins!
Features
- Config-Driven: Enable/disable tools by editing
config.json - Zero Dependencies: Pure Node.js (18+), no npm packages needed
- Plugin Architecture: Easy to add new plugins
- Security: Built-in access controls and sandboxing per tool
- Simple: ~500 lines of core code
- Fast: Minimal overhead, direct tool execution
Quick Start
# 1. Create or edit config.json
cp config.example.json config.json
# 2. Start the server
node server.js
# Or specify a config file
node server.js my-config.json
How It Works
Config File Structure
The config.json file controls everything:
{
"server": {
"name": "my-mcp-server",
"version": "1.0.0"
},
"plugins": [
{
"name": "utils",
"type": "builtin",
"module": "utils",
"enabled": true,
"tools": [
{
"name": "echo",
"enabled": true
},
{
"name": "calculate",
"enabled": true
}
]
}
]
}
That's it! No code changes needed to add/remove tools.
Adding a Tool
Want to enable file operations? Just edit the config:
{
"plugins": [
{
"name": "filesystem",
"type": "builtin",
"module": "filesystem",
"enabled": true,
"tools": [
{
"name": "read_file",
"enabled": true,
"allowedPaths": [".", "/tmp"]
},
{
"name": "write_file",
"enabled": true
}
]
}
]
}
Restart the server - done!
Disabling a Tool
Set "enabled": false:
{
"name": "delete_file",
"enabled": false // ← Tool won't be available
}
Built-in Plugins
Filesystem Plugin
File and directory operations with path restrictions.
Tools:
read_file- Read file contentswrite_file- Write to fileslist_directory- List directory contentsfile_info- Get file metadatadelete_file- Delete files
Config Options:
{
"name": "read_file",
"enabled": true,
"allowedPaths": [".", "/tmp"], // Restrict access
"readonly": false // Make filesystem readonly
}
Shell Plugin
Execute shell commands with whitelist/blacklist support.
Tools:
exec_command- Execute shell commands
Config Options:
{
"name": "exec_command",
"enabled": true,
"allowedCommands": ["ls", "pwd", "cat"], // Whitelist
"blockedCommands": ["rm", "sudo"], // Blacklist
"maxBuffer": 1048576 // 1MB output limit
}
HTTP Plugin
Make HTTP requests with domain restrictions.
Tools:
http_get- GET requestshttp_post- POST requests
Config Options:
{
"name": "http_get",
"enabled": true,
"allowedDomains": ["api.github.com", "example.com"]
}
Utils Plugin
Utility functions for common tasks.
Tools:
echo- Echo back input (testing)calculate- Safe math evaluationtimestamp- Get current timebase64_encode- Base64 encodingbase64_decode- Base64 decoding
Creating Custom Plugins
1. Create Plugin File
// plugins/my-plugin.js
export default {
// Optional initialization
async init(config) {
console.log('Plugin initialized:', config);
},
tools: {
my_tool: {
description: 'Description of what this tool does',
inputSchema: {
type: 'object',
properties: {
input: {
type: 'string',
description: 'Input parameter'
}
},
required: ['input']
},
async execute(args, config) {
// args = input parameters
// config = tool-specific config from config.json
return `Result: ${args.input}`;
}
}
}
};
2. Add to Config
{
"plugins": [
{
"name": "my-plugin",
"type": "builtin",
"module": "my-plugin",
"enabled": true,
"tools": [
{
"name": "my_tool",
"enabled": true,
"customOption": "value"
}
]
}
]
}
3. Restart Server
That's it! Your tool is now available.
External Plugins
Load plugins from outside the project:
{
"plugins": [
{
"name": "external-plugin",
"type": "external",
"module": "/absolute/path/to/plugin.js",
"enabled": true,
"tools": [...]
}
]
}
Security Features
Path Restrictions
{
"name": "read_file",
"allowedPaths": ["./data", "/tmp"] // Only these paths accessible
}
Command Whitelisting
{
"name": "exec_command",
"allowedCommands": ["ls", "cat", "grep"] // Only these commands
}
Domain Filtering
{
"name": "http_get",
"allowedDomains": ["trusted-api.com"] // Only these domains
}
Read-Only Mode
{
"name": "write_file",
"readonly": true // Prevent writes
}
Configuration Reference
Server Config
{
"server": {
"name": "server-name", // MCP server name
"version": "1.0.0" // Server version
}
}
Plugin Config
{
"name": "plugin-name", // Unique plugin identifier
"type": "builtin", // "builtin" or "external"
"module": "plugin-file", // Plugin file/path
"enabled": true, // Enable/disable entire plugin
"required": false, // Fail if plugin can't load
"tools": [...] // Array of tool configs
}
Tool Config
{
"name": "tool-name", // Tool identifier
"enabled": true, // Enable/disable this tool
// ... custom options passed to tool's execute()
}
Examples
Example 1: Read-Only Filesystem
{
"plugins": [
{
"name": "filesystem",
"type": "builtin",
"module": "filesystem",
"enabled": true,
"tools": [
{
"name": "read_file",
"enabled": true,
"allowedPaths": ["/var/log"]
},
{
"name": "list_directory",
"enabled": true
}
]
}
]
}
Example 2: Safe Shell Access
{
"plugins": [
{
"name": "shell",
"type": "builtin",
"module": "shell",
"enabled": true,
"tools": [
{
"name": "exec_command",
"enabled": true,
"allowedCommands": ["ls", "pwd", "cat", "grep", "find"],
"blockedCommands": ["rm", "sudo", "su"],
"maxBuffer": 1048576
}
]
}
]
}
Example 3: HTTP API Client
{
"plugins": [
{
"name": "http",
"type": "builtin",
"module": "http",
"enabled": true,
"tools": [
{
"name": "http_get",
"enabled": true,
"allowedDomains": [
"api.github.com",
"httpbin.org"
]
}
]
}
]
}
Testing
Using MCP Inspector
# Install MCP Inspector
npm install -g @modelcontextprotocol/inspector
# Test your server
mcp-inspector node server.js
Manual Testing
Send JSON-RPC requests via stdin:
# Initialize
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | node server.js
# List tools
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | node server.js
# Call a tool
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"message":"Hello!"}}}' | node server.js
Logging
Control log level via environment variable:
# Debug mode
LOG_LEVEL=DEBUG node server.js
# Quiet mode
LOG_LEVEL=ERROR node server.js
Log levels: ERROR, WARN, INFO (default), DEBUG
Architecture
┌─────────────────────────────────────┐
│ MCP Client (Claude) │
└─────────────┬───────────────────────┘
│ JSON-RPC over stdio
┌─────────────▼───────────────────────┐
│ core/mcp-protocol.js │
│ (JSON-RPC handler, stdio I/O) │
└─────────────┬───────────────────────┘
│
┌─────────────▼───────────────────────┐
│ core/plugin-manager.js │
│ (Loads plugins from config.json) │
└─────────────┬───────────────────────┘
│
┌───────┴───────┬─────────────┐
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌──▼────┐
│filesystem │ │ shell │ │ http │
│ plugin │ │ plugin │ │ plugin│
└───────────┘ └─────────────┘ └───────┘
Files
.
├── server.js # Entry point
├── config.json # Your configuration
├── config.example.json # Example config
├── package.json # Project metadata
├── core/
│ ├── mcp-protocol.js # MCP/JSON-RPC implementation
│ ├── plugin-manager.js # Plugin loader
│ └── logger.js # Logging utility
├── plugins/
│ ├── filesystem.js # File operations
│ ├── shell.js # Shell commands
│ ├── http.js # HTTP requests
│ └── utils.js # Utilities
└── README.md # This file
FAQ
Q: How do I add a new tool?
A: Edit config.json and add the tool to a plugin's tools array. Restart the server.
Q: Can I create my own plugins?
A: Yes! Create a .js file in plugins/ following the plugin structure, then reference it in config.json.
Q: How do I restrict file access?
A: Use the allowedPaths option in the filesystem tool config.
Q: Is this secure?
A: It has built-in security features (path restrictions, command whitelisting, etc.), but treat it like any tool that executes code - configure it carefully and run with appropriate permissions.
Q: Can I use this in production?
A: Yes, but review the security settings carefully. Consider running in a container or with restricted user permissions.
License
MIT
Contributing
Contributions welcome! The codebase is intentionally simple and zero-dependency to keep it maintainable.