MCP Framework

Um framework TypeScript para construir servidores Model Context Protocol (MCP).

Documentação

MCP Framework

MCP-Framework é um framework para construir servidores Model Context Protocol (MCP) de forma elegante em TypeScript.

MCP-Framework oferece arquitetura pronta para uso, com descoberta automática baseada em diretórios para ferramentas, recursos e prompts. Use nossas poderosas abstrações MCP para definir ferramentas, recursos ou prompts de forma elegante. Nossa CLI facilita a criação do seu próprio servidor MCP.

Recursos

  • 🛠️ Descoberta e carregamento automáticos de ferramentas, recursos e prompts
  • Suporte a múltiplos transportes (stdio, SSE, HTTP Stream)
  • Desenvolvimento TypeScript-first com segurança total de tipos
  • Construído sobre o SDK MCP oficial
  • Classes base fáceis de usar para ferramentas, prompts e recursos
  • Autenticação pronta para endpoints SSE (OAuth 2.1, JWT, API Key)

Projetos construídos com MCP Framework

Os seguintes projetos e serviços são construídos usando MCP Framework:

Um serviço de gorjetas em criptomoedas que permite que assistentes de IA ajudem usuários a enviar gorjetas em criptomoedas para criadores de conteúdo diretamente da interface de chat. O serviço MCP permite:

  • Verificar tipos de carteira para usuários
  • Preparar gorjetas em criptomoedas para usuários/agentes concluírem Instruções de configuração para vários clientes (Cursor, Sage, Claude Desktop) estão disponíveis na documentação do servidor MCP.

Apoie nosso trabalho

Tip in Crypto

Leia a documentação completa aqui

Criando um repositório com mcp-framework

Usando a CLI (Recomendado)

# Install the framework globally
npm install -g mcp-framework

# Create a new MCP server project
mcp create my-mcp-server

# Navigate to your project
cd my-mcp-server

# Your server is ready to use!

Uso da CLI

O framework fornece uma CLI poderosa para gerenciar seus projetos de servidor MCP:

Criação de Projeto

# Create a new project
mcp create <your project name here>

# Create a new project with the new EXPERIMENTAL HTTP transport
Heads up: This will set cors allowed origin to "*", modify it in the index if you wish
mcp create <your project name here> --http --port 1337 --cors

Opções:

--http: Usar transporte HTTP em vez do stdio padrão

--port : Especificar porta HTTP (padrão: 8080)

--cors: Habilitar CORS com acesso wildcard (*)

Adicionando uma Ferramenta

# Add a new tool
mcp add tool price-fetcher

Build e Validação

O framework fornece validação abrangente para garantir que suas ferramentas estejam devidamente documentadas e funcionais:

# Build with automatic validation (recommended)
npm run build

# Build with custom validation settings
MCP_SKIP_TOOL_VALIDATION=false npm run build  # Force validation (default)
MCP_SKIP_TOOL_VALIDATION=true npm run build   # Skip validation (not recommended)

Validando Ferramentas

# Validate all tools have proper descriptions (for Zod schemas)
mcp validate

Este comando verifica se todas as ferramentas que usam esquemas Zod possuem descrições para cada campo. A validação é executada automaticamente durante o build, mas você também pode executá-la de forma independente:

  • ✅ Durante o build: npm run build valida ferramentas automaticamente
  • ✅ Independente: mcp validate para validação manual
  • ✅ Desenvolvimento: Use o helper defineSchema() para feedback imediato
  • ✅ Runtime: O servidor valida ferramentas na inicialização

Exemplo de erro de validação:

❌ Tool validation failed:
  ❌ PriceFetcher.js: Missing descriptions for fields in price_fetcher: symbol, currency. 
All fields must have descriptions when using Zod object schemas. 
Use .describe() on each field, e.g., z.string().describe("Field description")

Integrando validação em CI/CD:

{
  "scripts": {
    "build": "tsc && mcp-build",
    "test": "jest && mcp validate",
    "prepack": "npm run build && mcp validate"
  }
}

Adicionando um Prompt

# Add a new prompt
mcp add prompt price-analysis

