tokenbill-mcp 1.0.0 → 1.1.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 CHANGED
@@ -1,114 +1,131 @@
1
- # Tokenbill (토큰빌) — AI API 비용 대시보드
2
-
3
- OpenAI·Anthropic API 사용 비용과 토큰을 한 화면에서 추적하는 서비스.
4
- FastAPI + SQLite + 바닐라 JS 프론트엔드(단일 HTML).
5
-
6
- ## 실행 방법
7
-
8
- ```bash
9
- pip install -r requirements.txt
10
- cp .env.example .env # SECRET_KEY를 긴 랜덤 문자열로 변경
11
- export $(cat .env | xargs) # 또는 환경변수로 직접 설정
12
- uvicorn app.main:app --reload
13
- ```
14
-
15
- http://localhost:8000 접속 → 회원가입 → 프로바이더 키 등록.
16
-
17
- - **체험(데모)**: 키에 `demo` 로 시작하는 아무 값이나 넣으면 가짜 사용 데이터가 생성됩니다.
18
- - **실제 연동**: OpenAI는 조직 **Admin 키**(`sk-admin-…`, platform.openai.com → Organization → Admin Keys),
19
- Anthropic도 **Admin 키**(`sk-ant-admin-…`, console.anthropic.com → Settings → Admin Keys)가 필요합니다.
20
- 일반 API 키로는 사용량 조회가 안 됩니다.
21
- - Google AI는 Cloud Billing 연동이 필요해서 MVP에서는 미지원(데모만 가능).
22
- - **다중 조직**: 프로바이더당 키를 여러 개(조직별 이름 붙여서) 등록할 수 있고,
23
- 대시보드에서 조직별 이번 달 비용이 나뉘어 보입니다. 차트·합계는 전체 조직 합산 기준.
24
- - **프로젝트 드릴다운**: 조직 행을 클릭하면 프로젝트(OpenAI Project / Anthropic
25
- Workspace) 단위로 펼쳐지고, 프로젝트마다 모델별 비용·토큰이 표시됩니다.
26
- - **구글 로그인** (선택): `GOOGLE_CLIENT_ID` 환경변수를 설정하면 로그인 화면에
27
- "Google로 계속하기" 버튼이 나타납니다. Google Cloud Console에서 OAuth 클라이언트
28
- ID(웹)를 만들고, 승인된 JavaScript 출처에 서비스 도메인(https)을 등록해야 합니다.
29
- 도메인 없이 공인 IP로는 Google 정책상 동작하지 않습니다.
30
-
31
- API 문서: http://localhost:8000/docs (FastAPI 자동 생성)
32
-
33
- ## 구조
34
-
35
- ```
36
- app/
37
- main.py # FastAPI 앱, 라우트, 스케줄러(매일 03시 KST 자동 수집)
38
- models.py # User / ProviderKey / UsageDaily (날짜×프로바이더×모델 요약)
39
- security.py # JWT 인증, bcrypt 해시, API Fernet 암호화
40
- collector.py # 수집 오케스트레이션, 수동 갱신 쿨다운(10분)
41
- providers/
42
- collectors.py # OpenAI/Anthropic usage API 호출 + 데모 생성기
43
- prices.py # 모델별 단가표 (비용 = 토큰 × 단가 근사)
44
- static/index.html # 프론트엔드 (로그인 + 대시보드)
45
- ```
46
-
47
- ## 설계 메모
48
-
49
- - **저장 최소화**: 원본 로그는 프로바이더에 두고, "날짜 × 프로바이더 × 모델 × 비용/토큰"
50
- 요약 행만 보관. 사용자당 하루 수십 행 수준.
51
- - **갱신 정책**: 매일 1회 자동(APScheduler) + "지금 갱신" 수동(10분 쿨다운).
52
- 프로바이더 과금 데이터 자체가 지연 반영이라 실시간성은 목표가 아님.
53
- - **비용 계산**: 금액은 프로바이더 **cost API 실측값** 기준.
54
- usage API(토큰·모델별)로 분해를 만들고, 모델별 근사 비용을 cost API의 일 총액에 맞게
55
- 비례 보정한다 합계는 항상 실제 청구 금액과 일치. cost API 호출이 실패하면
56
- `prices.py` 단가표 근사값으로 폴백. 단가표는 "싼 모델 절약 시뮬레이션" 등에 계속 사용
57
- (자동 수집으로 대체 예정 LiteLLM의 model_prices JSON 참고).
58
- - **키 보안**: API 키는 SECRET_KEY에서 유도한 Fernet 키로 암호화 저장, 화면에는 마스킹만 노출.
59
-
60
- ## 배포 실제 운영 구성 (EC2 + Docker + GitHub Actions)
61
-
62
- 현재 운영: AWS EC2(Ubuntu 24.04, `ubuntu@52.79.213.236`)에서 **docker**로 실행.
63
- `main`에 푸시하면 GitHub Actions([build.yml](.github/workflows/build.yml))가
64
- 이미지를 빌드해 `ghcr.io/jonghoon5922/tokenbill:latest`로 올린다 — 서버에서 빌드하지 않는다.
65
-
66
- - SECRET_KEY: 서버의 `~/.tokenbill-secret` 파일에 보관 (한 줄)
67
- - DB: `tokenbill-data` 도커 볼륨 컨테이너 `/data/tokenbill.db` (재배포해도 유지)
68
-
69
- ### 버전 배포 절차
70
-
71
- ```bash
72
- # 0) (스키마 변경이 있는 배포면) DB 백업
73
- docker cp tokenbill:/data /home/ubuntu/tokenbill-data-backup-$(date +%Y%m%d)
74
-
75
- # 1) GitHub Actions 빌드 완료 확인 pull
76
- docker pull ghcr.io/jonghoon5922/tokenbill:latest
77
-
78
- # 2) 컨테이너 교체 (볼륨·시크릿 유지)
79
- docker stop tokenbill && docker rm tokenbill
80
- docker run -d --name tokenbill -p 8000:8000 -v tokenbill-data:/data \
81
- -e SECRET_KEY="$(cat ~/.tokenbill-secret)" --restart unless-stopped \
82
- ghcr.io/jonghoon5922/tokenbill:latest
83
-
84
- # 3) 확인
85
- docker logs --tail 30 tokenbill
86
- curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/
87
- ```
88
-
89
- 롤백: `ghcr.io/jonghoon5922/tokenbill:<커밋 SHA>` 태그로 같은 절차 반복 + 백업 복원.
90
-
91
- 주의: `SECRET_KEY`는 한 번 정하면 **바꾸지 말 것** — 이 키로 프로바이더 API 키를
92
- 암호화하므로, 바뀌면 저장된 키를 복호화할 없다.
93
-
94
- ### 첫 서버 세팅 (참고)
95
-
96
- ```bash
97
- openssl rand -hex 32 > ~/.tokenbill-secret && chmod 600 ~/.tokenbill-secret
98
- docker volume create tokenbill-data
99
- # 이후 위 "컨테이너 교체" 절차의 run 명령과 동일
100
- ```
101
-
102
- ### HTTPS
103
-
104
- 외부 공개 시 앞단에 Caddy나 nginx를 두는 것을 권장.
105
- Caddy면 `Caddyfile`에 `내도메인.com { reverse_proxy localhost:8000 }` 두 줄로 끝.
106
-
107
- 사용자가 늘면 `DATABASE_URL` 환경변수로 Postgres 전환 가능 (드라이버 추가 필요).
108
-
109
- ## 다음 단계 아이디어
110
-
111
- - 예산 초과 이메일/텔레그램 알림 (스케줄러에서 체크)
112
- - 프로바이더 cost API 연동으로 정확한 청구 금액 표시
113
- - "한 단계 싼 모델로 바꾸면 월 $X 절약" 시뮬레이션
114
- - Google (Cloud Billing), 기타 프로바이더 추가
1
+ # Tokenbill (토큰빌) — AI API 비용 대시보드
2
+
3
+ OpenAI·Anthropic API 사용 비용과 토큰을 한 화면에서 추적하는 서비스.
4
+ FastAPI + SQLite + 바닐라 JS 프론트엔드(단일 HTML).
5
+
6
+ ## 실행 방법
7
+
8
+ ```bash
9
+ pip install -r requirements.txt
10
+ cp .env.example .env # SECRET_KEY를 긴 랜덤 문자열로 변경
11
+ export $(cat .env | xargs) # 또는 환경변수로 직접 설정
12
+ uvicorn app.main:app --reload
13
+ ```
14
+
15
+ http://localhost:8000 접속 → 회원가입 → 프로바이더 키 등록.
16
+
17
+ - **체험(데모)**: 키에 `demo` 로 시작하는 아무 값이나 넣으면 가짜 사용 데이터가 생성됩니다.
18
+ - **실제 연동**: OpenAI는 조직 **Admin 키**(`sk-admin-…`, platform.openai.com → Organization → Admin Keys),
19
+ Anthropic도 **Admin 키**(`sk-ant-admin-…`, console.anthropic.com → Settings → Admin Keys)가 필요합니다.
20
+ 일반 API 키로는 사용량 조회가 안 됩니다.
21
+ - Google AI는 Cloud Billing 연동이 필요해서 MVP에서는 미지원(데모만 가능).
22
+ - **다중 조직**: 프로바이더당 키를 여러 개(조직별 이름 붙여서) 등록할 수 있고,
23
+ 대시보드에서 조직별 이번 달 비용이 나뉘어 보입니다. 차트·합계는 전체 조직 합산 기준.
24
+ - **프로젝트 드릴다운**: 조직 행을 클릭하면 프로젝트(OpenAI Project / Anthropic
25
+ Workspace) 단위로 펼쳐지고, 프로젝트마다 모델별 비용·토큰이 표시됩니다.
26
+ - **구글 로그인** (선택): `GOOGLE_CLIENT_ID` 환경변수를 설정하면 로그인 화면에
27
+ "Google로 계속하기" 버튼이 나타납니다. Google Cloud Console에서 OAuth 클라이언트
28
+ ID(웹)를 만들고, 승인된 JavaScript 출처에 서비스 도메인(https)을 등록해야 합니다.
29
+ 도메인 없이 공인 IP로는 Google 정책상 동작하지 않습니다.
30
+
31
+ API 문서: http://localhost:8000/docs (FastAPI 자동 생성)
32
+
33
+ ## MCP 업로더 + Duet 타스크 보드
34
+
35
+ `npx -y tokenbill-mcp@latest` 하나가 Claude Code 창마다 붙어 세 가지를 한다:
36
+
37
+ - **토큰 업로드** 시작할 때와 `sync_usage` 도구로 로컬 로그를 tokenbill.my에 올린다.
38
+ - **대화 뷰어** http://127.0.0.1:8377 ( PC의 로그만 읽는다).
39
+ - **Duet 타스크 보드** http://127.0.0.1:8737. 창에서 일이 타스크로 저절로 기록된다.
40
+ Claude가 `create_task`·`join_task`·`report_progress`·`complete_session` 도구 8개로 스스로 기록하고,
41
+ 보드는 프로젝트(= 창을 연 폴더)별로 보여준다. 기록은 `~/.duet`에 파일로만 남고 서버로 올라가지 않는다.
42
+ 규칙과 화면은 [Duet](https://github.com/Jonghoon5922/duet)(Python 판)과 같고 기록 형식도 같다 — `uploader/duet/`.
43
+
44
+ ```bash
45
+ claude mcp add -s user tokenbill -- npx -y tokenbill-mcp@latest --token tbu_...
46
+ npm test # Duet 규칙 단위 테스트
47
+ npm run smoke # 진짜 stdio 프로세스 여러 개로 한 바퀴
48
+ ```
49
+
50
+ ## 구조
51
+
52
+ ```
53
+ app/
54
+ main.py # FastAPI 앱, 라우트, 스케줄러(매일 03시 KST 자동 수집)
55
+ models.py # User / ProviderKey / UsageDaily (날짜×프로바이더×모델 요약)
56
+ security.py # JWT 인증, bcrypt 해시, API Fernet 암호화
57
+ collector.py # 수집 오케스트레이션, 수동 갱신 쿨다운(10분)
58
+ providers/
59
+ collectors.py # OpenAI/Anthropic usage API 호출 + 데모 생성기
60
+ prices.py # 모델별 단가표 (비용 = 토큰 × 단가 근사)
61
+ static/index.html # 프론트엔드 (로그인 + 대시보드)
62
+ ```
63
+
64
+ ## 설계 메모
65
+
66
+ - **저장 최소화**: 원본 로그는 프로바이더에 두고, "날짜 × 프로바이더 × 모델 × 비용/토큰"
67
+ 요약 행만 보관. 사용자당 하루 수십 수준.
68
+ - **갱신 정책**: 매일 1회 자동(APScheduler) + "지금 갱신" 수동(10분 쿨다운).
69
+ 프로바이더 과금 데이터 자체가 지연 반영이라 실시간성은 목표가 아님.
70
+ - **비용 계산**: 금액은 프로바이더 **cost API 실측값** 기준.
71
+ usage API(토큰·모델별)로 분해를 만들고, 모델별 근사 비용을 cost API의 일 총액에 맞게
72
+ 비례 보정한다 합계는 항상 실제 청구 금액과 일치. cost API 호출이 실패하면
73
+ `prices.py` 단가표 근사값으로 폴백. 단가표는 "싼 모델 절약 시뮬레이션" 등에 계속 사용
74
+ (자동 수집으로 대체 예정 — LiteLLM의 model_prices JSON 참고).
75
+ - **키 보안**: API 키는 SECRET_KEY에서 유도한 Fernet 키로 암호화 저장, 화면에는 마스킹만 노출.
76
+
77
+ ## 배포 — 실제 운영 구성 (EC2 + Docker + GitHub Actions)
78
+
79
+ 현재 운영: AWS EC2(Ubuntu 24.04, `ubuntu@52.79.213.236`)에서 **docker**로 실행.
80
+ `main`에 푸시하면 GitHub Actions([build.yml](.github/workflows/build.yml))가
81
+ 이미지를 빌드해 `ghcr.io/jonghoon5922/tokenbill:latest`로 올린다 서버에서 빌드하지 않는다.
82
+
83
+ - SECRET_KEY: 서버의 `~/.tokenbill-secret` 파일에 보관 (한 줄)
84
+ - DB: `tokenbill-data` 도커 볼륨 → 컨테이너 `/data/tokenbill.db` (재배포해도 유지)
85
+
86
+ ### 버전 배포 절차
87
+
88
+ ```bash
89
+ # 0) (스키마 변경이 있는 배포면) DB 백업
90
+ docker cp tokenbill:/data /home/ubuntu/tokenbill-data-backup-$(date +%Y%m%d)
91
+
92
+ # 1) GitHub Actions 빌드 완료 확인 후 pull
93
+ docker pull ghcr.io/jonghoon5922/tokenbill:latest
94
+
95
+ # 2) 컨테이너 교체 (볼륨·시크릿 유지)
96
+ docker stop tokenbill && docker rm tokenbill
97
+ docker run -d --name tokenbill -p 8000:8000 -v tokenbill-data:/data \
98
+ -e SECRET_KEY="$(cat ~/.tokenbill-secret)" --restart unless-stopped \
99
+ ghcr.io/jonghoon5922/tokenbill:latest
100
+
101
+ # 3) 확인
102
+ docker logs --tail 30 tokenbill
103
+ curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/
104
+ ```
105
+
106
+ 롤백: `ghcr.io/jonghoon5922/tokenbill:<커밋 SHA>` 태그로 같은 절차 반복 + 백업 복원.
107
+
108
+ 주의: `SECRET_KEY`는 한 번 정하면 **바꾸지 말 것** — 이 키로 프로바이더 API 키를
109
+ 암호화하므로, 바뀌면 저장된 키를 복호화할 수 없다.
110
+
111
+ ### 서버 세팅 (참고)
112
+
113
+ ```bash
114
+ openssl rand -hex 32 > ~/.tokenbill-secret && chmod 600 ~/.tokenbill-secret
115
+ docker volume create tokenbill-data
116
+ # 이후 위 "컨테이너 교체" 절차의 run 명령과 동일
117
+ ```
118
+
119
+ ### HTTPS
120
+
121
+ 외부 공개 시 앞단에 Caddy나 nginx를 두는 것을 권장.
122
+ Caddy면 `Caddyfile`에 `내도메인.com { reverse_proxy localhost:8000 }` 두 줄로 끝.
123
+
124
+ 사용자가 늘면 `DATABASE_URL` 환경변수로 Postgres 전환 가능 (드라이버 추가 필요).
125
+
126
+ ## 다음 단계 아이디어
127
+
128
+ - 예산 초과 시 이메일/텔레그램 알림 (스케줄러에서 체크)
129
+ - 프로바이더 cost API 연동으로 정확한 청구 금액 표시
130
+ - "한 단계 싼 모델로 바꾸면 월 $X 절약" 시뮬레이션
131
+ - Google (Cloud Billing), 기타 프로바이더 추가
package/package.json CHANGED
@@ -1,19 +1,24 @@
1
1
  {
2
2
  "name": "tokenbill-mcp",
3
- "version": "1.0.0",
4
- "description": "Tokenbill MCP — Claude Code·Codex·Gemini CLI 구독 토큰을 tokenbill.my 리더보드에 자동 집계하고, 로컬 대화 뷰어(--viewer)를 제공합니다. Auto-uploads your AI subscription token usage to the tokenbill.my leaderboard, with a local transcript viewer.",
3
+ "version": "1.1.0",
4
+ "description": "Tokenbill MCP — Claude Code·Codex·Gemini CLI 구독 토큰을 tokenbill.my 리더보드에 자동 집계하고, 로컬 대화 뷰어(--viewer)와 Duet 타스크 보드(127.0.0.1:8737)를 제공합니다. Auto-uploads your AI subscription token usage to the tokenbill.my leaderboard, with a local transcript viewer and the Duet task board.",
5
5
  "bin": {
6
6
  "tokenbill-mcp": "./uploader/index.js"
7
7
  },
8
8
  "files": [
9
- "uploader/"
9
+ "uploader/",
10
+ "!uploader/duet/test/"
10
11
  ],
12
+ "scripts": {
13
+ "test": "node --test uploader/duet/test/core.test.js",
14
+ "smoke": "node uploader/duet/test/smoke.js"
15
+ },
11
16
  "repository": {
12
17
  "type": "git",
13
18
  "url": "git+https://github.com/Jonghoon5922/tokenbill.git"
14
19
  },
15
20
  "homepage": "https://tokenbill.my",
16
- "keywords": ["mcp", "claude-code", "codex-cli", "gemini-cli", "cursor", "tokens", "leaderboard", "usage"],
21
+ "keywords": ["mcp", "claude-code", "codex-cli", "gemini-cli", "cursor", "tokens", "leaderboard", "usage", "tasks", "duet"],
17
22
  "engines": { "node": ">=18" },
18
23
  "license": "MIT"
19
24
  }