home / skills / meriley / claude-code-skills / mcp-server-reviewing

mcp-server-reviewing skill

/skills/mcp-server-reviewing

npx playbooks add skill meriley/claude-code-skills --skill mcp-server-reviewing

Review the files below or copy the command above to add this skill to your agents.

Files (4)
SKILL.md
12.0 KB
---
name: mcp-server-reviewing
description: Audits MCP servers for security vulnerabilities, missing validation, error handling issues, and production readiness. Use when reviewing MCP PRs or auditing server quality.
version: 1.0.0
---

# MCP Server Reviewing

## Purpose

Audit MCP (Model Context Protocol) servers for security issues, architectural violations, missing validation, and production readiness. Ensure servers follow SDK best practices.

## When to Use This Skill

- Reviewing MCP server code in PRs
- Auditing existing MCP servers for quality
- Pre-release security and quality checks
- Verifying MCP servers follow best practices

## When NOT to Use This Skill

- Writing new MCP servers (use **mcp-server-writing**)
- General TypeScript/Python code review (use language-specific reviewers)
- Reviewing non-MCP server code

---

## Severity Classification

| Severity     | Description                                                  | Action                    |
| ------------ | ------------------------------------------------------------ | ------------------------- |
| **CRITICAL** | Security vulnerabilities, secrets exposure, data leaks       | Block PR, fix immediately |
| **HIGH**     | Missing validation, error swallowing, transport violations   | Block PR, require fix     |
| **MEDIUM**   | Missing descriptions, poor error messages, logging issues    | Request fix before merge  |
| **LOW**      | Style issues, optimization opportunities, minor improvements | Suggest improvements      |

---

## Automated Detection Commands

Run these commands to detect common violations. Each command includes the violation code for reference.

### Security Violations (S1-S5)

**S1: Hardcoded Secrets**

```bash
grep -rn "api[_-]\?key\s*[:=]" --include="*.ts" --include="*.py" src/ | grep -v "process\.env\|os\.environ"
```

**S2: Console.log to stdout (breaks stdio transport)**

```bash
grep -rn "console\.log\|print(" --include="*.ts" --include="*.py" src/ | grep -v "console\.error\|sys\.stderr\|\.test\.\|\.spec\."
```

**S3: Missing ReDoS Protection**

```bash
grep -rn "new RegExp\|\.match\|\.replace\|\.split" --include="*.ts" --include="*.py" src/ | grep -v "safeInput\|MAX_INPUT"
```

**S4: Unsafe eval/exec**

```bash
grep -rn "eval(\|exec(\|Function(" --include="*.ts" --include="*.py" src/
```

**S5: SQL Injection Risk**

```bash
grep -rn "query.*\`\|execute.*f\"\|cursor\.execute.*%" --include="*.ts" --include="*.py" src/
```

### Architecture Violations (A1-A5)

**A1: Missing Tool Descriptions**

```bash
grep -rn "name:\s*['\"]" --include="*.ts" src/ -A 3 | grep -B 3 "inputSchema" | grep -v "description"
```

**A2: Missing inputSchema Property Descriptions**

```bash
grep -rn "properties:" --include="*.ts" src/ -A 10 | grep -E "type.*string|type.*number" | grep -v "description"
```

**A3: Tools Without Validation**

```bash
grep -rn "request\.params\|args\." --include="*.ts" src/ | grep -v "validate\|ajv\|zod\|schema"
```

**A4: Missing isError Flag**

```bash
grep -rn "content.*error\|success.*false" --include="*.ts" src/ | grep -v "isError"
```

**A5: Direct Response Without JSON**

```bash
grep -rn "text:.*\`" --include="*.ts" src/ | grep -v "JSON\.stringify"
```

### Error Handling Violations (E1-E5)

**E1: Empty Catch Blocks**

```bash
grep -rn "catch.*{" --include="*.ts" --include="*.py" src/ -A 2 | grep -E "^\s*}\s*$"
```

**E2: Swallowed Errors (catch without rethrow or return)**

```bash
grep -rn "catch" --include="*.ts" src/ -A 5 | grep -v "throw\|return\|logger\|console\.error"
```

**E3: Missing Error Context**

```bash
grep -rn "throw new Error\|raise.*Error" --include="*.ts" --include="*.py" src/ | grep -v ":\|context\|failed"
```

**E4: Generic Error Messages**

```bash
grep -rn "\"error\"\|\"Error\"\|\"failed\"" --include="*.ts" src/ | grep -v "suggestion\|field\|message"
```

