Skip to main content
Glama
mqasim7

MCP Secure Server

by mqasim7
README.md
# MCP Secure Server

A secure Model Context Protocol (MCP) server implementation with HMAC-signed token authentication, rate limiting, and comprehensive audit logging.

## Features

### šŸ”’ Security
- **HMAC-signed API tokens** with expiration and scope-based access control
- **Rate limiting** (configurable, default: 60 requests/minute)
- **Timestamp validation** to prevent replay attacks (5-minute window)
- **Comprehensive audit logging** for all operations
- **Secrets management** via environment variables

### šŸ› ļø Tools
- **ping** - Returns server status and timestamp
- **search_records** - Query a local dataset with filtering options
- **create_integration** - Persist integration configurations locally

### šŸ“Š Monitoring & Observability
- Structured logging with Winston
- Audit trail for security events
- Rate limiting headers
- Health check endpoint

## Quick Start

### 1. Installation

```bash
git clone <repository-url>
cd mcp-secure-server
npm install
```

### 2. Environment Setup

```bash
cp .env.example .env
# Edit .env with your configuration
```

**Important**: Change the default secrets in production!

### 3. Initialize Data Directories

```bash
npm run setup
```

### 4. Development

```bash
# Start in development mode
npm run dev

# Or build and start
npm run build
npm start
```

The server will start on `http://localhost:3000` (configurable via `PORT` environment variable).

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `PORT` | Server port | `3000` |
| `NODE_ENV` | Environment | `development` |
| `JWT_SECRET` | JWT signing secret | āš ļø **Change in production** |
| `HMAC_SECRET` | HMAC signing secret | āš ļø **Change in production** |
| `TOKEN_EXPIRY` | Token expiration (seconds) | `3600` |
| `MAX_TOKEN_AGE_MINUTES` | Max token age for replay protection | `5` |
| `RATE_LIMIT_WINDOW_MS` | Rate limit window | `60000` |
| `RATE_LIMIT_MAX_REQUESTS` | Max requests per window | `60` |
| `RECORDS_PATH` | Path to records dataset | `./data/records.json` |
| `INTEGRATIONS_PATH` | Path to integrations storage | `./data/integrations.json` |
| `LOG_LEVEL` | Logging level | `info` |
| `AUDIT_LOG_FILE` | Audit log file path | `./logs/audit.log` |

## API Documentation

### Authentication

All MCP endpoints require a Bearer token in the Authorization header:

```
Authorization: Bearer <your-token>
```

### Generate Token

Generate a new API token:

```bash
POST /auth/token
Content-Type: application/json

{
  "userId": "your-user-id",
  "scope": "read" // or "write"
}
```

**Response:**
```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "userId": "your-user-id",
  "scope": "read",
  "expiresIn": 3600
}
```

### Health Check

Check server status (no authentication required):

```bash
GET /health
```

**Response:**
```json
{
  "status": "ok",
  "timestamp": "2024-03-07T10:30:00.000Z",
  "version": "1.0.0"
}
```

### List Tools

Get available tools:

```bash
POST /mcp/tools/list
Content-Type: application/json
Authorization: Bearer <token>

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}
```

**Response:**
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "ping",
        "description": "Returns server status and current timestamp",
        "inputSchema": {
          "type": "object",
          "properties": {},
          "required": []
        }
      },
      // ... other tools
    ]
  }
}
```

### Tool Execution

Execute a tool:

```bash
POST /mcp/tools/call
Content-Type: application/json
Authorization: Bearer <token>

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "<tool-name>",
  "params": { /* tool-specific parameters */ }
}
```

## Tools Reference

### 1. ping

Returns server status and timestamp.

**Scope Required:** Any (read/write)

**Parameters:** None

**Example:**
```bash
curl -X POST http://localhost:3000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "ping",
    "params": {}
  }'
```

**Response:**
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "status": "ok",
    "timestamp": "2024-03-07T10:30:00.000Z",
    "serverTime": 1709810200000,
    "uptime": 3600.5,
    "version": "1.0.0"
  }
}
```

