fix(build): 改用 node runtime 發布,移除對 bun 的執行期依賴 - #22
Conversation
- Extract langfuseApi, getAuthHeader, baseUrl to src/lib/api.ts - Move 6 Prompt tools to src/tools/prompts.ts with registerPromptTools() - Move 2 Trace tools to src/tools/traces.ts with registerTraceTools() - Move 2 Observation tools to src/tools/observations.ts with registerObservationTools() - Move 2 Score tools to src/tools/scores.ts with registerScoreTools() - Move 1 Session tool to src/tools/sessions.ts with registerSessionTools() - Simplify src/index.ts to register and initialize tools - Enhance langfuseApi() to support array query parameters for future Datasets/Metrics tools - Maintain all 13 existing tools, no functional changes Prepares codebase for Phase 1: adding Datasets tools Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New tools for dataset-based evaluation workflows: - listDatasets: List all datasets with search/pagination - getDataset: Fetch dataset metadata and stats - createDataset: Create new dataset for evals - listDatasetItems: List input/output pairs in dataset - createDatasetItem: Add evaluation samples to dataset - getDatasetItem: Fetch single dataset item - listDatasetRuns: List eval executions against dataset - getDatasetRun: Fetch eval run results Supports Langfuse eval management workflows. Total tools now: 21 (13 existing + 8 new) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New tools for usage and performance analytics: - getDailyMetrics: Query daily metrics (latency, tokens, scores, cost) with filters - getUsageSummary: Get usage summary for time period Supports analytics and cost tracking for Langfuse deployments. Total tools now: 23 (13 existing + 8 datasets + 2 metrics) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New tools for score schema management: - listScoreConfigs: List all custom score definitions - getScoreConfig: Fetch score config with data types and categories - createScoreConfig: Define new numeric or categorical score type - updateScoreConfig: Update score config (name, categories, description) Supports custom scoring metrics and eval configurations. Total tools now: 27 (13 existing + 8 datasets + 2 metrics + 4 score-configs) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…etadata Phase 4 completion: Project Management tools integrated. Total tools: 28 (6 prompts + 2 traces + 2 observations + 2 scores + 1 sessions + 8 datasets + 2 metrics + 4 score-configs + 1 project) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Instance Management, Organization Projects, API Keys, and Memberships management tools: - Instance Management (8 tools): listInstances, getInstance, createInstance, updateInstance, deleteInstance, listInstanceEvents, getInstanceStatus, configureInstanceSettings - Organization Projects (5 tools): listOrganizationProjects, getOrganizationProject, createOrganizationProject, updateOrganizationProject, deleteOrganizationProject - Organization API Keys (3 tools): listOrganizationApiKeys, createOrganizationApiKey, deleteOrganizationApiKey - Organization Memberships (6 tools): listOrganizationMembers, addOrganizationMember, updateOrganizationMember, removeOrganizationMember, listProjectMembers, updateProjectMember **Architecture changes:** - Enhanced api.ts with multi-auth support (Basic Auth, Admin Bearer, Org Bearer) - Added authType and rawPath parameters to langfuseApi() - New environment variables: LANGFUSE_ADMIN_API_KEY, LANGFUSE_ORG_API_KEY - Modular tool registration pattern for 4 new tool modules Total tools expanded from 28 to 50. All existing tools (Prompt, Traces, Observations, Scores, Sessions, Datasets, Metrics, Score Configs, Project) remain unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- HIGH-1: Add regex validation to all ID parameters (instanceId, orgId, projectId, memberId, keyId) to prevent path traversal Pattern: /^[a-zA-Z0-9_-]+$/ enforces alphanumeric, underscore, and hyphen characters only Applied to: instance-management, organization-projects, organization-apikeys, organization-memberships - HIGH-2: Validate environment variables in getBasicAuthHeader() Missing LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY now throws explicit error instead of silent authentication failure - HIGH-3: Move PATCH operation validation from Zod schema to handler Resolved MCP SDK ZodEffects incompatibility by moving .refine() validation to runtime checks Ensures updateInstance, updateOrganizationProject, updateOrganizationMember, updateProjectMember require at least one field All changes verified: typecheck ✓, lint ✓, build ✓ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**Schema Validation (MEDIUM severity)**: - Add datetime validation to metrics queries (fromTimestamp, toTimestamp) - Add datetime validation to session queries (fromTimestamp, toTimestamp) - Add min(1) constraint to instance creation/update fields (maxUsers, maxRequests) **API Testing (Dependency Injection Pattern)**: - Refactor langfuseApi() to accept optional Fetcher parameter for testability - Add type-safe Fetcher type to avoid 'any' types in tests - Implement comprehensive test coverage without any type assertions: - Timeout handling with AbortController - Content-Type validation (JSON vs text) - 204 No Content response handling - Error propagation with cause preservation - Authorization header validation - Failed response handling **Error Handling**: - Add cause preservation for thrown errors (ESLint preserve-caught-error) - Improve timeout error messages All tests passing: 23 pass, 0 fail Type checking: ✅ No errors Linting: ✅ No warnings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add missing tags parameter forwarding in listTraces - Update server version from 1.0.0 to 1.1.0 - Add .min(1) validation to name fields: - createInstance (instance-management.ts) - createOrganizationProject (organization-projects.ts) - updateOrganizationProject (organization-projects.ts) - createOrganizationApiKey (organization-apikeys.ts) - Update README.md environment variables documentation - Add LANGFUSE_ADMIN_API_KEY explanation - Add LANGFUSE_ORG_API_KEY explanation - Clarify which tools require which API keys Fixes: #3
- Add claude-code-review.yml (4-phase prompt) - Add claude.yml (@claude interactive trigger) - Add .github/copilot-instructions.md (Node/TS template) - Add .prettierignore with .worktrees/ exclusion Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RED — tests fail because LangfuseApiError and withRetry are not yet exported from api.ts. Covers: instanceof check, status field, retry on 429, no-retry on non-429, retry exhaustion.
- LangfuseApiError extends Error with status: number field - withRetry<T> retries on HTTP 429 using configurable delay sequence - langfuseApi now throws LangfuseApiError instead of plain Error
…eClient RED — resetLangfuseClient not yet exported from client.ts. Covers: env validation, singleton pattern, reset behaviour.
Allows test suites to reset the singleton between cases without reaching into module internals.
RED — registerTraceTools ignores second client argument, calls real langfuseApi instead of mock. Tests fail with 404.
registerTraceTools now accepts client parameter (default: getLangfuseClient()) enabling typed fetchTraces/fetchTrace calls with SDK retry behaviour.
RED — registerObservationTools ignores second client argument.
registerObservationTools now accepts client parameter (default: getLangfuseClient()) enabling typed fetchObservations/fetchObservation calls.
RED — registerSessionTools ignores second client argument.
registerSessionTools now accepts client parameter (default: getLangfuseClient()) enabling typed fetchSessions calls.
SDK fetchTraces/fetchSessions expect Date | null | undefined for fromTimestamp/toTimestamp. Also fix bun:test mock.calls tuple type access via double unknown cast.
- traces/observations/sessions handlers now catch SDK errors and return
MCP-idiomatic { isError: true, content: [...] } instead of propagating
unhandled rejections
- Add error-path tests for all three tool families
- Update ToolHandler type to include isError field
- Simplify mock.calls cast to Array<unknown[]> with explicit element cast
# Conflicts: # src/lib/api.test.ts # src/lib/api.ts # src/tools/observations.ts # src/tools/sessions.ts # src/tools/traces.ts
… safety - Wrap langfuseApi() HTTP fetch logic with withRetry() so 429 responses automatically retry with configurable delays (default: 1s/2s/4s) - Add retryDelays option to langfuseApi() opts for caller control - Fix lastError initialization to Error type, eliminating potential non-Error throws from withRetry() - Add langfuseApi 429-retry integration test; add retryDelays: [] to existing error tests to prevent unintended retries
- @v1.0.70 → @v1 - gh pr comment → gh pr review --comment (posts in Reviews section, not comments)
chore: add Bun runtime config
- Add .github/workflows/ci.yml with lint/typecheck/test jobs (bun, concurrency dedup, push-safe if:) - Upgrade claude-code-review.yml to 6-phase prompt (FETCH→FILTER→TRIAGE→WRITE→Self-check→POST) with profile switch (chill/assertive), pr_ctx step for workflow_dispatch fix, and path filter - Add packageManager/engines fields to package.json per Bun standard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Floating @v1 tag is mutable and could be redirected to a malicious commit. Pin to the latest released version for supply chain safety. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Plugin credentials via ${VAR} are user-level (global). This change
lets each project/worktree drop a .env.langfuse file (gitignored)
to override LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY / LANGFUSE_HOST
without touching ~/.zshenv.
Priority: .env.langfuse > Plugin \${VAR} > ~/.zshenv
ci: 移除 Claude review workflows
@jurislm/langfuse-mcp 的 published bin (dist/index.js) 帶有 `#!/usr/bin/env bun` shebang,且 build 使用 `--target bun`。但此套件是透過 `npx @jurislm/langfuse-mcp@latest` 由 Claude Code 啟動,執行環境不保證有 bun 在 PATH 上——實測 `.bun/bin` 僅存在於 ~/.zshrc(互動式 shell),任何 login shell 或 GUI 啟動的行程都會直接失敗: env: bun: No such file or directory 改為 `--target node` + node shebang。原始碼完全沒有使用 Bun.* API(grep 驗證 為 0 處),故無相容性風險。engines 同步由 bun 改為 node >= 18。 與 hetzner-mcp / coolify-mcp 一致(兩者皆為 node shebang,可正常經 npx 啟動)。 新增 src/index.test.ts 防止迴歸:斷言 entrypoint shebang 為 node、build script target 為 node。已反向驗證——把 shebang 改回 bun 時該測試確實 fail。 驗證: - 53 + 2 tests / typecheck / lint 全綠 - 以 env -i(僅 HOME + 最小 PATH,無 bun)純 node 執行 dist/index.js: MCP initialize handshake 成功、tools/list 回傳 50 個工具、 listPrompts 實打 Langfuse API 回傳 isError:false 與正常分頁結果
承 6859c4f。code review 找出兩個讓該修正形同虛設的問題: 1. README.md 與 CLAUDE.md 的整合範例仍叫使用者用 `"command": "bunx"`。 bunx 無論 shebang 為何都以 bun runtime 執行,照文件設定的人完全享受不到 node 化的好處;在沒有 bun 的機器上依舊以 `env: bun: No such file or directory` 失敗。兩處改為 `npx -y`。 (README 的 `bun install` / `bun run dev` 等開發指令維持不變——bun 仍是 本 repo 的開發工具,只有「發布產物的執行期」不該依賴它。) 2. src/index.test.ts 守錯了 artifact:它斷言 `src/index.ts` 的 shebang, 但 npx 實際執行的是 `dist/index.js`。任何讓 dist 退回 bun 的變更 (換 bundler、加 postbuild、bun 預設值改變)都能通過該測試。 新增 scripts/check-dist-runtime.mjs 直接檢查 dist/index.js 的 shebang 與是否殘留 Bun.* 呼叫,掛在 prepublishOnly——剛好落在產物產生之後、 上傳 npm 之前。原測試簡化為只留原始碼的早期訊號,並移除對 `pkg.scripts.build` 字串的脆弱斷言(`--target=node` 等價寫法會誤判)。 驗證: - 54 tests / typecheck / lint 全綠 - 守衛反向驗證:竄改 dist shebang 為 bun → exit 1;注入 Bun.file → exit 1; 正常產物 → exit 0
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 30 seconds Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
此 PR 旨在讓 @jurislm/langfuse-mcp 的「發布產物執行期」改為 Node runtime(避免 npx @jurislm/langfuse-mcp 在無 Bun 環境下因 shebang 失敗),並補上 publish 前針對 dist/index.js 的 runtime 守衛,同步更新文件範例的啟動方式。
Changes:
- 將 entrypoint shebang 改為
#!/usr/bin/env node,並把bun buildtarget 調整為node、start改用node dist/index.js、engines設定為node >= 18。 - 新增
scripts/check-dist-runtime.mjs並掛到prepublishOnly,在 publish 前檢查dist/index.jsshebang 與是否殘留Bun.*參照。 - 更新 README/CLAUDE 文件範例由
bunx改為npx -y;移除 Claude 相關 GitHub Actions workflow;新增 CodeRabbit 設定檔。
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/index.ts |
將 shebang 切到 node,並加入 .env.langfuse 載入邏輯 |
src/index.test.ts |
新增測試,針對 src/index.ts shebang 提供早期失敗訊號 |
scripts/check-dist-runtime.mjs |
新增 publish 前守衛:檢查 dist/index.js shebang 與 Bun API 參照 |
package.json |
build/start/engines 調整為 node 執行期;prepublishOnly 串上 dist 守衛腳本 |
README.md |
Claude Code 範例改用 npx -y 啟動 |
CLAUDE.md |
整合範例改用 npx -y 啟動 |
.github/workflows/claude.yml |
移除 Claude Code workflow |
.github/workflows/claude-code-review.yml |
移除 Claude Code Review workflow |
.coderabbit.yaml |
新增 CodeRabbit 自動審查語言/語氣設定 |
| // Load per-project credentials from .env.langfuse (gitignored, no new deps) | ||
| import { existsSync, readFileSync } from "fs"; | ||
| import { join } from "path"; | ||
| const _envFile = join(process.cwd(), ".env.langfuse"); | ||
| if (existsSync(_envFile)) { | ||
| for (const line of readFileSync(_envFile, "utf-8").split("\n")) { | ||
| const t = line.trim(); | ||
| if (!t || t.startsWith("#")) continue; | ||
| const eq = t.indexOf("="); | ||
| if (eq === -1) continue; | ||
| const key = t.slice(0, eq).trim(); | ||
| const val = t.slice(eq + 1).trim().replace(/^["']|["']$/g, ""); | ||
| process.env[key] = val; | ||
| } | ||
| } |
| * 環境變數(優先順序:.env.langfuse > Plugin ${VAR} > ~/.zshenv): | ||
| * LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_HOST |
| const shebang = source.split("\n", 1)[0]; | ||
| if (shebang !== "#!/usr/bin/env node") { | ||
| fail(`dist/index.js shebang is ${JSON.stringify(shebang)}, expected "#!/usr/bin/env node"`); | ||
| } |
| "command": "npx", | ||
| "args": ["-y", "@jurislm/langfuse-mcp@latest"], | ||
| "env": { |
|
改由 |
問題
@jurislm/langfuse-mcp的 published bin (dist/index.js) 帶有#!/usr/bin/env bunshebang,build 使用--target bun。但此套件是透過
npx @jurislm/langfuse-mcp@latest由 Claude Code 啟動,執行環境不保證有 bun。實測.bun/bin僅存在於~/.zshrc(互動式 shell),任何 login shell 或 GUI 啟動的行程都會直接失敗:驗證方式:
修法
#!/usr/bin/env nodebun build --target nodeengines→{ "node": ">=18" }原始碼完全沒有使用
Bun.*API(grep 驗證為 0 處),無相容性風險。與hetzner-mcp/coolify-mcp一致(兩者皆為 node shebang,可正常經 npx 啟動)。bun install/bun run dev等開發指令維持不變——bun 仍是本 repo 的開發工具,只有「發布產物的執行期」不該依賴它。Code review 追加修正(668923a)
文件仍叫使用者用
bunx:README.md:111與CLAUDE.md:172的整合範例是"command": "bunx"。bunx無論 shebang 為何都以 bun runtime 執行,照文件設定的人完全享受不到這次修正。兩處改為npx -y。測試守錯 artifact:原測試斷言
src/index.ts的 shebang,但 npx 實際執行的是dist/index.js。任何讓 dist 退回 bun 的變更(換 bundler、加 postbuild、bun 預設值改變)都能通過該測試。新增
scripts/check-dist-runtime.mjs直接檢查dist/index.js的 shebang 與是否殘留Bun.*呼叫,掛在prepublishOnly——剛好落在產物產生之後、上傳 npm 之前。驗證
env -i(僅HOME+ 最小 PATH,無 bun)純 node 執行dist/index.js:MCPinitializehandshake 成功、tools/list回傳 50 個工具、listPrompts實打 Langfuse API 回傳isError: falseexit 1;注入Bun.file→exit 1;正常產物 →exit 0Test plan
bun run testbun run typecheckbun run lintnode scripts/check-dist-runtime.mjs(含反向驗證)jurislm-tools/plugins/langfuse/.mcp.json比照 coolify/hetzner 套用 login shell +env -i