Nicolas Dabene
Back to blog
11 December 2025 Nicolas Dabene 3 min

How to Secure MCP Server?

Secure Your MCP Server: Permissions, Validation and Protection

API IA development security Tutorial artificial intelligence
How to Secure MCP Server?

Secure Your MCP Server: Permissions, Validation and Protection

Secure Your MCP Server: Permissions, Validation and Protection

Your MCP server now exposes several tools that AIs can discover and use. Great! But a crucial question arises: who can use what? In this article, we’ll transform your server into a secured fortress, without sacrificing its ease of use. Because a powerful server must also be a protected server.

Introduction

In 15 years of API development, I learned a golden rule: security isn’t added as an afterthought, it’s designed from the start. An MCP server that gives access to your files, your data, your sensitive resources requires several layers of protection. But don’t worry: securing doesn’t mean complicating.

Today, we’ll implement four essential security pillars: input validation (to avoid malicious data), authentication (who are you?), authorization (what are you allowed to do?) and resource limiting (to avoid abuse). By the end of this article, your server will be production-ready.

The Four Pillars of MCP Security

Before coding, let’s understand our defense-in-depth strategy:

1. Input Validation

The principle: Never trust incoming data. Always validate, clean, verify.

Why? A poorly validated parameter can allow access to sensitive files (../../etc/passwd), code injection, or server crash.

2. Authentication

The principle: Identify who is using your server. Each request must be associated with a verified identity.

Why? Without authentication, anyone can use your tools. It’s like leaving your house without a lock.

3. Authorization

The principle: Verify permissions. Even authenticated, not everyone can do everything.

Why? Your intern doesn’t need access to HR files. Granular permissions protect your sensitive data.

4. Resource Limiting

The principle: Impose quotas, size limits, timeouts.

Why? Prevent a malicious user (or error) from saturating your server with 10,000 requests per second.

Robust Input Validation

Let’s start with the most important: validate all inputs. Create src/security/validator.ts:

<span class="c1">// src/security/validator.ts</span>
<span class="k">import</span> <span class="nx">path</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">InputSchema</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../mcp/protocol</span><span class="dl">'</span><span class="p">;</span>

