npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tecof/mcp

v0.2.6

Published

Tecof Developer API için stdio MCP sunucusu — tema reposundan sayfa oluşturma/güncelleme araçları

Readme

@tecof/mcp

Tecof Developer API v1 için stdio MCP sunucusu. Bir Tecof tema reposunun içinden çalışır; tema bileşenlerini diskten (AST) okur, ajanın yazdığı basit "bölüm" tanımlarını editör dokümanına çevirir ve Developer API ile taslak sayfa oluşturur/günceller. Sayfa yayınlama her zaman panelden yapılır (API'de publish yok). Aynı sunucu headless CMS içeriklerini ve e-ticaret kataloğunu (ürün) da yönetir — ürün yazması taslak DEĞİLDİR.

  • SDK: @modelcontextprotocol/server@^2 (+ zod@^4) — McpServer + serveStdio
  • Node ≥ 20, ESM
  • Tool annotations (readOnlyHint, destructiveHint) ve _meta["anthropic/requiresUserInteraction"] (silme) destekli
  • İki çalışma modu (0.2.0): local (varsayılan — 26 araç bu pakette, Developer API v1 doğrudan) ve remote (araç kataloğu backend'in Tools API'sinden canlı gelir; paketteki snapshot yalnız yayın anındaki backend mcp kataloğunun kopyasıdır ve canlı katalog önceliklidir, bkz. remote mod). stdio hiç istemiyorsanız backend'in kendi uzak HTTP MCP sunucusu var: https://api.tecof.com/mcp.

Kurulum

Tema reposunun kökünde:

# 1) Panelden API anahtarı üretin: Ayarlar → Geliştirici / API Anahtarları
#    (scope: pages:read, pages:write; CMS için cms:*, ürün araçları için products:read/products:write)
# 2) .env (gitignore'da) içine yazın
echo 'TECOF_API_TOKEN=tcf_...' >> .env

Sunucu npx ile çalışır; global kurulum gerekmez:

npx -y @tecof/mcp@latest

Ortam değişkenleri

TECOF_PROJECT_DIRCLAUDE_PROJECT_DIRprocess.cwd() sırasıyla proje dizini bulunur; .env ve .env.local buradan okunur. process.env ezilmez — dosya değerleri yalnız boş olan anahtarları doldurur (.env.local > .env).

| Değişken | Zorunlu | Açıklama | |---|---|---| | TECOF_API_TOKEN | evet | tcf_… kişisel erişim anahtarı | | TECOF_API_URL | evet* | Backend adresi; yoksa NEXT_PUBLIC_BASE_URL kullanılır | | TECOF_THEME_ID | hayır | Global tema id; yoksa NEXT_PUBLIC_THEME_ID, o da yoksa mağazanın aktif teması | | TECOF_LOCAL_URL | hayır | Yerel önizleme kökü (varsayılan http://localhost:3000) | | TECOF_PROJECT_DIR | hayır | Tema reposu başka dizindeyse | | TECOF_MCP_MODE | hayır | local (varsayılan) | remote — bkz. remote mod | | TECOF_TOOLSETS | hayır | remote modda yalnız bu modüller (virgülle: pages,cms,media,products,domains,general) |

Eksik token/URL durumunda sunucu yine başlar; list_components ve validate_document çalışır, sayfa araçları yol gösteren bir hata döner. Loglar yalnız stderr'e yazılır; yakalanmamış hatalar da stderr'e düşer, süreç çökmez.

Güvenlik: TECOF_API_URL https olmalı. http:// (loopback dışı) bir adres verilirse başlangıçta stderr uyarısı basılır ve her tool hatasına aynı ipucu eklenir; http→https yönlendirmeleri takip edilmez (Node fetch yönlendirmede Authorization'ı düşürür, yanıltıcı 401 çıkardı) — 3xx yanıtı "TECOF_API_URL şeması/host'u yanlış" hatasına çevrilir. İstek zaman aşımı (30 sn) header + gövde okumasının tamamını kapsar.

Claude Code — .mcp.json

{
  "mcpServers": {
    "tecof": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "${TECOF_MCP_PACKAGE:-@tecof/mcp@latest}"]
    }
  }
}

