systa-mcp 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/SKILL.md +175 -43
- package/package.json +4 -2
- package/server.js +1457 -140
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ claude mcp add systa \
|
|
|
101
101
|
|
|
102
102
|
## Araçlar (tools)
|
|
103
103
|
|
|
104
|
-
Toplam **
|
|
104
|
+
Toplam **64 araç** vardır; `tools/list` yanıtı anahtarın kapsamına göre filtrelenir
|
|
105
105
|
(bkz. "Scope-aware araç listesi"). Aşağıdakiler en sık kullanılan çekirdek araçlardır —
|
|
106
106
|
tam katalog `list_capabilities` ile keşfedilir.
|
|
107
107
|
|
|
@@ -190,8 +190,12 @@ printf '%s\n' \
|
|
|
190
190
|
## Yayınlama (maintainer)
|
|
191
191
|
|
|
192
192
|
Paket sıfır bağımlılıklıdır; `files` whitelist'i yalnızca `server.js`, `SKILL.md`,
|
|
193
|
-
`README.md` içerir.
|
|
194
|
-
|
|
193
|
+
`README.md` içerir.
|
|
194
|
+
|
|
195
|
+
> **SKILL.md'nin tek kaynağı bu dizindeki `mcp-server/SKILL.md` dosyasıdır.** Doğrudan burada
|
|
196
|
+
> düzenlenir. (Eskiden `Analiz Dökümanları/.../systa_client_skill_TASLAK.md` kaynak gösteriliyordu;
|
|
197
|
+
> o dosya 2026-06-16'da donmuş bir taslaktır ve gerçek SKILL.md'nin yarısı kadardır. Oradan
|
|
198
|
+
> kopyalamak içeriğin yarısını siler.)
|
|
195
199
|
|
|
196
200
|
```bash
|
|
197
201
|
cd Backend/mcp-server
|
package/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
version: 1.
|
|
2
|
+
version: 1.3.0
|
|
3
3
|
name: systa
|
|
4
4
|
description: |
|
|
5
5
|
Drive SysTa (Talep Takip Sistemi / SysTa) — a
|
|
@@ -67,6 +67,8 @@ Before any SysTa action, confirm connectivity, auth and identity. Do this once p
|
|
|
67
67
|
|
|
68
68
|
If bootstrap fails, deliver a one-line reason ("anahtar süresi dolmuş", "key expired", "endpoint için yetki yok") and stop — never fabricate a result.
|
|
69
69
|
|
|
70
|
+
5. **Yorum yazacaksan ÖNCE sözleşmeyi oku.** Yorum gövdesi düz metin değil **TipTap JSON**'dur ve tablo/başlık/liste destekler; talep (`#125`) ve görev kartı (`##1809`) referansları özel işaret istemez. Yorum, durum notu veya talep açıklaması yazmadan önce → [Yorum ekle (comment)](#yorum-ekle-comment--add_request_comment--post-apirequestsrequestnumbercomments). Bu adım atlanırsa tablolar boş hücreyle, referanslar düz metin olarak çıkar.
|
|
71
|
+
|
|
70
72
|
## SysTa nedir / temel kavramlar (glossary)
|
|
71
73
|
|
|
72
74
|
Short shared vocabulary. Use these words with the user; never expose raw REST paths or internal jargon.
|
|
@@ -94,45 +96,54 @@ yanıtındaki `glossary` alias'larının ayna kopyasıdır (MCP yokken de geçer
|
|
|
94
96
|
ASCII'dir — eşleştirmede aksanı yok say. Modülü bulduktan sonra `describe_module(modül)`
|
|
95
97
|
veya `describe_endpoint` ile gövdeyi netleştir.
|
|
96
98
|
|
|
97
|
-
| Doğal dil (alias) | Modül | Birincil giriş
|
|
98
|
-
| ------------------------------------------------------------ | --------------- |
|
|
99
|
-
| talep, talepler, is, destek talebi | request | list_requests / create_request
|
|
100
|
-
| geciken, overdue, gecikmis, sla ihlali, deadline gecmis | request/sla | list_requests(overdue:true / slaBreached:true)
|
|
101
|
-
| toplu guncelle, hepsini, birden cok talep | request | bulk_update_requests
|
|
102
|
-
| kullanici bul, isim cozumle, kime, hangi ahmet | user | resolve_user_by_name / list_users
|
|
103
|
-
| sirket bul, kategori bul, ekip bul, id cozumle, lookup | multiple | list_lookup(kind:'company'/'category'/'team'/...)
|
|
104
|
-
| projeyi klonla, projeyi cogalt, duplicate project | project | duplicate_project
|
|
105
|
-
| snapshot fark, baseline karsilastir, plan diff | plan | compare_plan_baseline
|
|
106
|
-
| yorumlar, ekler, degisiklik gecmisi, denetim | request | list_request_comments / list_request_files / list_request_history
|
|
107
|
-
|
|
|
108
|
-
|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
|
|
|
99
|
+
| Doğal dil (alias) | Modül | Birincil giriş |
|
|
100
|
+
| ------------------------------------------------------------ | --------------- | ----------------------------------------------------------------------------------------------- |
|
|
101
|
+
| talep, talepler, is, destek talebi | request | list_requests / create_request |
|
|
102
|
+
| geciken, overdue, gecikmis, sla ihlali, deadline gecmis | request/sla | list_requests(overdue:true / slaBreached:true) |
|
|
103
|
+
| toplu guncelle, hepsini, birden cok talep | request | bulk_update_requests |
|
|
104
|
+
| kullanici bul, isim cozumle, kime, hangi ahmet | user | resolve_user_by_name / list_users |
|
|
105
|
+
| sirket bul, kategori bul, ekip bul, id cozumle, lookup | multiple | list_lookup(kind:'company'/'category'/'team'/...) |
|
|
106
|
+
| projeyi klonla, projeyi cogalt, duplicate project | project | duplicate_project |
|
|
107
|
+
| snapshot fark, baseline karsilastir, plan diff | plan | compare_plan_baseline |
|
|
108
|
+
| yorumlar, ekler, degisiklik gecmisi, denetim | request | list_request_comments / list_request_files / list_request_history |
|
|
109
|
+
| yorum yaz, tablo, referans, #125, ##1809, kod blogu, baslik | request | add_request_comment — govde TipTap JSON; tablo/liste commentTextJson ile, referanslar DUZ METIN |
|
|
110
|
+
| gorev, task, kart, card | kanban | manage_request_card / move_request_card |
|
|
111
|
+
| pano, board, kanban / kolon, column, asama, liste | kanban | get_request_board / create_request_board |
|
|
112
|
+
| durum gecisi onizle, izinli gecisler, hangi duruma gecebilir | request | list_allowed_transitions |
|
|
113
|
+
| plan modu, sprint kapsami, plan mode setup | plan | create_plan_mode |
|
|
114
|
+
| durum, oncelik, atanan, planla, denetim, gecmis | request | get_request / list_requests |
|
|
115
|
+
| tahmini efor, planlanan sure (estimatedEffort) | request | update_request (TAHMIN alani, defter DEGIL) |
|
|
116
|
+
| efor gir, efor yaz, calistigim sure, efor defteri, mesai | effort | log_effort / list_effort_targets / list_effort_entries |
|
|
117
|
+
| eksik efor girisim var mi, efor uyumu | effort | get_effort_compliance |
|
|
118
|
+
| proje, klonla | project | list_projects / create_project |
|
|
119
|
+
| onaya sunma, snapshot, sprint, sprinti kapat, optimize et | plan | submit_plan_for_approval / create_plan_baseline |
|
|
120
|
+
| onay, onayla, reddet | approvals | list_pending_approvals / respond_to_approval |
|
|
121
|
+
| onay tipleri, kime onaya gonderelim | approvals | list_approval_types |
|
|
122
|
+
| red nedeni, neden reddedildi, gecerli red sebepleri | approvals | list_rejection_reasons |
|
|
123
|
+
| bu talep neden dondu, neden yazamiyorum, kilitli alan | approvals | get_request_freeze |
|
|
124
|
+
| sla, sure taahhudu | sla | (sla endpoints) |
|
|
125
|
+
| release, surum, go/no-go, deployment | release | create_release_list / add_release_item (listeyi ID ile hedefle) |
|
|
126
|
+
| surum numarasi, versionLabel, ayni gun iki liste | release | create_release_list -> id + versionLabel (tarih DEGIL) |
|
|
127
|
+
| musaitlik, izin (leave), vekil | user/automation | systa_api_call /user-availability, /user-leaves |
|
|
128
|
+
| vendor, sirket, musteri | company | systa_api_call GET /companies |
|
|
129
|
+
| organizasyon birimi, departman, bolum, birim | department | GET /api/departments |
|
|
130
|
+
| takim, ekip, team | team | GET /api/teams |
|
|
131
|
+
| yetki paketi, izin (permission) | security | (bundle/permission endpoints) |
|
|
132
|
+
| alt form, sub-form | forms | systa_api_call GET /forms/:id |
|
|
133
|
+
| rapor, raporlama, disa aktar, export, excel, csv | report | systa_api_call /reports/preview,/reports/export |
|
|
134
|
+
| ozel sorgu, sorgu, query builder, ad-hoc, veri cek | query-builder | querybuilder_describe_fields / \_execute_query |
|
|
135
|
+
| hesap tablosu, gridpad, tablo, excel, spreadsheet, hucre | spreadsheet | GET /api/spreadsheets |
|
|
136
|
+
| dosya, ek, attachment, yukle, upload, indir, download | file | upload_file_to / download_request_file |
|
|
137
|
+
| bildirim, notification, uyari, okundu, push | notification | GET /api/notifications |
|
|
138
|
+
| yetenek, beceri, skill, otomatik etiketleme | skill | GET /api/skills |
|
|
139
|
+
| duyuru, announcement, bildiri, ilan | announcement | GET /api/announcements |
|
|
140
|
+
| urun guncellemesi, surum notu, yenilikler, changelog | product-update | GET /api/product-updates |
|
|
141
|
+
| not, kisisel not, hatirlatma | note | GET /api/dashboard/notes |
|
|
142
|
+
| yer imi, favori, bookmark, kisayol | bookmark | GET /api/dashboard/bookmarks |
|
|
143
|
+
| degerlendirme, puanlama, memnuniyet, geri bildirim | ratings | POST /api/ratings |
|
|
144
|
+
| anket, oylama, karar alalim, ekibe soralim, secenek sun | decisions | systa_api_call POST /requests/:n/decisions |
|
|
145
|
+
| github, repo, pull request, commit, issue aktar | github | systa_api_call /github/me/{connection,repos,import,push} |
|
|
146
|
+
| gosterge paneli, dashboard, widget, ozet, grafik, panel | dashboard | GET /api/dashboard/init |
|
|
136
147
|
|
|
137
148
|
> Bu tablo, katalogdaki ~25 modülün kullanıcı-yüzeyli olanlarından bir alt küme kapsar. Listede olmayan
|
|
138
149
|
> bir kelime için `list_capabilities` çağır — anahtarının erişebildiği güncel modül/alias
|
|
@@ -164,7 +175,7 @@ Each maps a P0 user verb to a tool/endpoint, with the opinionated defaults from
|
|
|
164
175
|
|
|
165
176
|
1. Need `title` (min 5 chars) — if missing or too short, ask once. Never invent it.
|
|
166
177
|
2. Defaults: `channel='API'` (AI/MCP source), `statusId` ← default open/new status (resolve via `GET /api/statuses`, pick the non-final entry status), `priority='normal'` unless the user signals "acil/critical". `description` can be a plain string. **`companyId` — DIKKAT:** genelde `user.companyId` DEĞİL — B2B talepler MÜŞTERİ şirketi için açılır. Şirket adı netlesmediyse `systa_api_call GET /companies?search=<ad>` ile çöz veya kullanıcıya SOR. `prepare_create_request(companyId)` proaktif seçenekleri döner.
|
|
167
|
-
3. **Efor** (`estimatedEffort`/`personDay`): KANONIK GÜN. Kullanıcı "N saat" derse ÖNCE `list_capabilities.effortPolicy.hoursPerDay` ile böl (varsayılan 8), sonra yaz. "8 saat" → `estimatedEffort=1` (8/8=1 gün), "4 saat" → `estimatedEffort=0.5`. Aynı kural `manage_request_card.estimatedEffort` ve `bulk_update_requests.updates.estimatedEffort` için de geçerli.
|
|
178
|
+
3. **Efor** (`estimatedEffort`/`personDay`): bu alan **PLANLANAN TAHMİN**tir; gerçekleşen çalışma kaydı DEĞİLDİR (onun için `log_effort` / efor defteri kullanılır — ayrı modül, ayrı uç). KANONIK GÜN. Kullanıcı "N saat" derse ÖNCE `list_capabilities.effortPolicy.hoursPerDay` ile böl (varsayılan 8), sonra yaz. "8 saat" → `estimatedEffort=1` (8/8=1 gün), "4 saat" → `estimatedEffort=0.5`. Aynı kural `manage_request_card.estimatedEffort` ve `bulk_update_requests.updates.estimatedEffort` için de geçerli.
|
|
168
179
|
4. Submit; report "Talep #<num> açıldı — '<title>'". If the user also said "bana ata", chain assignment below.
|
|
169
180
|
|
|
170
181
|
### Üzerimdeki işler / talepleri listele (what's on my plate) — `list_requests` → `GET /api/requests`
|
|
@@ -186,7 +197,98 @@ Each maps a P0 user verb to a tool/endpoint, with the opinionated defaults from
|
|
|
186
197
|
|
|
187
198
|
### Yorum ekle (comment) — `add_request_comment` → `POST /api/requests/:requestNumber/comments`
|
|
188
199
|
|
|
189
|
-
|
|
200
|
+
> **Yorum gövdesi düz metin DEĞİL, TipTap JSON dokümanıdır.** Bu bölümü yorum yazmadan önce oku — tablo, başlık, liste ve talep/görev referansları buradan çıkar.
|
|
201
|
+
|
|
202
|
+
**İki çağrı biçimi** (en az biri zorunlu: `text` / `commentTextJson` / `fileIds`):
|
|
203
|
+
|
|
204
|
+
| Ne yazıyorsun | Argüman | Not |
|
|
205
|
+
| ---------------------------------- | ----------------- | ------------------------------------------------------------------------ |
|
|
206
|
+
| Sıradan yorum | `text` | Tool tek paragrafa sarar |
|
|
207
|
+
| Tablo / başlık / liste / kod bloğu | `commentTextJson` | TAM doküman; verilirse `text` yok sayılır |
|
|
208
|
+
| Dosya eki | `fileIds` | Önce `upload_file_to`; dosya hem yorumda hem Dosyalar sekmesinde görünür |
|
|
209
|
+
|
|
210
|
+
**Render edilen düğümler** (otorite: frontend `jsonToHtml`; listede olmayan düğüm sessizce yalnız içeriğiyle basılır):
|
|
211
|
+
`doc`, `paragraph`, `heading{level:1..3}`, `text`, `hardBreak`, `bulletList`, `orderedList`, `listItem`, `blockquote`, `codeBlock{language}`, `table`, `tableRow`, `tableHeader`, `tableCell`, `mention{id,label}`.
|
|
212
|
+
**Metin işaretleri (marks):** `bold`, `italic`, `underline`, `strike`, `code`, `link{href}`, `textStyle{color,fontSize,fontFamily}`, `highlight{color}`.
|
|
213
|
+
|
|
214
|
+
**Tablo iç içe sırası KATIDIR** — `table > tableRow > (tableHeader | tableCell) > paragraph > text`.
|
|
215
|
+
Hücreye doğrudan `text` koyarsan hücre **boş** görünür.
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"type": "doc",
|
|
220
|
+
"content": [
|
|
221
|
+
{
|
|
222
|
+
"type": "heading",
|
|
223
|
+
"attrs": { "level": 3 },
|
|
224
|
+
"content": [{ "type": "text", "text": "Bulgular" }]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"type": "table",
|
|
228
|
+
"content": [
|
|
229
|
+
{
|
|
230
|
+
"type": "tableRow",
|
|
231
|
+
"content": [
|
|
232
|
+
{
|
|
233
|
+
"type": "tableHeader",
|
|
234
|
+
"content": [{ "type": "paragraph", "content": [{ "type": "text", "text": "Bulgu" }] }]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"type": "tableHeader",
|
|
238
|
+
"content": [{ "type": "paragraph", "content": [{ "type": "text", "text": "Kart" }] }]
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"type": "tableRow",
|
|
244
|
+
"content": [
|
|
245
|
+
{
|
|
246
|
+
"type": "tableCell",
|
|
247
|
+
"content": [
|
|
248
|
+
{
|
|
249
|
+
"type": "paragraph",
|
|
250
|
+
"content": [{ "type": "text", "text": "Filo uyarısı çıkmıyor" }]
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"type": "tableCell",
|
|
256
|
+
"content": [
|
|
257
|
+
{ "type": "paragraph", "content": [{ "type": "text", "text": "##1809" }] }
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"type": "paragraph",
|
|
266
|
+
"content": [
|
|
267
|
+
{ "type": "text", "text": "Ayrıntı " },
|
|
268
|
+
{ "type": "text", "marks": [{ "type": "bold" }], "text": "#125" },
|
|
269
|
+
{ "type": "text", "text": " talebinde." }
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Talep ve görev kartı referansı — özel işaret GEREKMEZ
|
|
277
|
+
|
|
278
|
+
Gövdede geçen şu düz metin tokenları otomatik olarak **tıklanabilir rozete** çevrilir:
|
|
279
|
+
|
|
280
|
+
| Yazım | Neye gider | Tıklayınca |
|
|
281
|
+
| -------- | --------------------------- | ---------------------------------------------- |
|
|
282
|
+
| `#125` | **Talep** (request) | Talep önizlemesi açılır |
|
|
283
|
+
| `##1809` | **Görev kartı** (task card) | Kartın önizlemesi açılır, oradan karta gidilir |
|
|
284
|
+
|
|
285
|
+
- **Link mark'ı / `href` / öznitelik EKLEME** — renderer token'ı kendisi rozete çevirir. Elle `<a>` üretmek rozeti bozar.
|
|
286
|
+
- Sayı: `#` için **talep numarası**, `##` için kartın **global `card.id`**'si.
|
|
287
|
+
Panoda kartın üstünde görünen `#3` talep-içi **sıra numarasıdır**, referans DEĞİLDİR — `card.id`'yi `get_request_board` / `cards/list` çıktısından al.
|
|
288
|
+
- **Öneki karıştırmak kullanıcıyı yanlış kayda götürür**: aynı sayı hem talep hem kart olarak var olabilir. Kart kastediyorsan çift diyez şart.
|
|
289
|
+
- Rozetler her yorum görünümünde ve sürüm karar akışındaki yorumlarda da çalışır.
|
|
290
|
+
|
|
291
|
+
İstenmedikçe `@mention` ekleme.
|
|
190
292
|
|
|
191
293
|
### Durum değiştir / tamamla / kapat (change status) — `change_request_status` → `PUT /api/requests/:requestNumber`
|
|
192
294
|
|
|
@@ -231,6 +333,11 @@ Each maps a P0 user verb to a tool/endpoint, with the opinionated defaults from
|
|
|
231
333
|
### Sürüm oluştur (release) — `create_release_list` → `POST /api/releases/lists`
|
|
232
334
|
|
|
233
335
|
- `releaseType='standard'`, `requireAllStakeholderApprovals=false`, `companyId` from scope. Add items with `add_release_item`. Deployment workflow steps (`close-servers` → `start-db-migration` → `start-server-update` → `open-servers` → `complete`) are live ops — **never auto-advance blindly**; show which step you're on and confirm. Release notes: generate → review → publish (never auto-publish).
|
|
336
|
+
- **Bir listenin kimliği = `id` + CalVer sürümü (`versionLabel`, örn. `2026.09.1`) — TARİH DEĞİL.** Aynı şirket **aynı gün İKİ liste** yayınlayabilir, bu yüzden "23 Eylül'deki liste" tek bir listeyi göstermez: tarihle liste arama/eşleştirme güvenilir değildir ve yanlış listeye yazma riski taşır.
|
|
337
|
+
- `create_release_list` yanıtı `versionYear` / `versionMonth` / `versionSeq` / `versionFinalized` alanlarının yanında hazır `versionLabel` döner. **Kullanıcıya listeyi `versionLabel` ile adlandır, kendi tarafında `id`'yi sakla.** `versionFinalized=false` ise numara HENÜZ GEÇİCİDİR (liste onaylanırken değişebilir) — kesinmiş gibi sunma.
|
|
338
|
+
- Sonraki tüm çağrılar listeyi **sayısal `id` ile** hedefler: `add_release_item(listId)`, `get_release_workflow`, `advance_release_workflow(listId)`, `decide_release_stage(itemId)`. Hiçbirinde tarih liste seçmez. `add_release_item`'daki `plannedProdDate` de liste SEÇMEZ; yalnızca **talebin** `plannedProdDate` özel alanını ezer (boşsa listenin deployment tarihinden türetilir).
|
|
339
|
+
- Talep listeye **ID ile** bağlanır (`target_release_list_id`), tarihle değil. Kullanıcı "şu tarihteki sürüme ekle" derse önce o tarihteki listeleri getir, birden fazlaysa `versionLabel` ile **hangisi olduğunu sor** — tahmin etme.
|
|
340
|
+
- Sürüm webhook'larının gövdesi (`release.list.published`, `release.workflow.failed`, `release.item.added` …) `deploymentDate` yanında **her zaman bir `versionLabel` anahtarı** taşır; sürüm çözülemediyse `null` gelir. Dış sisteme sürümden bahsederken bu alanı kullan, `null` ise tarihe düş.
|
|
234
341
|
|
|
235
342
|
### GitHub: bağla / issue aktar / push (kişisel entegrasyon) — `github.self`
|
|
236
343
|
|
|
@@ -242,6 +349,27 @@ Kullanıcının kendi GitHub bağlantısı üzerinden talep açma/aktarma. Tüm
|
|
|
242
349
|
- **Issue içe aktar (GitHub → SysTa talep):** `systa_api_call` `POST /github/me/import` — seçili repo'nun issue'larını kullanıcının KENDİ talepleri olarak içe aktarır (idempotent, createdBy=self). "şu repodan issue'ları SysTa'ya aktar / GitHub'dan talep aç" → bu. Mutating + canlı: hangi repo / kaç issue özetini göster, **onay al**.
|
|
243
350
|
- **Talep push (SysTa → GitHub issue):** `systa_api_call` `POST /github/me/push` — kullanıcının talebini kendi repo'suna GitHub issue'su olarak gönderir/günceller (idempotent, node_id). Dış yan-etki (GitHub'a yazar) → **onay al**.
|
|
244
351
|
|
|
352
|
+
### Efor gir (log worked time) — `log_effort`
|
|
353
|
+
|
|
354
|
+
SysTa'da "efor" iki ayrı şeydir ve karıştırılması veri bozar:
|
|
355
|
+
|
|
356
|
+
- **Tahmini efor** (`estimatedEffort` / `personDay`): talebin PLANLANAN süresi. `update_request` ile yazılır.
|
|
357
|
+
- **Efor defteri** (`log_effort`): kullanıcının GERÇEKLEŞEN çalışma kaydı. Ayrı modül, ayrı uç, ayrı izin.
|
|
358
|
+
|
|
359
|
+
Kullanıcı "bu haftaki eforumu yaz / 3 saat çalıştım / dün toplantıdaydım" derse **defter** kastedilir.
|
|
360
|
+
|
|
361
|
+
1. **Önce `list_effort_targets`** çağır (`from`/`to` ver; aralık en fazla 366 gün). Dönen `enabledTargets` hangi hedef türünün açık olduğunu söyler: kapalı bir hedefi kullanıcıya ÖNERME. `candidates` son dokunulan talep/projeleri, `categories` efor türlerini, `activityTypes` serbest aktivite türlerini verir. Kimlikler uydurulamaz.
|
|
362
|
+
2. **`log_effort`** ile yaz. `requestId` / `projectId` / `activityTypeId` üçlüsünden **TAM BİRİ** verilmelidir; sıfır da iki de reddedilir. `inputUnit` ZORUNLUDUR (`minute|hour|day`) — saat/gün çevrimini sen yapma, sunucu kanonik güne çevirir. `entryDate` boşsa bugün yazılır; **gelecek tarih reddedilir**.
|
|
363
|
+
3. Hata karşılıkları: `403 EFFORT_TARGET_DISABLED` → o hedef türü vendor ayarında kapalı (adım 1'i oku). `403 EFFORT_SCOPE_DENIED` → kullanıcı efor modülü kapsamı dışında. `409 EFFORT_TARGET_IMMUTABLE` → bir kaydın hedefi **asla** değiştirilemez; sil ve yeniden gir.
|
|
364
|
+
4. Okuma: `list_effort_entries(from, to)` kendi defterini döner; başkasınınki için `userId` ver (ek yetki ister). "Eksiğim var mı" sorusu tek çağrıyla `get_effort_compliance`.
|
|
365
|
+
|
|
366
|
+
5. **BİRİM: iki farklı kural, karıştırma.** `log_effort`'ta çevrimi SEN YAPMA — kullanıcı ne dediyse o birimle gönder (`3 saat` → `inputValue:3, inputUnit:'hour'`; `yarım gün` → `inputValue:0.5, inputUnit:'day'`; `45 dakika` → `inputValue:45, inputUnit:'minute'`). Sunucu kanonik güne çevirir ve çevrimde HEDEFİN şirketinin `hoursPerDay` değerini kullanır; senin bölmen yanlış şirketin katsayısını uygulayabilir. Buna karşılık `estimatedEffort` (tahmin) alanına yazarken çevrimi SEN yaparsın (bkz. "Talep aç" adım 3). Sonucu kullanıcıya bildirirken vendor'un görünüm birimini kullan: `list_capabilities.effortPolicy.displayUnit` saat ise "3 saat işlendi" de, "0,375 gün" deme.
|
|
367
|
+
|
|
368
|
+
6. **Kullanıcı efor girişine TABİ İSE proaktif ol.** Efor takibi vendor ayarıyla açılır ve kullanıcı kapsam içindeyse zorunlu hale gelir. Bunu `list_effort_targets` yanıtındaki `settings` (compliance alanları) ya da tek çağrıyla `get_effort_compliance` söyler; `satisfied:false` "bu kullanıcının eksik girişi var" demektir.
|
|
369
|
+
- Kullanıcı MCP üzerinden bir işi TAMAMLADIĞINDA (talep kapatma, statü ilerletme, kart tamamlama gibi), efor modülü açıksa **süreyi sor**: "Bu işe ne kadar zaman ayırdın? Efor defterine işleyeyim mi?" Süreyi UYDURMA ve kullanıcı vermeden yazma — defter kaydı kullanıcının beyanıdır.
|
|
370
|
+
- Kullanıcı "bugün ne yapmalıyım / eksiğim var mı" diye sorduğunda `get_effort_compliance` çağır ve eksik varsa hangi güne ne kadar gerektiğini söyle.
|
|
371
|
+
- Efor modülü bu vendor'da kapalıysa ya da kullanıcı kapsam dışındaysa (`403 EFFORT_SCOPE_DENIED`) hatırlatma YAPMA; olmayan bir yükümlülüğü dayatmak gürültüdür.
|
|
372
|
+
|
|
245
373
|
## Zincirleme & hata kurtarma (chaining & error recovery)
|
|
246
374
|
|
|
247
375
|
SysTa returns structured errors. Recover deterministically instead of giving up.
|
|
@@ -258,6 +386,10 @@ SysTa returns structured errors. Recover deterministically instead of giving up.
|
|
|
258
386
|
6. **`409 conflict`** (optimistic concurrency on cards/edits) — re-read the entity to get the latest `updatedAt`, then retry the mutation once with the fresh value; warn the user only if it conflicts again.
|
|
259
387
|
7. **Dual-path "list vs create" endpoints** (e.g. `POST /api/sla/definitions`, `POST /api/sla/standby-configs`) — an empty/filter-only body lists; a full body creates. Choose the body shape that matches the intent; don't accidentally create when the user asked to list.
|
|
260
388
|
8. **Multi-tenant safety.** Never carry an id across vendors. If a resolved id isn't found in the caller's vendor scope, treat it as not-found (step 3), not as a public-schema fallback.
|
|
389
|
+
9. **`409 REQUEST_FROZEN_BY_APPROVAL`** — the request is FROZEN by a pending approval, so every write on it is refused (update, status change, assignment, comment, kanban card, file upload). This is **not** a permission problem and **not** a transition problem: retrying, calling `list_allowed_transitions` or re-authenticating will not help. Call `get_request_freeze(requestId)` to see which approval froze it and which fields are still writable (`writableFieldKeys` — non-empty only under a custom freeze scope). Then either write only those fields, or tell the user the request is waiting on an approval and offer to wait / cancel it. `list_requests` and `get_request` both carry `isFrozen` — check it BEFORE attempting a write.
|
|
390
|
+
10. **`403 FEATURE_NOT_ENABLED`** — the vendor's API/MCP module is off, either because the licence lacks `api_access` or because a vendor admin disabled the `mcp` preference. This gate runs before any scope check, so **every** tool fails the same way. Do not tell the user to regenerate the key; tell them to have the vendor administrator enable API/MCP access.
|
|
391
|
+
11. **`422 REJECTION_REASON_*` / `409 APPROVAL_SEQUENCE_NOT_ACTIVE`** — rejection reasons come from a per-approval-type catalog: call `list_rejection_reasons(approvalTypeId)` and send a `key` from it (`REJECTION_REASON_NOT_ALLOWED` means the code is not bound to that type; `REJECTION_REASON_NOTE_REQUIRED` means that reason needs a non-empty `rejectionReasonText`). `APPROVAL_SEQUENCE_NOT_ACTIVE` means a sequential chain has not reached your group yet — report that it is waiting on an earlier step instead of retrying.
|
|
392
|
+
12. **Partial success is real.** `bulk_update_requests` can return HTTP 200 while skipping frozen requests; the tool adds a `partialSuccess` block when fewer rows changed than you asked for. Always compare the requested count with `updatedCount` and name the ids that did not change. Never report "all done" from a 200 alone.
|
|
261
393
|
|
|
262
394
|
## DX / Keşif Notları (talep 166 — prod'da doğrulanmış)
|
|
263
395
|
|
|
@@ -281,7 +413,7 @@ Gerçek AI kullanımında tespit edilen sürtünme noktaları; her biri canlı d
|
|
|
281
413
|
### Talep açma — `description` = ilk yorum (commentNo 1)
|
|
282
414
|
|
|
283
415
|
- Verdiğin `description` talebin **ilk yorumu** olarak materyalize edilir.
|
|
284
|
-
- **Tablo/zengin içerik** için: `systa_api_call POST /requests` ile `descriptionJson` alanına TipTap doc (tablo dahil) gönder — bu da comment #1 olur. **Ayrıca ayrı yorum EKLEME** (çift yorum olur). İçeriği yalnız ayrı yorumda istiyorsan `description` boş bırak.
|
|
416
|
+
- **Tablo/zengin içerik** için: `systa_api_call POST /requests` ile `descriptionJson` alanına TipTap doc (tablo dahil) gönder — bu da comment #1 olur. Düğüm/tablo sözleşmesi ve `#125` / `##1809` referansları yorumla **aynıdır** → [Yorum ekle](#yorum-ekle-comment--add_request_comment--post-apirequestsrequestnumbercomments). **Ayrıca ayrı yorum EKLEME** (çift yorum olur). İçeriği yalnız ayrı yorumda istiyorsan `description` boş bırak.
|
|
285
417
|
|
|
286
418
|
### Kanban
|
|
287
419
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "systa-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "MCP stdio server for SysTa (Talep Takip Sistemi) — lets AI agents (Claude, Codex) use the SysTa REST API via a scoped API key. Zero npm dependencies (native Node).",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "server.js",
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"start": "node server.js",
|
|
17
17
|
"check:version-sync": "node scripts/check-version-sync.js",
|
|
18
|
-
"prepublishOnly": "node scripts/check-version-sync.js"
|
|
18
|
+
"prepublishOnly": "node scripts/check-version-sync.js && node scripts/check-release-integrity.js --skip-npm",
|
|
19
|
+
"check:release-integrity": "node scripts/check-release-integrity.js",
|
|
20
|
+
"check:release-integrity:self-test": "node scripts/check-release-integrity.js --self-test"
|
|
19
21
|
},
|
|
20
22
|
"engines": {
|
|
21
23
|
"node": ">=18"
|