Skip to main content
Glama

EL-KITE MCP

Aplikasi untuk membaca dan merapikan usulan jabatan akademik dosen (JAD) di EL-KITE LLDIKTI III (https://elkite-lldikti3.kemdiktisaintek.go.id) dari asisten AI, terminal, atau program lain.

Paket ini membaca profil dosen beserta riwayat jabatan fungsionalnya, daftar usulan JAD (Draft, Proses, Selesai), kedelapan tab draf usulan, dan AK Penyetaraan. Untuk merapikan draf, ia bisa mengubah empat isian (jenjang pendidikan pada jabatan sebelumnya, JAD usulan, bidang ilmu, dan tanggal penerbitan ijazah), mengunggah dokumen persyaratan, mengisi kegiatan IKD, dan menambah entri Bidang B. Semua alat yang menulis bawaannya uji coba dan membaca ulang EL-KITE sesudah mengirim; rinciannya di Mengubah draf usulan. Mengajukan usulan, mengubah status usulan, dan menghapus apa pun tidak bisa dilakukan lewat paket ini.

Tersedia dalam tiga bentuk, semuanya dari paket yang sama:

Mode

Untuk siapa

Referensi

MCP

asisten AI (Claude Code, dsb.)

docs/MCP.md

REST API

aplikasi apa pun lewat HTTP

docs/API.md

Pustaka

program Python Anda sendiri

bagian Pustaka

Ada juga CLI (./elkite draf, ./elkite ubah, dan seterusnya) untuk pemakaian langsung dari terminal; lihat docs/CLI.md.

Memakainya lewat asisten AI

Server MCP-nya bisa didaftarkan ke Claude Code, Codex, dan Antigravity. Yang tercepat, untuk Claude Code dari klona repositori ini:

claude mcp add elkite-mcp -s user -- /path/ke/elkite-mcp/elkite mcp

Sebelum tool-nya dipakai, login sekali di terminal dengan ./elkite login (lihat Login). Langkah untuk ketiga klien dan pengaturan izin pemanggilan tool ada di docs/MCP.md.

Related MCP server: SIAKAD MCP

Prasyarat

  • Python 3.10 atau lebih baru

  • Google Chrome (google-chrome) untuk login di jendela browser; xdotool opsional, untuk menaikkan jendela login ke paling atas

  • Akun EL-KITE LLDIKTI III yang aktif. Simpan username dan password di .env dengan izin 600 agar ./elkite login dapat mengisinya otomatis.

Pasang

Ada dua cara, pilih salah satu.

A. Berdiri sendiri. Klona lalu jalankan; cocok kalau Anda hanya mau memakai aplikasinya:

git clone https://github.com/alfa-yohannis/elkite-mcp.git
cd elkite-mcp
./elkite uji          # jalankan pertama menyiapkan .venv + dependensi sendiri

Peluncur membuat virtualenv dengan python3.14. Kalau versi itu tidak ada di mesin Anda, pilih interpreter lain: ELKITE_PYTHON=python3.12 ./elkite uji. Letak virtualenv bisa dipindah lewat ELKITE_VENV. Setiap kali pyproject.toml berubah, peluncur memasang ulang paketnya sendiri.

B. Sebagai paket, kalau aplikasi Anda sendiri yang akan memakainya. Paketnya belum ada di PyPI, jadi pasang dari repositorinya:

pip install "elkite-mcp[api,mcp] @ git+https://github.com/alfa-yohannis/elkite-mcp.git"
pip install "git+https://github.com/alfa-yohannis/elkite-mcp.git"   # pustaka saja

Login

Halaman login EL-KITE meminta username, password, dan jawaban soal hitungan (captcha). Simpan dua kredensial pertama di .env:

ELKITE_USERNAME=...
ELKITE_PASSWORD=...

./elkite login mengisi keduanya otomatis. Paket tidak menjawab captcha dan tidak mengirim form; Anda cukup menjawab captcha dan menekan Login. Setelah itu semua perintah, tool MCP, dan endpoint REST memakai sesi yang tersimpan:

./elkite login        # jendela Chrome terbuka di halaman login EL-KITE
./elkite cek-login    # periksa sesi yang tersimpan masih hidup

./elkite login menjalankan Google Chrome dengan profil khusus .elkite-browser/ langsung di halaman login, lalu menaikkan jendelanya ke paling atas kalau xdotool terpasang. Username/password dari .env diisi hanya ke tab HTTPS pada host EL-KITE dan kursor dipindahkan ke kolom captcha. Begitu Anda menjawab captcha, menekan Login, dan tab mendarat di beranda (/usulan), cookie untuk host EL-KITE disimpan ke .elkite-sesi.json dengan izin 600, lalu Chrome ditutup. Batas tunggunya 10 menit.

Perintah lain memakai cookie itu. Pemeriksaan sesinya satu GET ke /login: sesi yang hidup dialihkan EL-KITE ke beranda. Kalau sesi belum ada atau sudah habis, perintah berhenti dengan pesan "Sesi EL-KITE belum ada atau sudah habis. Jalankan ./elkite login, lalu selesaikan CAPTCHA dan tekan Login di jendela browser yang muncul." Tool MCP dan REST API meneruskan pesan itu apa adanya. Tidak ada yang login ulang secara otomatis. Sesi baru dari ./elkite login langsung terpakai tanpa menjalankan ulang server MCP atau REST API, dan kalau EL-KITE mengganti cookie sesinya di tengah jalan, cookie baru itu ditulis balik ke .elkite-sesi.json. Kiriman yang menulis tidak pernah diulang.

.env, .elkite-sesi.json, dan .elkite-browser/ ada di .gitignore. Ketiganya memberi akses ke akun EL-KITE Anda, jadi jangan disalin ke mana-mana. Lindungi .env dan .elkite-sesi.json dengan izin 600. Username, password, dan isi cookie tidak pernah dicetak.

Menjalankan

1. MCP

claude mcp add elkite-mcp -- /path/ke/elkite-mcp/elkite mcp   # dari klona
claude mcp add elkite-mcp -- elkite-mcp                       # setelah pip install

Cek servernya hidup tanpa mendaftarkannya dulu:

./elkite mcp        # bicara JSON-RPC lewat stdio; Ctrl-C untuk berhenti

Lalu minta asisten Anda, misalnya: "Tampilkan draf usulan JAD saya dan jelaskan berapa angka kredit yang masih kurang." Ada 16 tool. Delapan hanya membaca: cek_login, profil_dosen, daftar_usulan, baca_draf, baca_ak_penyetaraan, daftar_persyaratan, daftar_ikd, dan daftar_bidang_b. Delapan lainnya menulis ke draf dan bawaannya uji coba: ubah_jenjang_lama, ubah_jad_usulan, ubah_bidang_ilmu, ubah_tanggal_ijazah, unggah_persyaratan, tambah_ikd, ubah_ikd, dan tambah_bidang_b. Rinciannya di docs/MCP.md.

2. REST API

./elkite api                  # http://localhost:8000
PORT=9001 ./elkite api        # ganti port
uvicorn elkite_mcp.api:app --port 8000   # kalau terpasang sebagai paket

Dokumentasi interaktif ada di /docs. Semua endpoint memakai POST dengan badan JSON. Coba:

curl -X POST localhost:8000/usulan -H 'Content-Type: application/json' -d '{}'
curl -X POST localhost:8000/draf -H 'Content-Type: application/json' \
  -d '{"tab": "resume"}'

Untuk menempelkannya ke aplikasi FastAPI Anda sendiri:

from elkite_mcp.api import router
app.include_router(router, prefix="/elkite")

Endpoint selengkapnya di docs/API.md.

3. Pustaka

from elkite_mcp import KlienElkite, daftar_usulan, draf_usulan

klien = KlienElkite()                          # cookie dari .elkite-sesi.json; EL-KITE belum dihubungi
for baris in daftar_usulan(klien, "draft"):    # sesi diperiksa di sini
    print(baris.no_usulan, baris.status, baris.jad_usulan)

draf = draf_usulan(klien, tab="resume")        # nomor kosong: satu-satunya draf
print(draf["resume"]["total_ak"], draf["resume"]["rekomendasi"])

Setelan, alamat EL-KITE, dan letak berkas sesi boleh diberikan dari kode tanpa berkas setelan apa pun:

from elkite_mcp import KlienElkite, atur_setelan

atur_setelan(batas_halaman_detik=60)
klien = KlienElkite(base_url="https://elkite.contoh-karangan.ac.id",
                    berkas_sesi="/path/ke/.elkite-sesi.json")

Login dari kode juga lewat jendela Chrome, sama seperti ./elkite login:

from elkite_mcp.login_browser import login_lewat_browser

hasil = login_lewat_browser(kabar=print)    # kredensial terisi; Anda menyelesaikan captcha
print(hasil.berkas_sesi, hasil.jumlah_cookie)

Fungsi yang menulis bawaannya uji coba. Dengan uji_coba=False, form dikirim sekali, lalu tab-nya dibaca ulang untuk verifikasi:

from elkite_mcp import KlienElkite, ubah_tanggal_ijazah

klien = KlienElkite()
rencana = ubah_tanggal_ijazah(klien, "2004-07-18", jenjang="S-2")
print(rencana.sebelum, rencana.sesudah, rencana.isian, rencana.hambatan)

hasil = ubah_tanggal_ijazah(klien, "2004-07-18", jenjang="S-2", uji_coba=False)
print(hasil.berubah, hasil.sesudah, hasil.flash)

Fungsi baca lainnya profil_dosen, baca_ak_penyetaraan, daftar_persyaratan, daftar_ikd, dan daftar_bidang_b; fungsi tulis lainnya ubah_jenjang_lama, ubah_jad_usulan, ubah_bidang_ilmu, unggah_persyaratan, tambah_ikd, ubah_ikd, dan tambah_bidang_b. Semuanya menerima KlienElkite sebagai argumen pertama. Pembaca HTML (baca_profil, baca_data_dasar, baca_pendidikan, baca_ikd, baca_bidang_b, baca_persyaratan, baca_ak, baca_resume, baca_log, baca_data_dasar_pak, baca_resume_pak) menerima HTML beserta alamatnya dan tidak menyentuh jaringan.

Semua kegagalan berupa exception biasa: ElkiteError beserta turunannya (LoginPerluManusia, AlamatDitolak, PengubahanDitolak, HasilTidakPasti), dan KonfigurasiError untuk setelan yang tidak bisa dipakai. Pustaka tidak pernah memanggil sys.exit.

CLI

./elkite login                        # kredensial terisi; selesaikan captcha; sesi disimpan
./elkite cek-login                    # sesi yang tersimpan masih hidup?
./elkite profil                       # profil dosen dan riwayat jabatan fungsional
./elkite usulan --status proses       # daftar usulan JAD: draft, proses, selesai
./elkite draf --tab resume            # isi tab draf usulan JAD
./elkite ak-penyetaraan <nomor>       # data dasar, pendidikan, dan resume AK Penyetaraan
./elkite ubah jenjang S-2             # uji coba; --kirim untuk mengirim
./elkite persyaratan                  # dokumen persyaratan; `unggah` mengunggah satu
./elkite ikd                          # butir IKD; `tambah` dan `ubah` mengisi kegiatan
./elkite bidang-b --butir B0006       # butir Bidang B dan form TAMBAH butir itu
./elkite petakan <path>               # form, tabel, tautan, endpoint skrip

Terpasang sebagai paket, perintahnya elkite-login, elkite-cek-login, elkite-profil, elkite-usulan, elkite-draf, elkite-ak-penyetaraan, elkite-ubah, elkite-persyaratan, elkite-ikd, elkite-bidang-b, elkite-petakan, dan elkite-mcp, dengan argumen yang sama. Argumen selengkapnya di docs/CLI.md.

Mengubah draf usulan

Yang dikerjakan

CLI

Tool MCP

Tujuan POST di EL-KITE

ubah jenjang pendidikan pada jabatan sebelumnya

./elkite ubah jenjang

ubah_jenjang_lama

/usulan/usulan/update_jenjang

ubah JAD usulan

./elkite ubah jad

ubah_jad_usulan

/usulan/usulan/update_jad

ubah bidang ilmu

./elkite ubah bidang-ilmu

ubah_bidang_ilmu

/usulan/usulan/update_bid_ilmu

ubah tanggal ijazah di draf JAD

./elkite ubah tanggal-ijazah

ubah_tanggal_ijazah

/usulan/usulan/update_tgl_ijazah/<dosen_no>

ubah tanggal ijazah di AK Penyetaraan

./elkite ubah tanggal-ijazah --ak-penyetaraan

ubah_tanggal_ijazah

/usulan/pak/update_tgl_ijazah

unggah dokumen persyaratan

./elkite persyaratan unggah

unggah_persyaratan

/usulan/usulan/tambah_syarat

tambah kegiatan IKD

./elkite ikd tambah

tambah_ikd

/usulan/usulan/simpan_ikd

ubah kegiatan IKD

./elkite ikd ubah

ubah_ikd

/usulan/usulan/update_ikd

tambah entri butir Bidang B

./elkite bidang-b tambah

tambah_bidang_b

/usulan/usulan_dupak_b/tambah_B0004/<kode>/<kum>

Semuanya mengikuti alur yang sama:

  1. Tab yang memuat form-nya dibaca lebih dulu. Form dicari menurut action-nya, dan form yang memuat isian tak dikenal ditolak sebelum apa pun dikirim. Kode yang dibutuhkan form (jenis dokumen, id_detail_dharma, id kegiatan, AK) diambil dari tombol dan isian di halaman; kalau tombolnya tidak ada, kiriman sungguhan ditolak.

  2. Nilai baru diperiksa terhadap pilihan sah di form itu, dan nilai yang sudah sama tidak dikirim ulang. Berkas harus PDF (berakhiran .pdf dan berawalan %PDF) dan tidak melebihi batas yang tertulis di form: 10 MB untuk Persyaratan dan IKD, 5 MB untuk Bidang B.

  3. Tanpa --kirim di CLI, atau selama uji_coba dibiarkan pada bawaannya di pustaka, MCP, dan REST API, hasilnya rencana kiriman: tujuan form, isian yang akan dikirim, nilai sebelum dan sesudah, catatan, dan hambatan. Rencana yang membawa hambatan ditolak kalau dikirim sungguhan.

  4. Berkas atau entri yang sudah ada tidak ditimpa kecuali dengan --paksa di CLI atau paksa bernilai true. tambah_ikd tetap menolak butir yang sudah berisi kegiatan, karena EL-KITE hanya menerima satu kegiatan per butir dan satu kegiatan per dharma; untuk mengganti kegiatan yang ada pakai ubah_ikd.

  5. Kiriman sungguhan berangkat tepat sekali sebagai multipart/form-data, sama seperti tombol di browser, lalu tab-nya dibaca ulang. Berkas yang diunggah diunduh ulang dari tautannya di halaman dan md5-nya dicocokkan dengan berkas lokal. Kalau tautan itu membalas halaman kecil berisi <iframe> (tombol "Lihat Bukti" IKD begitu), berkas yang disematkannya yang diunduh. berubah bernilai true hanya kalau semuanya cocok; kalau tidak, kode keluar CLI bernilai 1 dan ok di MCP serta REST API bernilai false.

  6. Kalau kiriman sudah berangkat tetapi hasilnya tidak bisa dipastikan (EL-KITE membalas galat, sesinya ternyata habis, atau pengalihannya mengarah ke alamat yang tidak dibuka klien), yang muncul HasilTidakPasti. Kiriman tidak pernah diulang otomatis; baca ulang tab-nya sebelum mencoba lagi. Kalau penyebabnya sesi habis, jalankan ./elkite login dulu.

Unggahan dan entri yang sudah terkirim tidak bisa dihapus lewat paket ini; yang keliru harus dihapus sendiri di browser. Tanggal ijazah draf JAD dan AK Penyetaraan dikirim ke endpoint yang berbeda. Pada akun yang diamati keduanya menunjuk baris riwayat pendidikan yang sama, jadi tanggal yang diubah lewat draf JAD langsung terbaca juga di AK Penyetaraan; tetap baca ulang keduanya sesudah mengubah. Pada draf yang diamati per Oktober 2026, kolom Aksi tab Persyaratan kosong untuk semua dokumen, sehingga unggah_persyaratan menolak mengirim sampai EL-KITE menampilkan tombol unggahnya.

Setelan

Semua setelan opsional. Yang menang, dari yang paling khusus:

argumen pemanggil -> atur_setelan() -> environment -> .env -> elkite.yaml -> nilai bawaan

Di environment dan .env namanya berawalan ELKITE_ dan huruf besar (ELKITE_BASE_URL); di elkite.yaml tanpa awalan dan huruf kecil (base_url). Salin elkite.yaml.contoh menjadi elkite.yaml kalau perlu mengubah sesuatu. elkite.yaml dibaca sekali per proses, jadi jalankan ulang server MCP atau REST API sesudah mengubahnya.

elkite.yaml

Bawaan

Keterangan

website

https://elkite-lldikti3.kemdiktisaintek.go.id/login

halaman login; alamat EL-KITE diturunkan darinya

base_url

https://elkite-lldikti3.kemdiktisaintek.go.id

alamat EL-KITE, kalau perlu disebut terpisah

no_usulan

kosong

nomor draf JAD kalau tidak disebut; kosong berarti satu-satunya draf

no_ak_penyetaraan

kosong

nomor AK Penyetaraan kalau tidak disebut

batas_login_detik

60

pemeriksaan sesi (GET /login)

batas_halaman_detik

120

permintaan lainnya

maks_pengalihan

10

pengalihan yang diikuti per permintaan

user_agent

User-Agent Chrome saat ./elkite login

User-Agent permintaan HTTP; tanpa berkas sesi, Chrome 126 di X11

Khusus ./elkite login, username dan password dibaca dari environment atau .env sebagai ELKITE_USERNAME dan ELKITE_PASSWORD; keduanya tidak diterima dari elkite.yaml, CLI, REST API, atau parameter tool MCP. Alamat EL-KITE dan halaman login harus https dan berada di host yang sama. Nomor usulan milik satu akun, jadi kalau elkite.yaml dibagikan, simpan nomornya di .env (ELKITE_NO_USULAN, ELKITE_NO_AK_PENYETARAAN).

Peluncur ./elkite membaca tiga variabel lain dari environment: ELKITE_PYTHON (interpreter pembuat virtualenv, bawaan python3.14), ELKITE_VENV (letak virtualenv, bawaan .venv di repositori), dan PORT (port ./elkite api, bawaan 8000).

Akar proyek

Akar proyek menentukan letak .elkite-sesi.json, .elkite-browser/, .env, elkite.yaml, dan data/, serta titik hitung path relatif, termasuk path berkas PDF yang akan diunggah:

  • dijalankan dari klona repositori ini: direktori repositori itu sendiri; peluncur ./elkite menyetelnya lewat ELKITE_AKAR_PROYEK

  • dipasang sebagai paket: direktori kerja proyek pemakai

Direktori di atasnya tidak pernah ikut ditelusuri, jadi hasilnya tidak berubah hanya karena aplikasi dipindah. Untuk menentukan sendiri, setel ELKITE_AKAR_PROYEK di environment atau panggil atur_akar_proyek().

Rancangan

pyproject.toml                metadata paket, dependensi, dan perintah terpasang
elkite                        peluncur untuk pemakaian berdiri sendiri
.env.contoh                   contoh kredensial login dan setelan pribadi
elkite.yaml.contoh            contoh setelan yang aman dibagikan
elkite_mcp/__init__.py        API publik paket ini
elkite_mcp/konfigurasi.py     akar proyek, setelan, letak berkas sesi, sesi HTTP
elkite_mcp/sesi.py            berkas sesi: simpan (izin 600), muat, dan pasang cookie
elkite_mcp/login_browser.py   ./elkite login: Chrome berprofil khusus, pantauan CDP, simpan cookie
elkite_mcp/elkite_client.py   KlienElkite: sesi dari berkas, pemeriksaan sesi, pagar GET dan POST, kiriman tepat sekali
elkite_mcp/halaman.py         pembaca HTML umum: teks, pasangan label-nilai, tabel, form, pesan flash (tanpa jaringan)
elkite_mcp/privasi.py         penyaring data pribadi sebelum keluar lewat CLI, REST API, atau MCP
elkite_mcp/profil.py          profil dosen dan riwayat jabatan fungsional
elkite_mcp/usulan.py          daftar usulan JAD dan pembaca kedelapan tab draf
elkite_mcp/ak_penyetaraan.py  data dasar, riwayat pendidikan, dan resume AK Penyetaraan
elkite_mcp/ubah.py            pengubah isian draf beserta bantuan bersama alat penulis
elkite_mcp/unggah.py          unggahan Persyaratan, IKD, dan Bidang B
elkite_mcp/cli.py             CLI (elkite-login, elkite-cek-login, elkite-draf, elkite-ubah, dan seterusnya)
elkite_mcp/api.py             REST API: router yang bisa ditempel + app siap pakai
elkite_mcp/mcp_server.py      MCP server (perintah elkite-mcp)
elkite_mcp/petakan_form.py    alat bantu memetakan halaman saat menambah kemampuan
tests/                        unit test dengan EL-KITE dan Chrome tiruan, tanpa jaringan
docs/                         referensi CLI, REST API, dan MCP

Catatan perilaku EL-KITE

Diamati pada EL-KITE asli pada Oktober 2026. Nama isian form ubah data, kode tombol, dan pilihan <select> dibaca ulang dari halaman setiap kali dipakai; yang tertulis di kode hanya path halaman dan tujuan POST yang diizinkan.

  • EL-KITE adalah aplikasi CodeIgniter. Alamatnya dipetakan langsung ke method controller, jadi membuka sebuah alamat dengan GET sudah bisa menjalankan aksinya. Karena itu klien menolak GET ke alamat yang tampak seperti aksi.

  • GET /login berisi form POST ke /login/login dengan isian username, password, dan captcha_answer, dengan soal hitungan di labelnya (misalnya "Berapa hasil dari 8 + 7 ?"). Paket ini tidak mengisi form itu dan tidak pernah mengirim apa pun ke /login/login; yang login selalu pemakai sendiri di browser. Login yang berhasil dibalas 303 ke /usulan/usulan, dan sesi yang masih hidup membuat GET /login dialihkan ke beranda. Pengalihan itulah yang dipakai untuk memeriksa sesi tersimpan.

  • Sesinya cookie ci_session CodeIgniter. Cookie yang diganti EL-KITE di tengah jalan ikut disimpan ulang ke .elkite-sesi.json.

  • Beranda juga memuat form berisian password, yaitu modal Ganti Password, tetapi tanpa captcha. Sebuah halaman dianggap halaman login hanya kalau isian password dan captcha ada di form yang sama.

  • Rantai sertifikat TLS-nya dikirim lengkap: Sectigo Public Server Authentication CA DV R36, lalu Root R46 yang ditandatangani silang USERTrust RSA. Bundel CA bawaan requests sudah cukup.

  • Templatnya admin Bootstrap. Isi halaman ada di .page-wrapper dan menu di aside.left-sidebar. Halaman detail menampilkan data sebagai baris form-group berisian readonly atau sebagai tabel "label : nilai", kadang dua pasangan per baris.

  • Form ubah data ada di modal Bootstrap yang dibuka tombol bertanda data-target="#id-modal", dan dikirim sebagai multipart/form-data. Form tanggal ijazah dan unggah persyaratan justru membungkus modalnya.

  • Pesan sesudah kiriman form dititipkan di atribut data-flashdata, data-flasherror, dan data-flashwarning, lalu ditampilkan skrip halaman. Pembacanya mencatat ketiganya sebagai berhasil, galat, dan peringatan.

  • Daftar usulan JAD dimuat DataTables lewat POST /usulan/usulan/usulan/<kode>, dengan kode 1 untuk Draft, 99 untuk Proses, dan 9 untuk Selesai. Kolom pertamanya memuat tombol Detail Ajuan dan Hapus; hanya tautan Detail Ajuan yang dipakai. Klien meminta 100 baris pertama per status.

  • Nomor usulan JAD terdiri atas 14 digit waktu pembuatan diikuti dosen_no. Nomor AK Penyetaraan sebaliknya: dosen_no diikuti enam digit jam pembuatan.

  • Draf usulan JAD punya delapan tab di /usulan/usulan/<tab>/<no_usulan>: usulans (Data Dasar), show_pendidikan (Riwayat Pendidikan), ikd, bidangB, persyaratan, show_skp (AK Integrasi/Penyetaraan, Konversi & Prestasi), show_resume, dan show_log.

  • Tab Data Dasar memuat form update_jenjang (no_usulan, jenjang_id_lama), update_jad (no_usulan, jabatan_usulan_no), dan update_bid_ilmu (dosen_no, no_usulan, sta, bid_ilmu). Pada draf yang diamati, pilihan jenjangnya 30 S-1, 32 Sp-1, 35 S-2, 36 S-2 Terapan, 37 Sp-2, 40 S-3, dan 41 S-3 Terapan, sedangkan pilihan JAD-nya 4 Lektor (200), 5 Lektor (300), 8 Lektor Kepala (400), 9 Lektor Kepala (550), dan 10 Lektor Kepala (700). Label opsinya diawali ikon, yang dibuang saat dibaca.

  • Di tab Riwayat Pendidikan, tanggal penerbitan ijazah tampil di isian readonly, dan tombol "Ubah data" membuka modal #edit_tgl<id_rwy_didik_formal>. Form draf JAD menuju /usulan/usulan/update_tgl_ijazah/<dosen_no> (isian id_rwy_didik_formal, no_usulan, tgl_ijazah), sedangkan AK Penyetaraan memakai /usulan/pak/update_tgl_ijazah dengan tambahan id_sdm. Keduanya endpoint terpisah, tetapi id_rwy_didik_formal-nya sama, dan tanggal yang diubah lewat salah satunya terbaca di keduanya.

  • Menu AK Penyetaraan dibuka lewat /usulan/pak/pak_baru, dan halaman itu membuat Draft AK Penyetaraan baru. Klien tidak pernah membukanya, jadi nomor AK Penyetaraan harus disebut sendiri (salin dari alamat /usulan/pak/detail/<nomor> di browser) atau disimpan di ELKITE_NO_AK_PENYETARAAN. Tab yang dibaca adalah detail, show_pendidikan, dan show_resume di bawah /usulan/pak/. Tombol "Buat Usulan Baru" menuju /usulan/usulan/tambah, yang juga tidak pernah dibuka.

  • Tab Persyaratan punya form unggah POST /usulan/usulan/tambah_syarat berisi jenis, no_usulan, dan berkas (PDF, maks. 10 MB). Kode jenis dikirim tombol unggah lewat atribut data-nama. Pada draf yang diamati, kolom Aksi kosong untuk semua dokumen, jadi tombol dan kodenya belum ada, dan alat unggah menolak menebak.

  • Di tab IKD, tombol Tambah tiap butir membawa data-id (id_detail_dharma) dan data-sudah-ada="1" kalau butir itu, atau butir lain di dharma yang sama, sudah terisi: EL-KITE hanya menerima satu kegiatan per dharma ("pilih salah satu dari setiap Dharma"). Tombol "Lihat Bukti" membalas halaman kecil berisi <iframe> ke /assets/download_file_ikd/<berkas>. Form tambahnya POST /usulan/usulan/simpan_ikd (usulan_no, id_detail_dharma, ket_ikd, file_bukti_ikd PDF maks. 10 MB). Ubahnya lewat /usulan/usulan/update_ikd (id_ikd, usulan_no, file_lama_ikd, ket_ikd, dan file_bukti_ikd yang opsional).

  • Halaman butir Bidang B ada di /usulan/usulan_dupak_b/dupak/<kode>/<no_usulan>. Form TAMBAH-nya POST /usulan/usulan_dupak_b/tambah_B0004/<kode>/<kum> dengan isian semester, thn_akademik, jp, pk, tgl, satuan_hasil, syarat, uraian, url_web, url, keterangan, dan berkas (PDF maks. 5 MB), ditambah isian tersembunyi no_usulan, kum (AK), dan volum. Butir B0004 juga punya k dan kategori_jurnal. Untuk usulan Lektor, satu poin hanya berisi satu data. Paket ini tidak bisa menghapus entri.

  • Halaman Profil (/usulan/profil) memuat identitas dalam tabel "label : nilai" dua pasangan per baris, kartu "Perhatian !" tentang kelayakan mengajukan JAD berikutnya, kartu Sinta Score dan H Index, jabatan fungsional dan pangkat saat ini beserta riwayatnya, dan riwayat pendidikan.

  • Aksi yang tidak pernah dipanggil paket ini: form login (/login/login), proses_usulanbaru (mengajukan usulan, usulan_status 10), update_statusjad, ganti_password, apa pun yang memuat hapus atau delete, logout, pak_baru, serta tombol sinkron SISTER/PDDIKTI dan ubah foto di Profil. Pagar klien menolak semuanya sebelum dikirim.

Keamanan dan batasan

  • Verifikasi sertifikat TLS selalu aktif dan tidak ada setelan untuk mematikannya. Uji memastikan verify=False tidak muncul di kode paket.

  • Setiap permintaan dibatasi ke host EL-KITE lewat https. Alamat lain, alamat http://, dan pengalihan ke host lain ditolak sebelum dikirim.

  • GET hanya membaca. Alamat yang path atau query-nya memuat potongan kata aksi ditolak, juga pada setiap langkah pengalihan. Daftarnya POTONGAN_GET_DILARANG di elkite_client.py, antara lain hapus, delete, logout, pak_baru, tambah, update, upload, unggah, simpan, sinkron, kirim, ajukan, batal, dan submit.

  • POST hanya ke path terdaftar tanpa query: tiga tabel DataTables yang hanya membaca (PATH_POST_BACA) dan form ubah data yang masing-masing punya alat beruji coba (PATH_POST_TULIS, POLA_POST_TULIS). Path yang memuat login, proses_usulan, usulanbaru, statusjad, ganti_password, hapus, delete, logout, atau pak_baru selalu ditolak, juga kalau kelak ada yang menambahkannya ke daftar, dan juga pada lapisan permintaan terbawah.

  • Kiriman ubah data berangkat tepat sekali dan tidak diulang, juga saat sesinya ternyata habis. Pengalihan sesudahnya diikuti sebagai GET selama masih di EL-KITE; pengalihan 307/308 yang meminta POST diulang tidak diikuti.

  • Tidak ada alat untuk mengajukan usulan, mengubah status, menghapus, mengganti password, logout, atau membuka menu AK Penyetaraan. Unggahan dan entri yang sudah terkirim tidak bisa dihapus lewat paket ini.

  • Username dan password hanya dibaca dari environment atau .env, lalu dikirim ke dua kolom pada tab login HTTPS di host EL-KITE. Nilainya tidak dicetak dan tidak diterima oleh CLI, REST API, atau tool MCP. Paket tidak menjawab captcha dan tidak mengirim form login. Isi cookie sesi tidak muncul di repr(), pesan galat, maupun keluaran CLI; .elkite-sesi.json selalu ditulis dengan izin 600.

  • ./elkite login memakai Target.getTargets untuk memastikan tab yang benar, Target.attachToTarget dan Runtime.evaluate untuk mengisi dua kredensial, lalu Target.detachFromTarget, Storage.getCookies, Browser.getVersion, dan Browser.close. Skrip browser hanya mengisi dua input, memicu event input dan change, serta memfokuskan kolom captcha; tidak ada jawaban captcha, klik, atau pengiriman form. Port DevTools dipilih Chrome sendiri dan hanya mendengarkan 127.0.0.1, tetapi selama jendela login terbuka, program lain di mesin yang sama bisa menyambung ke sana. Jangan menjalankannya di mesin bersama.

  • Nilai berlabel data pribadi (tempat dan tanggal lahir, NIK, NPWP, nomor HP, alamat, rekening) ditulis (disembunyikan) saat halaman dibaca, sebelum keluar lewat CLI, REST API, atau MCP. Penyaringnya mencocokkan kata pada label (KATA_PRIBADI di privasi.py).

  • REST API tidak punya autentikasi sendiri dan memakai sesi EL-KITE yang tersimpan di mesin server, jadi siapa pun yang bisa menghubunginya bertindak atas nama akun itu. uvicorn bawaannya hanya mendengarkan 127.0.0.1; jangan membukanya ke jaringan lain tanpa pelindung di depannya.

  • Berkas biner seperti PDF ditolak pembaca halaman. Unduhan hanya dipakai untuk mencocokkan md5 berkas yang baru diunggah.

  • data/, .elkite-sesi.json, dan .elkite-browser/ sudah masuk .gitignore. ./elkite petakan --html menyimpan HTML mentah yang memuat data pribadi di data/.

Menambah kemampuan baru

./elkite login                      # 1. kredensial terisi; selesaikan captcha kalau sesi belum ada
./elkite petakan <path>             # 2. petakan halamannya ke data/form_<path>.json
./elkite petakan <path> --html      #    simpan juga HTML mentahnya untuk dibaca
# 3. tulis pembaca HTML tanpa jaringan (baca_*) beserta dataclass hasilnya
# 4. tiru struktur halamannya di tests/halaman_tiruan.py dengan data karangan,
#    lalu tulis ujinya
# 5. daftarkan di cli.py, api.py, dan mcp_server.py

Path halaman diambil dari alamat di browser. ./elkite petakan hanya melakukan GET lewat pagar yang sama dengan alat lain, jadi alamat yang memuat kata aksi ditolak. Nilai isian password dan isian berlabel data pribadi ditulis <disamarkan>, tetapi HTML mentah dari --html tidak disaring. Keduanya tersimpan di data/.

Alat yang menulis mengikuti pola ubah.py. Ia menerima uji_coba yang bawaannya True dan mengembalikan HasilUbah berisi rencana kiriman. Form-nya dibaca dari halaman pada sesi yang sama, dan isian yang tidak dikenal ditolak. Tujuan POST-nya ditambahkan ke PATH_POST_TULIS atau POLA_POST_TULIS di elkite_client.py, kirimannya lewat kirim_sekali(), lalu tab-nya dibaca ulang untuk verifikasi. Di CLI, kiriman sungguhan butuh --kirim, dan instruksi MCP-nya meminta asisten menjalankan uji coba lebih dulu lalu meminta persetujuan pemakai. Path yang memuat potongan di POTONGAN_POST_DILARANG tetap ditolak walau sudah didaftarkan.

Konvensi penulisan skrip

  • Satu modul untuk satu menu EL-KITE (profil.py, usulan.py, ak_penyetaraan.py); pengubah dan pengunggah dipisah di ubah.py dan unggah.py.

  • Pembaca HTML (baca_*) tidak menyentuh jaringan dan menghasilkan dataclass; fungsi yang mengambil halaman memanggil pembaca itu. CLI, REST API, dan MCP memakai bentuk dict dari dataclass yang sama.

  • Setiap kelas, method, dan fungsi punya docstring.

  • Fungsi ditulis datar, tanpa fungsi bersarang di dalam fungsi.

  • Nama variabel dan fungsi ditulis utuh dan deskriptif (sesi_http, alamat_kirim), tanpa singkatan satu-dua huruf.

  • Komentar hanya untuk hal yang tidak terbaca dari kodenya.

  • Nilai rahasia dan data pribadi tidak pernah dicetak.

Pengujian

./elkite uji

237 unit test, semuanya berjalan tanpa jaringan, tanpa akun, dan tanpa membuka browser. EL-KITE digantikan SitusTiruan di tests/conftest.py, yang menjawab seperti aplikasi CodeIgniter aslinya: sesi lewat cookie ci_session, pengalihan ke /login saat sesi habis, DataTables lewat POST, form ubah data di modal, dan berkas unggahan yang bisa diunduh ulang untuk dicocokkan md5-nya. Sesi yang sudah login diberikan lewat berkas sesi karangan. Halaman tiruannya ada di tests/halaman_tiruan.py.

./elkite login diuji dengan Chrome, xdotool, dan DevTools tiruan: argumen peluncurnya, pembacaan DevToolsActivePort, pembatasan pengisian kredensial ke tab login HTTPS pada host EL-KITE (termasuk menunggu tab selesai dimuat), tidak adanya jawaban captcha atau pengiriman form, deteksi beranda, penyaringan cookie, izin berkas sesi, dan penutupan Chrome saat waktu habis. Satu uji memakai klien websockets sungguhan ke server CDP tiruan di 127.0.0.1. Ada juga uji yang memastikan tidak satu pun antarmuka HTTP mengirim apa pun ke /login/login.

Selama uji, akar proyek dipindah ke direktori sementara supaya .env dan .elkite-sesi.json asli tidak terbaca, variabel ELKITE_* di environment dibuang, sesi HTTP sungguhan diblokir, dan subprocess.Popen diblokir sehingga Chrome atau program lain tidak bisa jalan. Uji REST API dan MCP dilewati kalau FastAPI, httpx2, atau paket mcp belum terpasang. Nama dosen, NIDN, nomor usulan, perguruan tinggi, tanggal, dan nilai cookie di berkas uji dan dokumentasi seluruhnya dikarang.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to pull teaching evidence from SIAKAD Pradita, such as class lists, lecture minutes, and signed student attendance, ready to be attached as BKD proof.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to automate filling BKD data into SISTER, handling SSO login, CSRF tokens, label-to-code translation, and file uploads, with tools for checking login, listing menus and schemas, looking up references and lecturers, managing activity documents, and submitting activities in a dry-run mode by default.
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Lets an AI assistant read and fill an Innoslate project through your own logged-in browser session, surveying the project, reading your documents and guides, and proposing a plan before writing entities, trace links, artifacts and reports after a dry run. It works on the free tier where API keys are refused, since every call goes through the browser instead.
    18
    MIT