<span class="cm">/**
 * Validation error
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ValidationError</span> <span class="kd">extends</span> <span class="nb">Error</span> <span class="p">{</span>
  <span class="kd">constructor</span><span class="p">(</span>
    <span class="nx">message</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span>
    <span class="k">public</span> <span class="nx">field</span><span class="p">?:</span> <span class="kr">string</span><span class="p">,</span>
    <span class="k">public</span> <span class="nx">expected</span><span class="p">?:</span> <span class="kr">string</span>
  <span class="p">)</span> <span class="p">{</span>
    <span class="k">super</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">ValidationError</span><span class="dl">'</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Parameter validator based on JSON Schema
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ParameterValidator</span> <span class="p">{</span>

  <span class="cm">/**
   * Validate parameters according to schema
   */</span>
  <span class="k">static</span> <span class="nx">validate</span><span class="p">(</span><span class="nx">params</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span> <span class="nx">schema</span><span class="p">:</span> <span class="nx">InputSchema</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="c1">// Check that params is an object</span>
    <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">params</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span> <span class="o">||</span> <span class="nx">params</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span><span class="dl">'</span><span class="s1">Parameters must be an object</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Check required fields</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">requiredField</span> <span class="k">of</span> <span class="nx">schema</span><span class="p">.</span><span class="nx">required</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nx">requiredField</span> <span class="k">in</span> <span class="nx">params</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">requiredField</span><span class="p">}</span><span class="s2">' is required`</span><span class="p">,</span>
          <span class="nx">requiredField</span>
        <span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// Validate each property</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="p">[</span><span class="nx">fieldName</span><span class="p">,</span> <span class="nx">fieldValue</span><span class="p">]</span> <span class="k">of</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">entries</span><span class="p">(</span><span class="nx">params</span><span class="p">))</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">fieldSchema</span> <span class="o">=</span> <span class="nx">schema</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="nx">fieldName</span><span class="p">];</span>

      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fieldSchema</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' is not allowed`</span><span class="p">,</span>
          <span class="nx">fieldName</span>
        <span class="p">);</span>
      <span class="p">}</span>

      <span class="k">this</span><span class="p">.</span><span class="nx">validateField</span><span class="p">(</span><span class="nx">fieldName</span><span class="p">,</span> <span class="nx">fieldValue</span><span class="p">,</span> <span class="nx">fieldSchema</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Validate a specific field
   */</span>
  <span class="k">private</span> <span class="k">static</span> <span class="nx">validateField</span><span class="p">(</span>
    <span class="nx">fieldName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span>
    <span class="nx">value</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span>
    <span class="nx">schema</span><span class="p">:</span> <span class="kr">any</span>
  <span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="c1">// Type validation</span>
    <span class="kd">const</span> <span class="nx">actualType</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">value</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">expectedType</span> <span class="o">=</span> <span class="nx">schema</span><span class="p">.</span><span class="kd">type</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="nx">expectedType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">string</span><span class="dl">'</span> <span class="o">&&</span> <span class="nx">actualType</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">string</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' must be a string`</span><span class="p">,</span>
        <span class="nx">fieldName</span><span class="p">,</span>
        <span class="nx">expectedType</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="nx">expectedType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span> <span class="o">&&</span> <span class="nx">actualType</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' must be a number`</span><span class="p">,</span>
        <span class="nx">fieldName</span><span class="p">,</span>
        <span class="nx">expectedType</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="nx">expectedType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">boolean</span><span class="dl">'</span> <span class="o">&&</span> <span class="nx">actualType</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">boolean</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' must be a boolean`</span><span class="p">,</span>
        <span class="nx">fieldName</span><span class="p">,</span>
        <span class="nx">expectedType</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Enumeration validation</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">schema</span><span class="p">.</span><span class="kr">enum</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">schema</span><span class="p">.</span><span class="kr">enum</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">value</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' must be one of: </span><span class="p">${</span><span class="nx">schema</span><span class="p">.</span><span class="kr">enum</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">'</span><span class="s1">, </span><span class="dl">'</span><span class="p">)}</span><span class="s2">`</span><span class="p">,</span>
        <span class="nx">fieldName</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Length validation for strings</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">expectedType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">string</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">schema</span><span class="p">.</span><span class="nx">minLength</span> <span class="o">&&</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="nx">schema</span><span class="p">.</span><span class="nx">minLength</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' must contain at least </span><span class="p">${</span><span class="nx">schema</span><span class="p">.</span><span class="nx">minLength</span><span class="p">}</span><span class="s2"> characters`</span><span class="p">,</span>
          <span class="nx">fieldName</span>
        <span class="p">);</span>
      <span class="p">}</span>

      <span class="k">if</span> <span class="p">(</span><span class="nx">schema</span><span class="p">.</span><span class="nx">maxLength</span> <span class="o">&&</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">schema</span><span class="p">.</span><span class="nx">maxLength</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' cannot exceed </span><span class="p">${</span><span class="nx">schema</span><span class="p">.</span><span class="nx">maxLength</span><span class="p">}</span><span class="s2"> characters`</span><span class="p">,</span>
          <span class="nx">fieldName</span>
        <span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// Range validation for numbers</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">expectedType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">schema</span><span class="p">.</span><span class="nx">minimum</span> <span class="o">!==</span> <span class="kc">undefined</span> <span class="o">&&</span> <span class="nx">value</span> <span class="o"><</span> <span class="nx">schema</span><span class="p">.</span><span class="nx">minimum</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' must be greater than or equal to </span><span class="p">${</span><span class="nx">schema</span><span class="p">.</span><span class="nx">minimum</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span>
          <span class="nx">fieldName</span>
        <span class="p">);</span>
      <span class="p">}</span>

      <span class="k">if</span> <span class="p">(</span><span class="nx">schema</span><span class="p">.</span><span class="nx">maximum</span> <span class="o">!==</span> <span class="kc">undefined</span> <span class="o">&&</span> <span class="nx">value</span> <span class="o">></span> <span class="nx">schema</span><span class="p">.</span><span class="nx">maximum</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' cannot exceed </span><span class="p">${</span><span class="nx">schema</span><span class="p">.</span><span class="nx">maximum</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span>
          <span class="nx">fieldName</span>
        <span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// Pattern validation for strings</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">expectedType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">string</span><span class="dl">'</span> <span class="o">&&</span> <span class="nx">schema</span><span class="p">.</span><span class="nx">pattern</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">regex</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">schema</span><span class="p">.</span><span class="nx">pattern</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">regex</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">value</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
          <span class="s2">`Field '</span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2">' doesn't match expected format`</span><span class="p">,</span>
          <span class="nx">fieldName</span>
        <span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * File path validator
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">PathValidator</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">allowedDirectories</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>
  <span class="k">private</span> <span class="nx">blockedPaths</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>

  <span class="kd">constructor</span><span class="p">(</span><span class="nx">allowedDirectories</span><span class="p">:</span> <span class="kr">string</span><span class="p">[],</span> <span class="nx">blockedPaths</span><span class="p">:</span> <span class="kr">string</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[])</span> <span class="p">{</span>
    <span class="c1">// Resolve all paths to absolute</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">allowedDirectories</span> <span class="o">=</span> <span class="nx">allowedDirectories</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">dir</span> <span class="o">=></span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">dir</span><span class="p">));</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">blockedPaths</span> <span class="o">=</span> <span class="nx">blockedPaths</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">p</span> <span class="o">=></span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">p</span><span class="p">));</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Validate that a path is safe
   */</span>
  <span class="nx">validatePath</span><span class="p">(</span><span class="nx">filePath</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
    <span class="c1">// Resolve absolute path</span>
    <span class="kd">const</span> <span class="nx">absolutePath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">filePath</span><span class="p">);</span>

    <span class="c1">// Check path traversal (../)</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">absolutePath</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="s1">..</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="dl">'</span><span class="s1">Paths with ".." are not allowed (path traversal)</span><span class="dl">'</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Check that path is in an allowed directory</span>
    <span class="kd">const</span> <span class="nx">isInAllowedDir</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">allowedDirectories</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nx">dir</span> <span class="o">=></span>
      <span class="nx">absolutePath</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="nx">dir</span><span class="p">)</span>
    <span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">isInAllowedDir</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`Access denied: path must be in one of the allowed directories`</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// Check that path is not blocked</span>
    <span class="kd">const</span> <span class="nx">isBlocked</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">blockedPaths</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nx">blocked</span> <span class="o">=></span>
      <span class="nx">absolutePath</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="nx">blocked</span><span class="p">)</span>
    <span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="nx">isBlocked</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`Access denied: this path is explicitly blocked`</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="nx">absolutePath</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Add an allowed directory
   */</span>
  <span class="nx">addAllowedDirectory</span><span class="p">(</span><span class="nx">directory</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">allowedDirectories</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">directory</span><span class="p">));</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Block a specific path
   */</span>
  <span class="nx">blockPath</span><span class="p">(</span><span class="nx">pathToBlock</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">blockedPaths</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">pathToBlock</span><span class="p">));</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * File size validator
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">SizeValidator</span> <span class="p">{</span>
  <span class="cm">/**
   * Validate that a size is acceptable
   */</span>
  <span class="k">static</span> <span class="nx">validateSize</span><span class="p">(</span>
    <span class="nx">size</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span>
    <span class="nx">maxSize</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span>
    <span class="nx">fieldName</span><span class="p">:</span> <span class="kr">string</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">file</span><span class="dl">'</span>
  <span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">size</span> <span class="o">></span> <span class="nx">maxSize</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidationError</span><span class="p">(</span>
        <span class="s2">`The </span><span class="p">${</span><span class="nx">fieldName</span><span class="p">}</span><span class="s2"> is too large (max </span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">formatSize</span><span class="p">(</span><span class="nx">maxSize</span><span class="p">)}</span><span class="s2">)`</span>
      <span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Format size in bytes to readable format
   */</span>
  <span class="k">static</span> <span class="nx">formatSize</span><span class="p">(</span><span class="nx">bytes</span><span class="p">:</span> <span class="kr">number</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">units</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">bytes</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">KB</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">MB</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">GB</span><span class="dl">'</span><span class="p">];</span>
    <span class="kd">let</span> <span class="nx">size</span> <span class="o">=</span> <span class="nx">bytes</span><span class="p">;</span>
    <span class="kd">let</span> <span class="nx">unitIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">while</span> <span class="p">(</span><span class="nx">size</span> <span class="o">>=</span> <span class="mi">1024</span> <span class="o">&&</span> <span class="nx">unitIndex</span> <span class="o"><</span> <span class="nx">units</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">size</span> <span class="o">/=</span> <span class="mi">1024</span><span class="p">;</span>
      <span class="nx">unitIndex</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nx">size</span><span class="p">.</span><span class="nx">toFixed</span><span class="p">(</span><span class="mi">2</span><span class="p">)}</span><span class="s2"> </span><span class="p">${</span><span class="nx">units</span><span class="p">[</span><span class="nx">unitIndex</span><span class="p">]}</span><span class="s2">`</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

This complete validator checks:

Data types: string, number, boolean

Required values: mandatory fields are present

Enumerations: values are in allowed list

Lengths: min/max for strings

Ranges: min/max for numbers

Patterns: regular expressions for formats

Paths: protection against path traversal and unauthorized access

Sizes: file limits

JWT Authentication System

Now let’s create an authentication system based on JSON Web Tokens. Create src/security/auth.ts:

<span class="c1">// src/security/auth.ts</span>
<span class="k">import</span> <span class="nx">crypto</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">crypto</span><span class="dl">'</span><span class="p">;</span>

<span class="cm">/**
 * User interface
 */</span>
<span class="k">export</span> <span class="kr">interface</span> <span class="nx">User</span> <span class="p">{</span>
  <span class="nl">id</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">username</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">role</span><span class="p">:</span> <span class="dl">'</span><span class="s1">admin</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">user</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">readonly</span><span class="dl">'</span><span class="p">;</span>
  <span class="nl">permissions</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>
<span class="p">}</span>

<span class="cm">/**
 * Simplified JWT token (for demo - use a real JWT lib in prod)
 */</span>
<span class="kr">interface</span> <span class="nx">Token</span> <span class="p">{</span>
  <span class="nl">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">username</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">role</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">permissions</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>
  <span class="nl">expiresAt</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/**
 * Authentication manager
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">AuthManager</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">users</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nx">User</span><span class="o">></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
  <span class="k">private</span> <span class="nx">tokens</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nx">Token</span><span class="o">></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
  <span class="k">private</span> <span class="k">readonly</span> <span class="nx">SECRET_KEY</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="k">private</span> <span class="k">readonly</span> <span class="nx">TOKEN_DURATION</span> <span class="o">=</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span> <span class="c1">// 24 hours</span>

  <span class="kd">constructor</span><span class="p">(</span><span class="nx">secretKey</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">SECRET_KEY</span> <span class="o">=</span> <span class="nx">secretKey</span><span class="p">;</span>

    <span class="c1">// Create some test users</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">createUser</span><span class="p">({</span>
      <span class="na">id</span><span class="p">:</span> <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">username</span><span class="p">:</span> <span class="dl">'</span><span class="s1">admin</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">role</span><span class="p">:</span> <span class="dl">'</span><span class="s1">admin</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">permissions</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">]</span> <span class="c1">// All permissions</span>
    <span class="p">});</span>

    <span class="k">this</span><span class="p">.</span><span class="nx">createUser</span><span class="p">({</span>
      <span class="na">id</span><span class="p">:</span> <span class="dl">'</span><span class="s1">2</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">username</span><span class="p">:</span> <span class="dl">'</span><span class="s1">user</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">role</span><span class="p">:</span> <span class="dl">'</span><span class="s1">user</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">permissions</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">readFile</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">listFiles</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">searchFiles</span><span class="dl">'</span><span class="p">]</span>
    <span class="p">});</span>

    <span class="k">this</span><span class="p">.</span><span class="nx">createUser</span><span class="p">({</span>
      <span class="na">id</span><span class="p">:</span> <span class="dl">'</span><span class="s1">3</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">username</span><span class="p">:</span> <span class="dl">'</span><span class="s1">readonly</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">role</span><span class="p">:</span> <span class="dl">'</span><span class="s1">readonly</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">permissions</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">readFile</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">listFiles</span><span class="dl">'</span><span class="p">]</span>
    <span class="p">});</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Create a user
   */</span>
  <span class="nx">createUser</span><span class="p">(</span><span class="nx">user</span><span class="p">:</span> <span class="nx">User</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">username</span><span class="p">,</span> <span class="nx">user</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Authenticate a user and generate a token
   */</span>
  <span class="nx">authenticate</span><span class="p">(</span><span class="nx">username</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">password</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="kr">string</span> <span class="o">|</span> <span class="kc">null</span> <span class="p">{</span>
    <span class="c1">// In production, verify hashed password!</span>
    <span class="c1">// This is simplified for demo</span>
    <span class="kd">const</span> <span class="nx">user</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">username</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">user</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Generate a token</span>
    <span class="kd">const</span> <span class="nx">tokenId</span> <span class="o">=</span> <span class="nx">crypto</span><span class="p">.</span><span class="nx">randomBytes</span><span class="p">(</span><span class="mi">32</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="dl">'</span><span class="s1">hex</span><span class="dl">'</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">token</span><span class="p">:</span> <span class="nx">Token</span> <span class="o">=</span> <span class="p">{</span>
      <span class="na">userId</span><span class="p">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span>
      <span class="na">username</span><span class="p">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">username</span><span class="p">,</span>
      <span class="na">role</span><span class="p">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">role</span><span class="p">,</span>
      <span class="na">permissions</span><span class="p">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">permissions</span><span class="p">,</span>
      <span class="na">expiresAt</span><span class="p">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">TOKEN_DURATION</span>
    <span class="p">};</span>

    <span class="k">this</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">,</span> <span class="nx">token</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">tokenId</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Validate a token
   */</span>
  <span class="nx">validateToken</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">Token</span> <span class="o">|</span> <span class="kc">null</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">token</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Check expiration</span>
    <span class="k">if</span> <span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">></span> <span class="nx">token</span><span class="p">.</span><span class="nx">expiresAt</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">this</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">);</span>
      <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="nx">token</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Revoke a token
   */</span>
  <span class="nx">revokeToken</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Get a user
   */</span>
  <span class="nx">getUser</span><span class="p">(</span><span class="nx">username</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">User</span> <span class="o">|</span> <span class="kc">undefined</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">username</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Clean expired tokens
   */</span>
  <span class="nx">cleanExpiredTokens</span><span class="p">():</span> <span class="k">void</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="p">[</span><span class="nx">tokenId</span><span class="p">,</span> <span class="nx">token</span><span class="p">]</span> <span class="k">of</span> <span class="k">this</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">entries</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">now</span> <span class="o">></span> <span class="nx">token</span><span class="p">.</span><span class="nx">expiresAt</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Authentication middleware for Express
 */</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">authMiddleware</span><span class="p">(</span><span class="nx">authManager</span><span class="p">:</span> <span class="nx">AuthManager</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span> <span class="nx">next</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
    <span class="c1">// Get token from Authorization header</span>
    <span class="kd">const</span> <span class="nx">authHeader</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">authorization</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">authHeader</span> <span class="o">||</span> <span class="o">!</span><span class="nx">authHeader</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">'</span><span class="s1">Bearer </span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">401</span><span class="p">).</span><span class="nx">json</span><span class="p">({</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Missing authentication token</span><span class="dl">'</span>
      <span class="p">});</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">tokenId</span> <span class="o">=</span> <span class="nx">authHeader</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">7</span><span class="p">);</span> <span class="c1">// Remove "Bearer "</span>
    <span class="kd">const</span> <span class="nx">token</span> <span class="o">=</span> <span class="nx">authManager</span><span class="p">.</span><span class="nx">validateToken</span><span class="p">(</span><span class="nx">tokenId</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">401</span><span class="p">).</span><span class="nx">json</span><span class="p">({</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Invalid or expired token</span><span class="dl">'</span>
      <span class="p">});</span>
    <span class="p">}</span>

    <span class="c1">// Add user info to request</span>
    <span class="nx">req</span><span class="p">.</span><span class="nx">user</span> <span class="o">=</span> <span class="nx">token</span><span class="p">;</span>
    <span class="nx">next</span><span class="p">();</span>
  <span class="p">};</span>
<span class="p">}</span>