**E5: Unhandled Promise Rejections**

```bash
grep -rn "\.then(" --include="*.ts" src/ | grep -v "\.catch\|await"
```

### Maintainability Violations (M1-M5)

**M1: Magic Numbers/Strings**

```bash
grep -rn "[0-9]\{4,\}\|timeout.*[0-9]" --include="*.ts" --include="*.py" src/ | grep -v "const\|MAX_\|MIN_\|DEFAULT_"
```

**M2: Missing Type Annotations (Python)**

```bash
grep -rn "def.*(" --include="*.py" src/ | grep -v "->.*:"
```

**M3: TODO/FIXME in Production Code**

```bash
grep -rn "TODO\|FIXME\|XXX\|HACK" --include="*.ts" --include="*.py" src/
```

**M4: Duplicate Tool Definitions**

```bash
grep -rn "name:\s*['\"]" --include="*.ts" src/ | cut -d: -f3 | sort | uniq -d
```

**M5: Inconsistent Error Response Format**

```bash
grep -rn "isError.*true" --include="*.ts" src/ -B 5 | grep "text:" | grep -v "success\|errors"
```

---

## Manual Review Checklist

### Security Review

- [ ] **S1**: No hardcoded API keys, passwords, or secrets
- [ ] **S2**: All logging goes to stderr (not stdout)
- [ ] **S3**: Input length limited before regex processing
- [ ] **S4**: No eval(), exec(), or dynamic code execution
- [ ] **S5**: Parameterized queries for any database access
- [ ] **S6**: Environment variables used for configuration
- [ ] **S7**: Sensitive data not logged (passwords, tokens, PII)

### Architecture Review

- [ ] **A1**: All tools have clear `description` fields
- [ ] **A2**: All inputSchema properties have `description`
- [ ] **A3**: Input validation before any processing
- [ ] **A4**: Error responses include `isError: true`
- [ ] **A5**: All responses are JSON-serialized
- [ ] **A6**: Resources use appropriate URI schemes
- [ ] **A7**: Prompts have clear argument descriptions

### Error Handling Review

- [ ] **E1**: No empty catch blocks
- [ ] **E2**: Errors logged or re-thrown, never swallowed
- [ ] **E3**: Error messages include context (what failed, why)
- [ ] **E4**: Error responses include `suggestion` field
- [ ] **E5**: Async operations properly awaited/handled
- [ ] **E6**: Graceful degradation for external dependencies

### Production Readiness Review

- [ ] **P1**: Structured logging with JSON format
- [ ] **P2**: Health check endpoint or mechanism
- [ ] **P3**: Configurable timeouts for external calls
- [ ] **P4**: Graceful shutdown handling
- [ ] **P5**: No debug/development code in production
- [ ] **P6**: Dependencies pinned to specific versions
- [ ] **P7**: Dockerfile or deployment configuration present

---

## Common Violations with Fixes

### S2: Logging to stdout (CRITICAL)

**Problem:** stdout is reserved for JSON-RPC messages. Logging there corrupts the transport.

```typescript
// ❌ BAD: Breaks MCP stdio transport
console.log("Processing request:", args);
```

```typescript
// ✅ GOOD: Log to stderr
console.error(
  JSON.stringify({
    timestamp: new Date().toISOString(),
    level: "INFO",
    message: "Processing request",
    context: { args_keys: Object.keys(args) },
  }),
);
```

### S3: Missing ReDoS Protection (HIGH)

**Problem:** Unbounded input to regex can cause catastrophic backtracking.

```typescript
// ❌ BAD: No input length limit
const matches = userInput.match(/complex.*pattern/);
```

```typescript
// ✅ GOOD: Limit input before regex
const MAX_INPUT_LENGTH = 50_000;
const safeInput = (text: string) =>
  text.length > MAX_INPUT_LENGTH ? text.slice(0, MAX_INPUT_LENGTH) : text;

const matches = safeInput(userInput).match(/complex.*pattern/);
```

### A1: Missing Tool Description (MEDIUM)

**Problem:** LLM can't understand when to use the tool.

```typescript
// ❌ BAD: No description
{
  name: "process_data",
  inputSchema: { type: "object", properties: { data: { type: "string" } } }
}
```

```typescript
// ✅ GOOD: Clear description explaining purpose and return value
{
  name: "process_data",
  description: "Validates and transforms input data according to specified format. Returns structured result with validation errors if any.",
  inputSchema: {
    type: "object",
    properties: {
      data: {
        type: "string",
        description: "Raw data string to process"
      },
      format: {
        type: "string",
        enum: ["json", "csv", "xml"],
        description: "Expected input format for validation"
      }
    },
    required: ["data", "format"]
  }
}
```