TECOF_MCP_PACKAGE env'i paket spec'ini ezer — npm'e yayınlanmadan önce ya da yerel geliştirme için bu repo klasörünü verin (npx -y /path/to/tecof-mcp klasördeki bin'i çalıştırır):

export TECOF_MCP_PACKAGE=/Users/<siz>/Desktop/Tecof/tecof-mcp   # claude'u bu shell'den başlatın

Yayınlama (npm)

npm run build && npm test && node scripts/smoke.mjs
npm version patch            # ya da minor
npm publish --access public  # @tecof kapsamı — tecof-theme-editor/analytics ile aynı hesap

Codex — .codex/config.toml

[mcp_servers.tecof]
command = "npx"
args = ["-y", "@tecof/mcp@latest"]

Gemini CLI — .gemini/settings.json

{
  "mcpServers": {
    "tecof": {
      "command": "npx",
      "args": ["-y", "@tecof/mcp@latest"]
    }
  }
}

Token hiçbir yapılandırma dosyasına yazılmaz; .env içinde kalır. İstemci süreci tema reposunun kökünde başlatır, sunucu .env'i oradan okur.

Uzak MCP (HTTP) — api.tecof.com/mcp

Backend, aynı araç kayıt defterini Streamable HTTP MCP sunucusu olarak da sunar: https://api.tecof.com/mcp. stdio paketi kurmadan, tema reposu olmadan (ör. Claude Desktop, claude.ai, Cursor) bağlanmak için bunu kullanın. Kimlik yine PAT'tir — Authorization: Bearer tcf_… static header olarak verilir (OAuth girişi faz 2'de; "sunucu isterse OAuth" seçenekleri yer tutucu sayfaya düşer). Araç adları, şemalar, hata kodları ve sonuç biçimi bu paketle birebirdir.

Toolset daraltma: X-Tecof-Toolsets: pages,cms başlığı ya da ?toolsets=pages,cms (modül adları; bilinmeyen yok sayılır). İlerleme bildirimi yalnız istemci progressToken gönderdiyse.

Claude Code

claude mcp add --transport http tecof https://api.tecof.com/mcp --header "Authorization: Bearer ${TECOF_API_TOKEN}"

ya da .mcp.json:

{
  "mcpServers": {
    "tecof": {
      "type": "http",
      "url": "${TECOF_API_URL:-https://api.tecof.com}/mcp",
      "headers": { "Authorization": "Bearer ${TECOF_API_TOKEN}" },
      "timeout": 600000
    }
  }
}

--header/headers OLMADAN Claude Code 401 challenge'ını izleyip OAuth yer tutucu sayfasına düşer.

Codex~/.codex/config.toml:

[mcp_servers.tecof]
url = "https://api.tecof.com/mcp"
bearer_token_env_var = "TECOF_API_TOKEN"
startup_timeout_sec = 20
tool_timeout_sec = 300

[mcp_servers.tecof.tools.delete_page]
approval_mode = "prompt"        # onay isteyen her araç için tekrarlayın (delete_cms_item, delete_product, domain_dns_*)

Gemini CLI.gemini/settings.json:

{
  "mcpServers": {
    "tecof": {
      "httpUrl": "https://api.tecof.com/mcp",
      "headers": { "Authorization": "Bearer $TECOF_API_TOKEN" },
      "timeout": 600000
    }
  }
}

Cursor.cursor/mcp.json:

{
  "mcpServers": {
    "tecof": {
      "url": "https://api.tecof.com/mcp",
      "headers": { "Authorization": "Bearer ${env:TECOF_API_TOKEN}" }
    }
  }
}

Claude Desktop / claude.ai — Settings → Connectors → Add custom connector → URL https://api.tecof.com/mcp, Authentication "None" + Request header Authorization: Bearer tcf_… (beta; "Required when the server asks" SEÇMEYİN). Static header desteği yoksa claude_desktop_config.json içinde köprü:

{
  "mcpServers": {
    "tecof": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.tecof.com/mcp", "--header", "Authorization: Bearer ${TECOF_API_TOKEN}"]
    }
  }
}

remote mod (stdio proxy)

TECOF_MCP_MODE=remote ile bu paket, araçları kendi içinden değil backend'in Tools API kataloğundan alır ve her çağrıyı sunucuya iletir:

| Adım | Ne olur | |---|---| | Başlangıç | GET /api/v1/tools?surface=mcp[&toolsets=…]3 sn bütçe, arka planda. Yetişmezse/erişilemezse paketle gelen snapshot (src/remote/catalog.snapshot.json — yayın anındaki backend mcp kataloğunun kopyası; canlı katalog önceliklidir) kullanılır ve stderr'e uyarı basılır; tools/list çevrimdışı da deterministiktir. Canlı katalog sonradan gelirse eksik araçlar eklenir ve tools/list_changed gönderilir. | | Çağrı | POST /api/v1/tools/:name?stream=1 — başlıklar Authorization: Bearer <TECOF_API_TOKEN>, X-Tecof-Surface: mcp. SSE çerçeveleri progress / result / error; sunucu düz application/json dönerse (idempotency replay, kimlik zinciri) zarf olduğu gibi okunur. | | İlerleme | SSE progress çerçeveleri yalnız istek _meta.progressToken taşıyorsa notifications/progress olur. | | Sonuç | content[0].text = JSON + structuredContent (+ credit, warnings). Hata isError:true, metin "<messageCode>: <mesaj>" + ipucu, structuredContent = { error: messageCode, message, status, …data, needsConfirmation? }. | | Onay | confirm:"required" araçları (delete_*, domain_dns_*, domain_nameservers_set) confirm:true olmadan 409 confirmation-required + confirmId döner; kullanıcı onayladıysa AYNI girdiyle confirm:true + confirmId gönderilir (PAT yüzeyinde tek geçişli onay). | | Yerel katalog | Tema reposunda components/ varsa list_components ve validate_document diskten çalışır; create_page/update_page hibrit: bölümler/operation'lar yerel katalogla inşa edilip doğrulanır, hazır document sunucuya gider (sunucu kendi kataloğuyla bir kez daha doğrular — yayında olmayan bileşen unknown-type). components/ yoksa dört araç da sunucudan. | | Yetki | Anahtarın scope'u yetmeyen araçlar da listelenir; hata çağrı anında insufficient-scope olarak döner. |

Snapshot'ı yenilemek (backend reposunda): npm run -s tools:list -- --json > ../tecof-mcp/src/remote/catalog.snapshot.json (-s şart: npm'in başlık satırları JSON'u bozar). test/remote.test.ts snapshot sözleşmesini denetler — kritik tema/kod araçları ve şema alanları eksikse kırmızı, generatedAt 14 günden eskiyse uyarı basar.

remote modda öne çıkan katalog araçları

Aşağıdakiler local modda yoktur; tanım ve şema backend kataloğundan gelir (kesin liste ve güncel şema için tools/list ya da src/remote/catalog.snapshot.json):