Granular Permission System

Now, let’s create a system that checks if a user can execute a specific tool. Create src/security/permissions.ts:

<span class="c1">// src/security/permissions.ts</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">User</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./auth</span><span class="dl">'</span><span class="p">;</span>

<span class="cm">/**
 * Permission error
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">PermissionError</span> <span class="kd">extends</span> <span class="nb">Error</span> <span class="p">{</span>
  <span class="kd">constructor</span><span class="p">(</span><span class="nx">message</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">super</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">PermissionError</span><span class="dl">'</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Permission manager
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">PermissionManager</span> <span class="p">{</span>
  <span class="cm">/**
   * Check if a user has permission to use a tool
   */</span>
  <span class="k">static</span> <span class="nx">hasPermission</span><span class="p">(</span>
    <span class="nx">user</span><span class="p">:</span> <span class="nx">User</span><span class="p">,</span>
    <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span>
    <span class="nx">params</span><span class="p">?:</span> <span class="kr">any</span>
  <span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="c1">// Admins have access to everything</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">permissions</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Check specific permission</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">user</span><span class="p">.</span><span class="nx">permissions</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">toolName</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Additional contextual permissions</span>
    <span class="c1">// For example, check allowed paths for readFile</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">toolName</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">readFile</span><span class="dl">'</span> <span class="o">&&</span> <span class="nx">params</span><span class="p">?.</span><span class="nx">file_path</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">canAccessPath</span><span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">params</span><span class="p">.</span><span class="nx">file_path</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Check access to a specific path
   */</span>
  <span class="k">private</span> <span class="k">static</span> <span class="nx">canAccessPath</span><span class="p">(</span><span class="nx">user</span><span class="p">:</span> <span class="nx">User</span><span class="p">,</span> <span class="nx">filePath</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="c1">// In readonly, only read in certain folders</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">role</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">readonly</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">allowedPaths</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">/public</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">/docs</span><span class="dl">'</span><span class="p">];</span>
      <span class="k">return</span> <span class="nx">allowedPaths</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nx">allowed</span> <span class="o">=></span>
        <span class="nx">filePath</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="nx">allowed</span><span class="p">)</span>
      <span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Get user permissions
   */</span>
  <span class="k">static</span> <span class="nx">getPermissions</span><span class="p">(</span><span class="nx">user</span><span class="p">:</span> <span class="nx">User</span><span class="p">):</span> <span class="kr">string</span><span class="p">[]</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">user</span><span class="p">.</span><span class="nx">permissions</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Check and throw error if no permission
   */</span>
  <span class="k">static</span> <span class="nx">requirePermission</span><span class="p">(</span>
    <span class="nx">user</span><span class="p">:</span> <span class="nx">User</span><span class="p">,</span>
    <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span>
    <span class="nx">params</span><span class="p">?:</span> <span class="kr">any</span>
  <span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">hasPermission</span><span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">,</span> <span class="nx">params</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nx">PermissionError</span><span class="p">(</span>
        <span class="s2">`Permission denied: you don't have access to tool '</span><span class="p">${</span><span class="nx">toolName</span><span class="p">}</span><span class="s2">'`</span>
      <span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Permission policy for a tool
 */</span>
<span class="k">export</span> <span class="kr">interface</span> <span class="nx">ToolPolicy</span> <span class="p">{</span>
  <span class="nl">allowedRoles</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>
  <span class="nl">requiredPermissions</span><span class="p">:</span> <span class="kr">string</span><span class="p">[];</span>
  <span class="nl">rateLimit</span><span class="p">?:</span> <span class="p">{</span>
    <span class="na">maxRequests</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
    <span class="nl">windowMs</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="p">};</span>
<span class="p">}</span>

<span class="cm">/**
 * Tool policy manager
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">PolicyManager</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">policies</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nx">ToolPolicy</span><span class="o">></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>

  <span class="cm">/**
   * Set a policy for a tool
   */</span>
  <span class="nx">setPolicy</span><span class="p">(</span><span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">policy</span><span class="p">:</span> <span class="nx">ToolPolicy</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">policies</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">toolName</span><span class="p">,</span> <span class="nx">policy</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Get a tool's policy
   */</span>
  <span class="nx">getPolicy</span><span class="p">(</span><span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">ToolPolicy</span> <span class="o">|</span> <span class="kc">undefined</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">policies</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Check that a user respects the policy
   */</span>
  <span class="nx">checkPolicy</span><span class="p">(</span><span class="nx">user</span><span class="p">:</span> <span class="nx">User</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">policy</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">policies</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">policy</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// No policy = allowed by default</span>
    <span class="p">}</span>

    <span class="c1">// Check role</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">policy</span><span class="p">.</span><span class="nx">allowedRoles</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">role</span><span class="p">)</span> <span class="o">&&</span>
        <span class="o">!</span><span class="nx">policy</span><span class="p">.</span><span class="nx">allowedRoles</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Check permissions</span>
    <span class="kd">const</span> <span class="nx">hasAllPermissions</span> <span class="o">=</span> <span class="nx">policy</span><span class="p">.</span><span class="nx">requiredPermissions</span><span class="p">.</span><span class="nx">every</span><span class="p">(</span><span class="nx">perm</span> <span class="o">=></span>
      <span class="nx">user</span><span class="p">.</span><span class="nx">permissions</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">perm</span><span class="p">)</span> <span class="o">||</span> <span class="nx">user</span><span class="p">.</span><span class="nx">permissions</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">)</span>
    <span class="p">);</span>

    <span class="k">return</span> <span class="nx">hasAllPermissions</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

Rate Limiting and Quotas

Let’s protect our server against abuse with a rate limiting system. Create src/security/rateLimit.ts:

<span class="c1">// src/security/rateLimit.ts</span>

<span class="cm">/**
 * Usage record
 */</span>
<span class="kr">interface</span> <span class="nx">UsageRecord</span> <span class="p">{</span>
  <span class="nl">count</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">resetAt</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/**
 * Rate limiting manager
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">RateLimiter</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">usage</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nx">UsageRecord</span><span class="o">></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>

  <span class="kd">constructor</span><span class="p">(</span>
    <span class="k">private</span> <span class="nx">maxRequests</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span>
    <span class="k">private</span> <span class="nx">windowMs</span><span class="p">:</span> <span class="kr">number</span>
  <span class="p">)</span> <span class="p">{}</span>

  <span class="cm">/**
   * Check and increment counter for a user
   */</span>
  <span class="nx">checkLimit</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
    <span class="kd">const</span> <span class="nx">record</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">usage</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>

    <span class="c1">// No record or expired window</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">record</span> <span class="o">||</span> <span class="nx">now</span> <span class="o">></span> <span class="nx">record</span><span class="p">.</span><span class="nx">resetAt</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">this</span><span class="p">.</span><span class="nx">usage</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="p">{</span>
        <span class="na">count</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="na">resetAt</span><span class="p">:</span> <span class="nx">now</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">windowMs</span>
      <span class="p">});</span>
      <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Limit reached</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">record</span><span class="p">.</span><span class="nx">count</span> <span class="o">>=</span> <span class="k">this</span><span class="p">.</span><span class="nx">maxRequests</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// Increment counter</span>
    <span class="nx">record</span><span class="p">.</span><span class="nx">count</span><span class="o">++</span><span class="p">;</span>
    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Get limit info for a user
   */</span>
  <span class="nx">getLimitInfo</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="p">{</span>
    <span class="nl">current</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
    <span class="nl">max</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
    <span class="nl">resetsAt</span><span class="p">:</span> <span class="nb">Date</span><span class="p">;</span>
  <span class="p">}</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">record</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">usage</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">record</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">current</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
        <span class="na">max</span><span class="p">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">maxRequests</span><span class="p">,</span>
        <span class="na">resetsAt</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">windowMs</span><span class="p">)</span>
      <span class="p">};</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="p">{</span>
      <span class="na">current</span><span class="p">:</span> <span class="nx">record</span><span class="p">.</span><span class="nx">count</span><span class="p">,</span>
      <span class="na">max</span><span class="p">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">maxRequests</span><span class="p">,</span>
      <span class="na">resetsAt</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">record</span><span class="p">.</span><span class="nx">resetAt</span><span class="p">)</span>
    <span class="p">};</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Reset counter for a user
   */</span>
  <span class="nx">reset</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">usage</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Clean expired records
   */</span>
  <span class="nx">cleanup</span><span class="p">():</span> <span class="k">void</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="p">[</span><span class="nx">userId</span><span class="p">,</span> <span class="nx">record</span><span class="p">]</span> <span class="k">of</span> <span class="k">this</span><span class="p">.</span><span class="nx">usage</span><span class="p">.</span><span class="nx">entries</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">now</span> <span class="o">></span> <span class="nx">record</span><span class="p">.</span><span class="nx">resetAt</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">usage</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="cm">/**
 * Rate limiting middleware for Express
 */</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">rateLimitMiddleware</span><span class="p">(</span><span class="nx">rateLimiter</span><span class="p">:</span> <span class="nx">RateLimiter</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span> <span class="nx">next</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">userId</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">user</span><span class="p">?.</span><span class="nx">userId</span> <span class="o">||</span> <span class="nx">req</span><span class="p">.</span><span class="nx">ip</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">rateLimiter</span><span class="p">.</span><span class="nx">checkLimit</span><span class="p">(</span><span class="nx">userId</span><span class="p">))</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">info</span> <span class="o">=</span> <span class="nx">rateLimiter</span><span class="p">.</span><span class="nx">getLimitInfo</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>
      <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">429</span><span class="p">).</span><span class="nx">json</span><span class="p">({</span>
        <span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="na">error</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Request limit reached</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">limit</span><span class="p">:</span> <span class="p">{</span>
          <span class="na">max</span><span class="p">:</span> <span class="nx">info</span><span class="p">.</span><span class="nx">max</span><span class="p">,</span>
          <span class="na">current</span><span class="p">:</span> <span class="nx">info</span><span class="p">.</span><span class="nx">current</span><span class="p">,</span>
          <span class="na">resetsAt</span><span class="p">:</span> <span class="nx">info</span><span class="p">.</span><span class="nx">resetsAt</span>
        <span class="p">}</span>
      <span class="p">});</span>
    <span class="p">}</span>

    <span class="nx">next</span><span class="p">();</span>
  <span class="p">};</span>
