burkut-mcp 1.0.0 → 1.0.2
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 +59 -43
- package/dist/client.d.ts +4 -6
- package/dist/client.js +30 -66
- package/dist/config.js +19 -5
- package/dist/index.js +8 -3
- package/dist/tools.js +73 -78
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="../assets/logo.png" alt="Bürküt Logo" width="100" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
>
|
|
5
|
+
<h1 align="center">Bürküt MCP Server</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<b>Claude Desktop, Cursor ve LLM tabanlı yapay zeka ajanları için Türkiye finans piyasası veri köprüsü.</b><br />
|
|
9
|
+
Borsa İstanbul (BIST), TEFAS Yatırım Fonları, KAP Bildirimleri, Halka Arzlar, Temettüler ve Makro Veriler.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/burkut-mcp"><img src="https://img.shields.io/npm/v/burkut-mcp?color=purple&style=flat-square&logo=npm&logoColor=white" alt="npm version" /></a>
|
|
14
|
+
<a href="https://modelcontextprotocol.io/"><img src="https://img.shields.io/badge/Protokol-MCP%20Standard%C4%B1-blueviolet?style=flat-square&logo=anthropic&logoColor=white" alt="MCP Protocol" /></a>
|
|
15
|
+
<a href="../LICENSE"><img src="https://img.shields.io/badge/Lisans-MIT-gray.svg?style=flat-square" alt="Lisans" /></a>
|
|
16
|
+
</p>
|
|
6
17
|
|
|
7
18
|
---
|
|
8
19
|
|
|
9
|
-
##
|
|
20
|
+
## Hızlı Başlangıç
|
|
10
21
|
|
|
11
|
-
|
|
22
|
+
Herhangi bir kurulum veya indirme gerektirmez. `npx` ile doğrudan çalıştırılır:
|
|
12
23
|
|
|
13
24
|
```bash
|
|
14
25
|
npx -y burkut-mcp
|
|
@@ -17,10 +28,10 @@ npx -y burkut-mcp
|
|
|
17
28
|
### 1. Claude Desktop ile Kullanım
|
|
18
29
|
|
|
19
30
|
Claude Desktop yapılandırma dosyanızı açın:
|
|
20
|
-
* **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
21
31
|
* **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
32
|
+
* **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
22
33
|
|
|
23
|
-
Aşağıdaki
|
|
34
|
+
Aşağıdaki tanımı ekleyin:
|
|
24
35
|
|
|
25
36
|
```json
|
|
26
37
|
{
|
|
@@ -29,54 +40,65 @@ Aşağıdaki yapılandırmayı ekleyin:
|
|
|
29
40
|
"command": "npx",
|
|
30
41
|
"args": ["-y", "burkut-mcp"],
|
|
31
42
|
"env": {
|
|
32
|
-
"BURKUT_API_KEY": "
|
|
43
|
+
"BURKUT_API_KEY": "BURKUT_API_ANAHTARINIZ"
|
|
33
44
|
}
|
|
34
45
|
}
|
|
35
46
|
}
|
|
36
47
|
}
|
|
37
48
|
```
|
|
38
49
|
|
|
39
|
-
>
|
|
50
|
+
> **Önemli:** `BURKUT_API_KEY` zorunludur. Kotanızı takip etmek ve servisi kullanabilmek için [burkutportfoy.com/developer](https://burkutportfoy.com/developer) adresinden saniyeler içinde **ücretsiz API anahtarınızı** oluşturup buraya ekleyin.
|
|
40
51
|
|
|
41
52
|
---
|
|
42
53
|
|
|
43
54
|
### 2. Cursor IDE ile Kullanım
|
|
44
55
|
|
|
45
|
-
Cursor
|
|
46
|
-
|
|
47
|
-
* **
|
|
48
|
-
* **
|
|
56
|
+
1. **Cursor Settings** → **Features** → **MCP Servers** yolunu izleyin.
|
|
57
|
+
2. **Add New MCP Server** butonuna tıklayın:
|
|
58
|
+
* **Name:** `burkut`
|
|
59
|
+
* **Type:** `command`
|
|
60
|
+
* **Command:** `npx -y burkut-mcp`
|
|
61
|
+
* **Env:** `BURKUT_API_KEY=BURKUT_API_ANAHTARINIZ`
|
|
49
62
|
|
|
50
63
|
---
|
|
51
64
|
|
|
52
|
-
##
|
|
65
|
+
## Desteklenen MCP Araçları (Tools)
|
|
53
66
|
|
|
54
|
-
|
|
|
55
|
-
| :--- | :--- |
|
|
56
|
-
| `burkut_search_funds` |
|
|
57
|
-
| `burkut_get_fund_detail` |
|
|
58
|
-
| `burkut_get_stock_quote` |
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
67
|
+
| Araç Adı | Parametreler | Açıklama |
|
|
68
|
+
| :--- | :--- | :--- |
|
|
69
|
+
| `burkut_search_funds` | `query`, `fundType`, `sortBy`, `limit` | TEFAS fonlarını filtreler; 1 ay, 3 ay, 6 ay ve 1 yıllık getirilerine göre sıralar. |
|
|
70
|
+
| `burkut_get_fund_detail` | `symbol` (örn: `MAC`, `TI2`) | Belirli bir fonun tüm periyot getirilerini, risk seviyesini ve detaylı künyesini döner. |
|
|
71
|
+
| `burkut_get_stock_quote` | `symbol` (örn: `THYAO`, `ASELS`) | BIST hissesinin 15 dk gecikmeli resmi fiyatını, günlük değişim oranını ve hacmini getirir. |
|
|
72
|
+
| `burkut_list_stocks` | `symbols` (örn: `THYAO,ASELS`) | BIST hisselerini listeler veya virgülle ayrılmış hisseleri toplu çeker. |
|
|
73
|
+
| `burkut_get_forex` | `symbol` (örn: `USD`, `EUR`) | Serbest piyasa ve TCMB döviz kurlarını getirir. |
|
|
74
|
+
| `burkut_get_gold` | `symbol` (örn: `ALTIN`, `CEYREK_ALTIN`) | Gram altın, çeyrek altın ve ons altın piyasa fiyatlarını döner. |
|
|
75
|
+
| `burkut_get_bonds` | - | Devlet tahvilleri ve hazine bonosu getirilerini listeler. |
|
|
76
|
+
| `burkut_get_viop` | - | VİOP vadeli işlem ve opsiyon kontrat fiyatlarını listeler. |
|
|
63
77
|
|
|
64
78
|
---
|
|
65
79
|
|
|
66
|
-
##
|
|
80
|
+
## Örnek Türkçe İstekler (Promptlar)
|
|
81
|
+
|
|
82
|
+
Claude Desktop veya Cursor'a doğrudan şu soruları sorabilirsiniz:
|
|
83
|
+
|
|
84
|
+
* *"Bana TEFAS'taki hisse senedi yoğun fonlar arasında son 1 yılda en çok kazandıran 5 fonu listele ve yıllık getirilerini göster."*
|
|
85
|
+
* *"MAC ve TI2 fonlarının risk puanlarını ve son 6 aylık performanslarını karşılaştır."*
|
|
86
|
+
* *"Bugün KAP'a düşen önemli şirket bildirimlerini ve yeni iş ilişkilerini özetle."*
|
|
87
|
+
* *"Bu hafta talep toplayacak veya aktif olan halka arzlar hangileri? Dağıtım yöntemleri nedir?"*
|
|
88
|
+
* *"FROTO ve TUPRS şirketlerinin son temettü dağıtım oranlarını karşılaştır."*
|
|
89
|
+
* *"TÜİK tarafından açıklanan son yıllık TÜFE enflasyon oranı ile güncel dolar kurunu getir."*
|
|
67
90
|
|
|
68
|
-
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Ortam Değişkenleri (Environment Variables)
|
|
69
94
|
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* *"Bu hafta talep toplayacak veya aktif olan halka arzlar hangileri? Fiyatları ve tarihleri nedir?"*
|
|
74
|
-
* *"FROTO ve TUPRS'ın son temettü dağıtım oranlarını karşılaştır."*
|
|
75
|
-
* *"Türkiye'deki son açıklanan yıllık TÜFE enflasyon oranı ile güncel dolar kurunu getir."*
|
|
95
|
+
* `BURKUT_API_KEY`: Geliştirici API Anahtarınız (zorunludur, https://burkutportfoy.com/developer adresinden ücretsiz alınır).
|
|
96
|
+
* `BURKUT_API_BASE_URL`: Hedef API adresi (Varsayılan: `https://api.burkutportfoy.com`).
|
|
97
|
+
* `BURKUT_TIMEOUT_MS`: İstek zaman aşımı süresi milisaniye cinsinden (Varsayılan: `15000`).
|
|
76
98
|
|
|
77
99
|
---
|
|
78
100
|
|
|
79
|
-
##
|
|
101
|
+
## Yerel Geliştirme (Local Development)
|
|
80
102
|
|
|
81
103
|
```bash
|
|
82
104
|
git clone https://github.com/sametakan29/burkut-sdks.git
|
|
@@ -85,26 +107,20 @@ npm install
|
|
|
85
107
|
npm run build
|
|
86
108
|
```
|
|
87
109
|
|
|
88
|
-
Yerel test
|
|
110
|
+
Yerel test:
|
|
89
111
|
```bash
|
|
90
112
|
node dist/index.js
|
|
91
113
|
```
|
|
92
114
|
|
|
93
|
-
Ortam Değişkenleri:
|
|
94
|
-
* `BURKUT_API_KEY`: Bürküt Developer API anahtarınız (opsiyonel).
|
|
95
|
-
* `BURKUT_API_BASE_URL`: Hedef API adresi (Varsayılan: `https://api.burkutportfoy.com`).
|
|
96
|
-
* `BURKUT_TIMEOUT_MS`: İstek zaman aşımı süresi (Varsayılan: `15000` ms).
|
|
97
|
-
|
|
98
115
|
---
|
|
99
116
|
|
|
100
|
-
##
|
|
117
|
+
## Destek ve İletişim
|
|
101
118
|
|
|
102
|
-
Her türlü geri bildirim, özel veri seti talepleri veya hata bildirimleri için:
|
|
103
119
|
* **E-posta:** [destek@burkutportfoy.com](mailto:destek@burkutportfoy.com)
|
|
104
|
-
* **GitHub Issues:** [burkut-sdks/issues](https://github.com/sametakan29/burkut-sdks/issues)
|
|
120
|
+
* **GitHub Issues:** [github.com/sametakan29/burkut-sdks/issues](https://github.com/sametakan29/burkut-sdks/issues)
|
|
105
121
|
|
|
106
122
|
---
|
|
107
123
|
|
|
108
|
-
##
|
|
124
|
+
## Lisans
|
|
109
125
|
|
|
110
|
-
|
|
126
|
+
Bu proje [MIT Lisansı](../LICENSE) ile korunmaktadır. Telif Hakkı © 2026 Bürküt Finansal Teknolojiler.
|
package/dist/client.d.ts
CHANGED
|
@@ -8,12 +8,10 @@ export declare class BurkutApiClient {
|
|
|
8
8
|
getFundDetail(symbol: string): Promise<any>;
|
|
9
9
|
getStocks(symbols?: string[]): Promise<any[]>;
|
|
10
10
|
getStockQuote(symbol: string): Promise<any>;
|
|
11
|
-
getKapAnnouncements(symbol?: string, page?: number, size?: number): Promise<any>;
|
|
12
|
-
getKapDetail(id: string): Promise<any>;
|
|
13
|
-
getIpoList(activeOnly?: boolean): Promise<any[]>;
|
|
14
|
-
getIpoDetail(symbol: string): Promise<any>;
|
|
15
|
-
getDividends(symbol?: string): Promise<any>;
|
|
16
|
-
getInflation(): Promise<any>;
|
|
17
11
|
getForex(): Promise<any[]>;
|
|
12
|
+
getForexDetail(symbol: string): Promise<any>;
|
|
18
13
|
getGold(): Promise<any[]>;
|
|
14
|
+
getGoldDetail(symbol: string): Promise<any>;
|
|
15
|
+
getBonds(): Promise<any[]>;
|
|
16
|
+
getViop(): Promise<any[]>;
|
|
19
17
|
}
|
package/dist/client.js
CHANGED
|
@@ -14,19 +14,17 @@ export class BurkutApiClient {
|
|
|
14
14
|
this.config = config || getConfig();
|
|
15
15
|
}
|
|
16
16
|
async request(path, options = {}) {
|
|
17
|
-
const { query
|
|
18
|
-
|
|
17
|
+
const { query } = options;
|
|
18
|
+
// BURKUT_API_KEY zorunludur: Geliştirici veri borusu (/api/public/v1) için şarttır.
|
|
19
|
+
if (!this.config.apiKey || !this.config.apiKey.trim()) {
|
|
20
|
+
throw new Error("Bürküt API Anahtarı eksik! Bürküt MCP sunucusunu kullanabilmek için lütfen https://burkutportfoy.com/developer adresinden ücretsiz bir API anahtarı alın ve ayarlarınıza 'BURKUT_API_KEY' ortam değişkeni olarak ekleyin.");
|
|
21
|
+
}
|
|
19
22
|
const headers = {
|
|
20
23
|
'Accept': 'application/json',
|
|
21
|
-
'User-Agent': 'burkut-mcp/1.0.
|
|
24
|
+
'User-Agent': 'burkut-mcp/1.0.2',
|
|
25
|
+
'X-API-Key': this.config.apiKey.trim(),
|
|
22
26
|
};
|
|
23
|
-
|
|
24
|
-
headers['X-API-Key'] = this.config.apiKey;
|
|
25
|
-
if (usePublicV1 && !path.startsWith('/api/public/v1')) {
|
|
26
|
-
resolvedPath = `/api/public/v1${path.replace(/^\/api\/v1/, '')}`;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const url = new URL(`${this.config.baseUrl}${resolvedPath}`);
|
|
27
|
+
const url = new URL(`${this.config.baseUrl}${path}`);
|
|
30
28
|
if (query) {
|
|
31
29
|
for (const [key, value] of Object.entries(query)) {
|
|
32
30
|
if (value !== undefined && value !== null) {
|
|
@@ -55,10 +53,10 @@ export class BurkutApiClient {
|
|
|
55
53
|
throw new Error(`Enstrüman veya veri bulunamadı (404 Not Found): ${path}`);
|
|
56
54
|
}
|
|
57
55
|
if (response.status === 401 || response.status === 403) {
|
|
58
|
-
throw new Error(`Yetkilendirme hatası (${response.status}): Geçersiz veya
|
|
56
|
+
throw new Error(`Yetkilendirme hatası (${response.status}): Geçersiz veya iptal edilmiş API Key. Lütfen https://burkutportfoy.com/developer üzerinden anahtarınızı kontrol edin.`);
|
|
59
57
|
}
|
|
60
58
|
if (response.status === 429) {
|
|
61
|
-
throw new Error(
|
|
59
|
+
throw new Error(`Kotanız doldu veya dakikalık hız sınırına takıldınız (429 Rate Limit): Lütfen birkaç saniye bekleyin veya https://burkutportfoy.com/developer adresinden planınızı yükseltin.`);
|
|
62
60
|
}
|
|
63
61
|
throw new Error(`Bürküt API Hatası (HTTP ${response.status}): ${errorDetail || response.statusText}`);
|
|
64
62
|
}
|
|
@@ -76,75 +74,41 @@ export class BurkutApiClient {
|
|
|
76
74
|
}
|
|
77
75
|
// --- Funds (TEFAS) ---
|
|
78
76
|
async getFunds() {
|
|
79
|
-
|
|
80
|
-
return this.request('/funds', { usePublicV1: true });
|
|
81
|
-
}
|
|
82
|
-
return this.request('/api/v1/market/funds');
|
|
77
|
+
return this.request('/funds');
|
|
83
78
|
}
|
|
84
79
|
async getFundDetail(symbol) {
|
|
85
80
|
const sym = normalizeSymbol(symbol);
|
|
86
|
-
|
|
87
|
-
return this.request(`/funds/${sym}`, { usePublicV1: true });
|
|
88
|
-
}
|
|
89
|
-
return this.request(`/api/v1/market/funds/${sym}`);
|
|
81
|
+
return this.request(`/funds/${sym}`);
|
|
90
82
|
}
|
|
91
83
|
// --- Stocks (BIST) ---
|
|
92
84
|
async getStocks(symbols) {
|
|
93
85
|
const query = symbols && symbols.length > 0 ? { symbols: symbols.map(normalizeSymbol).join(',') } : undefined;
|
|
94
|
-
|
|
95
|
-
return this.request('/stocks', { query, usePublicV1: true });
|
|
96
|
-
}
|
|
97
|
-
return this.request('/api/v1/market/stocks', { query });
|
|
86
|
+
return this.request('/stocks', { query });
|
|
98
87
|
}
|
|
99
88
|
async getStockQuote(symbol) {
|
|
100
89
|
const sym = normalizeSymbol(symbol);
|
|
101
|
-
|
|
102
|
-
return this.request(`/stocks/${sym}`, { usePublicV1: true });
|
|
103
|
-
}
|
|
104
|
-
return this.request(`/api/v1/market/stocks/${sym}`);
|
|
105
|
-
}
|
|
106
|
-
// --- KAP Announcements ---
|
|
107
|
-
async getKapAnnouncements(symbol, page = 1, size = 20) {
|
|
108
|
-
const sym = symbol ? normalizeSymbol(symbol) : undefined;
|
|
109
|
-
if (sym) {
|
|
110
|
-
return this.request(`/api/v1/kap/${sym}`, { query: { page, size } });
|
|
111
|
-
}
|
|
112
|
-
return this.request('/api/v1/kap', { query: { page, size } });
|
|
90
|
+
return this.request(`/stocks/${sym}`);
|
|
113
91
|
}
|
|
114
|
-
|
|
115
|
-
|
|
92
|
+
// --- Forex ---
|
|
93
|
+
async getForex() {
|
|
94
|
+
return this.request('/forex');
|
|
116
95
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (activeOnly) {
|
|
120
|
-
return this.request('/api/v1/ipo/active');
|
|
121
|
-
}
|
|
122
|
-
return this.request('/api/v1/ipo');
|
|
96
|
+
async getForexDetail(symbol) {
|
|
97
|
+
return this.request(`/forex/${normalizeSymbol(symbol)}`);
|
|
123
98
|
}
|
|
124
|
-
|
|
125
|
-
|
|
99
|
+
// --- Gold ---
|
|
100
|
+
async getGold() {
|
|
101
|
+
return this.request('/gold');
|
|
126
102
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (symbol) {
|
|
130
|
-
return this.request(`/api/v1/dividends/${normalizeSymbol(symbol)}`);
|
|
131
|
-
}
|
|
132
|
-
return this.request('/api/v1/dividends');
|
|
103
|
+
async getGoldDetail(symbol) {
|
|
104
|
+
return this.request(`/gold/${normalizeSymbol(symbol)}`);
|
|
133
105
|
}
|
|
134
|
-
// ---
|
|
135
|
-
async
|
|
136
|
-
return this.request('/
|
|
106
|
+
// --- Bonds ---
|
|
107
|
+
async getBonds() {
|
|
108
|
+
return this.request('/bonds');
|
|
137
109
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
return this.request('/api/v1/market/forex');
|
|
143
|
-
}
|
|
144
|
-
async getGold() {
|
|
145
|
-
if (this.config.apiKey) {
|
|
146
|
-
return this.request('/gold', { usePublicV1: true });
|
|
147
|
-
}
|
|
148
|
-
return this.request('/api/v1/market/gold');
|
|
110
|
+
// --- VIOP ---
|
|
111
|
+
async getViop() {
|
|
112
|
+
return this.request('/viop');
|
|
149
113
|
}
|
|
150
114
|
}
|
package/dist/config.js
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
+
function getCliArg(flag) {
|
|
2
|
+
if (typeof process === 'undefined' || !Array.isArray(process.argv))
|
|
3
|
+
return undefined;
|
|
4
|
+
const args = process.argv.slice(2);
|
|
5
|
+
for (let i = 0; i < args.length; i++) {
|
|
6
|
+
if (args[i] === flag && i + 1 < args.length) {
|
|
7
|
+
return args[i + 1];
|
|
8
|
+
}
|
|
9
|
+
if (args[i].startsWith(`${flag}=`)) {
|
|
10
|
+
return args[i].slice(flag.length + 1);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
1
15
|
export function getConfig() {
|
|
2
|
-
const envBaseUrl = process.env.BURKUT_API_BASE_URL;
|
|
3
|
-
//
|
|
4
|
-
const baseUrl = (envBaseUrl || 'https://api.burkutportfoy.com').replace(/\/+$/, '');
|
|
5
|
-
const apiKey = process.env.BURKUT_API_KEY || undefined;
|
|
6
|
-
const timeoutMs = parseInt(process.env.BURKUT_TIMEOUT_MS || '15000', 10);
|
|
16
|
+
const envBaseUrl = process.env.BURKUT_API_BASE_URL || getCliArg('--base-url');
|
|
17
|
+
// Varsayılan olarak doğrudan geliştirici veri borusuna (/api/public/v1) bağlanır
|
|
18
|
+
const baseUrl = (envBaseUrl || 'https://api.burkutportfoy.com/api/public/v1').replace(/\/+$/, '');
|
|
19
|
+
const apiKey = (process.env.BURKUT_API_KEY || getCliArg('--api-key') || getCliArg('-k') || '').trim() || undefined;
|
|
20
|
+
const timeoutMs = parseInt(process.env.BURKUT_TIMEOUT_MS || getCliArg('--timeout') || '15000', 10);
|
|
7
21
|
return {
|
|
8
22
|
baseUrl,
|
|
9
23
|
apiKey,
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ListPromptsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { BurkutApiClient } from './client.js';
|
|
6
6
|
import { TOOLS } from './tools.js';
|
|
7
7
|
import { getConfig } from './config.js';
|
|
@@ -10,10 +10,12 @@ async function main() {
|
|
|
10
10
|
const client = new BurkutApiClient(config);
|
|
11
11
|
const server = new Server({
|
|
12
12
|
name: 'burkut-mcp',
|
|
13
|
-
version: '1.0.
|
|
13
|
+
version: '1.0.2',
|
|
14
14
|
}, {
|
|
15
15
|
capabilities: {
|
|
16
16
|
tools: {},
|
|
17
|
+
resources: {},
|
|
18
|
+
prompts: {},
|
|
17
19
|
},
|
|
18
20
|
});
|
|
19
21
|
// Register tools list
|
|
@@ -26,6 +28,9 @@ async function main() {
|
|
|
26
28
|
})),
|
|
27
29
|
};
|
|
28
30
|
});
|
|
31
|
+
// Clean empty handlers for optional protocol capabilities
|
|
32
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: [] }));
|
|
33
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => ({ prompts: [] }));
|
|
29
34
|
// Handle tool calls
|
|
30
35
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
31
36
|
const { name, arguments: args } = request.params;
|
|
@@ -72,7 +77,7 @@ async function main() {
|
|
|
72
77
|
console.error(`[burkut-mcp] API Key configured: ${config.apiKey.slice(0, 6)}...`);
|
|
73
78
|
}
|
|
74
79
|
else {
|
|
75
|
-
console.error(`[burkut-mcp]
|
|
80
|
+
console.error(`[burkut-mcp] WARNING: No BURKUT_API_KEY configured. Tool calls will require an API key from https://burkutportfoy.com/developer`);
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
main().catch((err) => {
|
package/dist/tools.js
CHANGED
|
@@ -1,41 +1,49 @@
|
|
|
1
|
+
function unwrap(res) {
|
|
2
|
+
if (res && typeof res === 'object' && 'data' in res) {
|
|
3
|
+
return res.data;
|
|
4
|
+
}
|
|
5
|
+
return res;
|
|
6
|
+
}
|
|
1
7
|
export const TOOLS = [
|
|
2
8
|
{
|
|
3
9
|
name: 'burkut_search_funds',
|
|
4
|
-
description: '
|
|
10
|
+
description: 'TEFAS yatırım fonlarını ara, filtrele ve getirilerine (1 ay, 3 ay, 6 ay, 1 yıl) göre sırala.',
|
|
5
11
|
inputSchema: {
|
|
6
12
|
type: 'object',
|
|
7
13
|
properties: {
|
|
8
14
|
query: {
|
|
9
15
|
type: 'string',
|
|
10
|
-
description: '
|
|
16
|
+
description: 'Fon kodu (örn: "TI2", "MAC") veya isim anahtar kelimesi (örn: "Hisse", "Teknoloji", "Gümüş", "Eurobond").',
|
|
11
17
|
},
|
|
12
18
|
fundType: {
|
|
13
19
|
type: 'string',
|
|
14
|
-
description: '
|
|
20
|
+
description: 'Fon türü filtresi (örn: "Hisse Senedi Fonu", "Para Piyasası Fonu", "Değişken Fon", "Kıymetli Madenler Fonu").',
|
|
15
21
|
},
|
|
16
22
|
sortBy: {
|
|
17
23
|
type: 'string',
|
|
18
24
|
enum: ['yield1y', 'yield6m', 'yield3m', 'yield1m', 'dailyChangePct'],
|
|
19
|
-
description: '
|
|
25
|
+
description: 'Sıralama ölçütü (büyükten küçüğe). Varsayılan: "yield1y".',
|
|
20
26
|
},
|
|
21
27
|
limit: {
|
|
22
28
|
type: 'number',
|
|
23
|
-
description: '
|
|
29
|
+
description: 'Döndürülecek maksimum fon sayısı (varsayılan: 15, maksimum: 50).',
|
|
24
30
|
},
|
|
25
31
|
},
|
|
26
32
|
},
|
|
27
33
|
handler: async (client, args) => {
|
|
28
34
|
const raw = await client.getFunds();
|
|
29
35
|
let list = [];
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
const payload = unwrap(raw);
|
|
37
|
+
if (Array.isArray(payload)) {
|
|
38
|
+
list = payload;
|
|
32
39
|
}
|
|
33
|
-
else if (
|
|
34
|
-
list =
|
|
40
|
+
else if (payload && Array.isArray(payload.items)) {
|
|
41
|
+
list = payload.items;
|
|
35
42
|
}
|
|
36
43
|
if (args.query) {
|
|
37
44
|
const q = String(args.query).toLowerCase().trim();
|
|
38
45
|
list = list.filter((f) => (f.symbol && f.symbol.toLowerCase().includes(q)) ||
|
|
46
|
+
(f.code && f.code.toLowerCase().includes(q)) ||
|
|
39
47
|
(f.name && f.name.toLowerCase().includes(q)) ||
|
|
40
48
|
(f.fundType && f.fundType.toLowerCase().includes(q)));
|
|
41
49
|
}
|
|
@@ -51,11 +59,11 @@ export const TOOLS = [
|
|
|
51
59
|
});
|
|
52
60
|
const limit = Math.min(Math.max(Number(args.limit) || 15, 1), 50);
|
|
53
61
|
const results = list.slice(0, limit).map((f) => ({
|
|
54
|
-
kod: f.symbol,
|
|
62
|
+
kod: f.symbol || f.code,
|
|
55
63
|
isim: f.name,
|
|
56
64
|
tur: f.fundType || f.type,
|
|
57
|
-
fiyat: f.currentPrice,
|
|
58
|
-
gunlukDegisimPct: f.dailyChangePct,
|
|
65
|
+
fiyat: f.currentPrice ?? f.price,
|
|
66
|
+
gunlukDegisimPct: f.dailyChangePct ?? f.dailyChangePercent,
|
|
59
67
|
getiri1Ay: f.yield1m != null ? `%${f.yield1m}` : 'N/A',
|
|
60
68
|
getiri3Ay: f.yield3m != null ? `%${f.yield3m}` : 'N/A',
|
|
61
69
|
getiri6Ay: f.yield6m != null ? `%${f.yield6m}` : 'N/A',
|
|
@@ -71,137 +79,124 @@ export const TOOLS = [
|
|
|
71
79
|
},
|
|
72
80
|
{
|
|
73
81
|
name: 'burkut_get_fund_detail',
|
|
74
|
-
description: '
|
|
82
|
+
description: 'Belirli bir TEFAS fonunun (örn: MAC, TI2, TCD) çoklu periyot getirilerini, risk seviyesini ve detaylı künyesini getirir.',
|
|
75
83
|
inputSchema: {
|
|
76
84
|
type: 'object',
|
|
77
85
|
properties: {
|
|
78
86
|
symbol: {
|
|
79
87
|
type: 'string',
|
|
80
|
-
description: '
|
|
88
|
+
description: 'TEFAS fon kodu (örn: "MAC", "TI2", "TCD", "AFT").',
|
|
81
89
|
},
|
|
82
90
|
},
|
|
83
91
|
required: ['symbol'],
|
|
84
92
|
},
|
|
85
93
|
handler: async (client, args) => {
|
|
86
94
|
const fund = await client.getFundDetail(args.symbol);
|
|
87
|
-
return JSON.stringify(fund, null, 2);
|
|
95
|
+
return JSON.stringify(unwrap(fund), null, 2);
|
|
88
96
|
},
|
|
89
97
|
},
|
|
90
98
|
{
|
|
91
99
|
name: 'burkut_get_stock_quote',
|
|
92
|
-
description: '
|
|
100
|
+
description: 'Borsa İstanbul (BIST) hisse senedinin 15 dk gecikmeli resmi fiyatını, günlük değişim oranını ve hacmini getirir.',
|
|
93
101
|
inputSchema: {
|
|
94
102
|
type: 'object',
|
|
95
103
|
properties: {
|
|
96
104
|
symbol: {
|
|
97
105
|
type: 'string',
|
|
98
|
-
description: '
|
|
106
|
+
description: 'Hisse sembolü (örn: "THYAO", "ASELS", "KCHOL", "GARAN").',
|
|
99
107
|
},
|
|
100
108
|
},
|
|
101
109
|
required: ['symbol'],
|
|
102
110
|
},
|
|
103
111
|
handler: async (client, args) => {
|
|
104
112
|
const quote = await client.getStockQuote(args.symbol);
|
|
105
|
-
return JSON.stringify(quote, null, 2);
|
|
113
|
+
return JSON.stringify(unwrap(quote), null, 2);
|
|
106
114
|
},
|
|
107
115
|
},
|
|
108
116
|
{
|
|
109
|
-
name: '
|
|
110
|
-
description: '
|
|
117
|
+
name: 'burkut_list_stocks',
|
|
118
|
+
description: 'Borsa İstanbul (BIST) hisselerini listeler veya virgülle ayrılmış sembol listesinin verilerini toplu çeker.',
|
|
111
119
|
inputSchema: {
|
|
112
120
|
type: 'object',
|
|
113
121
|
properties: {
|
|
114
|
-
|
|
122
|
+
symbols: {
|
|
115
123
|
type: 'string',
|
|
116
|
-
description: '
|
|
117
|
-
},
|
|
118
|
-
limit: {
|
|
119
|
-
type: 'number',
|
|
120
|
-
description: 'Number of notifications to retrieve (default: 10, max: 30).',
|
|
124
|
+
description: 'Virgülle ayrılmış hisse sembolleri (örn: "THYAO,ASELS,EREGL"). Belirtilmezse popüler hisseleri döner.',
|
|
121
125
|
},
|
|
122
126
|
},
|
|
123
127
|
},
|
|
124
128
|
handler: async (client, args) => {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
const symList = args.symbols
|
|
130
|
+
? String(args.symbols).split(',').map((s) => s.trim()).filter(Boolean)
|
|
131
|
+
: undefined;
|
|
132
|
+
const stocks = await client.getStocks(symList);
|
|
133
|
+
return JSON.stringify(unwrap(stocks), null, 2);
|
|
128
134
|
},
|
|
129
135
|
},
|
|
130
136
|
{
|
|
131
|
-
name: '
|
|
132
|
-
description: '
|
|
137
|
+
name: 'burkut_get_forex',
|
|
138
|
+
description: 'Serbest piyasa ve TCMB döviz kurlarını (USD/TRY, EUR/TRY, GBP/TRY vb.) getirir.',
|
|
133
139
|
inputSchema: {
|
|
134
140
|
type: 'object',
|
|
135
141
|
properties: {
|
|
136
|
-
|
|
137
|
-
type: '
|
|
138
|
-
description: '
|
|
142
|
+
symbol: {
|
|
143
|
+
type: 'string',
|
|
144
|
+
description: 'Belirli bir para birimi kodu (örn: "USD", "EUR"). Belirtilmezse tüm döviz kurlarını döner.',
|
|
139
145
|
},
|
|
140
146
|
},
|
|
141
147
|
},
|
|
142
148
|
handler: async (client, args) => {
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
if (args.symbol) {
|
|
150
|
+
const item = await client.getForexDetail(args.symbol);
|
|
151
|
+
return JSON.stringify(unwrap(item), null, 2);
|
|
152
|
+
}
|
|
153
|
+
const data = await client.getForex();
|
|
154
|
+
return JSON.stringify(unwrap(data), null, 2);
|
|
145
155
|
},
|
|
146
156
|
},
|
|
147
157
|
{
|
|
148
|
-
name: '
|
|
149
|
-
description: '
|
|
158
|
+
name: 'burkut_get_gold',
|
|
159
|
+
description: 'Gram Altın, Çeyrek Altın, Yarım Altın, Tam Altın ve Ons fiyatlarını getirir.',
|
|
150
160
|
inputSchema: {
|
|
151
161
|
type: 'object',
|
|
152
162
|
properties: {
|
|
153
163
|
symbol: {
|
|
154
164
|
type: 'string',
|
|
155
|
-
description: '
|
|
165
|
+
description: 'Belirli bir altın türü (örn: "ALTIN", "CEYREK_ALTIN"). Belirtilmezse tüm değerli madenleri döner.',
|
|
156
166
|
},
|
|
157
167
|
},
|
|
158
168
|
},
|
|
159
169
|
handler: async (client, args) => {
|
|
160
|
-
|
|
161
|
-
|
|
170
|
+
if (args.symbol) {
|
|
171
|
+
const item = await client.getGoldDetail(args.symbol);
|
|
172
|
+
return JSON.stringify(unwrap(item), null, 2);
|
|
173
|
+
}
|
|
174
|
+
const data = await client.getGold();
|
|
175
|
+
return JSON.stringify(unwrap(data), null, 2);
|
|
162
176
|
},
|
|
163
177
|
},
|
|
164
178
|
{
|
|
165
|
-
name: '
|
|
166
|
-
description: '
|
|
179
|
+
name: 'burkut_get_bonds',
|
|
180
|
+
description: 'Devlet tahvilleri ve hazine bonoları faiz getirilerini listeler.',
|
|
167
181
|
inputSchema: {
|
|
168
182
|
type: 'object',
|
|
169
|
-
properties: {
|
|
170
|
-
category: {
|
|
171
|
-
type: 'string',
|
|
172
|
-
enum: ['all', 'inflation', 'forex', 'gold'],
|
|
173
|
-
description: 'Category to fetch: "inflation" for CPI/PPI, "forex" for FX rates, "gold" for precious metals, or "all" (default).',
|
|
174
|
-
},
|
|
175
|
-
},
|
|
183
|
+
properties: {},
|
|
176
184
|
},
|
|
177
|
-
handler: async (client
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
catch (e) {
|
|
193
|
-
results.forex = { error: e.message };
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
if (category === 'all' || category === 'gold') {
|
|
197
|
-
try {
|
|
198
|
-
results.gold = await client.getGold();
|
|
199
|
-
}
|
|
200
|
-
catch (e) {
|
|
201
|
-
results.gold = { error: e.message };
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return JSON.stringify(results, null, 2);
|
|
185
|
+
handler: async (client) => {
|
|
186
|
+
const data = await client.getBonds();
|
|
187
|
+
return JSON.stringify(unwrap(data), null, 2);
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: 'burkut_get_viop',
|
|
192
|
+
description: 'VİOP (Vadeli İşlem ve Opsiyon Piyasası) kontratlarını ve güncel uzlaşma fiyatlarını listeler.',
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {},
|
|
196
|
+
},
|
|
197
|
+
handler: async (client) => {
|
|
198
|
+
const data = await client.getViop();
|
|
199
|
+
return JSON.stringify(unwrap(data), null, 2);
|
|
205
200
|
},
|
|
206
201
|
},
|
|
207
202
|
];
|
package/package.json
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "burkut-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for Turkish Financial Markets (BIST, TEFAS, KAP, IPOs, Macro) powered by Bürküt API.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
-
"bin":
|
|
8
|
-
"burkut-mcp": "./dist/index.js"
|
|
9
|
-
},
|
|
7
|
+
"bin": "./dist/index.js",
|
|
10
8
|
"files": [
|
|
11
9
|
"dist"
|
|
12
10
|
],
|