Skip to content
Development
Skill

/middleware-pipeline

Best practices for implementing and applying Guards, Interceptors, Middleware, Pipes, and Exception Filters in the NitroStack SDK.

From plugin
nitrostack
2.5k199 skills1 MCP
Install
$ npx -y skills add nitrocloudofficial/nitrostack --skill middleware-pipeline --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/middleware-pipeline

Context preview

The summary Claude sees to decide when to auto-load this skill.

Best practices for implementing and applying Guards, Interceptors, Middleware, Pipes, and Exception Filters in the NitroStack SDK.

SKILL.md

middleware-pipeline.SKILL.md
name: nitrostack-middleware-pipeline
description: Best practices for implementing and applying Guards, Interceptors, Middleware, Pipes, and Exception Filters in the NitroStack SDK.

When to Use

Use this skill when implementing request validation, authorization checks, response mapping, logging, error handling, or performance tracking on NitroStack tool methods.

---

1. Guards (`Guard` and `@UseGuards`)

Guards determine if a request should be processed by a tool handler based on authentication, authorization, or other conditions.

Interface:

import { Guard, ExecutionContext } from '@nitrostack/core';

export interface Guard {
  canActivate(context: ExecutionContext): boolean | Promise<boolean>;
}

Example:

import { Guard, ExecutionContext, Injectable } from '@nitrostack/core';

@Injectable()
export class RolesGuard implements Guard {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const userRoles = context.clientMetadata?.roles || [];
    return userRoles.includes('admin');
  }
}

Apply the guard using `@UseGuards(...)`:

import { Tool, UseGuards, z } from '@nitrostack/core';
import { RolesGuard } from './roles.guard.js';

export class AdminTools {
  @Tool({
    name: 'delete_system_logs',
    description: 'Delete all system logs from the server.',
    inputSchema: z.object({}),
  })
  @UseGuards(RolesGuard)
  async deleteLogs() {
    return { success: true };
  }
}

---

2. Interceptors (`InterceptorInterface` and `@UseInterceptors`)

Interceptors can transform/intercept input arguments or mapped output from a tool method execution.

Interface:

import { ExecutionContext } from '@nitrostack/core';

export interface InterceptorInterface {
  intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown>;
}

Example:

import { InterceptorInterface, ExecutionContext, Injectable } from '@nitrostack/core';

@Injectable()
export class TimingInterceptor implements InterceptorInterface {
  async intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
    const start = Date.now();
    const result = await next();
    const duration = Date.now() - start;
    context.logger.info(`Execution took ${duration}ms`);
    return {
      ...result,
      _meta: { durationMs: duration }
    };
  }
}

---

3. Exception Filters (`ExceptionFilterInterface` and `@UseFilters`)

Exception filters catch any errors thrown within guards, interceptors, or the tool handlers themselves, mapping them into user-friendly JSON payloads.

Interface:

import { ExecutionContext } from '@nitrostack/core';

export interface ExceptionFilterInterface {
  catch(exception: unknown, context: ExecutionContext): unknown | Promise<unknown>;
}

Example:

import { ExceptionFilterInterface, ExecutionContext, Injectable } from '@nitrostack/core';

@Injectable()
export class CustomExceptionFilter implements ExceptionFilterInterface {
  catch(exception: unknown, context: ExecutionContext) {
    const message = exception instanceof Error ? exception.message : 'Unknown error';
    return {
      error: true,
      message,
      timestamp: new Date().toISOString()
    };
  }
}

Apply the filter using `@UseFilters(...)` on a tool method:

import { Tool, UseFilters, z } from '@nitrostack/core';
import { CustomExceptionFilter } from './custom-exception.filter.js';

export class LoggingTools {
  @Tool({
    name: 'generate_report',
    description: 'Generates system usage reports.',
    inputSchema: z.object({}),
  })
  @UseFilters(CustomExceptionFilter)
  async generateReport() {
    throw new Error('Report generation is not implemented yet.');
  }
}

---

4. Middleware (`MiddlewareInterface`, `@Middleware` and `@UseMiddleware`)

Middleware executes before the request reaches the tool handler, and can wrap the handler execution by invoking `next()`.

Interface:

import { ExecutionContext } from '@nitrostack/core';

export interface MiddlewareInterface {
  use(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown>;
}

Example:

import { Middleware, MiddlewareInterface, ExecutionContext } from '@nitrostack/core';

@Middleware()
export class LoggingMiddleware implements MiddlewareInterface {
  async use(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
    context.logger.info(`Entering tool: ${context.toolName}`);
    try {
      const result = await next();
      context.logger.info(`Exiting tool: ${context.toolName}`);
      return result;
    } catch (error) {
      context.logger.error(`Error in tool: ${error}`);
      throw error;
    }
  }
}

Apply the middleware using `@UseMiddleware(...)` on a tool method:

import { Tool, UseMiddleware, z } from '@nitrostack/core';
import { LoggingMiddleware } from './logging.middleware.js';

export class StationTools {
  @Tool({
    name: 'fetch_logs',
    description: 'Fetch station operations logs.',
    inputSchema: z.object({}),
  })
  @UseMiddleware(LoggingMiddleware)
  async fetchLogs() {
    return { status: 'operational' };
  }
}

---

5. Pipes (`PipeInterface`, `@Pipe` and `@UsePipes`)

Pipes are used to transform or validate input arguments before they reach the tool handler method.

Interface:

import { ArgumentMetadata } from '@nitrostack/core';

export interface PipeInterface<T = unknown, R = unknown> {
  transform(value: T, metadata: ArgumentMetadata): R | Promise<R>;
}

Example:

import { Pipe, PipeInterface, ArgumentMetadata } from '@nitrostack/core';

@Pipe()
export class TrimPipe implements PipeInterface<Record<string, unknown>, Record<string, unknown>> {
  transform(value: Record<string, unknown>, metadata: ArgumentMetadata) {
    const trimmed: Record<string, unknown> = {};
    for (const [
Read more
Ships withnitrostack

The full-stack TypeScript framework to build, test, and deploy production-ready MCP servers and AI-native apps.

Get the whole plugin
Stats
2,528
Stars
1,453
Forks
Active
Maintenance
TypeScript
Language
Apache-2.0
License
10d ago
Last commit
5mo ago
Created

Repo: nitrocloudofficial/nitrostack