### 2. search_records

Search through local dataset records.

**Scope Required:** read or write

**Parameters:**
- `query` (optional): Text search query
- `category` (optional): Filter by category
- `tags` (optional): Array of tags to filter by (AND operation)
- `limit` (optional): Maximum results (1-100, default: 10)

**Example:**
```bash
curl -X POST http://localhost:3000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "search_records",
    "params": {
      "query": "API",
      "category": "Security",
      "tags": ["auth", "jwt"],
      "limit": 5
    }
  }'
```

**Response:**
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "records": [
      {
        "id": "rec_002",
        "name": "User Authentication Service",
        "description": "OAuth2 and JWT-based authentication service",
        "category": "Security",
        "tags": ["auth", "oauth2", "jwt", "security"],
        "data": { /* ... */ },
        "createdAt": "2024-01-10T09:15:00.000Z",
        "updatedAt": "2024-02-10T16:45:00.000Z"
      }
    ],
    "total": 1,
    "query": "API",
    "filters": {
      "category": "Security",
      "tags": ["auth", "jwt"]
    }
  }
}
```

### 3. create_integration

Create and persist a new integration configuration.

**Scope Required:** write

**Parameters:**
- `name` (required): Integration name (1-100 chars)
- `type` (required): One of: `webhook`, `api`, `database`, `file`, `custom`
- `config` (required): Configuration object (type-specific validation)

**Type-specific config requirements:**
- `webhook`: `config.url` (string)
- `api`: `config.endpoint` (string)
- `database`: `config.connectionString` (string)
- `file`: `config.path` (string)
- `custom`: any object

**Example:**
```bash
curl -X POST http://localhost:3000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <write-token>" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "create_integration",
    "params": {
      "name": "Payment Webhook",
      "type": "webhook",
      "config": {
        "url": "https://api.example.com/webhooks/payments",
        "method": "POST",
        "headers": {
          "Authorization": "Bearer secret",
          "Content-Type": "application/json"
        },
        "retries": 3
      }
    }
  }'
```

**Response:**
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "integration": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Payment Webhook",
      "type": "webhook",
      "config": {
        "url": "https://api.example.com/webhooks/payments",
        "method": "POST",
        "headers": { /* ... */ },
        "retries": 3
      },
      "createdAt": "2024-03-07T10:30:00.000Z",
      "updatedAt": "2024-03-07T10:30:00.000Z",
      "userId": "your-user-id"
    },
    "message": "Integration created successfully"
  }
}
```

## Security Features

### HMAC Token Authentication

Tokens are JWT-signed with an additional HMAC signature for enhanced security:

1. **JWT Layer**: Standard JWT with RSA/HMAC signing
2. **HMAC Layer**: Additional HMAC-SHA256 signature of the payload
3. **Double Verification**: Both signatures must be valid

### Scope-based Access Control

- **read**: Can access `ping` and `search_records`
- **write**: Can access all tools including `create_integration`

### Replay Attack Protection

- Tokens include creation timestamp
- Requests are rejected if token is older than `MAX_TOKEN_AGE_MINUTES` (default: 5 minutes)
- Use fresh tokens for each session

### Rate Limiting

- Per-token rate limiting using token hash
- Configurable limits via environment variables
- Rate limit headers included in responses:
  - `X-RateLimit-Limit`
  - `X-RateLimit-Remaining`
  - `X-RateLimit-Reset`

### Audit Logging

All operations are logged with:
- Timestamp
- User ID
- Tool/method called
- Success/failure status
- Response latency
- Error details (if any)
- Client IP (if available)

Audit logs are stored separately from application logs for security compliance.

## Testing

### Automated Test Suite

Run the comprehensive test suite:

```bash
# Run all tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch
```

### Postman Collection

A complete Postman collection is available for API testing:

šŸ“ **`postman/`** directory contains:
- `MCP-Secure-Server.postman_collection.json` - 25+ API requests
- `MCP-Server-Environment.postman_environment.json` - Environment setup
- `README.md` - Detailed usage instructions

