@tinyweb_dev/tracking-mcp-server 0.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.
Files changed (109) hide show
  1. package/.env.example +43 -0
  2. package/CHANGELOG.md +60 -0
  3. package/LICENSE +21 -0
  4. package/README.md +419 -0
  5. package/dist/config.d.ts +43 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +85 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/http-client.d.ts +31 -0
  10. package/dist/http-client.d.ts.map +1 -0
  11. package/dist/http-client.js +152 -0
  12. package/dist/http-client.js.map +1 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +81 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/logger.d.ts +11 -0
  18. package/dist/logger.d.ts.map +1 -0
  19. package/dist/logger.js +41 -0
  20. package/dist/logger.js.map +1 -0
  21. package/dist/prompts/index.d.ts +14 -0
  22. package/dist/prompts/index.d.ts.map +1 -0
  23. package/dist/prompts/index.js +120 -0
  24. package/dist/prompts/index.js.map +1 -0
  25. package/dist/resources/index.d.ts +18 -0
  26. package/dist/resources/index.d.ts.map +1 -0
  27. package/dist/resources/index.js +168 -0
  28. package/dist/resources/index.js.map +1 -0
  29. package/dist/schemas/common.d.ts +27 -0
  30. package/dist/schemas/common.d.ts.map +1 -0
  31. package/dist/schemas/common.js +29 -0
  32. package/dist/schemas/common.js.map +1 -0
  33. package/dist/schemas/error.d.ts +236 -0
  34. package/dist/schemas/error.d.ts.map +1 -0
  35. package/dist/schemas/error.js +88 -0
  36. package/dist/schemas/error.js.map +1 -0
  37. package/dist/schemas/incident.d.ts +139 -0
  38. package/dist/schemas/incident.d.ts.map +1 -0
  39. package/dist/schemas/incident.js +53 -0
  40. package/dist/schemas/incident.js.map +1 -0
  41. package/dist/schemas/index.d.ts +13 -0
  42. package/dist/schemas/index.d.ts.map +1 -0
  43. package/dist/schemas/index.js +13 -0
  44. package/dist/schemas/index.js.map +1 -0
  45. package/dist/schemas/invitation.d.ts +77 -0
  46. package/dist/schemas/invitation.d.ts.map +1 -0
  47. package/dist/schemas/invitation.js +45 -0
  48. package/dist/schemas/invitation.js.map +1 -0
  49. package/dist/schemas/monitor.d.ts +183 -0
  50. package/dist/schemas/monitor.d.ts.map +1 -0
  51. package/dist/schemas/monitor.js +81 -0
  52. package/dist/schemas/monitor.js.map +1 -0
  53. package/dist/schemas/organization.d.ts +87 -0
  54. package/dist/schemas/organization.d.ts.map +1 -0
  55. package/dist/schemas/organization.js +39 -0
  56. package/dist/schemas/organization.js.map +1 -0
  57. package/dist/schemas/project.d.ts +82 -0
  58. package/dist/schemas/project.d.ts.map +1 -0
  59. package/dist/schemas/project.js +38 -0
  60. package/dist/schemas/project.js.map +1 -0
  61. package/dist/schemas/recipient-group.d.ts +51 -0
  62. package/dist/schemas/recipient-group.d.ts.map +1 -0
  63. package/dist/schemas/recipient-group.js +30 -0
  64. package/dist/schemas/recipient-group.js.map +1 -0
  65. package/dist/schemas/status-page.d.ts +144 -0
  66. package/dist/schemas/status-page.d.ts.map +1 -0
  67. package/dist/schemas/status-page.js +64 -0
  68. package/dist/schemas/status-page.js.map +1 -0
  69. package/dist/tools/_helpers.d.ts +33 -0
  70. package/dist/tools/_helpers.d.ts.map +1 -0
  71. package/dist/tools/_helpers.js +62 -0
  72. package/dist/tools/_helpers.js.map +1 -0
  73. package/dist/tools/errors.d.ts +20 -0
  74. package/dist/tools/errors.d.ts.map +1 -0
  75. package/dist/tools/errors.js +196 -0
  76. package/dist/tools/errors.js.map +1 -0
  77. package/dist/tools/incidents.d.ts +14 -0
  78. package/dist/tools/incidents.d.ts.map +1 -0
  79. package/dist/tools/incidents.js +105 -0
  80. package/dist/tools/incidents.js.map +1 -0
  81. package/dist/tools/index.d.ts +9 -0
  82. package/dist/tools/index.d.ts.map +1 -0
  83. package/dist/tools/index.js +22 -0
  84. package/dist/tools/index.js.map +1 -0
  85. package/dist/tools/invitations.d.ts +12 -0
  86. package/dist/tools/invitations.d.ts.map +1 -0
  87. package/dist/tools/invitations.js +82 -0
  88. package/dist/tools/invitations.js.map +1 -0
  89. package/dist/tools/monitors.d.ts +15 -0
  90. package/dist/tools/monitors.d.ts.map +1 -0
  91. package/dist/tools/monitors.js +129 -0
  92. package/dist/tools/monitors.js.map +1 -0
  93. package/dist/tools/organizations.d.ts +16 -0
  94. package/dist/tools/organizations.d.ts.map +1 -0
  95. package/dist/tools/organizations.js +152 -0
  96. package/dist/tools/organizations.js.map +1 -0
  97. package/dist/tools/projects.d.ts +22 -0
  98. package/dist/tools/projects.d.ts.map +1 -0
  99. package/dist/tools/projects.js +218 -0
  100. package/dist/tools/projects.js.map +1 -0
  101. package/dist/tools/recipient-groups.d.ts +12 -0
  102. package/dist/tools/recipient-groups.d.ts.map +1 -0
  103. package/dist/tools/recipient-groups.js +75 -0
  104. package/dist/tools/recipient-groups.js.map +1 -0
  105. package/dist/tools/status-pages.d.ts +17 -0
  106. package/dist/tools/status-pages.d.ts.map +1 -0
  107. package/dist/tools/status-pages.js +170 -0
  108. package/dist/tools/status-pages.js.map +1 -0
  109. package/package.json +77 -0
