Skip to content

Integración LSP (Language Server Protocol)

Versión: 1.0 Última actualización: 2026-01-26


Introducción

La integración LSP permite a mcp-scan comunicarse con servidores de lenguaje como Pyright (Python), typescript-language-server (TypeScript/JavaScript) y gopls (Go). Esto proporciona:

  • Análisis type-aware: Detección basada en tipos reales, no solo patrones
  • Call graphs precisos: Construcción de grafos de llamadas usando información del servidor
  • Resolución de símbolos: Seguimiento preciso de definiciones y referencias
  • Detección de tipos peligrosos: Identificación de Any, object, unknown

Arquitectura

┌─────────────────────────────────────────────────────────────────┐
│                         mcp-scan                                 │
│  ┌─────────────────────────────────────────────────────────────┐│
│  │                      LSP Manager                             ││
│  │  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐           ││
│  │  │   Python    │ │ TypeScript  │ │     Go      │           ││
│  │  │   Client    │ │   Client    │ │   Client    │           ││
│  │  └──────┬──────┘ └──────┬──────┘ └──────┬──────┘           ││
│  └─────────┼───────────────┼───────────────┼───────────────────┘│
└────────────┼───────────────┼───────────────┼────────────────────┘
             │               │               │
    JSON-RPC │      JSON-RPC │      JSON-RPC │
    (stdio)  │       (stdio) │       (stdio) │
             │               │               │
    ┌────────▼────────┐ ┌────▼─────┐ ┌───────▼───────┐
    │     Pyright     │ │ tsserver │ │     gopls     │
    │  (subprocess)   │ │(subproc) │ │  (subprocess) │
    └─────────────────┘ └──────────┘ └───────────────┘

Protocolo de Comunicación

LSP usa JSON-RPC 2.0 sobre stdio:

  1. Requests: Cliente envía método + params, servidor responde
  2. Notifications: Cliente envía sin esperar respuesta
  3. Headers: Content-Length: N\r\n\r\n{json}

Requisitos de Instalación

Servidores de Lenguaje Soportados

Lenguaje Servidor Comando
Python Pyright pyright-langserver --stdio
TypeScript typescript-language-server typescript-language-server --stdio
JavaScript typescript-language-server typescript-language-server --stdio
Go gopls gopls serve

Instalación de Servidores

Python (Pyright)

# Con npm (recomendado)
npm install -g pyright

# Verificar instalación
pyright-langserver --version

Nota: Pyright requiere Node.js 14+.

TypeScript/JavaScript

# Instalar typescript-language-server y typescript
npm install -g typescript typescript-language-server

# Verificar instalación
typescript-language-server --version

Go (gopls)

# Instalar gopls
go install golang.org/x/tools/gopls@latest

# Verificar que está en PATH
# Si ~/go/bin no está en PATH, añadirlo:
export PATH=$PATH:~/go/bin

# Verificar instalación
gopls version

Ubicaciones de Búsqueda

mcp-scan busca servidores en estas ubicaciones:

  1. $PATH del sistema
  2. ~/go/bin (binarios de Go)
  3. ~/.local/bin
  4. /usr/local/bin
  5. /opt/homebrew/bin (macOS ARM)
  6. ~/.npm-global/bin
  7. ~/node_modules/.bin

Uso desde CLI

Habilitar LSP

# Escaneo con LSP habilitado
mcp-scan scan --lsp ./mi-servidor-mcp

# Escaneo con modo debug LSP
LSP_DEBUG=1 mcp-scan scan --lsp ./mi-servidor-mcp

Configuración YAML

# .mcp-scan.yaml
lsp:
  enabled: true
  languages:
    - python
    - typescript
    - javascript
    - go

Output de Progreso

[*] Scanning ./mi-servidor-mcp...
[*] LSP: enabled
[*] Discovered 5 files
[*] Running pattern analysis...
[+] Scan completed in 2.3s
[+] Found 3 findings (2 high, 1 medium)

Debug Mode

Con LSP_DEBUG=1:

[LSP] Found 5 symbols, 4 functions in server.py
[LSP] Analyzing tool get_company_data at server.py:31:4
[LSP]   type: (function) def get_company_data(data_type: str) -> str
[LSP]   call graph: get_company_data -> 1 callees

Capacidades del Motor LSP

Operaciones Soportadas

Operación Método LSP Uso
Hover textDocument/hover Obtener tipos y documentación
Definition textDocument/definition Ir a definición
References textDocument/references Encontrar todas las referencias
Document Symbols textDocument/documentSymbol Listar símbolos del archivo
Call Hierarchy textDocument/prepareCallHierarchy Preparar jerarquía de llamadas
Incoming Calls callHierarchy/incomingCalls Quién llama a una función
Outgoing Calls callHierarchy/outgoingCalls A quién llama una función

Flujo de Detección

1. Identificar Tool Handler
2. Abrir documento en servidor LSP
3. Obtener símbolos del documento (GetDocumentSymbols)
4. Encontrar función handler por nombre
5. Obtener tipo con hover en SelectionRange
6. Verificar tipos peligrosos (Any, object, unknown)
7. Construir call graph desde handler
8. Buscar sinks peligrosos en el grafo
9. Generar findings con contexto de tipo
10. Cerrar documento

Reglas de Detección LSP

LSP-TYPE-001: Patrón de Tipo Peligroso

Severidad: Medium Confianza: Medium

Detecta cuando un tool handler tiene un tipo peligroso como Any, object o unknown.

# DETECTADO: parámetro con tipo Any
from typing import Any

@mcp.tool()
async def process_data(data: Any):  # LSP-TYPE-001
    # data puede ser cualquier cosa
    eval(str(data))

Tipos peligrosos:

Tipo Lenguaje Riesgo
Any Python Sin verificación de tipos
object Python/TS Genérico, sin restricciones
unknown TypeScript Tipo inseguro
any TypeScript Sin verificación de tipos

LSP-TYPE-002: Parámetro con Tipo Loose

Severidad: Low Confianza: Medium

Detecta parámetros en el schema del tool con tipos loose.

@mcp.tool(
    schema={
        "properties": {
            "data": {"type": "object"}  # LSP-TYPE-002
        }
    }
)
async def process(data):
    pass

LSP-SINK-001: Input de Tool Alcanza Sink Peligroso

Severidad: High Confianza: Medium

Detecta cuando un tool handler puede alcanzar un sink peligroso a través del call graph.

@mcp.tool()
async def execute_command(cmd: str):
    # LSP construye call graph y encuentra camino a os.system
    helper(cmd)

def helper(command):
    run_shell(command)

def run_shell(cmd):
    os.system(cmd)  # LSP-SINK-001: Sink peligroso alcanzado

Sinks peligrosos rastreados:

Sink Tipo Lenguaje
os.system Ejecución de comandos Python
subprocess.run Ejecución de comandos Python
subprocess.Popen Ejecución de comandos Python
eval Evaluación de código Python/JS
exec Ejecución de código Python
open Acceso a ficheros Python
sqlite3.execute Ejecución SQL Python
cursor.execute Ejecución SQL Python
requests.get Petición HTTP Python
urllib.request Petición HTTP Python
child_process.exec Ejecución de comandos Node.js
child_process.spawn Ejecución de comandos Node.js

Construcción del Call Graph

Algoritmo

1. PrepareCallHierarchy en posición del handler
2. Crear nodo raíz con información del símbolo
3. Para cada profundidad hasta maxDepth:
   ├── GetOutgoingCalls del nodo actual
   │         │
   │         ▼
   ├── Para cada llamada:
   │   │
   │   ├── Crear nodo para el callee
   │   │
   │   ├── Añadir edge con call sites
   │   │
   │   └── Recursión si no visitado
   └── Marcar nodo como visitado

Profundidad de Análisis

Profundidad Caso de Uso
1-2 Verificaciones rápidas, solo llamadas directas
3-5 Análisis estándar, cubre mayoría de vulnerabilidades
5-10 Análisis profundo, cadenas de llamadas complejas
10+ Análisis exhaustivo, impacto en rendimiento

Default: mcp-scan usa profundidad 5.


Rendimiento

Tiempos de Arranque

Servidor Arranque en frío Con caché
Pyright 2-5s <100ms
tsserver 1-3s <100ms
gopls 1-2s <100ms

Uso de Memoria

Servidor Memoria base Por 1000 ficheros
Pyright ~150MB +50MB
tsserver ~200MB +80MB
gopls ~100MB +30MB

Optimizaciones

  1. Caché de clientes: El manager mantiene clientes activos entre análisis
  2. Documento abierto una vez: Se abre al inicio y se cierra al final
  3. Visitation tracking: El call graph no revisita nodos ya visitados

Integración con Otros Motores

Con Motor de Patrones

LSP complementa las reglas de patrones proporcionando contexto de tipos:

Pattern Engine          LSP Detector
      │                      │
      │ Detecta llamada      │ Verifica tipo
      │ a subprocess.run     │ del argumento
      │                      │
      └──────────┬───────────┘
         Finding combinado:
         - Pattern: MCP-A001
         - LSP: tipo str verificado
         - Confianza: ALTA

Con Motor de Taint

LSP mejora la precisión del taint analysis:

Taint Engine                    LSP
      │                          │
      │ Detecta flujo            │ Obtiene tipos
      │ source → sink            │ en cada paso
      │                          │
      │ Puede perder tipo        │ Confirma que
      │ en propagación           │ tipo se mantiene
      │                          │
      └───────────┬──────────────┘
          Traza con tipos:
          [str] → [str] → [str] → sink

Limitaciones

Limitaciones Actuales

Limitación Impacto Mitigación
Requiere servidor instalado No funciona sin servidor Mensaje claro de error
Arranque lento Primera ejecución lenta Caché de clientes
Proyectos grandes Alto uso de memoria Limitar ficheros analizados
Código dinámico No puede seguir getattr Fallback a pattern matching
Cross-file limitado Depende del servidor gopls tiene mejor soporte

Casos No Soportados

# LSP no puede seguir esto:
func = getattr(module, "dangerous_" + user_input)
func()

# LSP no puede analizar eval:
code = f"subprocess.run('{cmd}')"
eval(code)

# Metaprogramación:
class Meta(type):
    def __new__(cls, name, bases, dct):
        dct['run'] = lambda self, x: os.system(x)
        return super().__new__(cls, name, bases, dct)

Troubleshooting

Problemas Comunes

Problema: El servidor no arranca

Error: language server not found: pyright-langserver
Solución: Instalar el servidor globalmente:
npm install -g pyright

Problema: No se encuentra gopls

Error: command not found: gopls
Solución: Asegurar que ~/go/bin está en PATH:
export PATH=$PATH:~/go/bin

Problema: No se obtiene información de tipos

[LSP] type: (nil)
Solución: Verificar que el proyecto tiene configuración válida (pyproject.toml, tsconfig.json, go.mod).

Problema: Análisis lento Solución: 1. Reducir profundidad del call graph 2. Limitar ficheros analizados 3. Usar --mode fast

Verificar Instalación

# Python
pyright-langserver --version

# TypeScript
typescript-language-server --version

# Go
gopls version

# Ejecutar con debug para ver qué servidores se encuentran
LSP_DEBUG=1 mcp-scan scan --lsp ./proyecto

Referencias


Esta documentación es para analistas de seguridad. Para uso general, consultar guia-usuario/.