Adicionando um Recurso

# Add a new resource
mcp add resource market-data

Fluxo de Desenvolvimento

  1. Crie seu projeto:

    mcp create my-mcp-server
    cd my-mcp-server
    
  2. Adicione ferramentas:

    mcp add tool data-fetcher
    mcp add tool data-processor
    mcp add tool report-generator
    
  3. Defina seus esquemas de ferramentas com validação automática:

    // tools/DataFetcher.ts
    import { MCPTool, MCPInput as AddToolInput } from "mcp-framework";
    

import { z } from "zod";

const AddToolSchema = z.object({ a: z.number().describe("First number to add"), b: z.number().describe("Second number to add"), });

class AddTool extends MCPTool { name = "add"; description = "Add tool description"; schema = AddToolSchema;

async execute(input: AddToolInput) { const result = input.a + input.b; return Result: ${result}; } } export default AddTool;


4. **Compile com validação automática:**
```bash
npm run build  # Automatically validates schemas and compiles
  1. Opcional: Execute validação independente:

    mcp validate  # Check all tools independently
    
  2. Teste seu servidor:

    node dist/index.js  # Server validates tools on startup
    
  3. Adicione ao Cliente MCP (veja o exemplo do Claude Desktop abaixo)

Dicas profissionais:

  • Use defineSchema() durante o desenvolvimento para feedback imediato
  • O processo de build detecta automaticamente descrições ausentes
  • A inicialização do servidor valida todas as ferramentas antes de aceitar conexões
  • Use o autocomplete do TypeScript com MCPInput<this> para melhor experiência de desenvolvimento

Usando com Claude Desktop

Desenvolvimento Local

Adicione esta configuração ao arquivo de configuração do Claude Desktop:

MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%/Claude/claude_desktop_config.json

{
"mcpServers": {
"${projectName}": {
      "command": "node",
      "args":["/absolute/path/to/${projectName}/dist/index.js"]
}
}
}

Após Publicação

Adicione esta configuração ao arquivo de configuração do Claude Desktop:

MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%/Claude/claude_desktop_config.json

{
"mcpServers": {
"${projectName}": {
      "command": "npx",
      "args": ["${projectName}"]
}
}
}

Build e Testes

  1. Faça alterações nas suas ferramentas
  2. Execute npm run build para compilar
  3. O servidor carregará automaticamente suas ferramentas na inicialização

Variáveis de Ambiente

O framework suporta as seguintes variáveis de ambiente para configuração:

VariávelDescriçãoPadrão
MCP_ENABLE_FILE_LOGGINGHabilitar registro em arquivos (true/false)false
MCP_LOG_DIRECTORYDiretório onde os arquivos de log serão armazenadoslogs
MCP_DEBUG_CONSOLEExibir mensagens de nível de depuração no console (true/false)false

Exemplo de uso:

# Enable file logging
MCP_ENABLE_FILE_LOGGING=true node dist/index.js

# Specify a custom log directory
MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs node dist/index.js

# Enable debug messages in console
MCP_DEBUG_CONSOLE=true node dist/index.js

Início Rápido

Definindo Ferramentas

MCP Framework usa esquemas Zod para definir entradas de ferramentas, proporcionando segurança de tipos, validação e documentação automática:

import { MCPTool, MCPInput } from "mcp-framework";
import { z } from "zod";

const AddToolSchema = z.object({
  a: z.number().describe("First number to add"),
  b: z.number().describe("Second number to add"),
});

class AddTool extends MCPTool {
  name = "add";
  description = "Add tool description";
  schema = AddToolSchema;

  async execute(input: MCPInput<this>) {
    const result = input.a + input.b;
    return `Result: ${result}`;
  }
}

export default AddTool;

Principais Benefícios:

  • ✅ Fonte única de verdade - Defina tipos e validação em um só lugar
  • ✅ Inferência automática de tipos - Tipos TypeScript são inferidos do seu esquema
  • ✅ Validação rica - Aproveite os poderosos recursos de validação do Zod
  • ✅ Descrições obrigatórias - O framework impõe documentação
  • ✅ Melhor suporte de IDE - Autocomplete completo e verificação de tipos
  • ✅ Código mais limpo - Sem definições de tipos duplicadas

Recursos Avançados de Esquema Zod

O framework suporta todos os recursos do Zod:

import { MCPTool, MCPInput } from "mcp-framework";
import { z } from "zod";

const AdvancedSchema = z.object({
  // String constraints and formats
  email: z.string().email().describe("User email address"),
  name: z.string().min(2).max(50).describe("User name"),
  website: z.string().url().optional().describe("Optional website URL"),
  
  // Number constraints
  age: z.number().int().positive().max(120).describe("User age"),
  rating: z.number().min(1).max(5).describe("Rating from 1 to 5"),
  
  // Arrays and objects
  tags: z.array(z.string()).describe("List of tags"),
  metadata: z.object({
    priority: z.enum(['low', 'medium', 'high']).describe("Task priority"),
    dueDate: z.string().optional().describe("Due date in ISO format")
  }).describe("Additional metadata"),
  
  // Default values
  status: z.string().default('pending').describe("Current status"),
  
  // Unions and enums
  category: z.union([
    z.literal('personal'),
    z.literal('work'),
    z.literal('other')
  ]).describe("Category type")
});

class AdvancedTool extends MCPTool {
  name = "advanced_tool";
  description = "Tool demonstrating advanced Zod features";
  schema = AdvancedSchema;

  async execute(input: MCPInput<this>) {
    // TypeScript automatically knows all the types!
    const { email, name, website, age, rating, tags, metadata, status, category } = input;
    
    console.log(input.name.toUpperCase()); // ✅ TypeScript knows this is valid
    console.log(input.age.toFixed(2));     // ✅ Number methods available
    console.log(input.tags.length);       // ✅ Array methods available
    console.log(input.website?.includes("https")); // ✅ Optional handling
    
    return `Processed user: ${name}`;
  }
}

Inferência Automática de Tipos

O tipo MCPInput<this> infere automaticamente o tipo de entrada correto do seu esquema, eliminando a necessidade de definições manuais de tipos:

class MyTool extends MCPTool {
  schema = z.object({
    name: z.string().describe("User name"),
    age: z.number().optional().describe("User age"),
    tags: z.array(z.string()).describe("User tags")
  });

  async execute(input: MCPInput<this>) {
    // TypeScript automatically knows:
    // input.name is string
    // input.age is number | undefined  
    // input.tags is string[]
    
    console.log(input.name.toUpperCase()); // ✅ TypeScript knows this is valid
    console.log(input.age?.toFixed(2));    // ✅ Handles optional correctly
    console.log(input.tags.length);       // ✅ Array methods available
  }
}

Sem mais interfaces duplicadas ou parâmetros de tipo genérico necessários!

Validação de Esquemas e Descrições

Todos os campos de esquema devem ter descrições. Isso garante que suas ferramentas estejam bem documentadas e proporciona melhor experiência do usuário nos clientes MCP.

O framework valida descrições em múltiplos níveis:

1. Validação em Tempo de Build (Recomendado)

npm run build  # Automatically validates during compilation

2. Validação em Tempo de Desenvolvimento

Use o helper defineSchema para feedback imediato:

import { defineSchema } from "mcp-framework";

// This will throw an error immediately if descriptions are missing
const MySchema = defineSchema({
  name: z.string(),  // ❌ Error: Missing description
  age: z.number().describe("User age")  // ✅ Good
});

3. Validação Independente

mcp validate  # Check all tools for proper descriptions

4. Validação em Runtime

O servidor valida automaticamente as ferramentas na inicialização.

Para pular a validação (não recomendado):

# Skip during build
MCP_SKIP_TOOL_VALIDATION=true npm run build

# Skip during development
NODE_ENV=production npm run dev

Configurando o Servidor

import { MCPServer } from "mcp-framework";

const server = new MCPServer();

// OR (mutually exclusive!) with SSE transport
const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      port: 8080            // Optional (default: 8080)
    }
  }
});

// Start the server
await server.start();

Configuração de Transporte

Transporte stdio (Padrão)

O transporte stdio é usado por padrão se nenhuma configuração de transporte for fornecida:

const server = new MCPServer();
// or explicitly:
const server = new MCPServer({
  transport: { type: "stdio" }
});

Transporte SSE

Para usar o transporte Server-Sent Events (SSE):

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      port: 8080,            // Optional (default: 8080)
      endpoint: "/sse",      // Optional (default: "/sse")
      messageEndpoint: "/messages", // Optional (default: "/messages")
      cors: {
        allowOrigin: "*",    // Optional (default: "*")
        allowMethods: "GET, POST, OPTIONS", // Optional (default: "GET, POST, OPTIONS")
        allowHeaders: "Content-Type, Authorization, x-api-key", // Optional (default: "Content-Type, Authorization, x-api-key")
        exposeHeaders: "Content-Type, Authorization, x-api-key", // Optional (default: "Content-Type, Authorization, x-api-key")
        maxAge: "86400"      // Optional (default: "86400")
      }
    }
  }
});

Transporte HTTP Stream

Para usar o transporte HTTP Stream:

const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: {
      port: 8080,                // Optional (default: 8080)
      endpoint: "/mcp",          // Optional (default: "/mcp") 
      responseMode: "batch",     // Optional (default: "batch"), can be "batch" or "stream"
      batchTimeout: 30000,       // Optional (default: 30000ms) - timeout for batch responses
      maxMessageSize: "4mb",     // Optional (default: "4mb") - maximum message size
      
      // Session configuration
      session: {
        enabled: true,           // Optional (default: true)
        headerName: "Mcp-Session-Id", // Optional (default: "Mcp-Session-Id")
        allowClientTermination: true, // Optional (default: true)
      },
      
      // Stream resumability (for missed messages)
      resumability: {
        enabled: false,          // Optional (default: false)
        historyDuration: 300000, // Optional (default: 300000ms = 5min) - how long to keep message history
      },
      
      // CORS configuration
      cors: {
        allowOrigin: "*"         // Other CORS options use defaults
      }
    }
  }
});

Modos de Resposta

O transporte HTTP Stream suporta dois modos de resposta:

  1. Modo Lote (Padrão): As respostas são coletadas e enviadas como uma única resposta JSON-RPC. Isso é adequado para padrões típicos de requisição-resposta e é mais eficiente para a maioria dos casos de uso.

  2. Modo Stream: Todas as respostas são enviadas por uma conexão SSE persistente aberta para cada requisição. Isso é ideal para operações de longa duração ou quando o servidor precisa enviar múltiplas mensagens em resposta a uma única requisição.

Você pode configurar o modo de resposta de acordo com suas necessidades específicas:

// For batch mode (default):
const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: {
      responseMode: "batch"
    }
  }
});

// For stream mode:
const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: {
      responseMode: "stream"
    }
  }
});

Recursos do Transporte HTTP Stream

  • Gerenciamento de Sessão: Rastreamento e gerenciamento automáticos de sessão
  • Retomabilidade de Stream: Suporte opcional para retomar streams após perda de conexão
  • Processamento em Lote: Suporte para requisições/respostas em lote JSON-RPC
  • Tratamento Abrangente de Erros: Respostas de erro detalhadas com códigos de erro JSON-RPC

Autenticação

MCP Framework fornece autenticação opcional para endpoints SSE. Você pode escolher entre autenticação JWT, API Key, OAuth 2.1, ou implementar seu próprio provedor de autenticação personalizado.

Autenticação JWT

import { MCPServer, JWTAuthProvider } from "mcp-framework";
import { Algorithm } from "jsonwebtoken";

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      auth: {
        provider: new JWTAuthProvider({
          secret: process.env.JWT_SECRET,
          algorithms: ["HS256" as Algorithm], // Optional (default: ["HS256"])
          headerName: "Authorization"         // Optional (default: "Authorization")
        }),
        endpoints: {
          sse: true,      // Protect SSE endpoint (default: false)
          messages: true  // Protect message endpoint (default: true)
        }
      }
    }
  }
});

Os clientes devem incluir um token JWT válido no cabeçalho Authorization:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Autenticação API Key

import { MCPServer, APIKeyAuthProvider } from "mcp-framework";

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      auth: {
        provider: new APIKeyAuthProvider({
          keys: [process.env.API_KEY],
          headerName: "X-API-Key" // Optional (default: "X-API-Key")
        })
      }
    }
  }
});

Os clientes devem incluir uma chave de API válida no cabeçalho X-API-Key:

X-API-Key: your-api-key

Autenticação OAuth 2.1

MCP Framework suporta autenticação OAuth 2.1 conforme a especificação MCP (2025-06-18), incluindo Metadados de Recursos Protegidos (RFC 9728) e validação adequada de tokens com suporte a JWKS.

A autenticação OAuth funciona com transportes SSE e HTTP Stream e suporta duas estratégias de validação:

Validação JWT (Recomendada para Performance)

A validação JWT busca chaves públicas no endpoint JWKS do seu servidor de autorização e valida tokens localmente. Esta é a opção mais rápida, pois não requer uma ida e volta ao servidor de autenticação para cada requisição.

import { MCPServer, OAuthAuthProvider } from "mcp-framework";

const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: {
      port: 8080,
      auth: {
        provider: new OAuthAuthProvider({
          authorizationServers: [
            process.env.OAUTH_AUTHORIZATION_SERVER
          ],
          resource: process.env.OAUTH_RESOURCE,
          validation: {
            type: 'jwt',
            jwksUri: process.env.OAUTH_JWKS_URI,
            audience: process.env.OAUTH_AUDIENCE,
            issuer: process.env.OAUTH_ISSUER,
            algorithms: ['RS256', 'ES256'] // Optional (default: ['RS256', 'ES256'])
          }
        }),
        endpoints: {
          initialize: true,  // Protect session initialization
          messages: true     // Protect MCP messages
        }
      }
    }
  }
});

Variáveis de Ambiente:

OAUTH_AUTHORIZATION_SERVER=https://auth.example.com
OAUTH_RESOURCE=https://mcp.example.com
OAUTH_JWKS_URI=https://auth.example.com/.well-known/jwks.json
OAUTH_AUDIENCE=https://mcp.example.com
OAUTH_ISSUER=https://auth.example.com

Introspecção de Token (Recomendada para Controle Centralizado)

A introspecção de token valida tokens chamando o endpoint de introspecção do seu servidor de autorização. Isso fornece controle centralizado e é útil quando você precisa de revogação de tokens em tempo real.

import { MCPServer, OAuthAuthProvider } from "mcp-framework";

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      auth: {
        provider: new OAuthAuthProvider({
          authorizationServers: [
            process.env.OAUTH_AUTHORIZATION_SERVER
          ],
          resource: process.env.OAUTH_RESOURCE,
          validation: {
            type: 'introspection',
            audience: process.env.OAUTH_AUDIENCE,
            issuer: process.env.OAUTH_ISSUER,
            introspection: {
              endpoint: process.env.OAUTH_INTROSPECTION_ENDPOINT,
              clientId: process.env.OAUTH_CLIENT_ID,
              clientSecret: process.env.OAUTH_CLIENT_SECRET
            }
          }
        })
      }
    }
  }
});

Variáveis de Ambiente:

OAUTH_AUTHORIZATION_SERVER=https://auth.example.com
OAUTH_RESOURCE=https://mcp.example.com
OAUTH_AUDIENCE=https://mcp.example.com
OAUTH_ISSUER=https://auth.example.com
OAUTH_INTROSPECTION_ENDPOINT=https://auth.example.com/oauth/introspect
OAUTH_CLIENT_ID=mcp-server
OAUTH_CLIENT_SECRET=your-client-secret

Recursos OAuth

  • Conformidade RFC 9728: Endpoint automático de Metadados de Recursos Protegidos em /.well-known/oauth-protected-resource
  • Cabeçalhos WWW-Authenticate RFC 6750: Respostas de erro OAuth adequadas com cabeçalhos de desafio
  • Cache de Chaves JWKS: Chaves públicas armazenadas em cache por 15 minutos (configurável)
  • Cache de Introspecção de Token: Resultados de introspecção armazenados em cache por 5 minutos (configurável)
  • Segurança: Tokens em strings de consulta são rejeitados automaticamente
  • Extração de Claims: Claims de token de acesso em seus manipuladores de ferramentas via AuthResult

Provedores OAuth Populares

O provedor OAuth funciona com qualquer servidor de autorização OAuth 2.1 compatível com RFC:

  • Auth0: Use o URI JWKS e emissor do seu tenant Auth0
  • Okta: Use a configuração do servidor de autorização Okta
  • AWS Cognito: Use o endpoint JWKS do seu pool de usuários Cognito
  • Azure AD / Entra ID: Use endpoints do Microsoft Entra ID
  • Personalizado: Qualquer servidor de autorização compatível com OAuth 2.1

Para guias de configuração detalhados com provedores específicos, veja o Guia de Configuração OAuth.

Uso pelo Cliente

Os clientes devem incluir um token de acesso OAuth válido no cabeçalho Authorization:

# Make a request with OAuth token
curl -X POST http://localhost:8080/mcp \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'

# Discover OAuth configuration
curl http://localhost:8080/.well-known/oauth-protected-resource

Melhores Práticas de Segurança

  • Sempre use HTTPS em produção - Tokens OAuth nunca devem ser transmitidos por conexões não criptografadas
  • Valide claims de audiência - Previne reutilização de tokens entre diferentes serviços
  • Use tokens de curta duração - Reduz o risco se tokens forem comprometidos
  • Habilite cache de introspecção de token - Reduz a carga no servidor de autorização mantendo a segurança
  • Monitore erros de token - Acompanhe tentativas de autenticação falhas para insights de segurança

Autenticação Personalizada

Você pode implementar seu próprio provedor de autenticação implementando a interface AuthProvider:

import { AuthProvider, AuthResult } from "mcp-framework";
import { IncomingMessage } from "node:http";

class CustomAuthProvider implements AuthProvider {
  async authenticate(req: IncomingMessage): Promise<boolean | AuthResult> {
    // Implement your custom authentication logic
    return true;
  }

  getAuthError() {
    return {
      status: 401,
      message: "Authentication failed"
    };
  }
}

Servidores MCP de Documentação (@mcpframework/docs)

Inicie um servidor MCP de documentação a partir de qualquer site Fumadocs ou qualquer site com llms.txt — agentes de IA obtêm ferramentas para pesquisar, navegar e recuperar sua documentação.

Início Rápido (CLI)

# Scaffold a new docs MCP server project
npx create-docs-mcp my-api-docs
cd my-api-docs

# Configure your docs site URL
cp .env.example .env
# Edit .env → set DOCS_BASE_URL=https://docs.myapi.com

# Build and run
npm run build
npm start

Início Rápido (Programático)

import { DocsServer, FumadocsRemoteSource } from "@mcpframework/docs";

const source = new FumadocsRemoteSource({
  baseUrl: "https://docs.myapi.com",
});

const server = new DocsServer({
  source,
  name: "my-api-docs",
  version: "1.0.0",
});

server.start();

Adaptadores de Fonte

AdaptadorMelhor ParaPesquisa
FumadocsRemoteSourceSites FumadocsPesquisa nativa Orama com fallback
LlmsTxtSourceQualquer site com llms.txtCorrespondência de texto local
DocSource personalizadoQualquer backend de documentaçãoSua implementação

Ferramentas MCP Integradas

FerramentaDescrição
search_docsPesquisar documentação por palavra-chave ou frase
get_pageRecuperar conteúdo markdown completo de uma página
list_sectionsNavegar pela estrutura da árvore de documentação

Adicione ao Seu Cliente MCP

# Claude Code
claude mcp add my-api-docs -- node /path/to/my-api-docs/dist/index.js

# Or with environment variable
claude mcp add my-api-docs -e DOCS_BASE_URL=https://docs.myapi.com -- node /path/to/my-api-docs/dist/index.js

Para configuração do Claude Desktop / Cursor e documentação completa, veja o README do @mcpframework/docs.

Licença

MIT