daepak-mcp 2.0.1__tar.gz
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.
- daepak_mcp-2.0.1/.gitignore +53 -0
- daepak_mcp-2.0.1/PKG-INFO +90 -0
- daepak_mcp-2.0.1/README.md +77 -0
- daepak_mcp-2.0.1/daepak_agent_mcp.py +148 -0
- daepak_mcp-2.0.1/pyproject.toml +40 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# --- секреты и личное ---
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
CLAUDE.local.md
|
|
6
|
+
|
|
7
|
+
# --- данные (бинарники не в git) ---
|
|
8
|
+
*.db
|
|
9
|
+
*.sqlite
|
|
10
|
+
*.sqlite3
|
|
11
|
+
data/
|
|
12
|
+
*.log
|
|
13
|
+
|
|
14
|
+
# --- Python ---
|
|
15
|
+
__pycache__/
|
|
16
|
+
*.py[cod]
|
|
17
|
+
.venv/
|
|
18
|
+
venv/
|
|
19
|
+
.python-version
|
|
20
|
+
*.egg-info/
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.ruff_cache/
|
|
23
|
+
.mypy_cache/
|
|
24
|
+
|
|
25
|
+
# --- OS / IDE ---
|
|
26
|
+
.DS_Store
|
|
27
|
+
.idea/
|
|
28
|
+
.vscode/
|
|
29
|
+
|
|
30
|
+
# playwright артефакты
|
|
31
|
+
.playwright-mcp/
|
|
32
|
+
|
|
33
|
+
# context-portal (conport) — локальная БД/логи машинной памяти, не в git
|
|
34
|
+
context_portal/
|
|
35
|
+
|
|
36
|
+
# graphify — граф зависимостей кода (машинный слой навигации, как индекс Serena);
|
|
37
|
+
# генерируется локально из кода (graphify update .), не в git
|
|
38
|
+
graphify-out/
|
|
39
|
+
|
|
40
|
+
# приватный ключ обратного туннеля
|
|
41
|
+
deploy/tunnel/
|
|
42
|
+
backups/
|
|
43
|
+
"Пустой 29.docx"
|
|
44
|
+
docs/naver-review/*.pdf
|
|
45
|
+
docs/deck/*.pdf
|
|
46
|
+
docs/deck/shots/
|
|
47
|
+
docs/deck/gen/
|
|
48
|
+
src/crypto_radar/_recent_commits.txt
|
|
49
|
+
|
|
50
|
+
# Beads / Dolt files (added by bd init)
|
|
51
|
+
.dolt/
|
|
52
|
+
.beads-credential-key
|
|
53
|
+
.beads/proxieddb/
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: daepak-mcp
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: Daepak market intelligence tools over MCP
|
|
5
|
+
Project-URL: Homepage, https://daepak.com
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: crypto,korea,market-data,mcp,trading
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: certifi>=2024.2.2
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Daepak MCP
|
|
15
|
+
|
|
16
|
+
Инструменты рыночной аналитики Daepak в любом движке с поддержкой MCP.
|
|
17
|
+
|
|
18
|
+
## Подключение
|
|
19
|
+
|
|
20
|
+
После публикации пакета:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
claude mcp add daepak -e DAEPAK_API_KEY=dpk_live_… -- uvx daepak-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Из репозитория, без установки:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
claude mcp add daepak -e DAEPAK_API_KEY=dpk_live_… -- python3 /path/to/mcp/daepak_agent_mcp.py
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Ключ заводится на странице **«Ключи»** в профиле. Зависимостей у сервера нет — только
|
|
33
|
+
стандартная библиотека Python 3.11+.
|
|
34
|
+
|
|
35
|
+
| переменная | по умолчанию | зачем |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `DAEPAK_API_KEY` | — | ключ `dpk_live_…`, обязателен |
|
|
38
|
+
| `DAEPAK_BASE_URL` | `https://daepak.com` | другой контур (стейдж) |
|
|
39
|
+
| `DAEPAK_TIMEOUT` | `120` | секунд на вызов |
|
|
40
|
+
|
|
41
|
+
## Что видит движок
|
|
42
|
+
|
|
43
|
+
Каталог приходит **отфильтрованным по правам ключа**: движок видит только то, что
|
|
44
|
+
действительно может вызвать, а не список с отказами. У каждого инструмента в описании
|
|
45
|
+
указана цена в кредитах — бюджет считается до вызова, а не по факту.
|
|
46
|
+
|
|
47
|
+
⚠️ **Владелец определяется ключом.** Назвать чужого пользователя в запросе нельзя.
|
|
48
|
+
До 30.08.2026 это было можно — и именно поэтому прежний мост не годился как публичный API.
|
|
49
|
+
|
|
50
|
+
## Права
|
|
51
|
+
|
|
52
|
+
| скоуп | что открывает |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `read:market` | цены, свечи, индикаторы, скор, уровни, нарративы, деривативы |
|
|
55
|
+
| `read:korea` | кимчи-премия, листинги Upbit, корейские бумаги |
|
|
56
|
+
| `read:us` | акции США, премаркет, гэп-статистика, опционы |
|
|
57
|
+
| `read:personal` | свои позиции, портфель, журнал, память |
|
|
58
|
+
| `write:personal` | запись в них же |
|
|
59
|
+
| `agent:chat` | ответы агента целиком |
|
|
60
|
+
|
|
61
|
+
Право читать не даёт права писать: это отдельный скоуп.
|
|
62
|
+
|
|
63
|
+
## Цены
|
|
64
|
+
|
|
65
|
+
| разряд | что | кредитов |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| своя база | цена, индикаторы, скор, уровни, свечи | 1 |
|
|
68
|
+
| внешний вызов | акции, токены, опционы, он-чейн | 5 |
|
|
69
|
+
| эмбеддинг и песочница | поиск новостей, исполнение кода | 20 |
|
|
70
|
+
|
|
71
|
+
Месячные кредиты и потолок частоты — по тарифу; текущий расход виден в `GET /v1/usage`.
|
|
72
|
+
|
|
73
|
+
## Когда кредиты кончились
|
|
74
|
+
|
|
75
|
+
Приходит `402` с двумя выходами: перейти на тариф выше (в ответе указан следующий и
|
|
76
|
+
сколько кредитов он даёт) или дождаться обновления в начале месяца.
|
|
77
|
+
|
|
78
|
+
⚠️ Счёта за перерасход **нет**: обслуживать в долг значит прислать счёт, которого никто
|
|
79
|
+
не ждал. Но и отказ без выхода читался бы как поломка, поэтому ответ всегда называет,
|
|
80
|
+
что делать.
|
|
81
|
+
|
|
82
|
+
## Публикация (для владельца)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
cd mcp && python -m build && python -m twine upload dist/*
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
⚠️ `certifi` в зависимостях вынужденно: на чистом venv без него КАЖДЫЙ вызов падает с
|
|
89
|
+
`CERTIFICATE_VERIFY_FAILED` — сборки Python для macOS не читают системное хранилище
|
|
90
|
+
сертификатов. Проверено установкой собранного пакета в пустое окружение.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Daepak MCP
|
|
2
|
+
|
|
3
|
+
Инструменты рыночной аналитики Daepak в любом движке с поддержкой MCP.
|
|
4
|
+
|
|
5
|
+
## Подключение
|
|
6
|
+
|
|
7
|
+
После публикации пакета:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
claude mcp add daepak -e DAEPAK_API_KEY=dpk_live_… -- uvx daepak-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Из репозитория, без установки:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
claude mcp add daepak -e DAEPAK_API_KEY=dpk_live_… -- python3 /path/to/mcp/daepak_agent_mcp.py
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Ключ заводится на странице **«Ключи»** в профиле. Зависимостей у сервера нет — только
|
|
20
|
+
стандартная библиотека Python 3.11+.
|
|
21
|
+
|
|
22
|
+
| переменная | по умолчанию | зачем |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| `DAEPAK_API_KEY` | — | ключ `dpk_live_…`, обязателен |
|
|
25
|
+
| `DAEPAK_BASE_URL` | `https://daepak.com` | другой контур (стейдж) |
|
|
26
|
+
| `DAEPAK_TIMEOUT` | `120` | секунд на вызов |
|
|
27
|
+
|
|
28
|
+
## Что видит движок
|
|
29
|
+
|
|
30
|
+
Каталог приходит **отфильтрованным по правам ключа**: движок видит только то, что
|
|
31
|
+
действительно может вызвать, а не список с отказами. У каждого инструмента в описании
|
|
32
|
+
указана цена в кредитах — бюджет считается до вызова, а не по факту.
|
|
33
|
+
|
|
34
|
+
⚠️ **Владелец определяется ключом.** Назвать чужого пользователя в запросе нельзя.
|
|
35
|
+
До 30.08.2026 это было можно — и именно поэтому прежний мост не годился как публичный API.
|
|
36
|
+
|
|
37
|
+
## Права
|
|
38
|
+
|
|
39
|
+
| скоуп | что открывает |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `read:market` | цены, свечи, индикаторы, скор, уровни, нарративы, деривативы |
|
|
42
|
+
| `read:korea` | кимчи-премия, листинги Upbit, корейские бумаги |
|
|
43
|
+
| `read:us` | акции США, премаркет, гэп-статистика, опционы |
|
|
44
|
+
| `read:personal` | свои позиции, портфель, журнал, память |
|
|
45
|
+
| `write:personal` | запись в них же |
|
|
46
|
+
| `agent:chat` | ответы агента целиком |
|
|
47
|
+
|
|
48
|
+
Право читать не даёт права писать: это отдельный скоуп.
|
|
49
|
+
|
|
50
|
+
## Цены
|
|
51
|
+
|
|
52
|
+
| разряд | что | кредитов |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| своя база | цена, индикаторы, скор, уровни, свечи | 1 |
|
|
55
|
+
| внешний вызов | акции, токены, опционы, он-чейн | 5 |
|
|
56
|
+
| эмбеддинг и песочница | поиск новостей, исполнение кода | 20 |
|
|
57
|
+
|
|
58
|
+
Месячные кредиты и потолок частоты — по тарифу; текущий расход виден в `GET /v1/usage`.
|
|
59
|
+
|
|
60
|
+
## Когда кредиты кончились
|
|
61
|
+
|
|
62
|
+
Приходит `402` с двумя выходами: перейти на тариф выше (в ответе указан следующий и
|
|
63
|
+
сколько кредитов он даёт) или дождаться обновления в начале месяца.
|
|
64
|
+
|
|
65
|
+
⚠️ Счёта за перерасход **нет**: обслуживать в долг значит прислать счёт, которого никто
|
|
66
|
+
не ждал. Но и отказ без выхода читался бы как поломка, поэтому ответ всегда называет,
|
|
67
|
+
что делать.
|
|
68
|
+
|
|
69
|
+
## Публикация (для владельца)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd mcp && python -m build && python -m twine upload dist/*
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
⚠️ `certifi` в зависимостях вынужденно: на чистом venv без него КАЖДЫЙ вызов падает с
|
|
76
|
+
`CERTIFICATE_VERIFY_FAILED` — сборки Python для macOS не читают системное хранилище
|
|
77
|
+
сертификатов. Проверено установкой собранного пакета в пустое окружение.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""MCP-сервер Daepak: инструменты рыночной аналитики в любой движок с MCP.
|
|
3
|
+
|
|
4
|
+
Сервер ничего не описывает сам: тянет каталог с `GET /v1/tools`, то есть видит ровно то,
|
|
5
|
+
что разрешено ключу, и не расходится с продуктом при добавлении инструментов.
|
|
6
|
+
|
|
7
|
+
Подключение:
|
|
8
|
+
|
|
9
|
+
claude mcp add daepak \
|
|
10
|
+
-e DAEPAK_API_KEY=dpk_live_… \
|
|
11
|
+
-- python3 /path/to/mcp/daepak_agent_mcp.py
|
|
12
|
+
|
|
13
|
+
Ключ заводится на странице «Ключи» в профиле. ⚠️ Владелец определяется КЛЮЧОМ: назвать
|
|
14
|
+
чужого пользователя в запросе нельзя — до 30.08.2026 это было можно, и именно поэтому
|
|
15
|
+
мост не годился как публичный API.
|
|
16
|
+
|
|
17
|
+
Каталог приходит уже отфильтрованным по правам ключа: движок видит только то, что
|
|
18
|
+
действительно может вызвать, а не список с отказами. У каждого инструмента объявлена
|
|
19
|
+
цена в кредитах — её видно в описании, чтобы бюджет считался ДО вызова.
|
|
20
|
+
|
|
21
|
+
Протокол: MCP 2024-11-05, JSON-RPC поверх stdin/stdout. Зависимостей нет.
|
|
22
|
+
"""
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import json
|
|
26
|
+
import os
|
|
27
|
+
import ssl
|
|
28
|
+
import sys
|
|
29
|
+
import urllib.error
|
|
30
|
+
import urllib.request
|
|
31
|
+
|
|
32
|
+
BASE = os.getenv("DAEPAK_BASE_URL", "https://daepak.com").rstrip("/")
|
|
33
|
+
KEY = os.getenv("DAEPAK_API_KEY", "")
|
|
34
|
+
TIMEOUT = float(os.getenv("DAEPAK_TIMEOUT", "120"))
|
|
35
|
+
# ⚠️ DAEPAK_USER_ID больше НЕ читается. Раньше им называли владельца в теле запроса —
|
|
36
|
+
# держатель общего ключа мог указать любого и получить чужие позиции и память.
|
|
37
|
+
|
|
38
|
+
# ⚠️ certifi обязателен, а не «желателен»: сборки Python для macOS не читают системное
|
|
39
|
+
# хранилище сертификатов, и без него КАЖДЫЙ вызов падает с CERTIFICATE_VERIFY_FAILED.
|
|
40
|
+
# Откат ниже оставлен для окружений, где сертификаты в системе есть (Linux-дистрибутивы).
|
|
41
|
+
try:
|
|
42
|
+
import certifi
|
|
43
|
+
_SSL_CTX = ssl.create_default_context(cafile=certifi.where())
|
|
44
|
+
except ImportError:
|
|
45
|
+
_SSL_CTX = ssl.create_default_context()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _http(method: str, path: str, body: dict | None = None) -> dict | list:
|
|
49
|
+
req = urllib.request.Request(
|
|
50
|
+
BASE + path, method=method,
|
|
51
|
+
data=json.dumps(body, ensure_ascii=False).encode() if body is not None else None,
|
|
52
|
+
headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"})
|
|
53
|
+
try:
|
|
54
|
+
with urllib.request.urlopen(req, timeout=TIMEOUT, context=_SSL_CTX) as r:
|
|
55
|
+
return json.loads(r.read().decode())
|
|
56
|
+
except urllib.error.HTTPError as e:
|
|
57
|
+
return {"error": f"HTTP {e.code}", "detail": e.read().decode()[:500]}
|
|
58
|
+
except Exception as e: # noqa: BLE001 — сеть/таймаут: движок должен увидеть причину, а не молчание
|
|
59
|
+
return {"error": f"{type(e).__name__}: {e}"}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _to_mcp(schema: dict) -> dict | None:
|
|
63
|
+
"""OpenAI function-schema → MCP tool. Формы обе: {"function":{...}} и плоская."""
|
|
64
|
+
fn = schema.get("function") if isinstance(schema.get("function"), dict) else schema
|
|
65
|
+
name = fn.get("name")
|
|
66
|
+
if not name:
|
|
67
|
+
return None
|
|
68
|
+
params = fn.get("parameters") or {"type": "object", "properties": {}}
|
|
69
|
+
desc = (fn.get("description") or "")[:1000]
|
|
70
|
+
price = schema.get("credits") or fn.get("credits")
|
|
71
|
+
if price: # цена рядом с описанием: бюджет считается ДО вызова
|
|
72
|
+
desc = f"{desc}\n[стоимость: {price} кредит(ов)]"
|
|
73
|
+
return {"name": name, "description": desc[:1024], "inputSchema": params}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
_tools_cache: list[dict] | None = None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def tools() -> list[dict]:
|
|
80
|
+
"""Схемы с моста. Кэшируем: список не меняется в пределах запуска сервера."""
|
|
81
|
+
global _tools_cache
|
|
82
|
+
if _tools_cache is None:
|
|
83
|
+
got = _http("GET", "/v1/tools")
|
|
84
|
+
raw = got.get("tools") if isinstance(got, dict) else None
|
|
85
|
+
if not raw:
|
|
86
|
+
# мост недоступен — отдаём пустой список; движок сообщит, что тулзов нет,
|
|
87
|
+
# вместо того чтобы падать на каждом вызове
|
|
88
|
+
err = got.get("error") if isinstance(got, dict) else "нет ответа"
|
|
89
|
+
print(f"[daepak-mcp] каталог недоступен: {err}", file=sys.stderr, flush=True)
|
|
90
|
+
return []
|
|
91
|
+
_tools_cache = [t for t in (_to_mcp(s) for s in raw) if t]
|
|
92
|
+
print(f"[daepak-mcp] инструментов доступно ключу: {len(_tools_cache)} · {BASE}",
|
|
93
|
+
file=sys.stderr, flush=True)
|
|
94
|
+
return _tools_cache
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def call_tool(name: str, args: dict) -> dict | list:
|
|
98
|
+
"""Вызов инструмента. Владелец берётся из ключа — в теле его нет и быть не может."""
|
|
99
|
+
out = _http("POST", f"/v1/tools/{name}", args or {})
|
|
100
|
+
# /v1 заворачивает результат вместе с расходом; движку нужны данные, а не обёртка,
|
|
101
|
+
# но цену и время оставляем рядом — по ним видно, во что обошёлся шаг
|
|
102
|
+
if isinstance(out, dict) and "data" in out:
|
|
103
|
+
data = out["data"]
|
|
104
|
+
if isinstance(data, dict):
|
|
105
|
+
return {**data, "_credits": out.get("credits_used"), "_ms": out.get("took_ms")}
|
|
106
|
+
return data
|
|
107
|
+
return out
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def main() -> None:
|
|
111
|
+
for line in sys.stdin:
|
|
112
|
+
line = line.strip()
|
|
113
|
+
if not line:
|
|
114
|
+
continue
|
|
115
|
+
try:
|
|
116
|
+
msg = json.loads(line)
|
|
117
|
+
except json.JSONDecodeError:
|
|
118
|
+
continue
|
|
119
|
+
mid = msg.get("id")
|
|
120
|
+
method = msg.get("method", "")
|
|
121
|
+
if method == "initialize":
|
|
122
|
+
resp = {"protocolVersion": "2024-11-05",
|
|
123
|
+
"capabilities": {"tools": {}},
|
|
124
|
+
"serverInfo": {"name": "daepak-agent", "version": "2.0.0"}}
|
|
125
|
+
elif method == "tools/list":
|
|
126
|
+
resp = {"tools": tools()}
|
|
127
|
+
elif method == "tools/call":
|
|
128
|
+
p = msg.get("params") or {}
|
|
129
|
+
out = call_tool(p.get("name", ""), p.get("arguments") or {})
|
|
130
|
+
resp = {"content": [{"type": "text", "text": json.dumps(out, ensure_ascii=False)}],
|
|
131
|
+
"isError": bool(isinstance(out, dict) and out.get("error"))}
|
|
132
|
+
elif method in ("notifications/initialized", "notifications/cancelled"):
|
|
133
|
+
continue # уведомления — без ответа
|
|
134
|
+
elif mid is None:
|
|
135
|
+
continue
|
|
136
|
+
else:
|
|
137
|
+
sys.stdout.write(json.dumps(
|
|
138
|
+
{"jsonrpc": "2.0", "id": mid,
|
|
139
|
+
"error": {"code": -32601, "message": f"method not found: {method}"}}) + "\n")
|
|
140
|
+
sys.stdout.flush()
|
|
141
|
+
continue
|
|
142
|
+
sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": mid, "result": resp},
|
|
143
|
+
ensure_ascii=False) + "\n")
|
|
144
|
+
sys.stdout.flush()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Упаковка MCP-сервера. Публикация — одна команда владельца:
|
|
2
|
+
# cd mcp && python -m build && python -m twine upload dist/*
|
|
3
|
+
# После этого подключение к любому движку становится:
|
|
4
|
+
# claude mcp add daepak -e DAEPAK_API_KEY=dpk_live_… -- uvx daepak-mcp
|
|
5
|
+
#
|
|
6
|
+
# ⚠️ Единственная зависимость — certifi, и она вынужденная. Сервер писался «без
|
|
7
|
+
# зависимостей», но проверка на чистом venv показала: без certifi вызов падает с
|
|
8
|
+
# CERTIFICATE_VERIFY_FAILED (сборки Python для macOS не используют системное хранилище
|
|
9
|
+
# сертификатов). У меня это не воспроизводилось, потому что certifi стоял в окружении
|
|
10
|
+
# проекта. Красивый принцип «ноль зависимостей» здесь означал бы сломанную установку у
|
|
11
|
+
# целой платформы.
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["hatchling"]
|
|
14
|
+
build-backend = "hatchling.build"
|
|
15
|
+
|
|
16
|
+
[project]
|
|
17
|
+
name = "daepak-mcp"
|
|
18
|
+
version = "2.0.1"
|
|
19
|
+
description = "Daepak market intelligence tools over MCP"
|
|
20
|
+
readme = "README.md"
|
|
21
|
+
requires-python = ">=3.10"
|
|
22
|
+
license = { text = "MIT" }
|
|
23
|
+
keywords = ["mcp", "market-data", "crypto", "korea", "trading"]
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
27
|
+
]
|
|
28
|
+
dependencies = ["certifi>=2024.2.2"]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://daepak.com"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
daepak-mcp = "daepak_agent_mcp:main"
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.wheel]
|
|
37
|
+
include = ["daepak_agent_mcp.py"]
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.sdist]
|
|
40
|
+
include = ["daepak_agent_mcp.py", "README.md", "pyproject.toml"]
|