<span class="p">}</span>

<span class="cm">/**
 * Quota manager per tool
 */</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">QuotaManager</span> <span class="p">{</span>
  <span class="k">private</span> <span class="nx">quotas</span><span class="p">:</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="nb">Map</span><span class="o"><</span><span class="kr">string</span><span class="p">,</span> <span class="kr">number</span><span class="o">>></span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>

  <span class="cm">/**
   * Set a quota for a user and tool
   */</span>
  <span class="nx">setQuota</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">maxUsage</span><span class="p">:</span> <span class="kr">number</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">quotas</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">userId</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">this</span><span class="p">.</span><span class="nx">quotas</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">());</span>
    <span class="p">}</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">quotas</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">userId</span><span class="p">)</span><span class="o">!</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">toolName</span><span class="p">,</span> <span class="nx">maxUsage</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Check and decrement quota
   */</span>
  <span class="nx">checkQuota</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">userQuotas</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">quotas</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">userQuotas</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// No quota = unlimited</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">remaining</span> <span class="o">=</span> <span class="nx">userQuotas</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">toolName</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="nx">remaining</span> <span class="o">===</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// No quota for this tool</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="nx">remaining</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">false</span><span class="p">;</span> <span class="c1">// Quota exhausted</span>
    <span class="p">}</span>

    <span class="nx">userQuotas</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">toolName</span><span class="p">,</span> <span class="nx">remaining</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Get remaining quota
   */</span>
  <span class="nx">getRemainingQuota</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="kr">number</span> <span class="o">|</span> <span class="kc">null</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">userQuotas</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">quotas</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">userId</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">userQuotas</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">null</span><span class="p">;</span> <span class="c1">// Unlimited</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="nx">userQuotas</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">toolName</span><span class="p">)</span> <span class="o">||</span> <span class="kc">null</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="cm">/**
   * Reset a user's quota
   */</span>
  <span class="nx">resetQuota</span><span class="p">(</span><span class="nx">userId</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">maxUsage</span><span class="p">:</span> <span class="kr">number</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">setQuota</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="nx">toolName</span><span class="p">,</span> <span class="nx">maxUsage</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>

Conclusion

Congratulations! You now have a production-ready MCP server with four security layers:

  • ✅ Complete input validation
  • ✅ Token authentication
  • ✅ Granular authorization
  • ✅ Rate limiting and quotas

Your server can now be exposed in production with confidence. AIs can use it securely, each user has their specific permissions, and abuse is automatically blocked.

In the next and final article of the series, we’ll connect your secured server to Claude Desktop and test the complete integration in real conditions. You’ll finally see the entire system working end-to-end with a real AI.

Meanwhile, test your security system! Try to bypass it, test the limits, verify everything is well protected. A good security system is a system that has been attacked and resisted.


Article published on December 10, 2025 by Nicolas Dabène - PHP & PrestaShop Expert with 15+ years of experience in software architecture and AI integration

Also read:

LinkedIn

Follow my AI and e-commerce analysis

I share practical notes on AI agents, PrestaShop architecture, MCP and automation for e-commerce teams.

Follow on LinkedIn