local-delegate-mcp 0.1.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.
Files changed (31) hide show
  1. local_delegate_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
  2. local_delegate_mcp-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +18 -0
  3. local_delegate_mcp-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +12 -0
  4. local_delegate_mcp-0.1.0/.github/workflows/ci.yml +50 -0
  5. local_delegate_mcp-0.1.0/.github/workflows/publish.yml +30 -0
  6. local_delegate_mcp-0.1.0/.gitignore +27 -0
  7. local_delegate_mcp-0.1.0/.pre-commit-config.yaml +14 -0
  8. local_delegate_mcp-0.1.0/.python-version +1 -0
  9. local_delegate_mcp-0.1.0/CHANGELOG.md +24 -0
  10. local_delegate_mcp-0.1.0/CODE_OF_CONDUCT.md +33 -0
  11. local_delegate_mcp-0.1.0/CONTRIBUTING.md +45 -0
  12. local_delegate_mcp-0.1.0/LICENSE +21 -0
  13. local_delegate_mcp-0.1.0/PKG-INFO +130 -0
  14. local_delegate_mcp-0.1.0/README.md +103 -0
  15. local_delegate_mcp-0.1.0/docs/Investigacion-empaquetado-publicacion-MCP.md +264 -0
  16. local_delegate_mcp-0.1.0/docs/recipes/claude-code-integration.md +68 -0
  17. local_delegate_mcp-0.1.0/docs/recipes/update_agents.py +66 -0
  18. local_delegate_mcp-0.1.0/examples/.env.example +25 -0
  19. local_delegate_mcp-0.1.0/examples/claude_desktop_config.example.json +12 -0
  20. local_delegate_mcp-0.1.0/pyproject.toml +63 -0
  21. local_delegate_mcp-0.1.0/scripts/extract_dashboard_js.py +23 -0
  22. local_delegate_mcp-0.1.0/server.json +34 -0
  23. local_delegate_mcp-0.1.0/src/local_delegate/__init__.py +12 -0
  24. local_delegate_mcp-0.1.0/src/local_delegate/__main__.py +8 -0
  25. local_delegate_mcp-0.1.0/src/local_delegate/autostart.py +83 -0
  26. local_delegate_mcp-0.1.0/src/local_delegate/config.py +91 -0
  27. local_delegate_mcp-0.1.0/src/local_delegate/server.py +479 -0
  28. local_delegate_mcp-0.1.0/src/local_delegate/web/__init__.py +1 -0
  29. local_delegate_mcp-0.1.0/src/local_delegate/web/metrics.py +742 -0
  30. local_delegate_mcp-0.1.0/tests/test_smoke.py +46 -0
  31. local_delegate_mcp-0.1.0/uv.lock +1012 -0
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Reporte de bug
3
+ about: Algo no funciona como debería
4
+ title: "[bug] "
5
+ labels: bug
6
+ ---
7
+
8
+ **Descripción**
9
+ Qué pasa vs. qué esperabas.
10
+
11
+ **Reproducir**
12
+ Pasos para reproducir el problema.
13
+
14
+ **Entorno**
15
+ - SO:
16
+ - Versión de `local-delegate-mcp`:
17
+ - Backend OpenAI-compatible (llama-swap / Ollama / LM Studio / vLLM) y versión:
18
+ - `LOCAL_DELEGATE_BASE_URL`:
19
+
20
+ **Logs**
21
+ Salida relevante (sin secretos).
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: Propuesta de mejora
3
+ about: Sugiere una idea o una nueva capacidad
4
+ title: "[feat] "
5
+ labels: enhancement
6
+ ---
7
+
8
+ **Problema**
9
+ Qué necesidad o fricción motiva la propuesta.
10
+
11
+ **Propuesta**
12
+ Qué te gustaría que hiciera.
13
+
14
+ **Alternativas**
15
+ Otras opciones que consideraste.
16
+
17
+ **Contexto**
18
+ ¿Encaja con el objetivo de mantener el paquete genérico (cualquier endpoint OpenAI-compatible)?
@@ -0,0 +1,12 @@
1
+ ## Descripción
2
+
3
+ <!-- Qué cambia y por qué. -->
4
+
5
+ ## Checklist
6
+
7
+ - [ ] `uv run ruff check .` pasa
8
+ - [ ] `uv run ruff format --check .` pasa
9
+ - [ ] `uv run pytest` pasa
10
+ - [ ] Actualicé `CHANGELOG.md` (sección *Unreleased*) si aplica
11
+ - [ ] No incluyo secretos ni configs reales (solo `*.example`)
12
+ - [ ] El cambio mantiene el paquete **genérico** (nada específico de un backend/máquina en el código)
@@ -0,0 +1,50 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v6
16
+ with:
17
+ python-version: "3.11"
18
+
19
+ - name: Sync deps
20
+ run: uv sync --group dev
21
+
22
+ - name: Lint (ruff)
23
+ run: uv run ruff check .
24
+
25
+ - name: Format check (ruff)
26
+ run: uv run ruff format --check .
27
+
28
+ - name: Tests (pytest)
29
+ run: uv run pytest -q
30
+
31
+ - name: Setup Node
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version: "20"
35
+
36
+ - name: Validate dashboard JS
37
+ run: |
38
+ uv run python scripts/extract_dashboard_js.py dashboard.js
39
+ node --check dashboard.js
40
+
41
+ secrets:
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ with:
46
+ fetch-depth: 0
47
+ - name: Scan for secrets (gitleaks)
48
+ uses: gitleaks/gitleaks-action@v2
49
+ env:
50
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,30 @@
1
+ name: Publish
2
+
3
+ # Publica en PyPI al empujar un tag vX.Y.Z, usando Trusted Publishing (OIDC):
4
+ # sin tokens guardados en secrets. Requiere configurar un "trusted publisher" en PyPI
5
+ # para el proyecto local-delegate-mcp (owner ZahiriNatZuke, repo local-delegate,
6
+ # workflow publish.yml, environment pypi).
7
+
8
+ on:
9
+ push:
10
+ tags: ["v*"]
11
+
12
+ jobs:
13
+ pypi:
14
+ runs-on: ubuntu-latest
15
+ environment: pypi
16
+ permissions:
17
+ id-token: write # necesario para OIDC / Trusted Publishing
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v6
23
+ with:
24
+ python-version: "3.11"
25
+
26
+ - name: Build
27
+ run: uv build
28
+
29
+ - name: Publish to PyPI (trusted publishing)
30
+ run: uv publish --trusted-publishing always
@@ -0,0 +1,27 @@
1
+ # Datos de uso (NUNCA versionar): el log de delegaciones
2
+ usage.jsonl
3
+ *.jsonl
4
+
5
+ # Python
6
+ __pycache__/
7
+ *.py[oc]
8
+ build/
9
+ dist/
10
+ wheels/
11
+ *.egg-info/
12
+
13
+ # Entornos virtuales
14
+ .venv/
15
+ .env
16
+
17
+ # Artefactos de demo / scratch
18
+ _demo*
19
+ scratch_*
20
+ scratch/
21
+
22
+ # Config local de Claude Code (lleva rutas absolutas / puede tener secretos)
23
+ .claude/
24
+
25
+ # Secretos y credenciales (por si acaso; solo se versionan *.example)
26
+ *.secret
27
+ secrets.*
@@ -0,0 +1,14 @@
1
+ # pre-commit: bloquea secretos y aplica lint/formato antes de cada commit.
2
+ # Instala con: uv run pre-commit install
3
+ repos:
4
+ - repo: https://github.com/gitleaks/gitleaks
5
+ rev: v8.18.4
6
+ hooks:
7
+ - id: gitleaks
8
+
9
+ - repo: https://github.com/astral-sh/ruff-pre-commit
10
+ rev: v0.6.9
11
+ hooks:
12
+ - id: ruff
13
+ args: [--fix]
14
+ - id: ruff-format
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ Todos los cambios notables de este proyecto se documentan aquí.
4
+ El formato sigue [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/)
5
+ y el proyecto usa [Versionado Semántico](https://semver.org/lang/es/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-07-07
10
+
11
+ ### Added
12
+ - Servidor MCP stdio con 9 tools texto→texto (`local_summarize`, `local_classify`,
13
+ `local_extract`, `local_boilerplate`, `local_delegate`, `local_lint_summary`,
14
+ `local_commit_msg`, `local_translate`, `local_explain_code`).
15
+ - Cliente genérico de cualquier endpoint OpenAI-compatible (llama-swap, Ollama, LM Studio, vLLM),
16
+ configurable por variables de entorno; sin rutas hardcodeadas (`platformdirs` para el log).
17
+ - Web de métricas embebida (dashboard de uso/ahorro) en un hilo daemon.
18
+ - Logging JSONL por llamada (`usage.jsonl`) para calcular el ahorro de contexto.
19
+ - Auto-arranque de llama-swap opcional (opt-in, `LOCAL_DELEGATE_AUTOSTART=0` por defecto).
20
+ - Empaquetado para PyPI (`local-delegate-mcp`) ejecutable con `uvx`; `server.json` para el
21
+ registro oficial de MCP.
22
+
23
+ [Unreleased]: https://github.com/ZahiriNatZuke/local-delegate/compare/v0.1.0...HEAD
24
+ [0.1.0]: https://github.com/ZahiriNatZuke/local-delegate/releases/tag/v0.1.0
@@ -0,0 +1,33 @@
1
+ # Código de conducta — Contributor Covenant
2
+
3
+ ## Nuestro compromiso
4
+
5
+ Con el interés de fomentar una comunidad abierta y acogedora, quienes contribuimos y mantenemos
6
+ este proyecto nos comprometemos a hacer de la participación una experiencia libre de acoso para
7
+ todas las personas, sin importar edad, tamaño corporal, discapacidad, etnia, identidad y expresión
8
+ de género, nivel de experiencia, nacionalidad, apariencia, raza, religión, u orientación e
9
+ identidad sexual.
10
+
11
+ ## Nuestros estándares
12
+
13
+ Ejemplos de comportamiento que contribuyen a un ambiente positivo:
14
+
15
+ - Usar lenguaje acogedor e inclusivo.
16
+ - Respetar puntos de vista y experiencias diferentes.
17
+ - Aceptar con gracia la crítica constructiva.
18
+ - Centrarse en lo que es mejor para la comunidad.
19
+
20
+ Ejemplos de comportamiento inaceptable:
21
+
22
+ - Lenguaje o imágenes sexualizadas y atención sexual no deseada.
23
+ - Comentarios insultantes o despectivos, y ataques personales o políticos (*trolling*).
24
+ - Acoso público o privado.
25
+ - Publicar información privada de terceros sin permiso.
26
+
27
+ ## Aplicación
28
+
29
+ Los casos de comportamiento abusivo, acosador o inaceptable pueden reportarse abriendo un issue o
30
+ contactando a quien mantiene el proyecto. Todas las quejas se revisarán e investigarán.
31
+
32
+ Este código de conducta es una adaptación del [Contributor Covenant](https://www.contributor-covenant.org),
33
+ versión 2.1.
@@ -0,0 +1,45 @@
1
+ # Contribuir a local-delegate
2
+
3
+ ¡Gracias por tu interés! Este proyecto es un MCP stdio en Python gestionado con [`uv`](https://docs.astral.sh/uv/).
4
+
5
+ ## Entorno de desarrollo
6
+
7
+ ```bash
8
+ uv sync --group dev # crea .venv e instala deps + dev tools
9
+ uv run pytest # tests
10
+ uv run ruff check . # lint
11
+ uv run ruff format . # formato
12
+ ```
13
+
14
+ Python **≥ 3.11**. Usa siempre `uv` (no el `python` del sistema).
15
+
16
+ ## Ejecutar el MCP localmente
17
+
18
+ ```bash
19
+ uv run local-delegate # arranca el server stdio (necesita un endpoint OpenAI-compatible)
20
+ ```
21
+
22
+ La web de métricas queda en `http://127.0.0.1:9393` (desactiva con `LOCAL_DELEGATE_WEB=0`).
23
+
24
+ ## Reglas del proyecto
25
+
26
+ - **Cliente genérico:** el paquete solo asume "un endpoint OpenAI-compatible en una URL". Nada
27
+ específico de un backend, hardware o máquina debe entrar al código: va a `docs/recipes/`.
28
+ - **Sin rutas hardcodeadas:** todo configurable por variables de entorno (ver README).
29
+ - **Nunca subas secretos** ni tus configs reales de Claude. Solo plantillas `*.example`.
30
+ `gitleaks` corre en pre-commit y CI.
31
+
32
+ ## Pull requests
33
+
34
+ 1. Crea una rama desde `main`.
35
+ 2. Asegúrate de que `ruff check`, `ruff format --check` y `pytest` pasan.
36
+ 3. Actualiza `CHANGELOG.md` (sección *Unreleased*).
37
+ 4. Describe el cambio con claridad en el PR.
38
+
39
+ ## pre-commit
40
+
41
+ ```bash
42
+ uv run pre-commit install # (o pipx run pre-commit install)
43
+ ```
44
+
45
+ Corre `gitleaks` antes de cada commit para bloquear secretos.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yohan González Almaguer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: local-delegate-mcp
3
+ Version: 0.1.0
4
+ Summary: Delegate mechanical text tasks to a local OpenAI-compatible LLM endpoint to conserve Claude subscription quota.
5
+ Project-URL: Homepage, https://github.com/ZahiriNatZuke/local-delegate
6
+ Project-URL: Repository, https://github.com/ZahiriNatZuke/local-delegate
7
+ Project-URL: Issues, https://github.com/ZahiriNatZuke/local-delegate/issues
8
+ Author: Yohan González Almaguer
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: claude,llama-swap,llm,local,mcp,ollama,openai-compatible,quota
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Topic :: Utilities
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: fastapi>=0.115
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: mcp>=1.2
24
+ Requires-Dist: platformdirs>=4
25
+ Requires-Dist: uvicorn>=0.30
26
+ Description-Content-Type: text/markdown
27
+
28
+ <!-- mcp-name: io.github.ZahiriNatZuke/local-delegate -->
29
+
30
+ # local-delegate
31
+
32
+ **Delega tareas mecánicas texto→texto a un LLM local para conservar la cuota de tu suscripción de Claude.**
33
+ Un servidor MCP (stdio) que es cliente **genérico** de cualquier endpoint OpenAI-compatible —
34
+ llama-swap, Ollama, LM Studio, vLLM.
35
+
36
+ [![PyPI](https://img.shields.io/pypi/v/local-delegate-mcp.svg)](https://pypi.org/project/local-delegate-mcp/)
37
+ [![CI](https://github.com/ZahiriNatZuke/local-delegate/actions/workflows/ci.yml/badge.svg)](https://github.com/ZahiriNatZuke/local-delegate/actions/workflows/ci.yml)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
39
+
40
+ ## ¿Por qué?
41
+
42
+ Cuando Claude tiene que resumir un log enorme, clasificar, extraer campos o generar boilerplate,
43
+ gasta cuota de tu suscripción en trabajo **mecánico**. `local-delegate` expone esas tareas como
44
+ tools MCP que corren en un LLM **local**: pasas `path` en vez de `text` y el archivo se lee
45
+ **del lado del servidor**, así el contenido grande **nunca entra al contexto de Claude**. Solo
46
+ vuelve el resultado corto — cuota que no gastaste.
47
+
48
+ ## Instalación rápida
49
+
50
+ Con [`uv`](https://docs.astral.sh/uv/) no hay nada que instalar: `uvx` baja y ejecuta el paquete aislado.
51
+
52
+ Añádelo a tu config de MCP (Claude Desktop / Claude Code):
53
+
54
+ ```json
55
+ {
56
+ "mcpServers": {
57
+ "local-delegate": {
58
+ "command": "uvx",
59
+ "args": ["local-delegate-mcp"]
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ Ver plantillas completas en [`examples/`](./examples).
66
+
67
+ ## Requisitos
68
+
69
+ Un **endpoint OpenAI-compatible** ya corriendo, accesible en `LOCAL_DELEGATE_BASE_URL`
70
+ (default `http://127.0.0.1:9292/v1`). Cualquiera sirve:
71
+
72
+ - **llama-swap** — ver [recipe con GPU Blackwell](./docs/recipes/) *(en construcción)*.
73
+ - **Ollama** — `http://127.0.0.1:11434/v1`.
74
+ - **LM Studio**, **vLLM**, o cualquier servidor que hable la API de OpenAI.
75
+
76
+ El paquete **no arranca** ningún backend por defecto (`LOCAL_DELEGATE_AUTOSTART=0`). El
77
+ auto-arranque de llama-swap es opt-in (ver tabla de configuración).
78
+
79
+ ## Tools
80
+
81
+ Pasar `path` (en vez de `text`) hace que el MCP lea el archivo server-side → ahorro real de cuota.
82
+
83
+ | Tool | Qué hace | Rol de modelo (default) |
84
+ |---|---|---|
85
+ | `local_summarize` | Resume texto o archivo | mecánico / largo (auto) |
86
+ | `local_classify` | Devuelve UNA etiqueta de una lista | mecánico |
87
+ | `local_extract` | Extrae campos → objeto JSON | mecánico |
88
+ | `local_boilerplate` | Genera código desde una spec | código |
89
+ | `local_delegate` | Escape genérico texto→texto | mecánico (o el que pases) |
90
+ | `local_lint_summary` | Resume logs de lint/tests/CI | mecánico / largo (auto) |
91
+ | `local_commit_msg` | Mensaje de commit desde un diff | código |
92
+ | `local_translate` | Traduce texto o archivo | mecánico / largo (auto) |
93
+ | `local_explain_code` | Explica código en prosa | código |
94
+
95
+ Los modelos locales **no** usan tool-calling: el server arma el prompt + guardrails, hace POST al
96
+ endpoint y devuelve **solo texto**.
97
+
98
+ ## Configuración
99
+
100
+ Todo por variables de entorno; nada hardcodeado. Los ids de modelo default son solo eso —
101
+ cámbialos por los de tu backend.
102
+
103
+ | Variable | Default | Descripción |
104
+ |---|---|---|
105
+ | `LOCAL_DELEGATE_BASE_URL` | `http://127.0.0.1:9292/v1` | Endpoint OpenAI-compatible |
106
+ | `LOCAL_DELEGATE_API_KEY` | *(vacío)* | Bearer token, si tu endpoint lo exige |
107
+ | `LOCAL_DELEGATE_TIMEOUT` | `180` | Timeout HTTP (segundos) |
108
+ | `LOCAL_DELEGATE_LOG` | *(dir de datos de usuario)* | Ruta del `usage.jsonl` |
109
+ | `LOCAL_DELEGATE_MODEL_MECHANICAL` | `gemma3-4b` | Modelo para clasificar/extraer/resumen corto |
110
+ | `LOCAL_DELEGATE_MODEL_LONG` | `llama31-8b` | Modelo para documentos largos |
111
+ | `LOCAL_DELEGATE_MODEL_CODE` | `qwen25-coder-14b` | Modelo para código |
112
+ | `LOCAL_DELEGATE_MODEL_FAST` | `qwen35-2b` | Modelo ultrarrápido / trivial |
113
+ | `LOCAL_DELEGATE_LONG_INPUT_CHARS` | `6000` | Umbral mecánico↔largo |
114
+ | `LOCAL_DELEGATE_WEB` | `1` | Web de métricas embebida (`0` para desactivar) |
115
+ | `LOCAL_DELEGATE_WEB_HOST` / `_PORT` | `127.0.0.1` / `9393` | Host/puerto de la web |
116
+ | `LOCAL_DELEGATE_AUTOSTART` | `0` | Auto-arranque de llama-swap (opt-in) |
117
+ | `LLAMASWAP_EXE` / `LLAMASWAP_CONFIG` / `LLAMASWAP_LISTEN` | — | Solo si `AUTOSTART=1` |
118
+
119
+ ## La métrica de ahorro
120
+
121
+ El MCP registra cada llamada en `usage.jsonl` y sirve un **dashboard** en
122
+ `http://127.0.0.1:9393`. El *ahorro de contexto* = caracteres de entrada leídos server-side
123
+ (llamadas con `source=path`) ÷ 4 ≈ tokens que nunca entraron al contexto de Claude.
124
+ Detalle en la [wiki](https://github.com/ZahiriNatZuke/local-delegate/wiki) *(en construcción)*.
125
+
126
+ ## Enlaces
127
+
128
+ - [Wiki](https://github.com/ZahiriNatZuke/local-delegate/wiki) · [Recipes](./docs/recipes)
129
+ - [CONTRIBUTING](./CONTRIBUTING.md) · [CODE OF CONDUCT](./CODE_OF_CONDUCT.md) · [CHANGELOG](./CHANGELOG.md)
130
+ - [Licencia MIT](./LICENSE)
@@ -0,0 +1,103 @@
1
+ <!-- mcp-name: io.github.ZahiriNatZuke/local-delegate -->
2
+
3
+ # local-delegate
4
+
5
+ **Delega tareas mecánicas texto→texto a un LLM local para conservar la cuota de tu suscripción de Claude.**
6
+ Un servidor MCP (stdio) que es cliente **genérico** de cualquier endpoint OpenAI-compatible —
7
+ llama-swap, Ollama, LM Studio, vLLM.
8
+
9
+ [![PyPI](https://img.shields.io/pypi/v/local-delegate-mcp.svg)](https://pypi.org/project/local-delegate-mcp/)
10
+ [![CI](https://github.com/ZahiriNatZuke/local-delegate/actions/workflows/ci.yml/badge.svg)](https://github.com/ZahiriNatZuke/local-delegate/actions/workflows/ci.yml)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
12
+
13
+ ## ¿Por qué?
14
+
15
+ Cuando Claude tiene que resumir un log enorme, clasificar, extraer campos o generar boilerplate,
16
+ gasta cuota de tu suscripción en trabajo **mecánico**. `local-delegate` expone esas tareas como
17
+ tools MCP que corren en un LLM **local**: pasas `path` en vez de `text` y el archivo se lee
18
+ **del lado del servidor**, así el contenido grande **nunca entra al contexto de Claude**. Solo
19
+ vuelve el resultado corto — cuota que no gastaste.
20
+
21
+ ## Instalación rápida
22
+
23
+ Con [`uv`](https://docs.astral.sh/uv/) no hay nada que instalar: `uvx` baja y ejecuta el paquete aislado.
24
+
25
+ Añádelo a tu config de MCP (Claude Desktop / Claude Code):
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "local-delegate": {
31
+ "command": "uvx",
32
+ "args": ["local-delegate-mcp"]
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ Ver plantillas completas en [`examples/`](./examples).
39
+
40
+ ## Requisitos
41
+
42
+ Un **endpoint OpenAI-compatible** ya corriendo, accesible en `LOCAL_DELEGATE_BASE_URL`
43
+ (default `http://127.0.0.1:9292/v1`). Cualquiera sirve:
44
+
45
+ - **llama-swap** — ver [recipe con GPU Blackwell](./docs/recipes/) *(en construcción)*.
46
+ - **Ollama** — `http://127.0.0.1:11434/v1`.
47
+ - **LM Studio**, **vLLM**, o cualquier servidor que hable la API de OpenAI.
48
+
49
+ El paquete **no arranca** ningún backend por defecto (`LOCAL_DELEGATE_AUTOSTART=0`). El
50
+ auto-arranque de llama-swap es opt-in (ver tabla de configuración).
51
+
52
+ ## Tools
53
+
54
+ Pasar `path` (en vez de `text`) hace que el MCP lea el archivo server-side → ahorro real de cuota.
55
+
56
+ | Tool | Qué hace | Rol de modelo (default) |
57
+ |---|---|---|
58
+ | `local_summarize` | Resume texto o archivo | mecánico / largo (auto) |
59
+ | `local_classify` | Devuelve UNA etiqueta de una lista | mecánico |
60
+ | `local_extract` | Extrae campos → objeto JSON | mecánico |
61
+ | `local_boilerplate` | Genera código desde una spec | código |
62
+ | `local_delegate` | Escape genérico texto→texto | mecánico (o el que pases) |
63
+ | `local_lint_summary` | Resume logs de lint/tests/CI | mecánico / largo (auto) |
64
+ | `local_commit_msg` | Mensaje de commit desde un diff | código |
65
+ | `local_translate` | Traduce texto o archivo | mecánico / largo (auto) |
66
+ | `local_explain_code` | Explica código en prosa | código |
67
+
68
+ Los modelos locales **no** usan tool-calling: el server arma el prompt + guardrails, hace POST al
69
+ endpoint y devuelve **solo texto**.
70
+
71
+ ## Configuración
72
+
73
+ Todo por variables de entorno; nada hardcodeado. Los ids de modelo default son solo eso —
74
+ cámbialos por los de tu backend.
75
+
76
+ | Variable | Default | Descripción |
77
+ |---|---|---|
78
+ | `LOCAL_DELEGATE_BASE_URL` | `http://127.0.0.1:9292/v1` | Endpoint OpenAI-compatible |
79
+ | `LOCAL_DELEGATE_API_KEY` | *(vacío)* | Bearer token, si tu endpoint lo exige |
80
+ | `LOCAL_DELEGATE_TIMEOUT` | `180` | Timeout HTTP (segundos) |
81
+ | `LOCAL_DELEGATE_LOG` | *(dir de datos de usuario)* | Ruta del `usage.jsonl` |
82
+ | `LOCAL_DELEGATE_MODEL_MECHANICAL` | `gemma3-4b` | Modelo para clasificar/extraer/resumen corto |
83
+ | `LOCAL_DELEGATE_MODEL_LONG` | `llama31-8b` | Modelo para documentos largos |
84
+ | `LOCAL_DELEGATE_MODEL_CODE` | `qwen25-coder-14b` | Modelo para código |
85
+ | `LOCAL_DELEGATE_MODEL_FAST` | `qwen35-2b` | Modelo ultrarrápido / trivial |
86
+ | `LOCAL_DELEGATE_LONG_INPUT_CHARS` | `6000` | Umbral mecánico↔largo |
87
+ | `LOCAL_DELEGATE_WEB` | `1` | Web de métricas embebida (`0` para desactivar) |
88
+ | `LOCAL_DELEGATE_WEB_HOST` / `_PORT` | `127.0.0.1` / `9393` | Host/puerto de la web |
89
+ | `LOCAL_DELEGATE_AUTOSTART` | `0` | Auto-arranque de llama-swap (opt-in) |
90
+ | `LLAMASWAP_EXE` / `LLAMASWAP_CONFIG` / `LLAMASWAP_LISTEN` | — | Solo si `AUTOSTART=1` |
91
+
92
+ ## La métrica de ahorro
93
+
94
+ El MCP registra cada llamada en `usage.jsonl` y sirve un **dashboard** en
95
+ `http://127.0.0.1:9393`. El *ahorro de contexto* = caracteres de entrada leídos server-side
96
+ (llamadas con `source=path`) ÷ 4 ≈ tokens que nunca entraron al contexto de Claude.
97
+ Detalle en la [wiki](https://github.com/ZahiriNatZuke/local-delegate/wiki) *(en construcción)*.
98
+
99
+ ## Enlaces
100
+
101
+ - [Wiki](https://github.com/ZahiriNatZuke/local-delegate/wiki) · [Recipes](./docs/recipes)
102
+ - [CONTRIBUTING](./CONTRIBUTING.md) · [CODE OF CONDUCT](./CODE_OF_CONDUCT.md) · [CHANGELOG](./CHANGELOG.md)
103
+ - [Licencia MIT](./LICENSE)