**Quick Setup:**
1. Import both files into Postman
2. Start the server: `npm start`
3. Run the collection for automated testing

**Features:**
- āœ… 60+ automated test assertions
- āœ… Complete security testing scenarios
- āœ… Authentication & authorization tests
- āœ… Rate limiting validation
- āœ… Error handling verification
- āœ… JSON-RPC 2.0 compliance checks

### Test Coverage

The test suite covers:
- āœ… Token generation and validation
- āœ… HMAC signature verification
- āœ… Expired token rejection
- āœ… Replay attack protection
- āœ… Scope validation
- āœ… Rate limiting
- āœ… All tool functionality
- āœ… Error handling
- āœ… Integration tests

## Sample Requests

### Complete Workflow Example

```bash
# 1. Generate a read token
READ_TOKEN=$(curl -s -X POST http://localhost:3000/auth/token \
  -H "Content-Type: application/json" \
  -d '{"userId": "demo-user", "scope": "read"}' | \
  jq -r '.token')

# 2. Generate a write token
WRITE_TOKEN=$(curl -s -X POST http://localhost:3000/auth/token \
  -H "Content-Type: application/json" \
  -d '{"userId": "demo-user", "scope": "write"}' | \
  jq -r '.token')

# 3. List available tools
curl -X POST http://localhost:3000/mcp/tools/list \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $READ_TOKEN" \
  -d '{"jsonrpc": "2.0", "id": 1}'

# 4. Ping the server
curl -X POST http://localhost:3000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $READ_TOKEN" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "ping", "params": {}}'

# 5. Search for API-related records
curl -X POST http://localhost:3000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $READ_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "search_records",
    "params": {"query": "API", "limit": 3}
  }'

# 6. Create an integration (requires write token)
curl -X POST http://localhost:3000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $WRITE_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "create_integration",
    "params": {
      "name": "Demo API Integration",
      "type": "api",
      "config": {
        "endpoint": "https://jsonplaceholder.typicode.com/posts",
        "method": "GET",
        "timeout": 5000
      }
    }
  }'
```

## Development

### Project Structure

```
mcp-secure-server/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ auth/           # Authentication logic
│   ā”œā”€ā”€ middleware/     # Express middleware
│   ā”œā”€ā”€ tools/          # MCP tools implementation
│   ā”œā”€ā”€ types/          # TypeScript type definitions
│   ā”œā”€ā”€ utils/          # Utilities (config, logging)
│   ā”œā”€ā”€ __tests__/      # Test files
│   └── index.ts        # Main server file
ā”œā”€ā”€ data/               # JSON data files
ā”œā”€ā”€ logs/               # Log files
ā”œā”€ā”€ .env.example        # Environment variables template
└── package.json
```

### Adding New Tools

1. Create tool implementation in `src/tools/`
2. Export tool schema and handler
3. Register in `src/index.ts`
4. Add tests in `src/__tests__/`

### Scripts

- `npm run dev` - Start development server with hot reload
- `npm run build` - Build TypeScript to JavaScript
- `npm start` - Start production server
- `npm test` - Run test suite
- `npm run lint` - Type check with TypeScript
- `npm run setup` - Initialize data directories and environment

## Security Best Practices

1. **Change default secrets** in production environments
2. **Use HTTPS** in production
3. **Set strong environment variables** for JWT and HMAC secrets
4. **Monitor audit logs** regularly
5. **Implement additional rate limiting** at reverse proxy level
6. **Regularly rotate secrets**
7. **Use scoped tokens** - generate read tokens for read-only operations

## Production Deployment

1. Set `NODE_ENV=production`
2. Configure strong secrets in environment variables
3. Set up proper log rotation
4. Configure reverse proxy (nginx/Apache) with HTTPS
5. Set up monitoring and alerting
6. Implement backup strategies for data files

## License

MIT

## Contributing

1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request

## Support

For issues and questions, please use the GitHub issue tracker.