Bir güvenlik duvarı yönetim aracı sunucusu, herkesin kendi kimliğiyle işlem yapması gereken araçların tam örneğidir. Her yöneticinin FortiOS REST API belirteci kendi yönetici profilini, kendi güvenilir adreslerini ve güvenlik duvarının günlüğünde kendi adını taşır. Paylaşılan tek bir belirteç bu üçünü birden siler. Bu makale, bir yöneticinin FortiGate araç sunucusunu bir kez nasıl bağladığını ve sonra herkesin kendi belirtecini ve ayarlarını My variables üzerinden, belirteci hiçbir zaman sohbete yazmadan nasıl getirdiğini anlatır.
Makale, 27 Eylül 2026’da incelediğimiz gerçek bir FortiGate araç sunucusundan yola çıkar: 240 araç ve her biri güvenlik duvarı adresini, VDOM’u ve API belirtecini araç argümanı olarak alıyor. Değiştirilmesi gereken ilk şey bu tasarımdır; nedenini bir sonraki bölüm açıklıyor.
Kim ne yapar
| Adım | Kim | Nerede |
|---|---|---|
| Araç sunucusunun belirteci araç argümanlarından değil, istekten okumasını sağlamak | Sunucunun geliştiricisi | Araç sunucusunun kodu |
| Sunucuyu kaydetmek, değişkenlerini tanımlamak, kimlerin kullanacağını seçmek | Bir konsol yöneticisi | /mcp |
| Bir FortiOS API belirteci oluşturup ayarlarıyla birlikte kaydetmek | Herkes kendisi | FortiGate, ardından My variables (/vault) |
| Sohbete kendi güvenlik duvarlarını sormak | Herkes kendisi | Sohbet çalışma alanı, düzenleyici eklentisi, kendi ajanları |
Kişiler sunucuyu kendileri kaydedemez ve değişken tanımlayamaz. Nedenleri Neden kişiler bunu kendileri kuramaz bölümünde.
Başlamadan önce: belirteç bir araç argümanı olmamalı
/mcp sayfasında sunucunun satırını açın ve araçlarının parametrelerine bakın. Bir
araç api_token, password ya da secret gibi bir değeri argüman olarak
alıyorsa burada durun.
Araç argümanını model yazar. Modelin api_token alanını doldurabilmesi için
belirtecin sohbette olması gerekir; yani kişi onu sohbete yapıştırır. Oradan sonra
belirteç:
- modelin bağlamındadır, dolayısıyla model sağlayıcısının önündedir;
- denetim izindedir, çünkü araç argümanları tam olarak kaydedilir;
- diğer istem metinleri gibi taranır ve saklanır.
İncelediğimiz sunucuda, kaydedilen 12 çağrının 4’ünün saklanan argümanlarında 16 karakter ya da daha uzun bir belirteç bulunuyordu. Kasa burada yardımcı olamaz: istek başlıklarını ya da kişiye özel, mühürlü bir paketi doldurur; araç argümanı asla yazmaz. Sunucunuz böyleyse, sohbete bir kez bile yazılmış her belirteci değiştirin.
Aynı şey, daha hafif bir biçimde, bir adres argümanı için de geçerlidir. Adresi seçebilen bir model, aracı kimsenin istemediği bir adrese yönlendirmeye ikna edilebilir.
Bir sunucu kişinin kendi değerlerini nasıl alabilir
Kasanın üç iletim yolu vardır. Hangisinin uyduğu sunucunun nasıl yapıldığına bağlıdır.
| Sunucu | Yol | Durum |
|---|---|---|
| Değiştirebildiğiniz uzak bir HTTP araç sunucusu ya da başlık okuyan üçüncü taraf bir servis | Başlık: değer, yalnızca o kişinin çağrılarında, yöneticinin adını verdiği başlığa yazılır | Canlı |
| Sizin çalıştırdığınız ve genişletebildiğiniz bir sunucu | Mühürlü paket: kişinin tüm değerleri, yalnızca bu sunucunun açabileceği tek bir şifreli başlıkta | Canlı |
| Belirtecini başlarken ortam değişkenlerinden okuyan bir stdio paketi | Ortam köprüsü: kişi başına, o kişinin değerleriyle başlatılan bir süreç | Canlı, yalnızca açık internet HTTPS (aşağıya bakın) |
HTTP konuşan bir FortiGate araç sunucusu için en basit yol başlıklardır ve makalenin geri kalanı bu yolu kullanır.
A bölümü: yönetici
A1. Sunucu argümanları değil, isteği okusun
Sunucunun geliştiricisinden tek bir değişiklik isteyin: FortiOS belirtecini ve isteğe bağlı olarak hedef cihazı ve VDOM’u her çağrının istek başlıklarından alsın ve bu parametreleri her aracın girdi şemasından kaldırsın. Aşağıda fikrin Python MCP SDK ile bir taslağı var; sunucunun kullandığı çatıya göre uyarlayın:
from mcp.server.fastmcp import FastMCP, Context
mcp = FastMCP("fortigate")
DEVICES = { # the firewalls this server may reach, chosen by its operator
"hq-fw": "https://203.0.113.10",
"branch-fw": "https://203.0.113.20",
}
def fortios_target(ctx: Context):
h = ctx.request_context.request.headers
token = h.get("authorization", "").removeprefix("Bearer ").strip()
if not token:
raise ValueError("No FortiOS token: set FORTIGATE_API_TOKEN on My variables.")
device = h.get("x-fortigate-device", "hq-fw")
if device not in DEVICES:
raise ValueError(f"Unknown device {device!r}. Known: {', '.join(DEVICES)}")
vdom = h.get("x-fortigate-vdom") or "root"
return DEVICES[device], token, vdom
@mcp.tool()
async def system_status(ctx: Context) -> dict:
"""FortiOS system status: firmware, hostname, serial, uptime, HA state."""
base, token, vdom = fortios_target(ctx)
... # GET {base}/api/v2/monitor/system/status?vdom={vdom}
# with the header Authorization: Bearer {token}
Taslaktaki iki tasarım kararı bilinçlidir:
- Adres değil, cihaz adı. Kişi, sunucuyu işleten kişinin denetlediği bir listeden
hq-fwseçer. Ne bir kişi ne de model sunucuyu rastgele bir adrese yönlendirebilir. Bu ayrıca kasanınurlbiçimli değerlerde özel ağ adreslerini reddeden kuralına da takılmaz; güvenlik duvarlarının yönetim adreslerinin çoğu özel ağ adresidir. - Sunucunun kendi erişim anahtarı ayrı bir başlıkta. Araç sunucusu, ona yalnızca
ağ geçidinin ulaşabilmesi için kendine ait bir anahtar istemeye devam etmelidir. Bu
anahtarı
Authorizationbaşlığına değil,X-Api-Keygibi bir başlığa koyun. Bir kişininAuthorizationdeğeri, sunucu düzeyindeki aynı adlıAuthorizationbaşlığının yerini alır; bu yüzden ikisi aynı başlığı paylaşamaz.
A2. Sunucuyu kaydedin
/mcp sayfasında Register a server:
| Alan | Değer |
|---|---|
| Name | FortiGate |
| URL | sunucunun streamable HTTP uç noktası, örneğin https://fortigate-mcp.corp.example/mcp |
| Auth | custom header, başlık X-Api-Key, Secret olarak sunucunun kendi erişim anahtarı |
| Identity | require user (signed assertion) işaretli |
Register & sync düğmesine basın. Keşif sunucunun kendi erişim anahtarıyla yapılır; bu yüzden araç listesi, henüz kimse bir FortiOS belirteci kaydetmeden de yüklenir.
A3. Değişkenleri tanımlayın
/mcp sayfasının Variables sekmesinde, bir kişinin getirdiği her değer için bir
değişken tanımlayın. Asıl önemli olan ilkidir; diğer ikisi bu tasarımın kullandığı
isteğe bağlı ayarlardır. Başlık adları örnektir: sunucunuz hangisini okuyorsa onu
kullanın.
| Değişken | İletim | Başlık | Şablon | Zorunlu | Gizli | Biçim |
|---|---|---|---|---|---|---|
FORTIGATE_API_TOKEN |
header | Authorization |
Bearer ${value} |
evet | evet | string |
FORTIGATE_DEVICE |
header | X-FortiGate-Device |
${value} |
hayır | hayır | string |
FORTIGATE_VDOM |
header | X-FortiGate-VDOM |
${value} |
hayır | hayır | string |
Her birine bir açıklama yazın; kişiler bunu kendi sayfalarında okur. Örneğin: “FortiOS REST API belirteciniz (salt okunur yeterli). System → Administrators → REST API Admin altında oluşturun.”
Platformun sizin yerinize uyguladıkları:
- Adlar ve başlıklar yöneticinindir. Kişi yalnızca değer girer. Başlık, şablon ya da sunucu seçemez.
- Taşıma başlıkları hedeflenemez.
Host,Content-*,Cookie,Mcp-Session-Idve tümX-GpuPool-*başlıkları iletim başlığı olarak reddedilir. - Bir değer satır sonu içeremez ve en fazla 8 KiB olabilir.
Zorunlu, o değer olmadan hiçbir şeyin çıkmaması demektir. Belirtecini kaydetmemiş bir kişi, kendi sayfasına doğrudan bağlantı içeren bir araç hatası alır ve istek sunucuya hiç ulaşmaz.
Bir FortiGate sunucusunun kişi başına makul olarak kabul edebileceği diğer ayarlar, hepsi örnektir:
| Değişken | Ne yapardı | Öneri |
|---|---|---|
FORTIGATE_TIMEOUT_SECONDS |
Büyük bir politika dışa aktarımı gibi yavaş işlemlere izin vermek | Zararsız; biçim number |
FORTIGATE_READ_ONLY |
Sunucudan bu kişi için yazma araçlarını reddetmesini istemek | İkinci bir koruma olarak faydalı; asıl koruma belirtecin yönetici profilidir |
FORTIGATE_VERIFY_TLS |
Sertifika denetimini kapatmak | Sunmayın. Kişi, kendi güvenlik duvarıyla konuştuğunu kanıtlayan denetimi kapatabilmemelidir |
FORTIGATE_HOST |
Cihaz adı yerine serbest bir adres | Kaçının; nedenleri A1’de |
A4. Kimlerin kullanacağını seçin
Sunucunun Access sütununda granted seçin ve güvenlik duvarlarını yöneten kişileri ekleyin. Diğer herkes, var olmayan bir sunucu için aldığı yanıtın aynısını alır. granted kipindeki bir sunucu, sohbet çalışma alanının paylaşılan araç listesinin de dışında tutulur; çünkü paylaşılan tek bir bağlantı kişileri birbirinden ayıramaz. Düzenleyici eklentisi ve ajanlar onu kişi başına listeler.
B bölümü: herkes kendisi
B1. Kendi FortiOS REST API belirtecinizi oluşturun
FortiGate üzerinde, hesap oluşturma yetkisi olan bir yönetici olarak:
- System → Administrators → Create New → REST API Admin yolunu izleyin.
- Kime ait olduğunu belli eden bir ad verin; örneğin
api-ayse. - Bir admin profile seçin. Durum, oturum ve politika sormak için salt okunur yeterlidir. Yazma yetkisini yalnızca sohbetten değişiklik yapmayı gerçekten istiyorsanız verin.
- Trusted Hosts alanına araç sunucusunun çağrı yaptığı adresi girin. Böylece belirteç sızsa bile başka hiçbir yerden çalışmaz.
- OK düğmesine basın ve anahtarı kopyalayın. FortiOS onu yalnızca bir kez gösterir.
B2. My variables’a kaydedin
Konsolda oturum açın, My variables (/vault) sayfasını açın ve FortiGate
bölümünü bulun:
| Değişken | Ne girilir |
|---|---|
FORTIGATE_API_TOKEN |
az önce kopyaladığınız anahtar |
FORTIGATE_DEVICE |
yöneticinizin verdiği cihaz adı, örneğin hq-fw (isteğe bağlı) |
FORTIGATE_VDOM |
VDOM’unuz, örneğin root (isteğe bağlı) |
Her birinde Save düğmesine basın. Belirteç satırı bundan sonra set ve kısa bir parmak izi gösterir; değer size bile bir daha gösterilmez. Cihaz ve VDOM gizli değildir, bu yüzden size geri gösterilir.
B3. Sorun
FortiGate araçlarının açık olduğu bir sohbette örneğin şunları sorun:
- Güvenlik duvarım hangi yazılım sürümünü ve çalışma süresini bildiriyor?
- Misafir VLAN’ından gelen trafiğe izin veren güvenlik duvarı politikalarını listele.
- Şu anda hangi IPsec tünelleri kapalı?
Her çağrı sizin belirtecinizi sizin cihazınıza ve VDOM’unuza taşır. Güvenlik
duvarının kendi günlüğü paylaşılan bir hesabı değil, api-ayse adını kaydeder.
Tek bir çağrıda ne nereye gider
you ──chat──▶ model ──tool call, no token──▶ gateway
gateway ──X-Api-Key: <server key>
Authorization: Bearer <your FortiOS token>
X-FortiGate-Device: hq-fw
X-FortiGate-VDOM: root ──────────────▶ FortiGate tool server ──▶ your firewall
audit trail: tool, arguments, and the variable NAMES used. Never the token.
Şemada: siz sohbete yazarsınız, model belirteç içermeyen bir araç çağrısı üretir ve ağ geçidi sizin değerlerinizi o çağrıya ekleyerek araç sunucusuna, oradan da güvenlik duvarınıza iletir. Denetim izi aracı, argümanları ve kullanılan değişkenlerin yalnızca adlarını kaydeder.
- Araç çağrısını model yazar ve içinde yazabileceği bir belirteç yoktur.
- Ağ geçidi değerlerinizi yalnızca o çağrıya ekler. Onları yalnızca bu çağrı için çözer; önbelleğe alınmazlar, hiçbir günlük satırında ve modelin bağlamında yer almazlar.
- Sunucunun yanıtı belirtecinizi bir gün geri yansıtırsa, denetim izindeki saklanan
kopya onun yerine
[uservar:FORTIGATE_API_TOKEN]gösterir.
Sunucu yalnızca ortam değişkenlerini okuyorsa
Bazı FortiGate araç sunucuları, FORTIGATE_HOST ve FORTIGATE_API_TOKEN değerlerini
başlarken bir kez ortamlarından okuyan komut satırı paketleridir. Bunlar için ortam
köprüsü kişi başına, o kişinin değerleriyle başlatılan bir süreç çalıştırır.
Yönetici sunucuyu bir örnek dosyasında tanımlar; aşağıdaki dosya bir örnektir:
{
"slug": "fortigate",
"name": "FortiGate",
"command": "fortigate-mcp",
"args": [],
"egress": "public-https",
"vars": [
{ "name": "FORTIGATE_API_TOKEN", "env": "FORTIGATE_API_TOKEN", "isSecret": true, "isRequired": true },
{ "name": "FORTIGATE_VDOM", "env": "FORTIGATE_VDOM", "isSecret": false }
]
}
Bu yolu seçmeden önce bir sınırı bilin: köprü bugün ya hiç ağ erişimi ya da yalnızca açık internet HTTPS sunar. Yönetim arayüzü özel bir ağda olan bir güvenlik duvarına, özel ağ çıkış seçeneği eklenene kadar köprüden ulaşılamaz. Yerel ağdaki bir güvenlik duvarı için yukarıdaki başlık yolunu kullanın.
Neden kişiler bunu kendileri kuramaz
Herkesin kendi araç sunucusunu kaydetmesine ve kendi değişkenlerini tanımlamasına izin vermek cazip gelebilir. Bu adımların her biri, platformun trafiği ve kimlik bilgilerini nereye göndereceğine dair bir karardır; bu yüzden yöneticilerde kalır:
- Sunucu kaydetmek bir hedef seçmektir. Ağ geçidi, bir kişinin yazdığı her adresi ağın içinden, aracı kullanan kişinin imzalı kimliğiyle çağırırdı. Bu, kimsenin açmak istemediği iç servislere giden bir yol ve sunucu paylaşılıyorsa başkalarının kimliklerini toplamanın bir yoludur.
- Değişken tanımlamak bir başlık ve şablon seçmektir. Değeri giren kişinin onun başlığını da seçebilmesi, bir değerin başka bir kimlik bilgisinin üzerine yazmasına yol açar. Bu, ağ geçitlerinde bilinen bir güvenlik açığı sınıfıdır ve burada kişilerin yalnızca değer girmesinin nedenidir.
- Erişim ve izinler, sunucuyu kimin kullanacağını belirler. Self servis, kendi kendinize erişim vermek anlamına gelirdi.
- Ortam köprüsü bir komut çalıştırır. O komutu seçmek, herkesin süreçlerinin yanında hangi kodun çalışacağını seçmektir.
Kişilerin denetiminde olan, onlara ait olan her şeydir: kendi belirteçleri, cihazları ve VDOM’ları; bunlar kendi sayfalarında girilir ve değiştirilir, başka hiç kimseye görünmez.
Bir şeyler yolunda gitmediğinde
| Durum | Ne yapmalı |
|---|---|
| Araçlar sohbette sizden belirteç istiyor | Sunucu belirteci hâlâ argüman olarak alıyor (Başlamadan önce bölümüne bakın). Yapıştırmayın; yöneticinize bildirin. |
| This tool needs your own FORTIGATE_API_TOKEN | Belirtecinizi My variables’a kaydedin; mesaj oraya bağlantı verir. |
Güvenlik duvarından 401 |
Belirteç iptal edilmiş, süresi dolmuş ya da adresiniz Trusted Hosts içinde değil. Yeni bir tane oluşturup değeri Replace ile değiştirin. |
Bir değişiklikte 403 |
Yönetici profiliniz salt okunur. Bu, amaçlanan korumadır. |
| Unknown device | Yöneticinizin listelediği bir cihaz adı kullanın. Sunucu başka her şeyi reddeder. |
| My variables’ta FortiGate yok | Henüz size izin verilmemiş. Yöneticinize başvurun. |
| Biri ayrılıyor | O kişi ya da Variables sekmesindeki bir yönetici değerlerini siler. FortiGate üzerindeki REST API yöneticisini de silin. |
Bu sayfanın başındaki adım adım gösterim aynı akışı başka bir araçla anlatır; GitHub makalesi ise başlık yolunu üçüncü taraf bir servisle kullanır.