Claude Skills Guide

MCP Server Vulnerability Scanning and Testing

When you expose an MCP server to external requests or integrate it with third-party services, security becomes a critical concern. MCP servers handle tool definitions, execute functions, and often access sensitive data sources. This guide provides practical approaches to scanning and testing your MCP server implementations for common vulnerability patterns.

Understanding the Attack Surface

MCP servers expose functions through a well-defined protocol. The attack surface includes:

Before writing tests, map what your server accepts and how it processes data. The supermemory skill can help track your testing progress across different vulnerability categories.

Setting Up Your Testing Environment

Create a dedicated test project for security scanning:

mkdir mcp-security-tests
cd mcp-security-tests
npm init -y
npm install --save-dev @anthropic-ai/mcp-sdk jest axios

Isolate your testing from production. Use environment variables to switch between test and production server URLs:

const SERVER_URL = process.env.MCP_SERVER_URL || 'http://localhost:3000';
const TEST_TIMEOUT = 5000;

Common Vulnerability Tests

Input Validation Testing

Test how your server handles malformed or malicious input. Create test cases that probe for common injection patterns:

describe('Input Validation', () => {
  test('rejects tool names with null bytes', async () => {
    const response = await axios.post(SERVER_URL, {
      jsonrpc: '2.0',
      id: 1,
      method: 'tools/list',
      params: {}
    });
    
    // Verify server processes requests safely
    expect(response.status).toBe(200);
  });

  test('handles excessively deep nesting in parameters', async () => {
    const maliciousPayload = {
      jsonrpc: '2.0',
      id: 2,
      method: 'tools/call',
      params: {
        name: 'execute_command',
        arguments: {
          data: { level1: { level2: { level3: { level4: {} } } } }
        }
      }
    };
    
    const response = await axios.post(SERVER_URL, maliciousPayload);
    expect(response.status).toBe(200);
  });
});

Authentication and Authorization

If your server exposes protected resources, test that auth is actually enforced:

describe('Authentication', () => {
  test('rejects requests without valid credentials', async () => {
    try {
      await axios.post(SERVER_URL, {
        jsonrpc: '2.0',
        id: 1,
        method: 'tools/call',
        params: { name: 'admin_function', arguments: {} }
      });
      fail('Should have thrown an error');
    } catch (error) {
      expect(error.response.status).toBe(401);
    }
  });

  test('prevents privilege escalation', async () => {
    const userToken = await getLimitedUserToken();
    const response = await axios.post(SERVER_URL, {
      jsonrpc: '2.0',
      id: 2,
      method: 'tools/call',
      params: { name: 'admin_only_function', arguments: {} }
    }, { headers: { Authorization: `Bearer ${userToken}` }});
    
    expect(response.status).toBe(403);
  });
});

Automating Security Scans

Integrate security testing into your CI/CD pipeline using the tdd skill for test-driven development of security requirements:

// security-scanner.test.js
const scanServer = require('./scanner');

describe('Automated Security Scan', () => {
  test('completes full vulnerability scan', async () => {
    const results = await scanServer(SERVER_URL, {
      timeout: TEST_TIMEOUT,
      checks: ['injection', 'auth', 'rate-limit', 'ssrf']
    });
    
    expect(results.critical).toHaveLength(0);
    expect(results.high).toHaveLength(0);
  });
});

Run scans regularly:

npm test -- --testPathPattern=security

Rate Limiting and DoS Protection

MCP servers can be targets for denial-of-service attacks. Test your rate limiting:

describe('Rate Limiting', () => {
  test('enforces request limits', async () => {
    const requests = [];
    const startTime = Date.now();
    
    // Send burst of requests
    for (let i = 0; i < 100; i++) {
      requests.push(
        axios.post(SERVER_URL, {
          jsonrpc: '2.0',
          id: i,
          method: 'tools/list',
          params: {}
        }).catch(err => ({ error: err }))
      );
    }
    
    const results = await Promise.all(requests);
    const rateLimited = results.filter(r => r.error?.response?.status === 429);
    
    expect(rateLimited.length).toBeGreaterThan(0);
  });
});

Testing Tool Implementations

Each tool your server exposes requires individual security testing. The frontend-design skill can help visualize your testing coverage:

describe('Tool-Specific Tests', () => {
  const tools = ['file_read', 'command_exec', 'http_request', 'database_query'];
  
  tools.forEach(tool => {
    test(`${tool} handles dangerous input safely`, async () => {
      const payloads = getPayloadsForTool(tool);
      
      for (const payload of payloads) {
        const response = await axios.post(SERVER_URL, {
          jsonrpc: '2.0',
          id: Math.random(),
          method: 'tools/call',
          params: { name: tool, arguments: payload }
        });
        
        // Verify no information leakage
        const result = response.data.result;
        expect(result).not.toContain('stack trace');
        expect(result).not.toContain('Internal Server Error');
      }
    });
  });
});

Continuous Monitoring

Security testing isn’t a one-time effort. Implement ongoing checks:

  1. Scheduled scans: Run security tests nightly
  2. Dependency scanning: Check for vulnerabilities in your MCP server dependencies
  3. Logging and alerting: Track suspicious patterns in production

Use the pdf skill to generate security reports for stakeholders:

const generateSecurityReport = require('./report-generator');

async function nightlyScan() {
  const results = await runSecurityTests();
  const report = await generateSecurityReport(results);
  
  await notifyTeam(report);
}

Conclusion

Securing your MCP server requires proactive testing throughout the development lifecycle. By implementing comprehensive test suites that cover input validation, authentication, rate limiting, and tool-specific vulnerabilities, you reduce the risk of security breaches. Automate these tests in your CI/CD pipeline and run them regularly to catch issues before production deployment.

The key is treating security testing as an integral part of your development process, not an afterthought. Start with the basics—input validation and authentication—then layer on more sophisticated tests as your server evolves. Pairing this with the MCP credential management and secrets handling guide ensures your authentication layer is as hardened as your validation logic.

Built by theluckystrike — More at zovo.one