| Tool | Girdi (özet) | Ne yapar | |---|---|---| | publish_page | page, confirm | Taslağı yayına alır — onay özeti taslak↔yayın farkını gösterir | | search_site_content | query, in?, types?, props?, pages?, includeSymbols? | Metni/bağlantıyı TÜM sayfalarda (taslak + yayın) ve ortak bileşenlerde arar; sayfa → düğüm → alan → dil | | replace_in_site | find, replace, süzgeçler, includeSymbols?, dryRun? | Toplu değiştirir; sayfalarda yalnız TASLAK (ortak bileşen includeSymbols ile CANLI) — onay ister | | diff_page | page | Taslak ile yayındaki sürümün farkı; son değiştiren başka kullanıcı mı | | publish_pages | pages[] | all, expectedModifiedDates? | Birden çok sayfayı TEK onayla yayınlar; özet her sayfanın farkını gösterir | | add_variants | product, expand | combinations, price?, stock?, dryRun? | Var olan ürüne kombinasyon ekler ("her renge XL ekle"); var olan kombinasyon atlanır — onay ister | | bulk_update_variants | scope, select, price | setPrice | stock | isActive…, dryRun? | Seçilen varyantların fiyat/stok/aktifliğini tek çağrıda yazar (≤200 ürün) — onay ister | | delete_variants | product, select, mode?: remove\|hide, dryRun? | TEK ürünün varyantlarını siler (varsayılan; 30 gün çöp kutusunda) ya da gizler; açık siparişte geçen varyantı silmez — onay ister | | restore_variants | product (ya da silinen SKU), variants?, dryRun? | Silinen varyantı 30 gün içinde AYNI kimlikle geri yükler (sipariş/fiyat geçmişi bağları geri gelir) — onay ister | | variant_performance | product?, period?, sortBy?, includeUnsold? | Kombinasyon bazında satış + stok kaç gün yeter; üründe beden/renk dağılımı ve hiç satmayanlar (salt-okunur) | | update_variant_type | type, rename?, values?[{value, rename?, colorCode?, order?}], removeValues?, dryRun? | Varyant tipini/değerlerini yeniden adlandırır (bütün katalogda anında), kullanılmayan değeri siler — onay ister | | merge_variant_values | type + (values, into) ya da intoType, dryRun? | Kopya değerleri ("siyah"→"Siyah") ya da tipleri ("Bedenler"→"Beden") birleştirir, ürün bağlarını yeniden yazar; çakışmada hiçbir şey yazmaz — onay ister | | list_themes / create_theme / theme_job_status / activate_theme | themeId, jobId, waitFor? | Özel tema aç (arka plan işi, onay + kredi), iş durumunu bekle, canlıya al (onay) | | theme_commit_files | message, files?, deletions?, confirm | Dosya yazma ve/veya silmeyi tek commit'te depoya gönderir; yalnız silme için files verilmeyebilir — onay ister | | theme_deploy_status | deploymentId?, waitFor?: none\|terminal, sinceDeploymentId?, timeoutSeconds? | Dağıtım durumu; sinceDeploymentId (commit yanıtındaki previousDeploymentId) eski READY'ye kanmadan yeni dağıtımı bekler | | theme_deploy_logs | deploymentId, errorsOnly?, limit? | ERROR veren dağıtımın derleme günlüğü (değerler maskelenir) | | ide_delete_files | sessionId, paths | Sandbox'tan dosya siler; silme ide_commit_push'ta depoya gider | | list_discounts / list_flash_sales | q?, isActive? / state?, page?, limit? | Kuponları / flaş satışları sayfalı listeler |

Araçlar

Aşağıdaki 26 araç local modun kendi tanımlarıdır. remote modda liste backend kataloğundan gelir: aynı 26 araç (aynı ad/şema) + domain, sipariş, müşteri, pazarlama, ayar, tema/kod ve genel modüllerin araçları ve backend'e eklenen her yeni araç — bkz. remote modda öne çıkan katalog araçları.

