CotForce MCP
Servidor MCP que impone el razonamiento paso a paso (Chain-of-Thought) — convierte modelos 4B
Documentación
CotForce-MCP
"Dale cerebro a tus modelos pequeños."
CotForce impone el razonamiento paso a paso (Chain-of-Thought), convirtiendo modelos de 4B parámetros en razonadores metódicos.
Por qué existe esto
Un Gemma de 4 mil millones de parámetros no puede resolver SEND + MORE = MONEY. Es un clásico acertijo criptoaritmético — 8 dígitos únicos, 5 columnas, 4 valores de acarreo. Un modelo 4B desnudo adivina al azar. Alucina dígitos. Pierde el rastro de los acarreos después de la columna 2.
El mismo modelo, con CotForce:
Step 1: Analyze the leftmost column. S+M+C3 = MO. Max sum is 19998. ∴ M=1.
Step 2: S+1+C3 = 10+O. With M=1 and carry, O must be 0.
Step 3: D+E = Y+10C1 → C1=1. Now R+C1=9 → C1=0→R=9 (used), C1=1→R=8.
...
Step 11: All digits assigned. 9567 + 1085 = 10652. Verified.
11 pasos estructurados de razonamiento. Cero alucinaciones. Respuesta correcta.
CotForce no hace más inteligentes a los modelos pequeños. Los obliga a pensar antes de hablar — que suele ser todo lo que necesitan.
⚡ Dos modos — una línea de configuración
CotForce usa el protocolo de muestreo MCP (sampling/createMessage) para llamar a los LLM. Si tu cliente lo soporta (Claude Desktop, Cursor), no necesitas nada adicional.
Si no — o si estás usando un modelo local como Gemma vía LMStudio — cambia al modo HTTP directo:
{
"mcpServers": {
"cotforce": {
"command": "node",
"args": ["node_modules/@slbdn/cotforce-mcp/index.js"],
"env": {
"MODE": "direct",
"API_BASE_URL": "http://localhost:1234/v1",
"MODEL": "gemma-4-e4b-it-mlx"
}
}
}
}
Eso es todo. El mismo Gemma 4B que no podía resolver SEND+MORE=MONEY arriba — ahora con CotForce, funcionando localmente a través de LMStudio.
🚀 Características
- Imposición rígida de CoT — obliga a cualquier LLM a generar JSON válido
{reasoning, result}mediante prompts de sistema estrictos y ejemplos few-shot. - Parser adaptativo multicapa — arquitectura de plugins con 5 parsers integrados (JSON directo, bloques delimitados, XML/etiquetas, balanceo de llaves, recuperación truncada) en un pipeline ordenado por prioridad. Añade parsers personalizados vía la interfaz
CotParser. Selecciona parsers mediante la variable de entornoCOT_PARSERS.- JSON directo (con eliminación de cercas de código)
- JSON dentro de bloques delimitados de markdown
- Extracción por XML / etiquetas heurísticas (
<reasoning>,Reasoning:) - Escáner de balanceo de llaves para objetos JSON anidados
- Validación en tiempo de ejecución con Zod — valida argumentos de herramientas y salida CoT parseada con esquemas estrictos.
- Reintento automático con aumento de temperatura — hasta 3 intentos (configurable) con temperatura creciente y sufijos de corrección.
- Memorándum de rechazo por solicitud — sin estado mutable global; seguro bajo llamadas concurrentes a herramientas.
- Presupuesto de tokens con tiktoken — conteo preciso de tokens usando la codificación
cl100k_basede OpenAI, con respaldo a heurística de caracteres. Ajusta víaREASONING_OVERHEAD. - Modelo configurable — establece la variable de entorno
MODELpara sugerir un modelo específico; déjala sin definir para el predeterminado del host. - Prompts específicos por modelo — selecciona automáticamente prompts de sistema ajustados para Claude, GPT-4, Gemini y Grok según
MODEL. - Compatibilidad universal — funciona con muestreo MCP (Claude Desktop) o llamadas HTTP directas a LLM (OpenAI, LMStudio, Ollama, cualquier API compatible con OpenAI). Establece
API_KEYpara usar modo directo. - Registro estructurado — registros con marca de tiempo y filtro por nivel a stderr (soporta
LOG_LEVEL). - Detección de truncamiento de salida — detecta cuando la respuesta del LLM alcanza el límite de tokens y reintenta con una pista de concisión (
TRUNCATION_THRESHOLD). - Exposición de uso de tokens — cada respuesta incluye conteos de tokens de entrada / salida / presupuesto para que los llamadores puedan optimizar.
- Esquema de resultado proporcionado por el usuario — el parámetro opcional
resultSchemavalida el mapa de tipos del camporesult; las discrepancias provocan reintentos. - Métricas estructuradas — contadores en memoria para solicitudes, tasas de éxito/fallo, truncamientos, reintentos, latencia y uso de tokens. Registrados al apagar.
- Suite de pruebas integral — 151 pruebas que cubren el pipeline de parsers, presupuesto de tokens, métricas, validación de esquemas, bucle de reintentos, notificaciones de progreso, caché e integración del servidor MCP.
📦 Instalación
npm install @slbdn/cotforce-mcp
# or
git clone https://github.com/islobodan/cotforce-mcp
cd cotforce-mcp
npm install
npm run build
Requiere Node.js ≥ 18.
Inicio rápido — Claude Desktop
Añade a claude_desktop_config.json:
{
"mcpServers": {
"cotforce": {
"command": "npx",
"args": ["-y", "@slbdn/cotforce-mcp"],
"env": {
"MODEL": "claude-3-5-sonnet"
}
}
}
}
Sin clonar, sin compilar. npx -y descarga y ejecuta directamente desde npm.
🔧 Configuración
El servidor se configura mediante variables de entorno (todas opcionales):
| Variable | Predeterminado | Descripción |
|---|---|---|
MODEL | (no definida) | Sugerencia de nombre de modelo (p. ej. claude-3-5-sonnet, gpt-4o). Si está vacía, no se envía sugerencia – el host MCP decide. |
MAX_RETRIES | 2 | Número de intentos de reintento antes de devolver la salida cruda. |
BASE_TEMP | 0.1 | Temperatura inicial de muestreo. |
TEMP_INCREMENT | 0.2 | Temperatura añadida por cada intento de reintento. |
TIMEOUT | 60000 / 120000 | Tiempo de espera de muestreo en ms (60s). El modo HTTP directo usa un valor predeterminado más largo (120s) porque los modelos locales son más lentos. |
CACHE_TTL | 3600000 | TTL de caché de resultados en ms (predeterminado 1 hora). Establece a 0 para desactivar. |
CACHE_MAX_ENTRIES | 100 | Máximo de resultados en caché antes de expulsar los más antiguos. |
COT_PARSERS | (todos) | Nombres de parsers separados por comas a usar (p. ej., direct-json,fenced-block). Omite los demás. |
TRUNCATION_THRESHOLD | 0.95 | Proporción de salida/presupuesto que activa la detección de truncamiento. Primero intenta recuperar JSON truncado, luego reintenta con 1.5x de presupuesto. |
REASONING_OVERHEAD | 800 | Sobrecarga fija de tokens añadida a la fórmula de presupuesto. Auméntala para modelos verbosos. |
FALLBACK_MODELS | (no definida) | Lista separada por comas de modelos de respaldo (p. ej. gpt-4o,claude-3-5-sonnet). Se recorren en caso de fallo. |
MODE | auto | auto, sampling o direct. auto usa HTTP directo cuando API_KEY está definida y el cliente carece de soporte de muestreo. |
API_KEY | (no definida) | Clave API del LLM para modo HTTP directo. Opcional para endpoints locales (LMStudio, Ollama). Requerida para proveedores remotos (OpenAI, Anthropic, etc.). |
API_BASE_URL | https://api.openai.com | URL base para modo HTTP directo. Cámbiala para LMStudio (http://localhost:1234/v1) u otros proveedores. |
LOG_LEVEL | INFO | Uno de DEBUG, INFO, WARN, ERROR. |
Ejemplo
MODEL=gpt-4o MAX_RETRIES=3 BASE_TEMP=0.2 TEMP_INCREMENT=0.15 LOG_LEVEL=DEBUG npx @slbdn/cotforce-mcp
🧪 Uso
Como herramienta MCP
Añade a la configuración de tu cliente MCP. Se incluye un archivo .mcp.json en el paquete para auto-descubrimiento por clientes como Cursor, VS Code y Windsurf. Copia la configuración relevante a los ajustes de tu cliente:
Con muestreo MCP (Claude Desktop):
{
"mcpServers": {
"cotforce": {
"command": "node",
"args": ["/path/to/cotforce-mcp/index.js"],
"env": {
"MODEL": "claude-3-5-sonnet",
"MAX_RETRIES": "2"
}
}
}
}
Con HTTP directo a LLM (LMStudio, OpenAI, Ollama):
{
"mcpServers": {
"cotforce": {
"command": "node",
"args": ["/path/to/cotforce-mcp/index.js"],
"env": {
"MODE": "direct",
"API_BASE_URL": "http://localhost:1234/v1",
"MODEL": "local-model",
"MAX_RETRIES": "2"
}
}
}
}
Nota:
API_KEYes opcional para endpoints locales como LMStudio u Ollama. Es requerida para proveedores remotos como OpenAI o Anthropic.
El
index.jsraíz es un lanzador que delega endist/index.js. Protege contra builds faltantes con un mensaje de error útil.
🩺 Solución de problemas
Respuesta truncada a mitad del razonamiento
Lo que ves: finish_reason: "length" en la respuesta del LLM. El razonamiento se corta antes del campo result.
Por qué: El presupuesto de tokens es demasiado ajustado. Un razonamiento complejo (como SEND+MORE=MONEY) puede necesitar 3000+ tokens de salida, pero el mínimo predeterminado es 4096 — mientras que el límite predeterminado a nivel de modelo puede variar.
Solución: Aumenta la sobrecarga del presupuesto:
REASONING_OVERHEAD=1600 # default is 800, raise for verbose models
O salta las capas de parser que consumen muchos tokens para ahorrar presupuesto para el razonamiento:
COT_PARSERS=direct-json,fenced-block # skip heuristic and brace-balanced
Tiempo de espera agotado del cliente MCP
Lo que ves: MCP error -32001: Request timed out antes de que aparezca la solución.
Por qué: El razonamiento CoT complejo lleva tiempo — 60-90 segundos para modelos locales como Gemma. Este error puede venir de dos lugares:
- El propio tiempo de espera de CotForce — predeterminado 120s para modo HTTP directo. Controlado por la variable de entorno
TIMEOUT. - El tiempo de espera del cliente MCP — LM Studio, Claude Desktop, Cursor, etc. tienen cada uno su propio tiempo de espera predeterminado para llamadas a herramientas (a menudo 30-60s). Esto es independiente del tiempo de espera de CotForce.
Solución — revisa ambos lados:
Aumenta el tiempo de espera de CotForce:
TIMEOUT=180000 # 3 minutes
Revisa el ajuste de tiempo de espera de tu cliente MCP:
LM Studio — añade "timeout" a mcp.json (milisegundos):
{
"mcpServers": {
"cotforce": {
"command": "node",
"args": ["index.js"],
"env": {
"TIMEOUT": "180000"
},
"timeout": 300000
}
}
}
Claude Desktop — el tiempo de espera de llamadas a herramientas no es directamente configurable. Un workaround es aumentar el TIMEOUT de CotForce para completar dentro de la ventana del cliente, o usar un modelo más rápido.
Cursor / VS Code — revisa la extensión MCP o .vscode/mcp.json para un ajuste de timeout o requestTimeout.
Llama a la herramienta
{
"name": "solve_problem",
"arguments": {
"prompt": "What is 7 * 8 + 2?"
}
}
Con validación de esquema de resultado
{
"name": "solve_problem",
"arguments": {
"prompt": "List the prime numbers between 10 and 20",
"resultSchema": {
"primes": "object",
"count": "number"
}
}
}
Si el campo result no coincide con el esquema, el servidor reintenta con una pista de corrección.
Más ejemplos
Consulta EXAMPLES.md para 16 ejemplos diversos que incluyen:
- Acertijos de lógica, probabilidad, problemas de palabras
- Análisis de código, regex, consultas SQL
- Escritura creativa, adaptación de recetas
- JSON anidado con validación de esquema
- Uso con diferentes modelos y respaldos
Ejemplo de respuesta
{
"content": [{
"type": "text",
"text": "🤖 Agentic CoT Result:\n\n**Reasoning:** Step 1: Multiply 7 * 8 = 56. Step 2: Add 2 to get 58.\n\n**Answer:** 58\n\n📊 Token Usage: 42 in / 150 out / 4096 budget"
}]
}
Si el parseo falla tras todos los reintentos, el servidor devuelve la salida cruda del LLM con una advertencia.
🧩 Parsers personalizados
El parser es un pipeline de plugins ordenado por prioridad. Cinco parsers integrados se ejecutan en orden:
| Prioridad | Nombre | Qué hace |
|---|---|---|
| 10 | direct-json | Parsea toda la salida como JSON (elimina cercas ```json) |
| 20 | fenced-block | Extrae JSON de bloques de código markdown |
| 30 | heuristic | Busca etiquetas XML <reasoning>/<result> o etiquetas Reasoning:/Result: |
| 40 | brace-balanced | Encuentra el primer {} balanceado en texto arbitrario |
| 50 | truncated-recovery | Recupera razonamiento de JSON truncado (alcanzó el límite de tokens) |
Filtra parsers vía la variable de entorno COT_PARSERS:
COT_PARSERS=direct-json,fenced-block node index.js
Escribe un parser personalizado:
import { CotParser, AgenticCotSchema } from "@slbdn/cotforce-mcp";
class YamlParser implements CotParser {
name = "yaml";
priority = 35; // runs after heuristic, before brace-balanced
parse(raw: string): { reasoning: string; result: unknown } | null {
// Custom YAML parsing logic here
return null; // return null if this output isn't YAML
}
}
Luego regístralo programáticamente:
import { defaultParserPipeline, ParserPipeline } from "@slbdn/cotforce-mcp";
const pipeline = defaultParserPipeline();
pipeline.addParser(new YamlParser());
const result = pipeline.parse(rawText);
📚 API
Herramienta: solve_problem
- Entrada:
{ prompt: string }— el problema a resolver. - Salida: ya sea:
- Éxito — resultado CoT estructurado.
- Fallo suave — salida cruda del LLM si el parseo falla tras todos los reintentos.
Muestreo / Llamada al LLM
CotForce soporta dos modos para llamar al LLM:
Muestreo MCP (predeterminado con clientes compatibles):
- Usa
sampling/createMessagenativo de MCP - El cliente selecciona y llama al modelo
- Requiere soporte del cliente (Claude Desktop, etc.)
HTTP directo (para clientes sin soporte de muestreo):
- Llama directamente a
/v1/chat/completionscompatible con OpenAI - Funciona con OpenAI, LMStudio, Ollama y cualquier proveedor compatible
- Se activa automáticamente en
MODE=autocuandoAPI_KEYestá definida y el cliente carece de muestreo - O fuerza con
MODE=direct
Ambos modos usan el mismo prompt de sistema con ejemplos few-shot y restricciones estrictas de esquema.
🏗️ Arquitectura
cotforce-mcp/
├── src/
│ ├── index.ts # MCP server, tool handlers, routing logic
│ └── lib/
│ ├── parser.ts # Parser pipeline: CotParser interface + 5 plugin parsers + Zod schemas
│ ├── tokens.ts # tiktoken integration + budget computation
│ ├── prompts.ts # Model-specific system prompts
│ ├── metrics.ts # In-memory request/performance counters
│ └── llm.ts # Direct HTTP LLM client (OpenAI-compatible)
├── tests/
│ ├── cache.test.ts # 10 unit tests for result caching
│ ├── parser.test.ts # 47 unit tests for parser layers
│ ├── tokens.test.ts # 23 unit tests for token budgeting
│ ├── schema.test.ts # 8 unit tests for result schema validation
│ ├── metrics.test.ts # 9 unit tests for metrics tracking
│ ├── prompts.test.ts # 12 unit tests for model-specific prompts
│ ├── llm.test.ts # 6 tests for direct mode detection
│ ├── retry.test.ts # 4 integration tests for retry loop
│ ├── progress.test.ts # 5 unit tests for progress notifications
│ └── server.test.ts # 9 integration tests via @slbdn/mcp-tester
├── index.js # Root launcher (delegates to dist/)
├── dist/ # Compiled TypeScript output
└── package.json
🧠 Cómo funciona
- El prompt de sistema impone salida JSON con
reasoningyresult. Variantes específicas por modelo ajustadas para Claude, GPT-4, Gemini, Grok. - El pipeline de parsers ejecuta 5 parsers integrados en orden de prioridad (JSON directo, bloques delimitados, XML/etiquetas, balanceo de llaves, recuperación truncada). La primera coincidencia válida gana. Se pueden añadir parsers personalizados vía la variable de entorno
COT_PARSERSy la interfazCotParser. - Lógica de reintento — si el parseo falla, inyecta un sufijo de corrección y aumenta la temperatura. Soporta modelos de respaldo (
FALLBACK_MODELS) cuando el modelo principal se niega. - Memoria de rechazo almacena un fragmento del último fallo para contextualizar la siguiente llamada (limitada por solicitud, segura para hilos).
- Presupuesto de tokens usa
estimateTokens()(heurística ligera) para el cálculo del presupuesto ycountTokens()(tiktoken) para conteos exactos. EstablecemaxTokensdinámicamente (entre 4096 y 8192) mediante la fórmulaoverhead + inputTokens × 4. Detecta truncamiento víafinish_reason: "length"e intenta recuperación JSON antes de reintentar.
🛠️ Desarrollo
git clone https://github.com/islobodan/cotforce-mcp
cd cotforce-mcp
npm install
npm run build # compile TypeScript to dist/
npm run dev # tsc --watch
npm run typecheck # type-check src/ and tests/
Scripts
| Script | Propósito |
|---|---|
npm run build | Compilar TypeScript (src/ → dist/) |
npm run dev | Compilación en modo de observación |
npm run typecheck | Verificación de tipos de TypeScript para código fuente y pruebas |
npm test | Ejecutar la suite completa de pruebas Jest (133 pruebas) |
npm run test:smoke | Prueba rápida de humo mediante la CLI de mcp-tester |
npm run test:tools | Listar herramientas disponibles mediante la CLI de mcp-tester |
Pruebas
La suite de pruebas utiliza Jest con ts-jest (ESM) y @slbdn/mcp-tester para pruebas de integración del servidor MCP:
- Pruebas de parser (
tests/parser.test.ts) — 47 pruebas unitarias que cubren los 5 plugins de parser, casos límite y validación deAgenticCotSchema. - Pruebas de tokens (
tests/tokens.test.ts) — 16 pruebas unitarias para integración detiktoken, cálculo de presupuesto y ajuste deREASONING_OVERHEAD. - Pruebas de esquema (
tests/schema.test.ts) — 8 pruebas unitarias para validación deresultSchemaproporcionado por el usuario. - Pruebas de métricas (
tests/metrics.test.ts) — 9 pruebas unitarias para contadores de solicitudes, seguimiento de latencia y promedios de uso de tokens. - Pruebas de prompts (
tests/prompts.test.ts) — 10 pruebas unitarias para selección de prompts específicos del modelo. - Pruebas de LLM (
tests/llm.test.ts) — 3 pruebas unitarias para detección de modo HTTP directo. - Pruebas de servidor (
tests/server.test.ts) — 11 pruebas de integración para descubrimiento de herramientas, validación de argumentos, ciclo de vida del servidor y llamadas concurrentes.
Los matchers personalizados de Jest están disponibles mediante @slbdn/mcp-tester:
expect(tools).toHaveTool("solve_problem");
expect(tools).toHaveToolWithSchema("solve_problem");
expect(result).toReturnTextContaining("Reasoning:");
⚠️ Limitaciones y Evaluación Honesta
- Sin monitoreo de producción real — solo registros estructurados; sin métricas agregadas.
- La fórmula de presupuesto de tokens es heurística — puede requerir ajustes para modelos muy verbosos.
- Las sugerencias de modelo son recomendaciones — el host de MCP decide qué modelo usar.
- Consulta la lista de tareas pendientes para mejoras planificadas.
📄 Licencia
MIT © Slobodan Ivkovic
⭐ Soporte
Si encuentras útil CotForce-MCP, ¡considera dar una estrella al repositorio y compartir tus comentarios!