mcp-vision-image-fadhli
README.md
# mcp-vision-image-fadhli
MCP server untuk analisis gambar lewat **[9router](https://github.com/decolua/9router)** — dengan **penemuan otomatis model vision yang benar-benar bekerja di mesin Anda**.
Tidak perlu daftar model hardcoded. Tidak perlu API key Google. Tidak ada quota free tier.
---
## Kenapa perlu penemuan otomatis?
9router mengekspos ratusan model, dan katalognya punya flag `capabilities.vision`. **Flag itu tidak bisa dipercaya.**
Diukur pada satu mesin (24 Sep 2026):
| | |
|---|---|
| Model di katalog | 824 |
| Mengklaim `vision: true` | 468 |
| **Benar-benar bisa memproses gambar** | **segelintir** |
Sampel 50 model yang mengklaim vision: hanya 4 yang menjawab benar. Sisanya gagal karena:
- `401/403` — API key provider mati
- `402` — kredit habis
- `5xx` — error upstream (dibungkus 9router jadi 503)
- **`200` dengan `content` kosong** — paling menyesatkan: HTTP sukses, tapi tidak ada jawaban
- timeout
**Yang penting:** penyebabnya hampir selalu **provider**, bukan model. Dan karena setiap instalasi 9router punya provider & akun yang berbeda, daftar model yang bekerja **tidak bisa di-hardcode** — harus ditemukan di mesin tempat server berjalan.
---
## Cara kerja
```
analyze_image
│
├─ 1. Coba model eksplisit / env ROUTER9_MODEL / cache / default
│ └─ berhasil? selesai. (kasus umum, cepat)
│
└─ 2. Semua gagal → pindai mesin ini
├─ sapu SATU model per provider (gelombang 1)
├─ provider hidup? perdalam di gelombang berikutnya
├─ uji pakai gambar 3 kotak, nilai jawabannya
└─ simpan hasil → pakai model tercepat
```
**Mengapa menyapu provider dulu:** kegagalan itu soal provider. Menguji 5 model dari provider yang sama itu sia-sia — kalau providernya mati, kelimanya mati. Gelombang 1 mengambil satu model per provider, jadi berapa pun jumlah providernya, sekali jalan langsung ketahuan mana yang hidup.
**Model dinilai secara objektif.** Gambar uji berisi 3 kotak (merah, hijau, biru). Model yang benar-benar bisa melihat akan menyebut ketiga warna; model yang mengarang tidak akan cocok.
---
## Instalasi
```bash
npm install -g mcp-vision-image-fadhli
```
Butuh **9router berjalan** di mesin yang sama (default `http://127.0.0.1:20128`).
### Konfigurasi MCP
Tambahkan ke `~/.claude.json` (atau config MCP klien Anda):
```json
{
"mcpServers": {
"mcp-vision-image": {
"type": "stdio",
"command": "node",
"args": ["C:\\path\\ke\\mcp-vision-image\\src\\server.js"],
"env": {
"ROUTER9_API_KEY": "sk-xxxxxxxxxxxx"
}
}
}
}
```
API key diambil dari dashboard 9router → **Endpoint & Key**.
> **Cuma satu key yang dibutuhkan.** Key 9router membuka seluruh pool model Anda — tidak perlu key Antigravity, B.AI, atau provider lain satu per satu.
### Variabel lingkungan
| Variabel | Default | Keterangan |
|---|---|---|
| `ROUTER9_API_KEY` | — | **Wajib.** API key 9router. |
| `VISION_PROVIDERS` | `ag,oc` | Provider yang dipakai, dipisah koma. Isi `*` untuk semua. |
| `ROUTER9_BASE_URL` | `http://127.0.0.1:20128` | Alamat 9router. |
| `ROUTER9_MODEL` | — | Paksa satu model, lewati pemilihan otomatis. |
| `ROUTER9_MAX_TOKENS` | `2000` | Batas token jawaban. |
| `ROUTER9_TIMEOUT_MS` | `120000` | Timeout per model. |
### Provider yang dipakai
Default **`ag,oc`** — Antigravity dan OpenCode Free. Keduanya dipakai karena
terukur, bukan dipilih sembarangan:
| Provider | Model | Verifikasi |
|---|---|---|
| `ag` (Antigravity) | `gemini-3.8-flash-medium`, `-high`, `3.7-flash-high` | ✅ 4,1 dtk |
| `oc` (OpenCode Free) | `mimo-v2.5-free`, `muse-spark-1.3-contributor-free`, `1.2-contributor-free` | ✅ 3,8–10 dtk |
Semua diuji 25 Sep 2026 lewat endpoint Anthropic 9router memakai gambar uji
(3 kotak merah/hijau/biru) — keempatnya menjawab dengan benar.
Kenapa dibatasi: memindai **semua** provider menemukan 4 model bekerja dari 30
diuji; dibatasi ke `ag,oc` menemukan **8 dari 8**. Provider lain menghabiskan
waktu dan kuota untuk model yang kreditnya kosong atau key-nya mati.
Ganti lewat env kalau instalasi Anda berbeda:
```json
"env": {
"ROUTER9_API_KEY": "sk-xxxxxxxxxxxx",
"VISION_PROVIDERS": "ag" // Antigravity saja
}
```
Provider yang diminta tapi **tidak ada** di katalog dilaporkan sebagai
peringatan — tidak diabaikan diam-diam.
### Catatan: kenapa endpoint Anthropic
Modul ini memanggil `/v1/messages`, bukan `/v1/chat/completions`. Dua alasan,
keduanya terukur:
1. **Input gambar di endpoint OpenAI mengembalikan `content` kosong** —
HTTP-nya 200, tapi jawabannya tidak ada, untuk semua model yang diuji.
2. **Provider `oc` kena gate tambahan di endpoint OpenAI.** OpenCode Free
hanya menjawab kalau tool quartet `{bash, glob, grep, read}` ikut dikirim;
tanpanya, HTTP 200 dengan `content` kosong. Endpoint Anthropic tidak
menerapkan gate itu, jadi `oc` bekerja tanpa trik tambahan.
Bentuk responsnya juga tidak seragam — Antigravity menjawab **SSE**, `oc`
menjawab **JSON**. Parser menangani keduanya.
---
## Tools
### `analyze_image`
Menganalisis gambar dari file lokal atau URL.
| Parameter | Keterangan |
|---|---|
| `image_path` | Path file lokal |
| `image_url` | URL gambar (diunduh otomatis) |
| `prompt` | Instruksi spesifik (opsional) |
| `model` | Paksa model tertentu (opsional) |
Jawabannya menyertakan model mana yang dipakai dan berapa lama.
### `discover_vision_models`
Memindai 9router untuk menemukan model yang benar-benar bisa memproses gambar di mesin ini. Hasilnya di-cache dan dipakai otomatis oleh `analyze_image`.
Jalankan ulang kalau daftar terasa basi (provider berganti, kredit berubah).
| Parameter | Default | Keterangan |
|---|---|---|
| `target` | 5 | Berhenti setelah sekian model bekerja |
| `max_probe` | 48 | Batas atas model diuji (pengaman kuota) |
| `include_non_vision` | false | Ikut uji yang tidak mengklaim vision — untuk memeriksa akurasi metadata |
**Batas selalu dilaporkan.** Kalau ada model yang tidak diuji karena kena batas, jumlahnya disebutkan — supaya hasilnya tidak terbaca "menyeluruh" padahal tidak.
### `get_usage_stats`
Statistik pemakaian per model, riwayat harian, status backend, dan ringkasan hasil pemindaian terakhir.
---
## Catatan teknis
### Kenapa endpoint Anthropic, bukan OpenAI?
Untuk input **gambar**, `/v1/chat/completions` di 9router mengembalikan **HTTP 200 dengan `content` kosong** — untuk semua model yang diuji. `/v1/messages` dengan model yang sama menjawab benar. Jadi ini soal jalur translasi gambar di 9router, bukan soal model.
| Endpoint | Hasil untuk input gambar |
|---|---|
| `/v1/chat/completions` | HTTP 200, `content` **kosong** |
| `/v1/messages` | jawaban benar |
### Blok thinking dibuang
Model thinking mengirim rantai penalaran di `thinking_delta` (sering dalam bahasa Mandarin). Parser hanya mengambil `text_delta`, dan `max_tokens` dijaga cukup tinggi supaya jatah tidak habis di thinking lalu menyisakan `content` kosong.
---
## Test
```bash
ROUTER9_API_KEY=xxx npm test
```
13 pemeriksaan, termasuk memanggil tool lewat protokol MCP sungguhan (stdio) dan memverifikasi jawaban terhadap gambar uji secara objektif.
Untuk memindai lebih luas di luar test:
```bash
node test/probe-vision.js --per-provider 2 # sampel stratifikasi
node test/probe-vision.js --all # sapu bersih
node test/probe-vision.js --only ag/gemini-3.8-flash-high
node test/probe-vision.js --control # uji akurasi metadata katalog
```
---
## Lisensi
MIT
TDQS
A4/5.0
Scored across 2 tools
Disambiguation5/5
The two tools have clearly distinct purposes: analyze_image handles image analysis, while get_usage_stats reports API usage metrics. No overlap or ambiguity exists.
Naming Consistency5/5
Both tools follow a consistent verb_noun pattern: analyze_image and get_usage_stats. The naming is uniform and predictable.
Tool Count3/5
With only 2 tools, the server feels thin but is reasonable for a focused single-purpose image analysis service. It sits at the borderline of being too minimal.
Completeness5/5
For its stated purpose of image analysis via Gemini Vision, the server covers the core operation (analyze_image) and adds useful monitoring (get_usage_stats). No obvious missing operations within this narrow domain.
Maintenance
ActivityMaintained
ResponsivenessNo issues