| Tool | Girdi | Ne yapar | |---|---|---| | get_site_context | — | Mağaza, diller, tema (themeId/merchantThemeId/domain), token scope/bitiş, sayfa sayısı | | list_components | category?, component?, detail?: summary\|full | Tema kataloğu (diskten AST, mtime cache). full: alanlar, seçenekler, slot allow, defaultProps, variants | | list_pages | includeTemplates? | Sayfa listesi (slug artan) | | get_page | page (id|slug), mode?: outline\|full | outline: bölüm/slot ağacı (id, type, kısa metin); full: draftData | | validate_document | { sections } veya { document } | Kaydetmeden doğrular; ok, errors, warnings, normalizedDocument | | create_page | slug, title, slugs?, titles?, sections, meta?, layoutFrom?, dryRun? | Taslak oluşturur; Header/Footer layoutFrom sayfasındaki (varsayılan home) ortak bileşenlerden kopyalanır. slugs/titles dile göre adres/ad verir ({tr:"hakkimizda", en:"about"}); verilmezse slug/title tüm açık dillerde kullanılır | | update_page | page, operations veya document, meta?, dryRun? | GET → işlemleri uygula → doğrula → PUT (expectedModifiedDate ile iyimser kilit; 409'da net mesaj) | | delete_page | page, confirm: true | Soft delete — kullanıcı onayı şart | | get_preview_url | page, locale? | 1 saatlik taslak önizleme linkleri (storefront + yerel) | | list_cms_collections | — | Headless CMS içerik tipleri (slug, ad, alan/içerik sayısı) | | get_cms_collection | collection (id|slug) | Alan şeması + her alan için beklenen veri biçimi (çok dilli mi, dosya objesi mi, referans id'si mi) — içerik yazmadan önce çağrılır | | create_cms_collection | slug, name?, fields?, displayField?, icon? | İçerik tipi açar; alan şeması katı doğrulanır (shortcode, tip, option, repeater, reference) | | update_cms_collection | collection, fields?, slug?, displayField?, allowFieldLoss? | Şemayı günceller; fields verilirse tamamen değişir. Veri taşıyan alanı silmek/tipini değiştirmek allowFieldLoss:true ister | | list_cms_items | collection, status?, search?, page?, limit? | İçerik listesi (özet; data dönmez) | | get_cms_item | collection, item (id|slug) | İçeriğin tamamı + modifiedDate (iyimser kilit için) | | create_cms_item | collection, slug, data?, metaTitle?, metaDescription? | TASLAK içerik oluşturur; data alan şemasına göre katı doğrulanır | | update_cms_item | collection, item, data?, dataMode?, slug?, allowPublishedEdit? | data varsayılan olarak birleştirilir (verilmeyen alan korunur); silmek için dataMode:"replace". İyimser kilit otomatik. Yayındaki içerik allowPublishedEdit:true ister | | delete_cms_item | collection, item, confirm: true, allowPublishedEdit? | Soft delete — kullanıcı onayı şart; yayındaki içerik ayrıca onay ister | | list_products | search?, status?, category?, brand?, tag?, updatedSince?, page?, limit?, detail?: summary\|full | Katalog listesi (ad, durum, marka/kategori/etiket adları, stok, kapak görseli). full: varyant sku/fiyat/stok + fiyat aralığı | | get_product | product (id|slug|SKU) | Ürünün tamamı: çok dilli alanlar, görseller (CDN URL), varyantlar. Güncellemeden önce çağrılır | | upsert_products | items (≤200), dryRun? | Oluşturur/günceller; anahtar slug → varyant sku. Marka/kategori/etiket adıyla çözülür, yoksa açılır; görsel URL'i sunucuda indirilir | | delete_product | product, confirm: true | Soft delete — kullanıcı onayı şart | | get_product_import_template | — | Panelin CSV içe aktarma şablonu (sütunlar + örnek satırlar + ham metin) |

Sonuçlar content[0].text (JSON) + structuredContent olarak döner; hatalar isError: true ile alan/yol bilgisi taşır (ajan düzeltebilsin diye).

Headless CMS akışı

list_cms_collectionsget_cms_collection (alan biçimleri) → create_cms_item / update_cms_item.

Sözleşme, sayfa araçlarıyla aynı: yazmalar taslaktır, yayınlamayı kullanıcı panelden yapar (status göndermek hata verir). Sayfalardan farklı olarak CMS'te taslak katmanı yoktur — yayındaki bir içeriği değiştirmek/silmek anında canlıya yansır, bu yüzden allowPublishedEdit: true istenir; bu bayrağı yalnız kullanıcı açıkça onayladıysa gönderin. Alan şeması değişikliğinde veri kaybı riski varsa (allowFieldLoss) aynı kural geçerlidir.

Veri biçimleri (data içinde): çok dilli alanlar [{code,value}]; görsel/dosya alanları list_media / import_image / generate_image çıktısındaki tam dosya objesi dizisi; reference alanları hedef içeriğin 24 haneli id'si; repeater satır nesnesi dizisi. Kesin liste her zaman get_cms_collection çıktısındadır.