### A4: Missing isError Flag (HIGH)

**Problem:** Client can't distinguish errors from successful responses.

```typescript
// ❌ BAD: Error without isError flag
return {
  content: [{ type: "text", text: JSON.stringify({ error: "Not found" }) }],
};
```

```typescript
// ✅ GOOD: Proper error response
return {
  content: [
    {
      type: "text",
      text: JSON.stringify({
        success: false,
        errors: [
          {
            field: "id",
            message: "Resource not found",
            suggestion: "Verify the ID exists and try again",
          },
        ],
      }),
    },
  ],
  isError: true,
};
```

### E1: Empty Catch Block (HIGH)

**Problem:** Errors are silently swallowed, making debugging impossible.

```typescript
// ❌ BAD: Silent failure
try {
  await riskyOperation();
} catch (error) {
  // do nothing
}
```

```typescript
// ✅ GOOD: Log and handle appropriately
try {
  await riskyOperation();
} catch (error) {
  logger.error("Risky operation failed", { error: error.message });
  return createErrorResponse([
    {
      field: "operation",
      message: "Operation failed",
      suggestion: "Check input parameters and retry",
    },
  ]);
}
```

### E4: Generic Error Messages (MEDIUM)

**Problem:** Users can't understand what went wrong or how to fix it.

```typescript
// ❌ BAD: Unhelpful error
return { error: "Something went wrong" };
```

```typescript
// ✅ GOOD: Specific, actionable error
return {
  success: false,
  errors: [
    {
      field: "partner_id",
      message: "Invalid UUID format: 'abc123'",
      suggestion: "Use format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    },
  ],
};
```

---

## Review Report Template

Use this template when reporting review findings:

```markdown
# MCP Server Review: [Server Name]

**Reviewer:** [Name]
**Date:** [Date]
**Files Reviewed:** [List of files]

## Summary

| Severity | Count |
| -------- | ----- |
| CRITICAL | X     |
| HIGH     | X     |
| MEDIUM   | X     |
| LOW      | X     |

**Recommendation:** [APPROVE / APPROVE WITH CHANGES / REQUEST CHANGES / BLOCK]

## Critical Issues

### [S1] Hardcoded API Key

- **File:** src/config.ts:42
- **Code:** `const API_KEY = "sk_live_..."`
- **Fix:** Move to environment variable

## High Issues

### [A4] Missing isError Flag

- **File:** src/tools/processor.ts:128
- **Code:** Error response without isError
- **Fix:** Add `isError: true` to error responses

## Medium Issues

### [A1] Missing Tool Description

- **File:** src/index.ts:56
- **Tool:** `validate_input`
- **Fix:** Add description explaining tool purpose

## Low Issues

### [M3] TODO Comment

- **File:** src/utils/parser.ts:89
- **Comment:** `// TODO: optimize this`
- **Suggestion:** Create ticket or remove

## Checklist Results

- [x] Security: 6/7 passed
- [x] Architecture: 5/7 passed
- [ ] Error Handling: 4/6 passed
- [x] Production: 7/7 passed
```

---

## Workflow

### Step 1: Run Automated Detection

```bash
# Run all security checks
grep -rn "console\.log\|api[_-]\?key\s*[:=]" --include="*.ts" src/

# Run all architecture checks
grep -rn "name:\s*['\"]" --include="*.ts" src/ -A 5 | grep -v description
```

### Step 2: Manual Checklist Review

Walk through each section of the manual review checklist, marking items as pass/fail.

### Step 3: Code Walkthrough

1. Read each tool definition
2. Trace request handling flow
3. Verify error paths
4. Check resource and prompt definitions

### Step 4: Generate Report

Use the review report template to document findings with specific file locations and code snippets.

### Step 5: Classify and Prioritize

1. Group findings by severity
2. Identify blocking issues (CRITICAL/HIGH)
3. Suggest fixes for each issue

---

## Related Skills

- **mcp-server-writing** - Create new MCP servers
- **security-scan** - General security scanning
- **quality-check** - Code quality checks

## Resources

- [MCP Best Practices](https://modelcontextprotocol.info/docs/best-practices/)
- [MCP FAQs](https://modelcontextprotocol.info/docs/faqs/)
- See **REFERENCE.md** for complete violation catalog
- See **CHECKLISTS/** for printable audit checklists