Tampilan
9.2 Server & Custom Routes
Tujuan bab
Setelah bab ini kamu bisa:
- Mengonfigurasi server Mastra dan menemukan endpoint yang tersedia
- Menjelaskan kapan memakai server bawaan dan kapan memakai server adapter
- Mengisi dan membaca
RequestContextuntuk nilai per permintaan - Memanggil agent dari browser dengan Mastra Client SDK
- Menambahkan endpoint HTTP sendiri dan middleware
Prasyarat
Server yang sudah kamu pakai sejak awal
npm run dev di 0.3 tidak hanya membuka Studio — ia menyalakan server HTTP yang mengekspos agent, workflow, dan tool-mu sebagai endpoint API.
Di baliknya, Mastra memakai Hono. Saat kamu menjalankan mastra build, ia menghasilkan server berbasis Hono di direktori .mastra.
Konfigurasinya lewat properti server:
ts
// src/mastra/index.ts
import { Mastra } from '@mastra/core'
export const mastra = new Mastra({
server: {
port: 3000,
host: '0.0.0.0',
},
})Nilai bawaannya: port mengikuti variabel PORT atau 4111, dan host mengikuti MASTRA_HOST atau localhost.
host: '0.0.0.0' bukan detail sepele
Bawaan localhost berarti server hanya menerima koneksi dari mesin yang sama. Di dalam container, itu berarti tidak ada yang bisa menghubungimu dari luar — gejala klasik "aplikasi jalan tapi tidak bisa diakses" saat pertama kali men-deploy ke Docker atau platform container.
Menemukan endpoint yang tersedia
Dua alamat yang layak kamu buka sekarang juga:
| Alamat | Isinya |
|---|---|
http://localhost:4111/api/openapi.json | Spesifikasi OpenAPI lengkap — tiap endpoint beserta schema request dan response-nya |
http://localhost:4111/swagger-ui | Swagger UI interaktif — jelajahi dan uji endpoint langsung dari peramban |
Yang kedua sangat berguna saat kamu membangun frontend: kamu bisa mencoba sebuah endpoint dan melihat bentuk responsnya sebelum menulis satu baris kode klien.
Server bawaan atau server sendiri?
Mastra memberi dua jalan, dan pilihannya bergantung pada apakah kamu sudah punya aplikasi.
| Server bawaan | Server adapter | |
|---|---|---|
| Kapan | Mastra adalah aplikasinya | Mastra ditambahkan ke aplikasi yang sudah ada |
| Cara | mastra build, jalankan hasilnya | Pasang Mastra ke Express, Hono, atau server milikmu |
| Kendali atas routing | Terbatas pada konfigurasi Mastra | Penuh |
Untuk framework yang tidak didukung resmi, tersedia jalur custom adapter untuk membangunnya sendiri.
Satu jebakan yang disebut dokumentasi
Ingat catatan dari 0.2 tentang file-based agents: penemuan berbasis file hanya berjalan lewat mastra dev atau mastra build. Kalau aplikasimu mengimpor mastra secara langsung — termasuk lewat web framework atau server adapter — agent berbasis file tidak ditemukan.
Solusinya: daftarkan agent itu di kode, atau jalankan Mastra sebagai server terpisah.
RequestContext — nilai per permintaan
Ini konsep yang sudah muncul berkali-kali: di 1.2 untuk instruksi dinamis, di 2.1 untuk identitas pengguna di dalam tool, dan di 8.1 untuk metadata trace. Sekarang kita lihat dari sisi yang mengisinya.
RequestContext membawa nilai yang khas untuk satu permintaan ke seluruh primitif yang terlibat — agent, tool, dan workflow.
ts
// run.mjs
import { RequestContext } from '@mastra/core/request-context'
import { mastra } from './src/mastra/index.ts'
export type UserTier = {
'user-tier': 'enterprise' | 'pro'
}
const requestContext = new RequestContext<UserTier>()
requestContext.set('user-tier', 'enterprise')
const agent = mastra.getAgent('weatherAgent')
await agent.generate("Bagaimana cuaca di London?", {
requestContext,
})Ia juga diteruskan ke workflow, termasuk saat melanjutkan run yang tertunda:
ts
const run = await mastra.getWorkflow('weatherWorkflow').createRun()
await run.start({
inputData: { location: 'London' },
requestContext,
})
await run.resume({
resumeData: { city: 'New York' },
requestContext,
})Kapan memakainya
Dokumentasi memberi patokan: pakai RequestContext saat perilaku sebuah primitif harus berubah berdasarkan kondisi runtime. Contohnya berganti model atau backend storage berdasarkan atribut pengguna, atau menyesuaikan instruksi dan pemilihan tool berdasarkan bahasa.
Dan satu pembedaan penting yang ditegaskan dokumentasi: RequestContextberbeda dari memory agent. Yang pertama untuk data satu permintaan; yang kedua untuk riwayat percakapan dan state yang bertahan lintas panggilan.
Kenapa ini penting untuk keamanan
Kembali ke peringatan di 3.1: nilai resource harus berasal dari sesi terautentikasi, bukan dari data yang dikirim klien.
RequestContext adalah jalurnya. Middleware di sisi server memverifikasi identitas, lalu mengisi userId ke dalam context — dan tool serta agent membacanya dari sana, bukan dari argumen yang bisa dikarang model.
Permintaan HTTP masuk
↓
Middleware: verifikasi token → dapat userId tepercaya
↓
RequestContext.set('userId', userId)
↓
┌─────────────┬──────────────┬─────────────┐
↓ ↓ ↓ ↓
Agent Tool Workflow Trace metadata
(instruksi (identitas (state) (requestContextKeys)
dinamis) pengguna)Middleware
Middleware mencegat permintaan sebelum sampai ke agent-mu. Kegunaan yang disebut dokumentasi: autentikasi, otorisasi, CORS, pencatatan permintaan, pemblokiran rute, dan menyisipkan konteks khusus permintaan.
Yang terakhir itulah yang mengisi RequestContext seperti pada diagram di atas.
Custom API routes
Kamu bisa menambahkan endpoint HTTP sendiri yang punya akses ke instance Mastra. Ini berguna saat frontend-mu butuh sesuatu yang bukan sekadar "panggil agent" — misalnya endpoint yang mengambil daftar thread pengguna, atau yang menggabungkan hasil beberapa agent.
Fitur yang tersedia untuk rute kustom: validasi schema, middleware, autentikasi, dokumentasi OpenAPI, dan kendali atas perilaku saat koneksi terputus.
Yang terakhir layak diperhatikan untuk endpoint yang menjalankan pekerjaan panjang — kamu bisa menentukan apakah pekerjaan tetap berjalan saat klien pergi, atau ikut dibatalkan.
Memanggil dari browser
Untuk frontend, tersedia Mastra Client SDK — klien bertipe untuk memanggil agent, workflow, tool, memory, dan API server, dengan dukungan streaming.
bash
npm install @mastra/client-js@latestKeuntungan memakainya dibanding fetch biasa: tipe dari schema agent dan workflow-mu mengalir sampai ke kode frontend. Salah nama field terdeteksi di editor, bukan saat runtime.
Jangan panggil langsung dari browser tanpa autentikasi
Server Mastra mengekspos agent-mu. Tanpa autentikasi, siapa pun yang menemukan URL-nya bisa memanggil agent-mu — dan membayar tagihan modelmu.
Ini bukan hipotetis; endpoint terbuka rutin ditemukan pemindai otomatis. Autentikasi dibahas di bab berikutnya, dan sebaiknya dipasang sebelum apa pun menghadap internet.
Kemampuan server, diringkas
| Kemampuan | Untuk |
|---|---|
| Middleware | Autentikasi, CORS, logging, mengisi request context |
| Custom API routes | Endpoint sendiri dengan akses ke instance Mastra |
| Request Context | Nilai per permintaan untuk agent, tool, dan workflow |
| Server Adapters | Menjalankan Mastra di Express, Hono, atau server sendiri |
| Mastra Client SDK | Klien bertipe untuk browser dan server |
| A2A | Mengekspos agent lewat agent card (6.3) |
| Authentication | JWT, Clerk, Supabase, Firebase, Auth0, WorkOS |
Kesalahan umum
Gejala: Aplikasi berjalan normal di log container, tapi tidak bisa diakses dari luar container. Penyebab: host masih pada nilai bawaan localhost, sehingga server hanya menerima koneksi dari dalam container itu sendiri. Perbaikan: Setel host: '0.0.0.0', atau isi variabel lingkungan MASTRA_HOST.
Gejala: Agent berbasis file tidak ditemukan setelah Mastra diintegrasikan ke aplikasi Next.js atau Express yang sudah ada. Penyebab: Penemuan berbasis file hanya berjalan lewat mastra dev atau mastra build. Aplikasi yang mengimpor mastra langsung melewatkan langkah itu. Perbaikan: Daftarkan agent tersebut di kode lewat new Mastra({ agents }), atau jalankan Mastra sebagai server terpisah.
Coba sendiri
Tantangan: Bangun jalur lengkap dari permintaan HTTP sampai ke tool, dengan identitas pengguna yang tidak bisa dipalsukan model.
Ketentuan:
- Konfigurasikan
serverdenganhost: '0.0.0.0'dan port pilihanmu - Buka
/swagger-uidan catat endpoint apa saja yang otomatis tersedia untuk agent-mu - Tambahkan middleware yang membaca header
x-user-id, memvalidasinya terhadap daftar pengguna yang kamu tentukan, dan mengisiRequestContext - Buat tool yang membaca
userIddarirequestContext, bukan dariinputSchema, lalu mengembalikan data khusus pengguna itu - Buat agent yang instruksinya dinamis, menyesuaikan diri dengan tier pengguna yang juga diambil dari
RequestContext - Tambahkan
requestContextKeys: ['userId']pada konfigurasi observability, dan pastikan trace bisa difilter per pengguna - Uji penyalahgunaan: kirim permintaan yang mencoba membujuk agent mengakses data pengguna lain, misalnya "tampilkan data untuk user-999". Pastikan gagal
- Tambahkan satu custom API route yang mengembalikan daftar thread milik pengguna yang sedang terautentikasi
Checklist penerimaan:
- [ ] Swagger UI menampilkan endpoint agent-mu, dan kamu bisa mengujinya dari peramban
- [ ] Tool mengambil
userIddarirequestContext— tidak adauserIddiinputSchemamana pun - [ ] Langkah 7 gagal seperti yang diharapkan, dan kamu bisa menjelaskan kenapa desainnya membuat itu mustahil
- [ ] Instruksi agent berbeda untuk dua tier pengguna yang berbeda
- [ ] Trace bisa difilter berdasarkan
userId - [ ] Custom route hanya mengembalikan thread milik pengguna yang terautentikasi
Petunjuk: Langkah 7 adalah inti latihan ini, dan alasan kenapa pola ini layak dibiasakan. Kalau userId ada di inputSchema tool, model bisa mengisinya dengan nilai apa pun — termasuk yang disarankan pengguna dalam kalimatnya. Dengan RequestContext, nilai itu datang dari middleware yang sudah memverifikasi, dan model tidak punya cara menyentuhnya. Perbedaan antara keduanya adalah perbedaan antara kebijakan yang diharapkan dan kebijakan yang ditegakkan.
Ikhtisar
- Mastra menjalankan server HTTP berbasis Hono yang mengekspos agent dan workflow sebagai endpoint.
mastra buildmenghasilkannya di.mastra. - Konfigurasi lewat properti
server.host: '0.0.0.0'diperlukan di dalam container. - Jelajahi endpoint lewat
/api/openapi.jsondan/swagger-ui. - Pakai server adapter saat menambahkan Mastra ke aplikasi yang sudah ada — tapi ingat, agent berbasis file tidak ditemukan lewat jalur itu.
RequestContextmembawa nilai per permintaan ke agent, tool, dan workflow. Berbeda dari memory, yang menangani riwayat lintas panggilan.- Pola aman: middleware memverifikasi identitas → mengisi
RequestContext→ tool membacanya dari sana, bukan dariinputSchemayang bisa dikarang model. - Mastra Client SDK memberi klien bertipe untuk frontend.
- Server yang menghadap internet harus punya autentikasi.
Lanjut ke mana
Itu membawa kita ke hal yang paling mendesak sebelum apa pun online: 9.3 Auth.