Ürün (e-ticaret) akışı

list_productsget_productupsert_products (önce dryRun: true). Scope: products:read / products:write (anahtarı panelden bu yetkilerle üretin). delete_product silmenin kendisi için yalnız products:write ister; ancak ürünü adres (slug) ya da SKU ile verirseniz araç önce ürünü okuyup id'ye çevirmek zorundadır, o okuma products:read gerektirir. Yalnız yazma yetkili bir anahtarla çalışıyorsanız ürünün 24 haneli id'sini verin.

Sayfa/CMS araçlarından iki farkı vardır ve ikisi de kritiktir:

  • Yazma taslak değildir. status: "active" ürünü anında vitrine çıkarır; status hiç gönderilmezse mevcut durum korunur (yeni üründe varsayılan draft).
  • Ürün temaya bağlı değildirthemeId gönderilmez; teması bozuk/eksik bir mağazada da katalog yönetilebilir.

upsert_products "yalnız dolu alan yazılır" kuralıyla çalışır ve bu kural varyant içinde de geçerlidir: göndermediğiniz price, compareAtPrice, isActive alanına dokunulmaz; stock kısayolu yalnız ilk depo satırını günceller, diğer depoların stoğunu silmez. variants listesinin KENDİSİ de opsiyoneldir: hiç göndermezseniz mevcut varyantlara dokunulmaz ({slug, status} ile yalnız durumu değiştirebilirsiniz), gönderirseniz boş olamaz. price de opsiyoneldir — yeni üründe boşsa 0, mevcut varyantta boşsa fiyat korunur. Eşleşmeyen SKU yeni varyant EKLER, listede olmayan varyant SİLİNMEZ (varyant silme panel işidir); bu yüzden bir ürünü baştan kurgularken get_product → değerleri kopyala → değiştireceğini değiştir → upsert_products akışı hâlâ en güvenlisidir.

Diğer notlar: marka/kategori/etiket adıyla verilir (yoksa açılır); images[] hem kütüphane dosyası ({uploadId} / {name}) hem uzak URL ({url}; SSRF korumalı indirilir, aynı URL bir kez) kabul eder; varyant ekseni options: {"Beden":"S"} biçimindedir. Fiyat ve stok kuralları sunucudadır. Alan tablosu, dosyayla (CSV/XLSX/JSON) içe aktarma ve sınırlar: backend docs/PRODUCT_IMPORT_EXPORT.md.

update_page operation'ları

append_section{section} (Footer'ın önüne), insert_section{section, before?|after?} (anchor yoksa append gibi Footer'ın önüne), replace_section{id, section}, remove_section{id}, move_section{id, before?|after?}, set_props{id, props} (sığ birleşim), set_slot{id, slot, children} (slotu komple değiştirir; önce yeni çocuklar inşa edilir, başarısızsa eski içerik korunur), set_root_props{props}.

Davranış notları:

  • Ortak bileşenler salt-okunur — alt düğümleri dahil. sharedComponentId taşıyan düğüm (Header/Footer) ve onun zones altındaki tüm torunları (Logo, NavLink, FooterColumn…) set_props/set_slot/replace_section/remove_section ile değiştirilemez; "ortak bileşen — panel editöründen düzenleyin" hatası döner. Ortak kökün kendisi remove_section ile sayfadan kaldırılabilir (uyarıyla; master etkilenmez). get_page outline'ında bu düğümler shared: true ile işaretlidir.
  • Hata / uyarı ayrımı (operations modu): GET'ten gelen doküman önce normalize edilir (props'ta kalmış inline slot dizileri → zones; master'ı silinmiş SharedComponentRef düğümleri uyarıyla düşer — backend PUT'ta aynısını yapar). Ajanın bu turda eklediği/değiştirdiği düğümler katı denetlenir (bilinmeyen type, allow ihlali, element-at-root → hata); önceden var olan, dokunulmayan düğümlerdeki ihlaller yalnız uyarıdır — tema değişmiş diye ilgisiz bir güncelleme kilitlenmez. document modunda ve create_page/validate_document'ta tüm düğümler katı denetlenir.
  • Boş operations: [] (meta da yoksa) → "uygulanacak işlem yok" hatası; PUT atılmaz. Yalnız meta verilirse draftData gönderilmez (status published→changed olmaz, gereksiz revizyon açılmaz); yanıtta savedDraft alanı bunu gösterir.
  • Backend'in kaydetme uyarıları (zarf kökündeki warnings: [{code,path,message}], örn. master'ı silinmiş Header bağının düşürülmesi) create_page/update_page yanıtında sunucu: [code] path: message satırları olarak döner.

