{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "Futtebol Agent API",
  "version": "1.10.26",
  "description": "Herramienta analitica de futbol cuantitativo con Dixon-Coles, XGBoost calibrado y simulacion Monte Carlo para 10 competiciones oficiales. Pensada para agentes autonomos.",
  "homepage": "https://futtebol.com",
  "documentation": "https://futtebol.com/llms.txt",
  "authentication": {
    "type": "bearer",
    "required": false,
    "description": "Los endpoints de lectura son publicos y anonimos. Si envias Authorization: Bearer <token> (obtenido en /api/auth/verify-otp) el servidor lo acepta y registra el uso, pero nunca es obligatorio ni cambia el resultado.",
    "obtain": "POST /api/auth/request-otp y despues POST /api/auth/verify-otp"
  },
  "mcp": {
    "protocol": "2025-06-18",
    "protocol_versions": [
      "2025-06-18",
      "2025-03-26",
      "2024-11-05"
    ],
    "transport": [
      "stdio",
      "http-jsonrpc"
    ],
    "package": "@futtebol/mcp-server",
    "published": true,
    "npm_version": "1.10.26",
    "npm_url": "https://www.npmjs.com/package/@futtebol/mcp-server",
    "install_command": "npx -y @futtebol/mcp-server",
    "install_verified": "npx -y @futtebol/mcp-server --version  # 1.10.26",
    "config_url": "https://futtebol.com/mcp.json",
    "remote_endpoint": "https://futtebol.com/api/agent/mcp",
    "client_config": {
      "configuracion minima (copiar y pegar)": {
        "mcpServers": {
          "futtebol": {
            "command": "npx",
            "args": [
              "-y",
              "@futtebol/mcp-server"
            ]
          }
        }
      },
      "Claude Desktop / Cursor / Kilo (mcp.json)": {
        "mcpServers": {
          "futtebol": {
            "command": "npx",
            "args": [
              "-y",
              "@futtebol/mcp-server"
            ]
          }
        }
      },
      "Claude Code (scoped al proyecto, archivo .mcp.json)": {
        "mcpServers": {
          "futtebol": {
            "command": "npx",
            "args": [
              "-y",
              "@futtebol/mcp-server"
            ]
          }
        }
      },
      "sin instalar nada (endpoint HTTP remoto)": {
        "transport": "http",
        "url": "https://futtebol.com/api/agent/mcp",
        "protocol": "2025-06-18"
      }
    },
    "flujo_recomendado": [
      "1. Descarga la configuracion: GET https://futtebol.com/mcp.json y copiala en el archivo de MCP de tu cliente.",
      "2. O instala en caliente: npx -y @futtebol/mcp-server (no requiere cambios en el proyecto).",
      "3. Comprueba la conexion: npx -y @futtebol/mcp-server --version  ->  1.10.26.",
      "4. O usa el endpoint HTTP sin instalar: POST https://futtebol.com/api/agent/mcp con JSON-RPC 2.0.",
      "5. Primera llamada obligatoria: tools/list para conocer el catalogo y get_leagues para conocer los ids validos."
    ],
    "notes": [
      "El servidor stdio habla JSON-RPC 2.0 delimitado por saltos de linea (NDJSON) y tambien acepta JSON concatenado o multilinea.",
      "El endpoint HTTP acepta POST con un objeto JSON-RPC o un lote, y GET para descubrir capacidades sin.initialize.",
      "El limite es de 120 llamadas por minuto y por IP; al superarlo responde HTTP 429 con el codigo JSON-RPC -32002.",
      "Un fallo de herramienta llega como result.isError=true con error.code not_found o invalid_input, nunca como numero inventado."
    ]
  },
  "rate_limit": {
    "requests_per_minute": 120,
    "scope": "por IP",
    "on_exceed": "HTTP 429 con JSON-RPC -32002"
  },
  "leagues": [
    {
      "id": "COL-Primera A",
      "name": "Liga BetPlay Dimayor",
      "country": "Colombia"
    },
    {
      "id": "SUD-Copa Sudamericana",
      "name": "CONMEBOL Sudamericana",
      "country": "Sudamérica"
    },
    {
      "id": "UCL-Champions League",
      "name": "UEFA Champions League",
      "country": "Europa"
    },
    {
      "id": "UEL-Europa League",
      "name": "UEFA Europa League",
      "country": "Europa"
    },
    {
      "id": "LIB-Copa Libertadores",
      "name": "CONMEBOL Libertadores",
      "country": "Sudamérica"
    },
    {
      "id": "GER-Bundesliga",
      "name": "Bundesliga",
      "country": "Alemania"
    },
    {
      "id": "ENG-Championship",
      "name": "Championship",
      "country": "Inglaterra"
    },
    {
      "id": "POR-Liga Portugal",
      "name": "Liga Portugal",
      "country": "Portugal"
    },
    {
      "id": "USA-MLS",
      "name": "Major League Soccer",
      "country": "EE.UU."
    },
    {
      "id": "UNL-UEFA Nations League",
      "name": "UEFA Nations League",
      "country": "Europa"
    }
  ],
  "resources": [
    {
      "uri": "futtebol://leagues",
      "name": "competiciones",
      "mimeType": "application/json",
      "description": "Catalogo de las 10 competiciones con temporada y fecha de actualizacion."
    },
    {
      "uri": "futtebol://llms.txt",
      "name": "llms-txt",
      "mimeType": "text/plain",
      "description": "Guia completa de integracion para agentes."
    },
    {
      "uri": "futtebol://standings/{league_id}",
      "name": "clasificacion",
      "mimeType": "application/json",
      "description": "Tabla de posiciones con puntos, forma y PPG de una competicion."
    }
  ],
  "quickstart": {
    "registro": "GET https://futtebol.com/mcp.json (configuracion lista para pegar)",
    "guia": "GET https://futtebol.com/llms.txt",
    "manifiesto": "GET https://futtebol.com/.well-known/agent.json",
    "datos_abiertos": [
      "GET https://futtebol.com/data/index.json",
      "GET https://futtebol.com/data/teams.json",
      "GET https://futtebol.com/ml/manifest.json"
    ]
  },
  "rest_equivalents": [
    {
      "method": "GET",
      "path": "/api/agent/status",
      "description": "Chequeo de salud: estado, versiones de protocolo, numero de herramientas."
    },
    {
      "method": "GET",
      "path": "/api/agent/leagues",
      "description": "Equivalente JSON de get_leagues."
    },
    {
      "method": "GET",
      "path": "/api/agent/matches?league={league_id}&status={status}&limit={n}",
      "description": "Equivalente JSON de get_matches."
    },
    {
      "method": "GET",
      "path": "/api/agent/predictions?match_id={match_id}",
      "description": "Equivalente JSON de get_match_predictions."
    },
    {
      "method": "GET",
      "path": "/api/agent/simulate?home_team={id}&away_team={id}&iterations={n}",
      "description": "Equivalente JSON de run_simulation."
    }
  ],
  "instructions": "Futtebol expone 10 competiciones oficiales con modelos Dixon-Coles y simulacion Monte Carlo. Flujo recomendado: 1) get_leagues para obtener los ids canonicos, 2) get_matches para obtener los partidos y sus match_id, 3) get_match_predictions para el informe reconciliado de un partido, 4) run_simulation para contrastar el Monte Carlo. Reglas no negociables: nunca inventes un league_id, un match_id ni un numero de probabilidad; si una herramienta falla, relay su mensaje y sus ids validos en lugar de rellenar el dato. Todas las probabilidades son porcentajes enteros 0-100 y las cuotas justas son 100/probabilidad, sin margen de casa de apuestas. Los match_id tienen el formato league_id::home_id::away_id::ts y deben copiarse literalmente desde get_matches.",
  "tools": [
    {
      "name": "get_leagues",
      "title": "Listar las 10 competiciones oficiales",
      "description": "Devuelve las 10 competiciones oficiales soportadas con su id canonico, nombre, pais, temporada y fecha de actualizacion del dato. Es el primer paso obligatorio: los ids que devuelve son los unicos valores validos para get_matches. No requiere argumentos.",
      "parameters": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "minimum": 1
          },
          "data_updated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "leagues": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "country": {
                  "type": "string"
                },
                "season": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "phase": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "stale": {
                  "type": "boolean"
                },
                "updated_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "name"
              ]
            }
          },
          "next_step": {
            "type": "string"
          }
        },
        "required": [
          "leagues",
          "total"
        ]
      },
      "example": {}
    },
    {
      "name": "get_matches",
      "title": "Buscar partidos de una competicion",
      "description": "Lista partidos reales de una competicion oficial con su match_id estable, equipos, fecha de arranque y estado normalizado (upcoming | live | finished). Soporta filtros de estado, equipo, rango de fechas y paginacion por cursor. Devuelve como maximo 200 partidos por llamada: pagina con cursor para ver mas.",
      "parameters": {
        "type": "object",
        "properties": {
          "league_id": {
            "type": "string",
            "minLength": 2,
            "maxLength": 64,
            "description": "Id canonico de la competicion, por ejemplo 'COL-Primera A', 'SUD-Copa Sudamericana', 'UCL-Champions League'. tambien acepta el codigo de pais (COL, UCL) o el nombre de la liga. Llama a get_leagues para ver los ids exactos."
          },
          "status": {
            "type": "string",
            "enum": [
              "all",
              "live",
              "upcoming",
              "finished"
            ],
            "default": "all",
            "description": "Filtro de estado. Valores: all = todos, upcoming = por jugar, live = en curso, finished = finalizados. Si no hay partidos en ese estado la respuesta trae matches vacio y un mensaje explicito, no un error."
          },
          "team": {
            "type": "string",
            "minLength": 2,
            "maxLength": 64,
            "description": "Filtra por equipo: id (atl-nacional), nombre (Atl. Nacional) o codigo (NAT). Opcional."
          },
          "date_from": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "Fecha minima inclusive en formato AAAA-MM-DD. Opcional."
          },
          "date_to": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "Fecha maxima inclusive en formato AAAA-MM-DD. Opcional."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 200,
            "default": 50,
            "description": "Numero maximo de partidos a devolver (1-200). Por defecto 50."
          },
          "cursor": {
            "type": "string",
            "maxLength": 200,
            "description": "Cursor opaco devuelto en next_step de la llamada anterior para continuar la paginacion. Opcional."
          }
        },
        "required": [
          "league_id"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "league_id": {
            "type": "string"
          },
          "resolved_from": {
            "type": "string"
          },
          "status_filter": {
            "type": "string"
          },
          "total_available": {
            "type": "integer",
            "minimum": 0
          },
          "returned": {
            "type": "integer",
            "minimum": 0
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "data_updated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "message": {
            "type": "string"
          },
          "next_step": {
            "type": "string"
          },
          "matches": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "match_id": {
                  "type": "string"
                },
                "league_id": {
                  "type": "string"
                },
                "home": {
                  "type": "string"
                },
                "away": {
                  "type": "string"
                },
                "home_id": {
                  "type": "string"
                },
                "away_id": {
                  "type": "string"
                },
                "kickoff": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "upcoming",
                    "live",
                    "finished",
                    "unknown"
                  ]
                },
                "score": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "match_id",
                "home",
                "away",
                "status"
              ]
            }
          }
        },
        "required": [
          "league_id",
          "matches"
        ]
      },
      "example": {
        "league_id": "COL-Primera A",
        "status": "upcoming",
        "limit": 5
      }
    },
    {
      "name": "get_match_predictions",
      "title": "Prediccion reconciliada de un partido",
      "description": "Devuelve el informe de prediccion reconciliado de un partido: 1X2 con cuotas justas, doble oportunidad, totales Over/Under 0.5 a 4.5, BTTS, goles esperados, marcadores mas probables y el desglose de cada motor (Dixon-Coles y Monte Carlo). Exige un match_id devuelto por get_matches: nunca inventes el id y nunca reportar numeros sin llamar a esta herramienta.",
      "parameters": {
        "type": "object",
        "properties": {
          "match_id": {
            "type": "string",
            "minLength": 8,
            "maxLength": 160,
            "description": "Identificador estable del partido con formato league_id::home_id::away_id::ts, por ejemplo COL-Primera A::jaguares-de-cordoba::alianza::1790542800. Copialo literalmente desde get_matches."
          }
        },
        "required": [
          "match_id"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "match_id": {
            "type": "string"
          },
          "league_id": {
            "type": "string"
          },
          "league_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "kickoff": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "upcoming",
              "live",
              "finished",
              "unknown"
            ]
          },
          "home": {
            "type": "object"
          },
          "away": {
            "type": "object"
          },
          "context": {
            "type": "object"
          },
          "top_scores": {
            "type": "array"
          },
          "next_step": {
            "type": "string"
          },
          "reconciled": {
            "type": "boolean"
          },
          "engine": {
            "type": "string"
          },
          "data_updated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "expected_goals": {
            "type": "object",
            "properties": {
              "home": {
                "type": "number"
              },
              "away": {
                "type": "number"
              },
              "total": {
                "type": "number"
              }
            },
            "required": [
              "home",
              "away",
              "total"
            ]
          },
          "consensus": {
            "type": "object",
            "properties": {
              "p1": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Probabilidad en porcentaje (0-100)."
              },
              "px": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Probabilidad en porcentaje (0-100)."
              },
              "p2": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Probabilidad en porcentaje (0-100)."
              },
              "fair_odds": {
                "type": "object",
                "properties": {
                  "1": {
                    "type": "number"
                  },
                  "2": {
                    "type": "number"
                  },
                  "X": {
                    "type": "number"
                  }
                },
                "required": [
                  "1",
                  "X",
                  "2"
                ]
              },
              "btts_yes": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Probabilidad en porcentaje (0-100)."
              },
              "over_2_5": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Probabilidad en porcentaje (0-100)."
              }
            },
            "required": [
              "p1",
              "px",
              "p2",
              "fair_odds",
              "btts_yes",
              "over_2_5"
            ]
          },
          "models": {
            "type": "object"
          }
        },
        "required": [
          "match_id",
          "consensus",
          "expected_goals",
          "reconciled"
        ]
      },
      "example": {
        "match_id": "COL-Primera A::jaguares-de-cordoba::alianza::1790542800"
      }
    },
    {
      "name": "run_simulation",
      "title": "Simulacion Monte Carlo de un enfrentamiento",
      "description": "Ejecuta una simulacion Monte Carlo (1000-100000 iteraciones) de un enfrentamiento entre dos equipos y devuelve probabilidades 1X2, totales, BTTS, porterias a cero y goles esperados. Acepta ids de equipo, nombres o codigos. No es decorativa: sus probabilidades deben coincidir con get_match_predictions para el mismo partido (difieren como maximo 1 punto porcentual).",
      "parameters": {
        "type": "object",
        "properties": {
          "home_team": {
            "type": "string",
            "minLength": 2,
            "maxLength": 64,
            "description": "Equipo local: id (atl-nacional), nombre (Atl. Nacional) o codigo (NAT). Se resuelve por similitud; si es ambiguo devuelve error con candidatos."
          },
          "away_team": {
            "type": "string",
            "minLength": 2,
            "maxLength": 64,
            "description": "Equipo visitante con el mismo formato que home_team. Obligatorio."
          },
          "league_id": {
            "type": "string",
            "minLength": 2,
            "maxLength": 64,
            "description": "Competicion a la que forzar el contexto del modelo. Opcional: si el equipo juega en varias se usa su liga principal."
          },
          "iterations": {
            "type": "integer",
            "minimum": 1000,
            "maximum": 100000,
            "default": 20000,
            "description": "Numero de iteraciones de la simulacion (1000-100000). Valores fuera de rango se ajustan automaticamente. Por defecto 20000."
          },
          "seed": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2147483647,
            "default": 42,
            "description": "Semilla del generador pseudoaleatorio. La misma semilla reproduce exactamente el mismo resultado. Por defecto 42."
          }
        },
        "required": [
          "home_team",
          "away_team"
        ],
        "additionalProperties": false
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "home_team": {
            "type": "string"
          },
          "away_team": {
            "type": "string"
          },
          "home_team_id": {
            "type": "string"
          },
          "away_team_id": {
            "type": "string"
          },
          "resolved_from": {
            "type": "object"
          },
          "league_id": {
            "type": "string"
          },
          "iterations": {
            "type": "integer",
            "minimum": 1000
          },
          "iterations_requested": {
            "type": [
              "integer",
              "null"
            ]
          },
          "seed": {
            "type": "integer"
          },
          "engine": {
            "type": "string"
          },
          "data_updated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "metrics": {
            "type": "object"
          },
          "monte_carlo": {
            "type": "object"
          },
          "dixon_coles": {
            "type": "object"
          },
          "top_scores": {
            "type": "array"
          }
        },
        "required": [
          "home_team",
          "away_team",
          "iterations",
          "metrics"
        ]
      },
      "example": {
        "home_team": "atl-nacional",
        "away_team": "tolima",
        "iterations": 20000,
        "seed": 42
      }
    }
  ]
}