package/.env.example ADDED
@@ -0,0 +1,43 @@
1
+ # Tiny Tracking MCP Server — environment configuration
2
+ # Copy this file to `.env` (for local dev) or set these vars in your MCP client config.
3
+
4
+ # --- REQUIRED ---
5
+
6
+ # Base URL of the Tiny Tracking backend (no trailing slash).
7
+ TT_API_URL=http://localhost:3000
8
+
9
+ # Personal Access Token (PAT). Generated from the Tiny Tracking dashboard:
10
+ # 1. Sign in to the dashboard
11
+ # 2. Settings → Personal access tokens → Manage tokens
12
+ # (or visit /<orgId>/settings/api-tokens directly)
13
+ # 3. Click "Create token", give it a name, choose an expiry
14
+ # 4. Copy the `tt_pat_<32 chars>` value SHOWN ONCE (the server only stores
15
+ # a bcrypt hash; you cannot retrieve the plaintext later)
16
+ # 5. Paste it here.
17
+ #
18
+ # Format: literal prefix `tt_pat_` followed by 32 base62-ish characters
19
+ # (e.g. `tt_pat_aB3xY9Q2cD7eF8gH1iJ4kL5mN6oP7qR8s`).
20
+ # Token inherits the owning user's permissions across all orgs/projects they
21
+ # are a member of. Treat as a password: never commit, never paste in public chats.
22
+ TT_API_KEY=tt_pat_replace_me
23
+
24
+ # --- OPTIONAL ---
25
+
26
+ # Default organization ID, used when a tool does not receive `org_id` explicitly.
27
+ # Find it in the URL of your dashboard: /<orgId>/...
28
+ TT_DEFAULT_ORG_ID=
29
+
30
+ # Request timeout in milliseconds (default: 15000).
31
+ TT_HTTP_TIMEOUT_MS=15000
32
+
33
+ # Number of retry attempts on transient errors — 5xx, 429, network (default: 3).
34
+ TT_HTTP_RETRIES=3
35
+
36
+ # Logger level: trace | debug | info | warn | error | fatal (default: info).
37
+ # Output always goes to stderr — stdout is reserved for MCP JSON-RPC.
38
+ LOG_LEVEL=info
39
+
40
+ # Client identifier sent in `X-MCP-Client` header.
41
+ # Used by the backend audit log to attribute requests to this MCP instance.
42
+ # Default: tiny-tracking-mcp/<pkg-version>.
43
+ TT_MCP_CLIENT_NAME=
package/CHANGELOG.md ADDED
@@ -0,0 +1,60 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@tinyweb_dev/tracking-mcp-server` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] — 2026-05-26
9
+
10
+ Initial public release.
11
+
12
+ ### Added
13
+
14
+ - **62 MCP tools** across 8 resource groups (organizations, projects,
15
+ monitors, status pages, incidents, errors, recipient groups, invitations)
16
+ wrapping the Tiny Tracking REST API.
17
+ - **6 read-only resource templates** for browsing org/project/monitor state
18
+ via `tinytracking://...` URIs.
19
+ - **3 prompt templates** (`triage-incident`, `summarize-error-group`,
20
+ `weekly-health-report`) that prime the agent with canonical investigation
21
+ workflows.
22
+ - **Confirmation pattern** on 10 destructive tools (`*_delete`,
23
+ `project_regenerate_api_key`, `invitation_revoke`, etc.) — each requires
24
+ an explicit `confirm_*` argument matching the resource's
25
+ name/slug/uuid before proceeding.
26
+ - **`X-MCP-Client: tiny-tracking-mcp/<version>` header** on every request so
27
+ backend audit logs can attribute calls to the MCP server.
28
+ - **Stdio transport** compatible with Claude Desktop, VS Code / Roo Code,
29
+ Cursor, ChatGPT Desktop, and any other MCP-compliant client.
30
+ - **Pino logger pinned to stderr** with automatic redaction of
31
+ `authorization`, `apiKey`, `token`, `password`, `secret`, `x-api-key`
32
+ fields — stdout is reserved for MCP JSON-RPC.
33
+ - **Axios HTTP client** with exponential-backoff retries on 5xx / 429 /
34
+ network errors and structured `McpError` mapping (401/403 →
35
+ `InvalidRequest`, 404/400/422 → `InvalidParams`, 5xx → `InternalError`).
36
+ - **219 unit tests** across 17 test files; coverage 98.60% lines / 97.96%
37
+ branches.
38
+
39
+ ### Backend dependencies (required server-side, shipped in the same release)
40
+
41
+ - **Personal Access Token (PAT) system**: new `POST/GET/DELETE /api/me/tokens`
42
+ endpoints, bcrypt cost-10 hashing, prefix-indexed lookup, soft revoke.
43
+ - **Enhanced `JwtAuthGuard`**: now accepts both better-auth session cookies
44
+ AND `Authorization: Bearer tt_pat_*` tokens, hydrating the same
45
+ `request.user` shape for both paths.
46
+ - **`Settings → API tokens` dashboard page**: user-facing CRUD UI for
47
+ generating, listing, and revoking PATs.
48
+ - **MCP audit log**: every request carrying the `X-MCP-Client` header is
49
+ asynchronously recorded to the `mcp_audit_log` table (user, token,
50
+ org/project context, method, path, status, request/response excerpt with
51
+ sensitive-field redaction, IP, user-agent, duration). Owner-only read
52
+ endpoint `GET /api/organizations/:orgId/audit-log`.
53
+
54
+ ### Engineering
55
+
56
+ - ESM module (`type: "module"`), TypeScript 5.7, Node ≥ 20.
57
+ - Build is `tsc -p tsconfig.json && chmod +x dist/index.js` so the published
58
+ binary is directly executable.
59
+ - `prepublishOnly` runs clean + typecheck + build + tests to guarantee no
60
+ broken release reaches the registry.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tinyweb dev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,419 @@
1
+ # @tinyweb_dev/tracking-mcp-server
2
+
3
+ > **MCP server cho Tiny Tracking** — cho phép các AI agent (Claude Desktop, Cursor, Roo Code, VS Code, ChatGPT Desktop, custom agents…) điều khiển và quản lý toàn bộ resource của nền tảng monitoring **Tiny Tracking** thông qua REST API.
4
+
5
+ Standalone Node.js package, không xâm lấn backend, deploy độc lập, dùng được cho mọi MCP client hỗ trợ stdio transport.
6
+
7
+ ---
8
+
9
+ ## Mục lục
10
+
11
+ - [Tính năng](#tính-năng)
12
+ - [Yêu cầu](#yêu-cầu)
13
+ - [Cài đặt](#cài-đặt)
14
+ - [Cấu hình](#cấu-hình)
15
+ - [Tích hợp với MCP client](#tích-hợp-với-mcp-client)
16
+ - [Claude Desktop](#claude-desktop)
17
+ - [VS Code / Roo Code](#vs-code--roo-code)
18
+ - [Cursor](#cursor)
19
+ - [Tool reference](#tool-reference)
20
+ - [Resources & Prompts](#resources--prompts)
21
+ - [Bảo mật & confirmation pattern](#bảo-mật--confirmation-pattern)
22
+ - [Troubleshooting](#troubleshooting)
23
+ - [Phát triển](#phát-triển)
24
+
25
+ ---
26
+
27
+ ## Tính năng
28
+
29
+ - **62 tools** wrap toàn bộ REST API của Tiny Tracking backend (8 resource groups)
30
+ - **6 resources** read-only cho agent browse nhanh workspace
31
+ - **3 prompt templates** (triage incident, summarize error, weekly report)
32
+ - **Stdio transport** — tương thích Claude Desktop, Cursor, Roo Code, VS Code, ChatGPT Desktop
33
+ - **Type-safe** end-to-end với zod schemas mirror các DTO backend
34
+ - **Auto-retry** với exponential backoff trên network errors / 5xx / 429
35
+ - **Audit-friendly** — mỗi request gắn header `X-MCP-Client: <name>/<version>`
36
+ - **Safe by default** — tools destructive (delete, regenerate key) bắt buộc xác nhận
37
+
38
+ ---
39
+
40
+ ## Yêu cầu
41
+
42
+ - **Node.js 22+**
43
+ - **Tiny Tracking backend** đang chạy và truy cập được (mặc định `http://localhost:3000`)
44
+ - **Personal Access Token (PAT)** — generate từ dashboard:
45
+ 1. Đăng nhập vào Tiny Tracking dashboard
46
+ 2. Vào **Settings → Personal access tokens → Manage tokens** (hoặc truy cập trực tiếp `/<orgId>/settings/api-tokens`)
47
+ 3. Bấm **Create token**, đặt tên (vd "Claude Desktop on MacBook"), chọn thời hạn → **Generate token**
48
+ 4. **Copy ngay** giá trị `tt_pat_...` được hiển thị — backend chỉ lưu bcrypt hash, plaintext không thể recover sau khi đóng dialog
49
+ 5. Paste vào `TT_API_KEY` trong MCP client config (xem ví dụ dưới)
50
+
51
+ Token thuộc về user, nên có quyền truy cập **toàn bộ org/project user đang là member**. Treat as password — không commit vào git, không paste vào public chat.
52
+
53
+ ---
54
+
55
+ ## Cài đặt
56
+
57
+ ### Từ source (recommended cho local dev)
58
+
59
+ ```bash
60
+ git clone https://github.com/yourusername/tiny-tracking.git
61
+ cd tiny-tracking/mcp-server
62
+ npm install
63
+ npm run build
64
+ ```
65
+
66
+ Sau khi build thành công, [`dist/index.js`](dist/index.js) là entrypoint, có thể chạy thử:
67
+
68
+ ```bash
69
+ TT_API_URL=http://localhost:3000 TT_API_KEY=tt_pat_xxx node dist/index.js
70
+ ```
71
+
72
+ Server sẽ in một dòng JSON ra **stderr** rồi treo chờ JSON-RPC từ stdin — đó là hành vi đúng cho một MCP server stdio.
73
+
74
+ ---
75
+
76
+ ## Cấu hình
77
+
78
+ Tất cả config qua biến môi trường. Xem [`.env.example`](.env.example) để có danh sách đầy đủ.
79
+
80
+ | Biến | Bắt buộc | Mô tả | Mặc định |
81
+ |---|:---:|---|---|
82
+ | `TT_API_URL` | ✅ | Base URL của Tiny Tracking backend (không trailing slash) | — |
83
+ | `TT_API_KEY` | ✅ | Personal Access Token format `tt_pat_<32 chars>` (generate ở Settings → API tokens) | — |
84
+ | `TT_DEFAULT_ORG_ID` | | Org UUID mặc định khi tool không nhận `org_id` | — |
85
+ | `TT_HTTP_TIMEOUT_MS` | | Timeout HTTP (ms) | `15000` |
86
+ | `TT_HTTP_RETRIES` | | Số lần retry với 5xx / 429 / network errors | `3` |
87
+ | `TT_MCP_CLIENT_NAME` | | Tên cho header `X-MCP-Client` | `mcp-server/<version>` |
88
+ | `LOG_LEVEL` | | `trace` \| `debug` \| `info` \| `warn` \| `error` \| `fatal` | `info` |
89
+
90
+ ---
91
+
92
+ ## Tích hợp với MCP client
93
+
94
+ ### Claude Desktop
95
+
96
+ Edit file config tại:
97
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
98
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
99
+
100
+ ```json
101
+ {
102
+ "mcpServers": {
103
+ "tiny-tracking": {
104
+ "command": "node",
105
+ "args": [
106
+ "/absolute/path/to/tiny-tracking/mcp-server/dist/index.js"
107
+ ],
108
+ "env": {
109
+ "TT_API_URL": "https://api.tinytracking.com",
110
+ "TT_API_KEY": "tt_pat_replace_me",
111
+ "TT_DEFAULT_ORG_ID": "org_uuid_optional",
112
+ "LOG_LEVEL": "info"
113
+ }
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ Restart Claude Desktop. Mở Settings → Developer → MCP để xem trạng thái connection. Trong chat, gõ `/` để thấy 3 prompt templates (`triage-incident`, `summarize-error-group`, `weekly-health-report`).
120
+
121
+ ### VS Code / Roo Code
122
+
123
+ Tạo `.vscode/mcp.json` trong workspace:
124
+
125
+ ```json
126
+ {
127
+ "servers": {
128
+ "tiny-tracking": {
129
+ "type": "stdio",
130
+ "command": "node",
131
+ "args": ["${workspaceFolder}/mcp-server/dist/index.js"],
132
+ "env": {
133
+ "TT_API_URL": "http://localhost:3000",
134
+ "TT_API_KEY": "tt_pat_replace_me"
135
+ }
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ > ⚠️ **Không commit** file `.vscode/mcp.json` có chứa token thật vào git. Thêm vào `.gitignore` hoặc dùng VS Code user settings.
142
+
143
+ ### Cursor
144
+
145
+ Tạo `.cursor/mcp.json` ở root project hoặc `~/.cursor/mcp.json` cho global config:
146
+
147
+ ```json
148
+ {
149
+ "mcpServers": {
150
+ "tiny-tracking": {
151
+ "command": "node",
152
+ "args": ["/absolute/path/to/tiny-tracking/mcp-server/dist/index.js"],
153
+ "env": {
154
+ "TT_API_URL": "http://localhost:3000",
155
+ "TT_API_KEY": "tt_pat_replace_me"
156
+ }
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Tool reference
165
+
166
+ Tổng **62 tools** chia theo 8 resource groups. Naming convention: `<resource>_<action>` (snake_case).
167
+
168
+ ### Organizations (8 tools)
169
+
170
+ | Tool | Mô tả |
171
+ |---|---|
172
+ | `org_list` | List orgs mà user có quyền truy cập |
173
+ | `org_get` | Lấy chi tiết 1 org |
174
+ | `org_create` | Tạo org mới (user thành owner) |
175
+ | `org_update` | Update name/slug/logo (owner only) |
176
+ | `org_delete` | 🔴 Xóa org + toàn bộ dữ liệu (yêu cầu `confirm_slug`) |
177
+ | `org_list_members` | List members và roles |
178
+ | `org_update_member_role` | Đổi role (owner/member/viewer) |
179
+ | `org_remove_member` | 🔴 Remove user khỏi org (yêu cầu `confirm_user_id`) |
180
+
181
+ ### Projects (12 tools)
182
+
183
+ | Tool | Mô tả |
184
+ |---|---|
185
+ | `project_list` | List projects trong 1 org |
186
+ | `project_create` | Tạo project mới (trả về API key) |
187
+ | `project_get` | Lấy chi tiết project |
188
+ | `project_update` | Update project |
189
+ | `project_delete` | 🔴 Xóa project + monitors + errors (yêu cầu `confirm_name`) |
190
+ | `project_get_api_key_prefix` | Lấy prefix API key (an toàn share) |
191
+ | `project_reveal_api_key` | 🔐 Reveal full API key (admin only) |
192
+ | `project_regenerate_api_key` | 🔴 Rotate API key — invalidate key cũ |
193
+ | `project_list_members` | List members + roles |
194
+ | `project_add_member` | Thêm user vào project |
195
+ | `project_update_member_role` | Đổi role (admin/editor/viewer) |
196
+ | `project_remove_member` | 🔴 Remove member |
197
+
198
+ ### Monitors (7 tools)
199
+
200
+ | Tool | Mô tả |
201
+ |---|---|
202
+ | `monitor_list` | List monitors trong project |
203
+ | `monitor_get` | Lấy chi tiết monitor |
204
+ | `monitor_create` | Tạo monitor (http/keyword/ping/tcp/ssl_cert) |
205
+ | `monitor_update` | Update monitor (partial) |
206
+ | `monitor_delete` | 🔴 Xóa monitor (yêu cầu `confirm_name`) |
207
+ | `monitor_toggle` | Pause / resume monitor |
208
+ | `monitor_get_results` | Lấy check history (default 50, max 500) |
209
+
210
+ ### Status Pages (9 tools)
211
+
212
+ | Tool | Mô tả |
213
+ |---|---|
214
+ | `status_page_list` | List status pages trong project |
215
+ | `status_page_get` | Lấy chi tiết + components |
216
+ | `status_page_create` | Tạo status page với slug public |
217
+ | `status_page_update` | Update name/theme/logo |
218
+ | `status_page_delete` | 🔴 Xóa status page (yêu cầu `confirm_slug`) |
219
+ | `status_page_add_component` | Thêm component (có thể link monitors) |
220
+ | `status_page_update_component` | Update component |
221
+ | `status_page_delete_component` | 🔴 Xóa component |
222
+ | `status_page_reorder_components` | Sắp xếp thứ tự component |
223
+
224
+ ### Incidents (6 tools)
225
+
226
+ | Tool | Mô tả |
227
+ |---|---|
228
+ | `incident_list` | List incidents của 1 status page |
229
+ | `incident_get` | Lấy incident + timeline updates |
230
+ | `incident_create` | Tạo incident manual |
231
+ | `incident_update` | Update title/status/impact/components |
232
+ | `incident_add_update` | Thêm update vào timeline (public) |
233
+ | `incident_resolve` | Resolve incident với optional message |
234
+
235
+ ### Errors (12 tools)
236
+
237
+ | Tool | Mô tả |
238
+ |---|---|
239
+ | `error_list` | List error groups của project |
240
+ | `error_get_project_stats` | Aggregate stats của project |
241
+ | `error_get` | Lấy chi tiết 1 error group |
242
+ | `error_get_summary` | Header summary (first/latest/total/IPs/users) |
243
+ | `error_get_timeseries` | Histogram occurrences theo hour/day/2w/2mo |
244
+ | `error_list_occurrences` | Paginated occurrences (cursor-based) |
245
+ | `error_get_occurrence` | Chi tiết 1 occurrence (stack, tags, user) |
246
+ | `error_get_occurrence_neighbors` | Latest/prev/next ids |
247
+ | `error_get_affected_ips` | Top IPs |
248
+ | `error_get_affected_users` | Top users |
249
+ | `error_resolve` | Mark resolved (auto-reopen nếu có occurrence mới) |
250
+ | `error_ignore` | Mark ignored (skip notifications) |
251
+
252
+ ### Recipient Groups (4 tools)
253
+
254
+ | Tool | Mô tả |
255
+ |---|---|
256
+ | `recipient_group_list` | List email distribution groups |
257
+ | `recipient_group_create` | Tạo group (name + emails) |
258
+ | `recipient_group_update` | Update group |
259
+ | `recipient_group_delete` | 🔴 Xóa group |
260
+
261
+ ### Invitations (4 tools)
262
+
263
+ | Tool | Mô tả |
264
+ |---|---|
265
+ | `invitation_list` | List pending invitations |
266
+ | `invitation_create` | Mời user (email + role, optional pre-assign project) |
267
+ | `invitation_resend` | Regenerate token + re-send email |
268
+ | `invitation_revoke` | 🔴 Cancel pending invitation |
269
+
270
+ Legend:
271
+ - 🔴 = **DESTRUCTIVE** — yêu cầu confirmation parameter
272
+ - 🔐 = **SENSITIVE** — trả về secret, không log/share
273
+
274
+ ---
275
+
276
+ ## Resources & Prompts
277
+
278
+ ### Resources (read-only)
279
+
280
+ Agent có thể list/fetch các URI sau qua `resources/list` và `resources/read`:
281
+
282
+ | URI | Mô tả |
283
+ |---|---|
284
+ | `tinytracking://organizations` | Tất cả orgs user có quyền |
285
+ | `tinytracking://organizations/{orgId}/projects` | Projects trong 1 org |
286
+ | `tinytracking://projects/{projectId}/overview` | Project + monitors + status pages + error stats |
287
+ | `tinytracking://projects/{projectId}/monitors` | Monitors của project |
288
+ | `tinytracking://projects/{projectId}/errors/stats` | Error stats |
289
+ | `tinytracking://projects/{projectId}/monitors/{monitorId}/health-summary` | Monitor + recent results (50) |
290
+
291
+ ### Prompts
292
+
293
+ 3 prompt templates dùng làm slash commands trong MCP client:
294
+
295
+ | Prompt | Args | Mục đích |
296
+ |---|---|---|
297
+ | `triage-incident` | `incident_id` | Điều tra root cause incident |
298
+ | `summarize-error-group` | `error_group_id`, `timeframe?` | Tóm tắt error cho dev |
299
+ | `weekly-health-report` | `org_id?` | Báo cáo health tuần qua |
300
+
301
+ ---
302
+
303
+ ## Bảo mật & confirmation pattern
304
+
305
+ ### Destructive actions
306
+
307
+ Các tool xóa/rotate/revoke đều yêu cầu một field xác nhận matching giá trị thật của resource:
308
+
309
+ | Tool | Field xác nhận | Match với |
310
+ |---|---|---|
311
+ | `org_delete` | `confirm_slug` | Org slug |
312
+ | `project_delete` | `confirm_name` | Project name |
313
+ | `project_regenerate_api_key` | `confirm_project_id` | Project UUID |
314
+ | `project_remove_member` | `confirm_user_id` | User UUID |
315
+ | `monitor_delete` | `confirm_name` | Monitor name |
316
+ | `status_page_delete` | `confirm_slug` | Status page slug |
317
+ | `status_page_delete_component` | `confirm_component_id` | Component UUID |
318
+ | `recipient_group_delete` | `confirm_group_id` | Group UUID |
319
+ | `invitation_revoke` | `confirm_invitation_id` | Invitation UUID |
320
+ | `org_remove_member` | `confirm_user_id` | User UUID |
321
+
322
+ Pattern này đảm bảo agent phải explicitly "repeat back" identifier — phòng case prompt injection hoặc nhầm lẫn UUID.
323
+
324
+ ### Secrets
325
+
326
+ - `TT_API_KEY` **không bao giờ** được hard-code vào file commit. Luôn đọc từ env hoặc MCP client config.
327
+ - Logger tự động redact các field nhạy cảm: `authorization`, `apiKey`, `token`, `password`, `secret`.
328
+ - `project_reveal_api_key` trả full key — đừng share log của tool call này.
329
+
330
+ ### Audit
331
+
332
+ Mọi HTTP request đều gắn header `X-MCP-Client: tiny-tracking-mcp/<version>`. Backend có thể filter audit log theo header này để phân biệt traffic agent vs UI.
333
+
334
+ ---
335
+
336
+ ## Troubleshooting
337
+
338
+ ### "Configuration error: TT_API_KEY still has placeholder value"
339
+
340
+ `.env` hoặc env client config vẫn chứa `tt_pat_replace_me`. Generate token thật ở dashboard → Settings → API tokens và thay vào.
341
+
342
+ ### "Authentication/authorization failed (401/403)"
343
+
344
+ - Kiểm tra `TT_API_KEY` còn hợp lệ (chưa expire, chưa revoke). Vào dashboard → Settings → API tokens để xem trạng thái và `lastUsedAt` của từng token.
345
+ - Verify user owner của PAT là member của org/project bạn đang thao tác — PAT thừa kế đúng permissions của user.
346
+ - Nếu token bị nghi ngờ leak, revoke ngay ở dashboard và generate token mới — backend sẽ từ chối token cũ từ request kế tiếp.
347
+
348
+ ### "Not found (404)"
349
+
350
+ UUID sai. Dùng resource `tinytracking://organizations` rồi đi xuống dần để chắc chắn lấy đúng id.
351
+
352
+ ### Agent không thấy server
353
+
354
+ 1. Check process Node có chạy không: `ps aux | grep tiny-tracking-mcp`
355
+ 2. Xem stderr log — Claude Desktop log tại `~/Library/Logs/Claude/mcp*.log`
356
+ 3. Verify path trong config trỏ tới `dist/index.js` đã build (`npm run build`)
357
+ 4. Đảm bảo Node 22+: `node --version`
358
+
359
+ ### "Origin ... not allowed by CORS"
360
+
361
+ Lỗi này KHÔNG xảy ra với MCP server (gọi server-to-server, không browser). Nếu thấy, backend đang reject Bearer token — kiểm tra `TT_API_URL` đúng và token hợp lệ.
362
+
363
+ ### Stdout bị "ô nhiễm" — agent disconnect
364
+
365
+ Chỉ xảy ra nếu có code `console.log` lẻ trong codebase. Tất cả log phải đi qua [`logger.ts`](src/logger.ts:1) (ghi stderr). Nếu thêm code mới, KHÔNG dùng `console.log`.
366
+
367
+ ---
368
+
369
+ ## Phát triển
370
+
371
+ ```bash
372
+ # Watch mode — auto-restart on file change
373
+ npm run dev
374
+
375
+ # Typecheck
376
+ npm run typecheck
377
+
378
+ # Build production bundle to dist/
379
+ npm run build
380
+
381
+ # Run tests (vitest)
382
+ npm test
383
+
384
+ # Lint
385
+ npm run lint
386
+ ```
387
+
388
+ ### Cấu trúc thư mục
389
+
390
+ ```
391
+ mcp-server/
392
+ ├── src/
393
+ │ ├── index.ts # Entrypoint — boots McpServer + StdioServerTransport
394
+ │ ├── config.ts # Env loader + zod validation
395
+ │ ├── http-client.ts # Axios + auth + retry + error mapping
396
+ │ ├── logger.ts # Pino → stderr (NEVER stdout)
397
+ │ ├── schemas/ # Zod schemas mirror các backend DTOs
398
+ │ ├── tools/ # 62 MCP tools (8 resource groups)
399
+ │ ├── resources/ # 6 read-only resource URIs
400
+ │ └── prompts/ # 3 prompt templates
401
+ ├── test/ # vitest specs
402
+ ├── dist/ # Build output (gitignored)
403
+ ├── package.json
404
+ ├── tsconfig.json
405
+ └── .env.example
406
+ ```
407
+
408
+ ### Thêm tool mới
409
+
410
+ 1. Thêm schema (nếu cần) vào `src/schemas/<resource>.ts`.
411
+ 2. Trong `src/tools/<resource>.ts`, thêm một `server.registerTool(...)` block theo pattern hiện có (dùng [`wrapHandler`](src/tools/_helpers.ts:1) + [`buildToolResult`](src/tools/_helpers.ts:1)).
412
+ 3. Nếu là destructive action, dùng [`requireConfirmation`](src/tools/_helpers.ts:1).
413
+ 4. `npm run typecheck && npm run build` để verify.
414
+
415
+ ---
416
+
417
+ ## License
418
+
419
+ MIT
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ declare const configSchema: z.ZodObject<{
3
+ TT_API_URL: z.ZodEffects<z.ZodString, string, string>;
4
+ TT_API_KEY: z.ZodEffects<z.ZodString, string, string>;
5
+ TT_DEFAULT_ORG_ID: z.ZodOptional<z.ZodString>;
6
+ TT_HTTP_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
7
+ TT_HTTP_RETRIES: z.ZodDefault<z.ZodNumber>;
8
+ TT_MCP_CLIENT_NAME: z.ZodOptional<z.ZodString>;
9
+ LOG_LEVEL: z.ZodDefault<z.ZodEnum<["trace", "debug", "info", "warn", "error", "fatal"]>>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ TT_API_URL: string;
12
+ TT_API_KEY: string;
13
+ TT_HTTP_TIMEOUT_MS: number;
14
+ TT_HTTP_RETRIES: number;
15
+ LOG_LEVEL: "trace" | "debug" | "info" | "warn" | "error" | "fatal";
16
+ TT_DEFAULT_ORG_ID?: string | undefined;
17
+ TT_MCP_CLIENT_NAME?: string | undefined;
18
+ }, {
19
+ TT_API_URL: string;
20
+ TT_API_KEY: string;
21
+ TT_DEFAULT_ORG_ID?: string | undefined;
22
+ TT_HTTP_TIMEOUT_MS?: number | undefined;
23
+ TT_HTTP_RETRIES?: number | undefined;
24
+ TT_MCP_CLIENT_NAME?: string | undefined;
25
+ LOG_LEVEL?: "trace" | "debug" | "info" | "warn" | "error" | "fatal" | undefined;
26
+ }>;
27
+ export type AppConfig = z.infer<typeof configSchema> & {
28
+ packageName: string;
29
+ packageVersion: string;
30
+ mcpClientHeader: string;
31
+ };
32
+ /**
33
+ * Load and validate configuration from environment variables.
34
+ *
35
+ * On validation failure, prints a clear error to stderr and exits(1) — this is
36
+ * intentional for stdio MCP servers, because returning an invalid config would
37
+ * cause downstream tools to fail in confusing ways.
38
+ */
39
+ export declare function loadConfig(): AppConfig;
40
+ /** Reset cached config (used by tests). */
41
+ export declare function _resetConfigForTests(): void;
42
+ export {};
43
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoCxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;EAkBhB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,GAAG;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAIF;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,SAAS,CA2BtC;AAED,2CAA2C;AAC3C,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
package/dist/config.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Environment configuration loader with zod validation.
3
+ *
4
+ * Loads from process.env (which may have been populated via dotenv when running
5
+ * locally, or directly by the MCP client config in production).
6
+ */
7
+ import { config as loadDotenv } from 'dotenv';
8
+ import { z } from 'zod';
9
+ import { readFileSync } from 'node:fs';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { dirname, join } from 'node:path';
12
+ // Load .env from package root if present (no-op when vars are already set).
13
+ // This is a no-op in production where the MCP client sets `env` directly.
14
+ loadDotenv();
15
+ function readPackageJson() {
16
+ try {
17
+ const here = dirname(fileURLToPath(import.meta.url));
18
+ // From src/ or dist/ — package.json is one level up
19
+ const pkgPath = join(here, '..', 'package.json');
20
+ const raw = readFileSync(pkgPath, 'utf-8');
21
+ return JSON.parse(raw);
22
+ }
23
+ catch {
24
+ return { name: '@tinyweb_dev/tracking-mcp-server', version: '0.0.0' };
25
+ }
26
+ }
27
+ const pkg = readPackageJson();
28
+ /* ------------------------------------------------------------------ */
29
+ /* Schema */
30
+ /* ------------------------------------------------------------------ */
31
+ const configSchema = z.object({
32
+ TT_API_URL: z
33
+ .string()
34
+ .url('TT_API_URL must be a valid URL')
35
+ .transform((url) => url.replace(/\/+$/, '')), // strip trailing slashes
36
+ TT_API_KEY: z
37
+ .string()
38
+ .min(1, 'TT_API_KEY is required')
39
+ .refine((v) => v !== 'tt_pat_replace_me', {
40
+ message: 'TT_API_KEY still has placeholder value. Set a real token.',
41
+ }),
42
+ TT_DEFAULT_ORG_ID: z.string().min(1).optional(),
43
+ TT_HTTP_TIMEOUT_MS: z.coerce.number().int().positive().default(15000),
44
+ TT_HTTP_RETRIES: z.coerce.number().int().min(0).max(10).default(3),
45
+ TT_MCP_CLIENT_NAME: z.string().min(1).optional(),
46
+ LOG_LEVEL: z
47
+ .enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal'])
48
+ .default('info'),
49
+ });
50
+ let cached = null;
51
+ /**
52
+ * Load and validate configuration from environment variables.
53
+ *
54
+ * On validation failure, prints a clear error to stderr and exits(1) — this is
55
+ * intentional for stdio MCP servers, because returning an invalid config would
56
+ * cause downstream tools to fail in confusing ways.
57
+ */
58
+ export function loadConfig() {
59
+ if (cached)
60
+ return cached;
61
+ const parsed = configSchema.safeParse(process.env);
62
+ if (!parsed.success) {
63
+ const issues = parsed.error.issues
64
+ .map((i) => ` • ${i.path.join('.') || '<root>'}: ${i.message}`)
65
+ .join('\n');
66
+ // eslint-disable-next-line no-console
67
+ console.error(`\n[tiny-tracking-mcp] Configuration error:\n${issues}\n\n` +
68
+ `Required env vars: TT_API_URL, TT_API_KEY\n` +
69
+ `See .env.example for full list.\n`);
70
+ process.exit(1);
71
+ }
72
+ const clientHeader = parsed.data.TT_MCP_CLIENT_NAME ?? `${pkg.name.split('/').pop()}/${pkg.version}`;
73
+ cached = {
74
+ ...parsed.data,
75
+ packageName: pkg.name,
76
+ packageVersion: pkg.version,
77
+ mcpClientHeader: clientHeader,
78
+ };
79
+ return cached;
80
+ }
81
+ /** Reset cached config (used by tests). */
82
+ export function _resetConfigForTests() {
83
+ cached = null;
84
+ }
85
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}