zerochat 8.2.0__tar.gz → 8.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zerochat-8.2.0/zerochat.egg-info → zerochat-8.3.0}/PKG-INFO +1 -1
- {zerochat-8.2.0 → zerochat-8.3.0}/pyproject.toml +1 -1
- {zerochat-8.2.0 → zerochat-8.3.0/zerochat.egg-info}/PKG-INFO +1 -1
- {zerochat-8.2.0 → zerochat-8.3.0}/zerochat.py +116 -39
- {zerochat-8.2.0 → zerochat-8.3.0}/LICENSE +0 -0
- {zerochat-8.2.0 → zerochat-8.3.0}/README.md +0 -0
- {zerochat-8.2.0 → zerochat-8.3.0}/setup.cfg +0 -0
- {zerochat-8.2.0 → zerochat-8.3.0}/zerochat.egg-info/SOURCES.txt +0 -0
- {zerochat-8.2.0 → zerochat-8.3.0}/zerochat.egg-info/dependency_links.txt +0 -0
- {zerochat-8.2.0 → zerochat-8.3.0}/zerochat.egg-info/entry_points.txt +0 -0
- {zerochat-8.2.0 → zerochat-8.3.0}/zerochat.egg-info/top_level.txt +0 -0
|
@@ -42,7 +42,7 @@ import webbrowser
|
|
|
42
42
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
43
43
|
from pathlib import Path
|
|
44
44
|
|
|
45
|
-
SOURCE_BACKEND_VERSION = "8.
|
|
45
|
+
SOURCE_BACKEND_VERSION = "8.3.0"
|
|
46
46
|
|
|
47
47
|
def _read_source_version(filename: str) -> str | None:
|
|
48
48
|
"""Lee la versión de un archivo del repositorio cuando se ejecuta desde fuentes."""
|
|
@@ -93,9 +93,11 @@ UI_VERSION = _read_ui_version()
|
|
|
93
93
|
DEFAULT_PORT = 6388
|
|
94
94
|
DEFAULT_HOST = "127.0.0.1"
|
|
95
95
|
DEFAULT_UI_URL = "https://albalday.github.io/zerochat/zerochat.html"
|
|
96
|
-
REMOTE_VERSION_URL = "https://raw.githubusercontent.com/albalday/zerochat/master/package.json"
|
|
97
|
-
PYPI_VERSION_URL = "https://pypi.org/pypi/zerochat/json"
|
|
98
96
|
REMOTE_SCRIPT_URL = "https://raw.githubusercontent.com/albalday/zerochat/master/zerochat.py"
|
|
97
|
+
# Las versiones remotas se consultan en las dos distribuciones que consume el
|
|
98
|
+
# usuario: la interfaz publicada en GitHub Pages y el ejecutable en GitHub.
|
|
99
|
+
REMOTE_UI_VERSION_URL = DEFAULT_UI_URL
|
|
100
|
+
REMOTE_BACKEND_VERSION_URL = REMOTE_SCRIPT_URL
|
|
99
101
|
CONSOLE_STATUS_IDLE_SECONDS = 8.0
|
|
100
102
|
CONSOLE_CONTROL = None
|
|
101
103
|
NOTICES: list[str] = []
|
|
@@ -335,22 +337,24 @@ def parse_version(ver: str) -> tuple[int, ...]:
|
|
|
335
337
|
return tuple(parts)
|
|
336
338
|
|
|
337
339
|
|
|
338
|
-
def
|
|
339
|
-
"""
|
|
340
|
+
def _read_remote_content(url: str) -> str:
|
|
341
|
+
"""Lee una cabecera acotada de un recurso publicado de ZeroChat."""
|
|
340
342
|
req = urllib.request.Request(url, headers={"User-Agent": f"ZeroChat/{VERSION}"})
|
|
341
343
|
with urllib.request.urlopen(req, timeout=3) as resp:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
344
|
+
return resp.read(4096).decode("utf-8", errors="ignore")
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def _read_remote_ui_version() -> str | None:
|
|
348
|
+
"""Extrae la versión del título de la interfaz servida por GitHub Pages."""
|
|
349
|
+
content = _read_remote_content(REMOTE_UI_VERSION_URL)
|
|
350
|
+
match = re.search(r"<title>\s*ZeroChat\s+v(\d+\.\d+\.\d+)\s*</title>", content, re.IGNORECASE)
|
|
351
|
+
return match.group(1) if match else None
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _read_remote_backend_version() -> str | None:
|
|
355
|
+
"""Extrae la versión estática del ejecutable publicado en GitHub."""
|
|
356
|
+
content = _read_remote_content(REMOTE_BACKEND_VERSION_URL)
|
|
357
|
+
match = re.search(r'^SOURCE_BACKEND_VERSION\s*=\s*["\'](\d+\.\d+\.\d+)["\']', content, re.MULTILINE)
|
|
354
358
|
return match.group(1) if match else None
|
|
355
359
|
|
|
356
360
|
|
|
@@ -360,14 +364,21 @@ def has_new_backend_version(remote_version: str, local_version: str = VERSION) -
|
|
|
360
364
|
|
|
361
365
|
|
|
362
366
|
def check_version():
|
|
363
|
-
"""Informa de
|
|
367
|
+
"""Informa de la versión de Pages y de actualizaciones del ejecutable."""
|
|
364
368
|
if get_dev_root() is not None:
|
|
365
369
|
return
|
|
366
370
|
try:
|
|
367
371
|
installed = is_installed_runtime()
|
|
368
|
-
|
|
369
|
-
if
|
|
370
|
-
notice = f"
|
|
372
|
+
remote_ui_version = _read_remote_ui_version()
|
|
373
|
+
if remote_ui_version:
|
|
374
|
+
notice = f"Interfaz web en GitHub Pages: v{remote_ui_version}."
|
|
375
|
+
if remote_ui_version != UI_VERSION:
|
|
376
|
+
notice += f" El ejecutable incluye la referencia v{UI_VERSION}; la interfaz remota se cargará al abrir el navegador."
|
|
377
|
+
add_notice(notice)
|
|
378
|
+
|
|
379
|
+
remote_backend_version = _read_remote_backend_version()
|
|
380
|
+
if remote_backend_version and has_new_backend_version(remote_backend_version):
|
|
381
|
+
notice = f"Nueva versión del servidor disponible (local: {VERSION}, remota: {compatibility_version(remote_backend_version)})."
|
|
371
382
|
if installed:
|
|
372
383
|
notice += f" Actualiza cuando quieras con: {sys.executable} -m pip install --upgrade --no-cache-dir zerochat"
|
|
373
384
|
else:
|
|
@@ -1635,11 +1646,7 @@ class McpServiceManager:
|
|
|
1635
1646
|
if services_root:
|
|
1636
1647
|
self.services_root = Path(services_root)
|
|
1637
1648
|
else:
|
|
1638
|
-
|
|
1639
|
-
Path.cwd() / "services",
|
|
1640
|
-
get_data_dir() / "services"
|
|
1641
|
-
]
|
|
1642
|
-
self.services_root = candidates[0] if get_dev_root() is not None and candidates[0].is_dir() else candidates[1]
|
|
1649
|
+
self.services_root = get_data_dir() / "services"
|
|
1643
1650
|
self.services_root.mkdir(parents=True, exist_ok=True)
|
|
1644
1651
|
self.config_file = get_data_dir() / "config" / "services.json"
|
|
1645
1652
|
self.config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -1656,36 +1663,45 @@ class McpServiceManager:
|
|
|
1656
1663
|
console_log(f"[{time.strftime('%H:%M:%S')}] [MCP {server_id}] {_mcp_trace_text(message)}", flush=True)
|
|
1657
1664
|
|
|
1658
1665
|
def _ensure_default_services(self):
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
service_json_file =
|
|
1662
|
-
|
|
1666
|
+
example_dir = self.services_root / "ejemplo"
|
|
1667
|
+
example_dir.mkdir(parents=True, exist_ok=True)
|
|
1668
|
+
service_json_file = example_dir / "service.json"
|
|
1669
|
+
example_server_file = example_dir / "ejemplo_mcp_server.py"
|
|
1670
|
+
example_readme_file = example_dir / "README.md"
|
|
1671
|
+
installer_example_file = example_dir / "installer.json.example"
|
|
1663
1672
|
|
|
1664
1673
|
if not service_json_file.exists():
|
|
1665
1674
|
service_json_file.write_text(json.dumps({
|
|
1666
1675
|
"schemaVersion": 1,
|
|
1667
|
-
"id": "
|
|
1676
|
+
"id": "ejemplo",
|
|
1668
1677
|
"displayName": {
|
|
1669
|
-
"es": "
|
|
1670
|
-
"en": "
|
|
1678
|
+
"es": "Ejemplo de MCP",
|
|
1679
|
+
"en": "MCP example"
|
|
1671
1680
|
},
|
|
1672
1681
|
"description": {
|
|
1673
|
-
"es": "
|
|
1674
|
-
"en": "Minimal MCP
|
|
1682
|
+
"es": "Plantilla mínima para crear servicios MCP gestionados por ZeroChat. Muestra el protocolo stdio y la estructura de configuración que debe seguir un nuevo MCP.",
|
|
1683
|
+
"en": "Minimal template for creating ZeroChat-managed MCP services. It demonstrates the stdio protocol and configuration structure for a new MCP."
|
|
1684
|
+
},
|
|
1685
|
+
"help": {
|
|
1686
|
+
"url": "help/mcp.html#crear-mcp-con-agente",
|
|
1687
|
+
"label": {
|
|
1688
|
+
"es": "Guía para crear un MCP gestionado",
|
|
1689
|
+
"en": "Guide to creating a managed MCP"
|
|
1690
|
+
}
|
|
1675
1691
|
},
|
|
1676
1692
|
"enabledByDefault": False,
|
|
1677
1693
|
"transport": "stdio",
|
|
1678
1694
|
"launch": {
|
|
1679
1695
|
"executable": "${pythonExecutable}",
|
|
1680
|
-
"args": ["${serviceDir}/
|
|
1696
|
+
"args": ["${serviceDir}/ejemplo_mcp_server.py"],
|
|
1681
1697
|
"cwd": "${serviceDir}",
|
|
1682
1698
|
"env": {},
|
|
1683
1699
|
"handshakeTimeoutSeconds": 10
|
|
1684
1700
|
}
|
|
1685
1701
|
}, indent=2), encoding="utf-8")
|
|
1686
1702
|
|
|
1687
|
-
if not
|
|
1688
|
-
|
|
1703
|
+
if not example_server_file.exists():
|
|
1704
|
+
example_server_file.write_text('''#!/usr/bin/env python3
|
|
1689
1705
|
import json, sys
|
|
1690
1706
|
|
|
1691
1707
|
def reply(req_id, result=None, error=None):
|
|
@@ -1702,7 +1718,7 @@ for raw in sys.stdin:
|
|
|
1702
1718
|
if method == "initialize":
|
|
1703
1719
|
reply(req_id, {
|
|
1704
1720
|
"protocolVersion": "2024-11-05",
|
|
1705
|
-
"serverInfo": {"name": "ZeroChat
|
|
1721
|
+
"serverInfo": {"name": "ZeroChat MCP Example", "version": "1.0.0"},
|
|
1706
1722
|
"capabilities": {"tools": {}}
|
|
1707
1723
|
})
|
|
1708
1724
|
elif method == "tools/list":
|
|
@@ -1726,6 +1742,66 @@ for raw in sys.stdin:
|
|
|
1726
1742
|
})
|
|
1727
1743
|
''', encoding="utf-8")
|
|
1728
1744
|
|
|
1745
|
+
if not installer_example_file.exists():
|
|
1746
|
+
installer_example_file.write_text(json.dumps({
|
|
1747
|
+
"schemaVersion": 1,
|
|
1748
|
+
"type": "npm",
|
|
1749
|
+
"product": {
|
|
1750
|
+
"package": "@scope/mcp-package",
|
|
1751
|
+
"version": "1.2.3"
|
|
1752
|
+
},
|
|
1753
|
+
"requirements": {
|
|
1754
|
+
"node": {"minimumMajor": 18}
|
|
1755
|
+
}
|
|
1756
|
+
}, indent=2) + "\n", encoding="utf-8")
|
|
1757
|
+
|
|
1758
|
+
if not example_readme_file.exists():
|
|
1759
|
+
example_readme_file.write_text('''# Ejemplo de MCP gestionado\n\nEsta carpeta es la plantilla para que un agente cree un servicio MCP gestionado por ZeroChat. Para crear uno nuevo, copie esta estructura en `~/zerochat/services/<id-seguro>/`; no modifique este ejemplo.\n\n## Archivos\n\n- `service.json` es obligatorio. Define el identificador, los textos visibles, el proceso y el campo estándar opcional `help`.\n- `installer.json` es opcional. Créelo a partir de `installer.json.example` solo si ZeroChat debe instalar un paquete npm. Fije siempre una versión exacta.\n- El ejecutable o script de arranque se declara en `launch`. Use `${serviceDir}`, `${pythonExecutable}` o `${nodeExecutable}` en lugar de rutas de usuario.\n\n## Campo de ayuda\n\nTodos los servicios pueden incluir:\n\n```json\n"help": {\n "url": "help/mcp.html",\n "label": { "es": "Texto en español", "en": "English text" }\n}\n```\n\nLa interfaz muestra ese enlace en la tarjeta del servicio. `url` debe ser una ruta relativa de ZeroChat o una URL `https:` o `http:`.\n\n## Instrucción para un agente\n\nCopia este texto y sustituye solo `<nombre-del-mcp>`:\n\n```text\nSiguiendo estrictamente la estructura de ~/zerochat/services/ejemplo, busca en Internet la documentación oficial de instalación del MCP <nombre-del-mcp> y crea en ~/zerochat/services/ el directorio y los JSON necesarios para instalarlo y ejecutarlo en ZeroChat. Usa exclusivamente fuentes oficiales, fija versiones concretas, añade la sección help con el enlace a la documentación oficial, no incluyas secretos y no inicies el servicio. Al terminar, resume los archivos creados, las fuentes consultadas y los requisitos pendientes.\n```\n''', encoding="utf-8")
|
|
1760
|
+
|
|
1761
|
+
example_readme_file.write_text('''# Crear un MCP gestionado por ZeroChat
|
|
1762
|
+
|
|
1763
|
+
Esta carpeta es la referencia para crear servicios MCP gestionados. La ubicación de producción es el directorio personal del usuario, seguido de `zerochat/services` (por ejemplo, `/home/usuario/zerochat/services`). No uses `~`, `$HOME` ni una ruta relativa como `services/`: primero identifica la ruta absoluta del directorio personal y úsala para localizar este archivo. El nuevo servicio se crea como carpeta hermana de `ejemplo`, nunca dentro de ella.
|
|
1764
|
+
|
|
1765
|
+
## Procedimiento obligatorio
|
|
1766
|
+
|
|
1767
|
+
1. Lee `README.md`, `service.json` y `installer.json.example` de la carpeta `ejemplo` situada en el directorio de datos de ZeroChat.
|
|
1768
|
+
2. Consulta solo la documentación oficial del MCP solicitado.
|
|
1769
|
+
3. Crea una carpeta con un identificador seguro y descriptivo junto a `ejemplo`.
|
|
1770
|
+
4. Crea `service.json` copiando esta estructura y adapta únicamente los valores necesarios.
|
|
1771
|
+
5. Crea `installer.json` solo si el MCP se distribuye como paquete npm. Copia `installer.json.example`, fija la versión exacta y declara la versión mínima de Node.js.
|
|
1772
|
+
6. Añade `help.url` con la página oficial de instalación y etiquetas en español e inglés.
|
|
1773
|
+
7. No incluyas tokens, contraseñas ni valores privados. Decláralos en `launch.env` con un marcador, por ejemplo `${HOME_ASSISTANT_TOKEN}`.
|
|
1774
|
+
8. No inicies el servicio. Al terminar, informa de los archivos creados, fuentes oficiales y requisitos pendientes.
|
|
1775
|
+
|
|
1776
|
+
## Límites de ZeroChat
|
|
1777
|
+
|
|
1778
|
+
ZeroChat gestiona procesos MCP por `stdio`. Puede instalar paquetes npm mediante `installer.json` y arrancarlos con `${nodeExecutable}`. También puede arrancar un ejecutable o script ya disponible con `launch`.
|
|
1779
|
+
|
|
1780
|
+
No inventes una configuración para un MCP que requiera OAuth interactivo, transporte remoto HTTP/SSE, Docker, Python u otro instalador no soportado por estos JSON. En ese caso, no crees archivos: explica el requisito y qué soporte faltaría.
|
|
1781
|
+
|
|
1782
|
+
## Contratos JSON
|
|
1783
|
+
|
|
1784
|
+
- `service.json` es obligatorio. Conserva `schemaVersion`, `id`, textos bilingües, `transport: "stdio"` y `launch`.
|
|
1785
|
+
- En `launch`, usa `${serviceDir}`, `${nodeExecutable}` o `${pythonExecutable}`; no uses rutas absolutas de usuario.
|
|
1786
|
+
- `installer.json` es opcional y hoy solo admite `type: "npm"`.
|
|
1787
|
+
- `help` es opcional, pero debe incluirse en todo servicio creado:
|
|
1788
|
+
|
|
1789
|
+
```json
|
|
1790
|
+
"help": {
|
|
1791
|
+
"url": "https://documentacion-oficial.example/install",
|
|
1792
|
+
"label": { "es": "Instalación oficial", "en": "Official installation" }
|
|
1793
|
+
}
|
|
1794
|
+
```
|
|
1795
|
+
|
|
1796
|
+
## Prompt para el usuario
|
|
1797
|
+
|
|
1798
|
+
Sustituye únicamente `<nombre-del-mcp>`:
|
|
1799
|
+
|
|
1800
|
+
```text
|
|
1801
|
+
Para instalar el MCP <nombre-del-mcp>, localiza el directorio personal del usuario y lee primero el archivo zerochat/services/ejemplo/README.md usando su ruta absoluta. Sigue exactamente sus instrucciones.
|
|
1802
|
+
```
|
|
1803
|
+
''', encoding="utf-8")
|
|
1804
|
+
|
|
1729
1805
|
# 2. playwright
|
|
1730
1806
|
playwright_dir = self.services_root / "playwright"
|
|
1731
1807
|
playwright_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -1871,6 +1947,7 @@ for raw in sys.stdin:
|
|
|
1871
1947
|
"id": server_id,
|
|
1872
1948
|
"displayName": server.get("displayName", {}),
|
|
1873
1949
|
"description": server.get("description", {}),
|
|
1950
|
+
"help": server.get("help"),
|
|
1874
1951
|
"enabled": pref.get("enabled", server.get("enabledByDefault", False)),
|
|
1875
1952
|
"status": "running" if running else self.states.get(server_id, "stopped"),
|
|
1876
1953
|
"toolCount": len(client.tools) if running else 0,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|