Yazarlık biçimi

Ajan doküman JSON'u değil, bölüm ağacı yazar; id üretimi, defaultProps birleşimi, slot → zone dönüşümü ve çok dilli kısayollar sunucuda yapılır.

{
  "type": "FeaturesSection",
  "props": { "columns": "3", "background": "dark" },
  "variant": "dark",                       // bileşenin variants anahtarı (varsa)
  "slots": {
    "contentSlot": [
      { "type": "Title", "props": { "text": { "tr": "Neden biz?", "en": "Why us?" }, "size": "lg" } }
    ],
    "itemsSlot": [
      { "type": "Card", "props": { "href": "/hakkimizda" },
        "slots": { "contentSlot": [ { "type": "Paragraph", "props": { "text": "<p>Hızlı teslimat</p>" } } ] } }
    ]
  }
}

Dönüşüm kuralları:

  1. type katalogda yoksa hata; kökte element kategorisi hata; slot çocuğu allow dışında hata.
  2. props = defaultProps (−id, −inline slot çocukları) ← variants[variant].props (+_variant) ← kullanıcı props.
  3. slots[slot] verildiyse o; verilmediyse defaultProps'taki örnek çocuklar; [] verilirse boş. Hepsi zones["<id>:<slot>"]'a yazılır, props[slot] = [].
  4. Çok dilli kısayollar: "metin"[{code: varsayılanDil, value}]; {tr, en}[{code,value}]; eksik dil uyarı. link: "/yol"[{code, value:{url, target:"_self"}}]. upload: URL string → dış dosya kaydı.
  5. select/radio değeri options dışındaysa hata. _ önekli anahtarlar hata (className serbest).
  6. id: 8 karakter [A-Za-z0-9_-], doküman genelinde tekil (geçerli+tekil bir props.id verilirse kabul edilir).

Geliştirme

npm install
npm run build        # tsc → dist/ (+ dist/bin.js +x)
npm test             # vitest (parser, build, validate, operations, api mock, config, uçtan uca MCP)
node scripts/smoke.mjs   # dist/bin.js'i stdio ile ayağa kaldırır: 1) local, 2) geçersiz /me, 3) remote + sahte katalog (SSE), 4) remote + erişilemeyen API → snapshot

Testler gerçek backend'e istek atmaz (fetch mock'u; remote testleri node:http ile yalnız 127.0.0.1'de sahte Tools API kurar); tema kataloğu test/fixtures/theme altındaki kopya bileşenlerden okunur.

Programatik kullanım (HTTP transport vb.):

import { buildServer, ServerContext, loadConfig } from "@tecof/mcp";
const ctx = new ServerContext({ config: loadConfig() });
const server = buildServer({ ctx }); // McpServer — istediğiniz transport'a bağlayın

// remote mod: kataloğu (≤3 sn) bekleyip kurun; yetişmezse snapshot ile kurulur
const remoteCtx = new ServerContext({ config: { ...loadConfig(), mode: "remote" } });
await remoteCtx.remoteCatalog.ready();
const proxy = buildServer({ ctx: remoteCtx });

Proje geliştirme bilgisi

Docs indeksi ve MCP protokol haritası, güncel kaynak ve test sınırlarını gösterir. Protokol/SDK/bağlantı işleri için tecof-mcp-protocol skill’i kullanılabilir; Claude aynı kaynağı .claude/skills bağlantısından okur.