- name
- mcp-server-bash-sdk
- description
- Build lightweight MCP servers in pure Bash with zero runtime overhead for AI tool integration
- triggers
- ["create an MCP server in bash","implement MCP protocol with shell scripts","build a bash MCP server","add tools to bash MCP server","configure MCP server in shell","write MCP tool functions in bash","debug bash MCP server","integrate bash MCP with Claude"]
# MCP Server Bash SDK
> Skill by [ara.so](https://ara.so) — MCP Skills collection.
## Overview
The MCP Server Bash SDK is a lightweight, zero-overhead implementation of the Model Context Protocol (MCP) server in pure Bash. It allows you to create MCP servers without Node.js, Python, or other heavy runtimes—just Bash and `jq` for JSON processing. The SDK handles JSON-RPC 2.0 protocol communication over stdio while you focus on implementing tool functions.
**Key Benefits:**
- Zero runtime overhead compared to Node.js/Python
- Simple function-based tool definition
- Automatic tool discovery via naming convention
- External JSON configuration for tools and server metadata
- Perfect for API wrappers and system utilities
## Installation
### Requirements
- Bash shell (4.0+)
- `jq` for JSON processing
Install `jq`:
```bash
# macOS
brew install jq
# Ubuntu/Debian
sudo apt-get install jq
# RHEL/CentOS
sudo yum install jq
```
### Clone and Setup
```bash
git clone https://github.com/muthuishere/mcp-server-bash-sdk
cd mcp-server-bash-sdk
chmod +x mcpserver_core.sh moviemcpserver.sh
```
### Test Installation
```bash
echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_movies"}, "id": 1}' | ./moviemcpserver.sh
```
## Core Concepts
### Architecture
- **mcpserver_core.sh**: Protocol layer handling JSON-RPC and MCP communication
- **Your server script**: Business logic with `tool_*` functions
- **assets/**: JSON configuration files for tools and server metadata
- **Communication**: JSON-RPC 2.0 over stdio
### Tool Function Contract
All tool functions must follow these rules:
1. **Naming**: Prefix with `tool_` + exact name from `tools_list.json`
2. **Parameters**: Accept single parameter `$1` containing JSON arguments
3. **Success**: Echo result and `return 0`
4. **Failure**: Echo error message and `return 1`
5. **Discovery**: Automatically exposed based on `tools_list.json`
## Creating Your First MCP Server
### Step 1: Create Server Script
Create `weatherserver.sh`:
```bash
#!/bin/bash
# Override configuration paths BEFORE sourcing core
MCP_CONFIG_FILE="$(dirname "${BASH_SOURCE[0]}")/assets/weatherserver_config.json"
MCP_TOOLS_LIST_FILE="$(dirname "${BASH_SOURCE[0]}")/assets/weatherserver_tools.json"
MCP_LOG_FILE="$(dirname "${BASH_SOURCE[0]}")/logs/weatherserver.log"
# Source the MCP server core
source "$(dirname "${BASH_SOURCE[0]}")/mcpserver_core.sh"
# Access environment variables
API_KEY="${WEATHER_API_KEY:-}"
BASE_URL="${WEATHER_API_URL:-https://api.openweathermap.org/data/2.5}"
# Tool: Get current weather
tool_get_weather() {
local args="$1"
local location=$(echo "$args" | jq -r '.location')
# Validate required parameters
if [[ -z "$location" ]]; then
echo "Missing required parameter: location"
return 1
fi
if [[ -z "$API_KEY" ]]; then
echo "WEATHER_API_KEY environment variable not set"
return 1
fi
# Call external API
local response=$(curl -s "${BASE_URL}/weather?q=${location}&appid=${API_KEY}&units=metric")
# Check for API errors
local cod=$(echo "$response" | jq -r '.cod')
if [[ "$cod" != "200" ]]; then
local message=$(echo "$response" | jq -r '.message // "API request failed"')
echo "Weather API error: $message"
return 1
fi
# Return formatted result
echo "$response" | jq '{
location: .name,
temperature: .main.temp,
description: .weather[0].description,
humidity: .main.humidity
}'
return 0
}
# Tool: Get weather forecast
tool_get_forecast() {
local args="$1"
local location=$(echo "$args" | jq -r '.location')
local days=$(echo "$args" | jq -r '.days // 3')
if [[ -z "$location" ]]; then
echo "Missing required parameter: location"
return 1
fi
# Call forecast API
local response=$(curl -s "${BASE_URL}/forecast?q=${location}&appid=${API_KEY}&units=metric&cnt=$((days * 8))")
echo "$response" | jq '{
location: .city.name,
forecast: [.list[] | {
date: .dt_txt,
temp: .main.temp,
description: .weather[0].description
}]
}'
return 0
}
# Start the MCP server
run_mcp_server "$@"
```
### Step 2: Create Tools Definition
Create `assets/weatherserver_tools.json`:
```json
{
"tools": [
{
"name": "get_weather",
"description": "Get current weather conditions for a specified location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name (e.g., 'London', 'New York') or coordinates"
}
},
"required": ["location"]
}
},
{
"name": "get_forecast",
"description": "Get weather forecast for the next few days",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or coordinates"
},
"days": {
"type": "integer",
"description": "Number of days to forecast (1-5)",
"default": 3
}
},
"required": ["location"]
}
}
]
}
```
### Step 3: Create Server Configuration
Create `assets/weatherserver_config.json`:
```json
{
"protocolVersion": "2025-03-26",
"serverInfo": {
"name": "WeatherServer",
"version": "1.0.0"
},
"capabilities": {
"tools": {
"listChanged": true
}
},
"instructions": "Provides weather information and forecasts using OpenWeatherMap API. Requires WEATHER_API_KEY environment variable."
}
```
### Step 4: Make Executable and Test
```bash
chmod +x weatherserver.sh
# Test tool call
echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_weather", "arguments": {"location": "London"}}, "id": 1}' | WEATHER_API_KEY=your_key ./weatherserver.sh
# Test tools list
echo '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}' | ./weatherserver.sh
```
## MCP Protocol Methods
### Initialize
```bash
echo '{"jsonrpc": "2.0", "method": "initialize", "params": {"protocolVersion": "2025-03-26", "capabilities": {}}, "id": 1}' | ./weatherserver.sh
```
### List Tools
```bash
echo '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}' | ./weatherserver.sh
```
### Call Tool
```bash
echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_weather", "arguments": {"location": "Paris"}}, "id": 1}' | ./weatherserver.sh
```
### List Prompts (if configured)
```bash
echo '{"jsonrpc": "2.0", "method": "prompts/list", "id": 1}' | ./weatherserver.sh
```
## Configuration
### Environment Variables
Access environment variables in your tool functions:
```bash
# In your server script
API_KEY="${MY_API_KEY:-default_value}"
BASE_URL="${MY_BASE_URL:-https://api.example.com}"
DEBUG="${MCP_DEBUG:-false}"
tool_example() {
local args="$1"
if [[ "$DEBUG" == "true" ]]; then
echo "Debug: Processing with API key: ${API_KEY:0:5}..." >&2
fi
# Use environment variables in API calls
curl -H "Authorization: Bearer $API_KEY" "$BASE_URL/endpoint"
}
```
### Custom Configuration Paths
Override default paths before sourcing core:
```bash
#!/bin/bash
# Custom paths
MCP_CONFIG_FILE="/custom/path/config.json"
MCP_TOOLS_LIST_FILE="/custom/path/tools.json"
MCP_LOG_FILE="/var/log/myserver.log"
source "$(dirname "${BASH_SOURCE[0]}")/mcpserver_core.sh"
```
### Logging
Enable debug logging:
```bash
# Set log file path
MCP_LOG_FILE="./logs/debug.log"
# Logs are written to stderr and optionally to file
# Check logs while running
tail -f ./logs/debug.log
```
## Integration with AI Assistants
### VS Code with GitHub Copilot
Add to `.vscode/settings.json`:
```json
{
"mcp": {
"servers": {
"weather-server": {
"type": "stdio",
"command": "/absolute/path/to/weatherserver.sh",
"args": [],
"env": {
"WEATHER_API_KEY": "your-api-key",
"MCP_DEBUG": "false"
}
}
}
}
}
```
### Claude Desktop
Add to Claude config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"weather-server": {
"command": "/absolute/path/to/weatherserver.sh",
"args": [],
"env": {
"WEATHER_API_KEY": "your-api-key"
}
}
}
}
```
### Testing with Copilot Chat
```
@workspace /mcp weather-server get weather for Tokyo
```
## Common Patterns
### Pattern: External API Wrapper
```bash
#!/bin/bash
source "$(dirname "${BASH_SOURCE[0]}")/mcpserver_core.sh"
API_TOKEN="${GITHUB_TOKEN:-}"
API_BASE="https://api.github.com"
tool_get_repo_info() {
local args="$1"
local owner=$(echo "$args" | jq -r '.owner')
local repo=$(echo "$args" | jq -r '.repo')
if [[ -z "$owner" ]] || [[ -z "$repo" ]]; then
echo "Missing required parameters: owner and repo"
return 1
fi
local response=$(curl -s -H "Authorization: token $API_TOKEN" \
"${API_BASE}/repos/${owner}/${repo}")
在 GitHub 查看