Comet Opik

ทางการ

สอบถามและวิเคราะห์ Opik logs, traces, prompts และข้อมูลเทเลเมทรีอื่นๆ ทั้งหมดจาก LLMs ของคุณด้วยภาษาธรรมชาติ

GitHub
221
ลองใช้ MCP นี้ผู้สนับสนุน

คุณทำอะไรได้บ้างด้วย Comet Opik MCP?

  • อ่าน traces และ projects — ขอ trace, span หรือ project ด้วย ID หรือชื่อ แล้วรับบันทึกแบบเต็มพร้อม children แบบ inline
  • แสดงรายการและกรอง traces — เรียกดู traces, spans หรือ threads ด้วยตัวกรอง OQL, ช่วงเวลา และการเรียงลำดับ เช่น "แสดง traces ที่ล้มเหลวใน project demo วันนี้"
  • ให้คะแนนและแสดงความคิดเห็นบน traces — แนบคะแนน feedback แบบตัวเลขหรือความคิดเห็นแบบข้อความอิสระไปยัง traces, spans หรือ threads ผ่าน write
  • บันทึกเวอร์ชัน prompt — สร้างหรืออัปเดตเวอร์ชัน prompt ใน workspace ของคุณโดยตรงจากแชท
  • จัดการ datasets และ experiments — สร้าง datasets, อัปเดต items และแนบผลลัพธ์การทดลองเพื่อเปรียบเทียบการรัน
  • ตรวจสอบ write schemas — ถาม schema สำหรับโครงสร้าง JSON ที่แน่นอนและฟิลด์ที่จำเป็นก่อนเรียกใช้การดำเนินการเขียนใดๆ

เอกสาร

เซิร์ฟเวอร์ MCP ของ Opik

เซิร์ฟเวอร์ Model Context Protocol (MCP) อย่างเป็นทางการสำหรับ Opik แพลตฟอร์มการสังเกตการณ์และประเมินผล LLM แบบโอเพนซอร์ส สร้างโดย Comet เชื่อมต่อ AI host ของคุณ (Claude Code, Cursor, VS Code Copilot, Codex, opencode หรือ MCP client ใดๆ) เข้ากับ Opik workspace ของคุณโดยตรง: อ่าน traces, บันทึก scores และบันทึกเวอร์ชัน prompt ทั้งหมดจากในแชท

สร้างขึ้นสำหรับวิศวกร LLM ที่ใช้งาน Opik อยู่แล้วและต้องการควบคุมมันจาก AI assistant ตัวเดียวกับที่ใช้เขียนโค้ด

กำลังย้ายจาก npx opik-mcp เวอร์ชันเก่าอยู่หรือไม่? เซิร์ฟเวอร์ TypeScript ถูกเลิกใช้งานและจะยุติการให้บริการใน 2026-11-15 เปลี่ยน npx -y opik-mcp เป็น uvx opik-mcp@latest ใน MCP client config ของคุณ คู่มือฉบับเต็ม: legacy/typescript/MIGRATION.md

You:    "Which traces in project 'demo' failed today?"
Claude: → list(entity_type="trace", project_name="demo") → "Three traces failed…"

You:    "Score trace 7f2e… 0.9 on helpfulness with reason 'great recovery'."
Claude: → write(score.create) → done

เริ่มต้นอย่างรวดเร็ว

คำสั่งเดียวลงทะเบียนเซิร์ฟเวอร์กับ AI clients บนเครื่องของคุณ ติดตั้งชุดทักษะ Opik และตรวจสอบการเชื่อมต่อ ต้องใช้ uv และไม่ต้องใช้ Opik SDK:

uvx opik mcp configure

มันตรวจจับ Claude Code, Cursor, VS Code Copilot, Codex และ opencode และใช้เซิร์ฟเวอร์ที่โฮสต์บน Opik Cloud (เข้าสู่ระบบผ่านเบราว์เซอร์ ไม่มีการเก็บ API key) หรือเซิร์ฟเวอร์ท้องถิ่นนี้ในที่อื่น MCP client อื่นๆ สามารถใช้ hosted URL ได้โดยตรง:

npx add-mcp https://www.comet.com/opik/api/v1/mcp --name opik-mcp

Add to Cursor Install in VS Code

คู่มือการตั้งค่า การแก้ไขปัญหา และ FAQ: comet.com/docs/opik/mcp-server README ที่เหลือครอบคลุมเซิร์ฟเวอร์ท้องถิ่น ซึ่งคำสั่งด้านบนตั้งค่าให้สำหรับ Opik แบบ self-hosted และโอเพนซอร์ส และคุณยังสามารถกำหนดค่าด้วยตนเองได้


การติดตั้งด้วยตนเอง

opik-mcp เป็นแพ็คเกจ Python (ต้องใช้ Python 3.13+) วิธีที่แนะนำในการรันคือ uvx ซึ่งดึงและรันเวอร์ชันล่าสุดที่เผยแพร่ตามความต้องการ — ไม่ต้องติดตั้งทั่วโลก ไม่ต้องจัดการ virtualenv

ติดตั้ง uv ครั้งเดียว:

curl -LsSf https://astral.sh/uv/install.sh | sh   # macOS / Linux
# or: brew install uv

คุณจะต้องมีสองสิ่งจาก Opik workspace ของคุณ:

  • OPIK_API_KEY — รับได้จาก comet.com/api/my/settings/
  • OPIK_WORKSPACE — ชื่อ workspace ของคุณ (ตัวพิมพ์เล็ก ตามที่ปรากฏใน URL) เช่น https://www.comet.com/acme-ai/... → OPIK_WORKSPACE=acme-ai ยอมรับ COMET_WORKSPACE เป็น alias ที่เลิกใช้แล้ว

Cloud พร้อม API key: ตั้งค่าเว้นแต่ค่าเริ่มต้นของบัญชีคุณเป็นค่าที่ต้องการ หากละไว้ เซิร์ฟเวอร์จะส่ง default ซึ่ง Comet แก้เป็น workspace เริ่มต้นของบัญชีคุณ ซึ่งใช้งานได้ แต่ถ้าคุณทำงานใน workspace ที่มีชื่อจริง คุณจะถูกชี้ไปที่อื่นโดยไม่มีอะไรบอก — การอ่านข้อมูลของคุณจะได้มาจากที่ผิดแทนที่จะล้มเหลว

Cloud ผ่าน OAuth: ปล่อยว่างไว้ workspace มาจาก token ที่คุณอนุญาต และเซิร์ฟเวอร์จะไม่สนใจการตั้งค่านี้โดยสิ้นเชิง

Local / โอเพนซอร์ส: ปล่อยว่างไว้ Opik โอเพนซอร์สมี workspace เดียวชื่อ default และไม่มีวิธีสร้างเพิ่ม ซึ่งเป็นสิ่งที่ค่า fallback ให้คุณพอดี

Self-hosted Comet: ตั้งค่า ต่างจากโอเพนซอร์ส การติดตั้งเหล่านี้มี workspace ที่มีชื่อจริง และมีความเสี่ยงเรื่อง workspace ผิดแบบเงียบๆ เช่นเดียวกัน

ไม่ว่ากรณีใด ตรวจสอบให้แน่ใจว่าค่าถูกแทนที่จริง สนิปเพ็ตที่แจกจ่ายทั่วไปมี placeholder เช่น <your-workspace> หรือ ${input:OPIK_WORKSPACE}; หากวางตามที่เป็น ค่าเหล่านั้นไม่ใช่ชื่อ workspace ตอนนี้เซิร์ฟเวอร์ปฏิเสธค่าเหล่านั้นทันที แทนที่จะปล่อยให้ backend ตอบกลับด้วยข้อผิดพลาดการตรวจสอบสิทธิ์ที่ไม่ได้อธิบายอะไรเลย

Claude Code

เพิ่มเซิร์ฟเวอร์ด้วยคำสั่งเดียว:

claude mcp add --transport stdio opik-mcp \
  --env OPIK_API_KEY=<your-key> \
  --env OPIK_WORKSPACE=<your-workspace> \
  -- uvx opik-mcp

หรือแก้ไข ~/.claude.json โดยตรง:

{
  "mcpServers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_API_KEY": "<your-key>",
        "OPIK_WORKSPACE": "<your-workspace>"
      }
    }
  }
}

รีสตาร์ท Claude Code ตรวจสอบด้วย /mcp — opik-mcp ควรปรากฏเป็นเชื่อมต่อแล้ว จากนั้นในแชท ถามว่า: "list my Opik projects" — Claude จะเรียกใช้เครื่องมือ list และคุณจะเห็นโปรเจกต์ใน workspace ของคุณ

Cursor

แก้ไข ~/.cursor/mcp.json (ระดับโลก) หรือ .cursor/mcp.json (ระดับโปรเจกต์) หรือเปิด Cmd+Shift+J → Features → Model Context Protocol:

{
  "mcpServers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_API_KEY": "<your-key>",
        "OPIK_WORKSPACE": "<your-workspace>"
      }
    }
  }
}

โหลด Cursor ใหม่; จุดสีเขียวข้าง opik-mcp ในแผง MCP ยืนยันการเชื่อมต่อ ถามในแชท: "list my Opik projects"

Cursor หมดเวลา 60 วินาที Cursor บังคับการหมดเวลาการเรียกเครื่องมือแบบตายตัวซึ่งไม่รีเซ็ตเมื่อมีการแจ้งความคืบหน้า ดู ข้อจำกัดของ host ที่รู้จัก

VS Code Copilot

.vscode/mcp.json ใน workspace ของคุณ (หรือ User Settings JSON):

{
  "servers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_API_KEY": "<your-key>",
        "OPIK_WORKSPACE": "<your-workspace>"
      }
    }
  }
}

โหลดหน้าต่างใหม่; ตัวบ่งชี้ MCP ใน Copilot Chat แสดง opik-mcp เมื่อเซิร์ฟเวอร์เข้าถึงได้ ถามในแชท: "list my Opik projects"

MCP Inspector (การทดสอบด้วยตนเอง)

OPIK_API_KEY=<your-key> OPIK_WORKSPACE=<your-workspace> \
  npx @modelcontextprotocol/inspector uvx opik-mcp

Opik แบบ Self-hosted

เพิ่ม COMET_URL_OVERRIDE (และ OPIK_URL หาก Opik อยู่ที่พาธที่ไม่ใช่ค่าเริ่มต้น) ในบล็อก env เดียวกันใน config ของ host:

{
  "mcpServers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_API_KEY": "<your-key>",
        "OPIK_WORKSPACE": "<your-workspace>",
        "COMET_URL_OVERRIDE": "https://opik.your-company.com",
        "OPIK_MCP_ANALYTICS_SOURCE": ""
      }
    }
  }
}

ละเว้น OPIK_WORKSPACE ในการติดตั้งโอเพนซอร์ส ซึ่ง default เป็น workspace เดียว; เก็บไว้บน Comet แบบ self-hosted ซึ่งมี workspace ที่มีชื่อจริง

การตั้งค่า OPIK_MCP_ANALYTICS_SOURCE="" เลือกไม่ใช้ป้ายกำกับแหล่งที่มาของ cloud-Comet ในเหตุการณ์ telemetry


เครื่องมือ

opik-mcp เผยพื้นผิวที่เล็กและเน้นผลลัพธ์ซึ่งครอบคลุมวงจรชีวิตทั้งหมด (อ่าน → ใส่คำอธิบาย → จัดระเบียบ → สร้าง → ทำซ้ำ)

เครื่องมือวัตถุประสงค์
readอ่านสากลด้วย id / ชื่อ / URI opik://
listรายการสากลพร้อมตัวกรองชื่อและแบ่งหน้า
writeเขียนสากล — บันทึก traces/spans, ให้คะแนน, แสดงความคิดเห็น, บันทึก prompts, จัดการ datasets และ experiments
schemaตรวจสอบ schema ของการดำเนินการเขียน (ใช้โดย LLM เพื่อสร้าง payload ที่ถูกต้อง)
read_skillอ่านหนึ่งในทักษะ agent ของ Opik ที่มาพร้อมกับเซิร์ฟเวอร์นี้

read

เครื่องมือเดียวสำหรับคำถาม "แสดง X ให้ฉันดู" รับ entity_type พร้อม id (UUID หรือสำหรับประเภทที่มีชื่อ ใช้ชื่อ) หรือ URI opik:// เต็ม การอ่านแบบรวม (trace, prompt, thread, agent_insights_issue) แทรก children แบบอินไลน์เพื่อให้การเรียกครั้งเดียวได้ภาพรวมทั้งหมด

เรกคอร์ดที่คุณระบุชื่อจะกลับมาทั้งหมด children ที่แทรกแบบอินไลน์ไม่เป็นเช่นนั้น: body ของพวกมันถูกดึงด้วย truncate=true ของ backend ดังนั้นฟิลด์ที่เกิน ~10 KB จะถูกตัดใน ClickHouse และรูปภาพ base64 จะถูกแทนที่ด้วย "[image]" — ไฟล์แนบหนึ่งรายการที่สะท้อนผ่าน 200 spans จะมีค่าใช้จ่ายมากกว่าทุกอย่างอื่นในการอ่าน คำตอบจะบอกใน spanBodies / messageBodies และ child ใดๆ จะกลับมาสมบูรณ์อีกครั้งผ่าน read("span", id) หรือ read("trace", trace_id) ของตัวเอง ซึ่งเข้าถึง endpoints ที่ไม่มีพารามิเตอร์ truncate เลย

คอลเลกชันที่แทรกแบบอินไลน์ยังจำกัดความยาว: 200 spans, 200 turns, 100 prompt versions เกินกว่านั้น spansTruncated / messagesTruncated / versionsTruncated เป็น true และบรรทัด moreSpans / moreMessages / moreVersions ข้างๆ เก็บจำนวนและคำสั่งเรียก list(...) ที่แน่นอนซึ่งดำเนินการต่อจากจุดที่ส่วนที่แทรกหยุด

เอนทิตีที่รองรับ: project, trace, span, dataset, dataset_item, experiment, prompt, thread, agent_insights_issue การค้นหาตามชื่อใช้ได้สำหรับ project, experiment, prompt, dataset (ช้ากว่า — สอง API calls — และอาจคืนค่าหลายรายการที่ตรงกัน) thread และ agent_insights_issue ถูกจำกัดขอบเขตตามโปรเจกต์: ส่ง project_id หรือ project_name หรือลิงก์/URI ที่มีโปรเจกต์ dataset และ dataset_item เคยถูกเรียกว่า test_suite และ test_suite_item; ชื่อเก่ายังคงใช้งานได้ แต่ไม่ถูกประกาศและโค้ดใหม่ควรใช้ชื่อใหม่

read(entity_type="trace", id="7f2e3c8a-…")
read(entity_type="project", id="demo")          # name lookup
read(entity_type="trace", id="opik://traces/7f2e3c8a-…")
read(entity_type="agent_insights_issue", id="<issue-uuid>", project_id="<project-uuid>")
read(entity_type="agent_insights_issue", id="https://www.comet.com/opik/<ws>/projects/<pid>/diagnostics?issue=<id>")

ลิงก์ที่คัดลอกจาก UI ของ Opik ใช้เป็น id: ลิงก์เธรดหรือลิงก์หน้า Diagnostics มีโปรเจกต์ ดังนั้นไม่ต้องใช้ project_id และประเภทเอนทิตีถูกนำมาจากลิงก์

การอ่าน project ตอบคำถาม "โปรเจกต์ของฉันเป็นอย่างไร" ในการเรียกครั้งเดียว มันคืนค่า {project, summary, vocabulary, contains, url}: เรกคอร์ด จากนั้นตัวเลขสี่ตัวที่หน้า Logs แสดงเป็นการ์ด (จำนวน traces, อัตราข้อผิดพลาด, ระยะเวลาเฉลี่ย, ค่าใช้จ่ายทั้งหมด) สำหรับ 7 วันล่าสุดเทียบกับ 7 วันก่อนหน้า เฉพาะการรับส่งข้อมูล SDK ตามที่แสดงบนหน้าจอ since / until เลื่อนหน้าต่างนั้น; since="30d" คือสิ่งที่ UI เปิด อัตราหรือค่าเฉลี่ยในช่วงเวลาที่ไม่มี traces จะกลับมาเป็น null เพราะอัตราข้อผิดพลาด 0% ในสัปดาห์ที่ไม่มีการรับส่งข้อมูลอ่านเหมือนสัปดาห์ที่แข็งแรง

vocabulary คือแผนที่ที่คุณต้องมีก่อนจะถามอย่างอื่น: ชื่อคะแนน feedback ของโปรเจกต์, คีย์การใช้งาน token และกฎอัตโนมัติที่ให้คะแนน traces ชื่อเหล่านี้คือชื่อที่ใส่ในตัวกรองหรือใน series= ด้านล่าง และการเดาชื่อจะได้หน้าว่างที่อ่านเหมือนข่าวดี ชื่อคะแนนและกฎถูกจำกัดจำนวน รายงานยอดรวมจริงเสมอ และระบุการเรียกที่คืนค่าส่วนที่เหลือ; คีย์การใช้งานถูกแสดงทั้งหมด เนื่องจากไม่มีอะไรอื่นแจกแจง contains ระบุ experiment, dataset, prompt version และ optimization run ล่าสุด ดังนั้น "เกิดอะไรขึ้นที่นี่" ไม่ต้องเรียกเพิ่มอีกสี่ครั้ง ส่วนที่โหลดไม่สำเร็จจะบอกแทนที่จะดูว่างเปล่า และส่วนที่ว่างเปล่าจะถูกละเว้น

การอ่าน agent_insights_issue คืนค่า {issue, example_trace_ids, details}: เรกคอร์ดปัญหา Diagnostics (ชื่อ, คำอธิบาย, สาเหตุ, คำแนะนำการแก้ไข, ความรุนแรง, สถานะ), id ที่ไม่ซ้ำของ traces ที่แสดงปัญหา (ตัวอย่างเดียวกับที่หน้า Diagnostics แสดง — เปิดด้วย read("trace", id)) และรายละเอียดรายวัน body ของ trace ไม่ถูกแทรกแบบอินไลน์ ดังนั้นการอ่านจึงเป็นการเรียก backend ครั้งเดียว since / until จำกัดแถวรายวัน; ค่าเริ่มต้นคือตลอดเวลา เมื่อเซิร์ฟเวอร์รู้ URL ของ Opik และ workspace ของเซสชัน การอ่านยังมี url (หน้า Diagnostics ของปัญหา) และ trace_url_template (ลิงก์ลึกสำหรับ traces ตัวอย่างใดๆ) เพื่อให้ผู้ช่วยส่งสิ่งที่คลิกได้ให้คุณ; ภายใต้เซสชัน OAuth ที่ไม่สามารถระบุ workspace ได้ ลิงก์จะถูกละเว้นแทนที่จะเดา

Traces เองไม่มี URL — ลิงก์สำหรับ trace ไม่สามารถหาได้จากฟิลด์ที่ read หรือ list คืนค่า และรูปแบบที่เดาจะ 404 คำแนะนำเซสชันระบุเทมเพลตแทน .../v1/session/redirect/projects/?trace_id={trace_id}&path=... เพื่อให้ผู้ช่วยกรอก id และส่งลิงก์ให้คุณ มันผ่านการเปลี่ยนเส้นทางของ opik-backend ซึ่งแก้โปรเจกต์และ workspace จาก trace ดังนั้นมันจึงทำงานในที่ที่ URL โปรเจกต์โดยตรงใช้ไม่ได้ รวมถึงเซสชัน OAuth ที่ไม่สามารถระบุ workspace ได้ มันเป็นลิงก์เดียวกับที่ Python SDK พิมพ์สำหรับ trace

list

เรียกดูหรือค้นหาคอลเลกชันด้วยการแบ่งหน้า ประเภทที่จำกัดขอบเขตตามโปรเจกต์ (trace, span, thread, agent_insights_issue, dataset_item, prompt_version) ต้องมี parent: UUID หรือชื่อโปรเจกต์, UUID ของ dataset หรือ UUID ของ prompt

list(entity_type="experiment", page=1, size=25)
list(entity_type="experiment", name="rerank")          # name substring filter
list(entity_type="agent_insights_issue", project_name="demo")             # open Diagnostics issues
list(entity_type="agent_insights_issue", project_id="<uuid>", status="resolved")
list(entity_type="trace", project_name="demo")         # latest traces of one project
list(entity_type="trace", project_name="demo",
     filters='error_info is_not_empty AND duration > 5000')
list(entity_type="span", project_name="demo",          # spans across the whole project
     filters='type = "llm" AND usage.total_tokens > 10000')
list(entity_type="thread", project_name="demo",
     filters='number_of_messages > 20 AND feedback_scores.helpfulness < 0.5')
list(entity_type="experiment",
     filters='dataset_id = "<dataset-uuid>" AND tags contains "baseline"')

ตัวกรอง trace, span, thread, experiment และ dataset_item รับสตริง OQL ซึ่งเป็นไวยากรณ์เดียวกับ search_traces(filter_string=…) ของ SDK:

<field>[.<key>] <op> <value> [AND ...]
ops: = != > >= < <= contains not_contains starts_with ends_with is_empty is_not_empty in not_in

สตริงอยู่ในเครื่องหมายคำพูดคู่ ตัวเลขไม่ต้องมีเครื่องหมาย duration เป็นมิลลิวินาที วันที่เป็น ISO-8601 instants พร้อมเขตเวลา ("2026-09-08T10:00:00Z") คะแนนและพจนานุกรมใช้คีย์: feedback_scores.accuracy < 0.5, metadata.environment = "prod" AND เป็นตัวเชื่อมเดียว

เช่นเดียวกับหน้า Logs ของ UI รายการ trace, span และเธรดเพิ่ม source = "sdk" เพื่อให้ traces ของ evaluator, playground และ experiment ไม่อยู่ในทาง; ตั้งชื่อ source ด้วยตัวเองเพื่อดู บรรทัดเอาต์พุตแรกสะท้อนตัวกรองที่ถูกใช้ ฟิลเตอร์ที่ไม่ดีจะล้มเหลวก่อนที่จะถึงแบ็กเอนด์พร้อมกับสิ่งที่จำเป็นในการแก้ไข: ตำแหน่งของข้อผิดพลาดทางไวยากรณ์ ชื่อฟิลด์ที่ใกล้เคียงที่สุด ตัวดำเนินการที่ถูกต้องสำหรับ ประเภทของฟิลด์ หรือรูปแบบค่าที่คาดหวัง ฟิลด์ที่มีชุดค่าปิด (source, span type, thread status, visibility_mode) จะถูกตรวจสอบ กับชุดนั้นด้วย ทุกองค์ประกอบของรายการ in รวมอยู่ด้วย source คือสิ่งที่ แบ็กเอนด์ตรวจสอบเอง และมันตอบค่าที่ไม่รู้จักด้วยรหัส 500 แทนที่จะเป็น 400 ดังนั้น source = "SDK" จะเป็นข้อผิดพลาดเซิร์ฟเวอร์ที่ไม่ชัดเจนสำหรับ ตัวพิมพ์ใหญ่ ส่วนที่เหลือจะถูกเปรียบเทียบเป็นสตริงและตอบด้วยหน้าว่าง ซึ่งอ่านว่า "ไม่มีการจับคู่" ในเมื่อความหมายจริงคือ "ไม่มีค่าดังกล่าว" ถาม schema("list.trace") (หรือ list.span, list.thread, list.experiment) สำหรับ ข้อมูลอ้างอิงฟิลด์ทั้งหมด รวมถึงค่าที่ยอมรับได้

การค้นหาหนึ่งกรณีในชุดข้อมูล list(entity_type="dataset_item", dataset_id=…) filters on the case itself: data.<key> สำหรับคีย์ที่ ชุดข้อมูลถูกสร้างขึ้นด้วย full_data สำหรับสตริงย่อยของเพย์โหลดทั้งหมด (การ สแกนเต็มรูปแบบ — ระบุคีย์เมื่อทำได้) รวมถึง id, tags, source, trace_id, span_id และการประทับเวลา data.<key> รับเฉพาะตัวดำเนินการสตริงหกตัวเท่านั้น (=, !=, contains, not_contains, starts_with, ends_with); แบ็กเอนด์ตอบการเปรียบเทียบด้วยรหัส 400 ดังนั้นตัวนี้จึงถูกปฏิเสธก่อน การเรียก เอนด์พอยต์นี้ไม่มีการเรียงลำดับและไม่มีการค้นหาข้อความอิสระ — sort ถูกปฏิเสธ แทนที่จะถูกทิ้ง read(entity_type="dataset_item", id=…) ส่งคืนหนึ่งกรณี ทั้งหมด ซึ่งเป็นวิธีที่อ่านค่าที่ตารางตัดออกไปกลับคืนมา

list(entity_type="dataset_item", dataset_id="<uuid>",
     filters='data.question contains "install"')
list(entity_type="dataset_item", dataset_id="<uuid>",
     filters='trace_id = "<trace-uuid>"')                 # the case made from that trace
read(entity_type="dataset_item", id="<item-uuid>")        # the case, uncut

ด้วย experiment_ids รายการเดียวกันนี้คือการเปรียบเทียบแทน — กรณีที่ แต่ละรันถูกแนบมา — และมันกรองบนรัน (feedback_scores.<name>, output, duration) ทั้งสองเป็นชุดฟิลด์ที่แตกต่างกันบนเอนด์พอยต์แบ็กเอนด์สองตัว: schema("list.dataset_item_case") คือกรณีของชุดข้อมูลเอง schema("list.dataset_item") คือการเปรียบเทียบ

การเรียงลำดับ trace, span, thread และ experiment รับ sort="<field> [asc|desc]", desc โดยค่าเริ่มต้นและฟิลด์เดียวเท่านั้น: sort="duration desc", sort="total_estimated_cost", sort="feedback_scores.accuracy asc", sort="usage.total_tokens" ฟิลด์จะถูก ตรวจสอบกับรายการที่เรียงลำดับได้ของเอนทิตีก่อนการเรียก เพราะแบ็กเอนด์ ละเว้นฟิลด์ที่ไม่สามารถเรียงลำดับได้อย่างเงียบ ๆ ในเวิร์กสเปซขนาดใหญ่มาก แบ็กเอนด์ ทิ้งการเรียงลำดับทั้งหมด; ส่วนหัวจะบอกเช่นนั้นเมื่อเกิดขึ้น

dataset_item เรียงลำดับเฉพาะเป็นการเปรียบเทียบ (ด้วย experiment_ids): เอนด์พอยต์ รายการไม่รับพารามิเตอร์การเรียงลำดับ ดังนั้นการเรียงลำดับในรายการธรรมดาจะถูกปฏิเสธ แทนที่จะถูกทิ้ง

กรอบเวลาและการค้นหา trace, span และ thread รับ since และ until, แต่ละอันเป็นช่วงสัมพัทธ์ ("30m", "1h", "7d") หรือช่วงเวลามาตรฐาน ISO-8601 พร้อมเขตเวลา ดังนั้น "ชั่วโมงที่ผ่านมา" จึงไม่ต้องคำนวณนาฬิกา กรอบเวลาอ้างอิงตาม เวลาสร้างเรกคอร์ด ซึ่งมีต้นทุนต่ำสำหรับแบ็กเอนด์และสอดคล้องกับ start_time ภายในไม่กี่วินาทีสำหรับการรับส่งข้อมูลสด สำหรับขอบเขตที่แน่นอน ใส่ start_time ใน filters สามประเภทเดียวกันนี้รับ search, ข้อความอิสระที่จับคู่ ที่ใดก็ได้ใน id, name, input, output, metadata, tags และ thread id การค้นหาสแกน ทั้งโปรเจกต์บนแบ็กเอนด์ ดังนั้นการเรียกครั้งแรกบนโปรเจกต์ขนาดใหญ่อาจใช้เวลา หลายสิบวินาที การเรียกเหล่านั้นได้รับหมดเวลา 60 วินาที การเพิ่ม since ทำให้เร็ว อีกครั้ง

การอ่านตาราง ระยะเวลาถูกติดป้าย duration_ms / ttft_ms และ แสดงเป็นมิลลิวินาทีทั้งจำนวน; ฟิลด์ยังคงเป็น duration ใน filters และ sort การประทับเวลาแสดงถึงวินาทีและต้นทุนเป็นทศนิยมธรรมดา แถวโปรเจกต์มี last_updated_trace_at เพื่อให้คุณเห็นว่าโปรเจกต์ใดมี การรับส่งข้อมูลสด; แถวเธรดมีข้อความแรก หน้าว่างภายใต้กรอบเวลา บอกว่าเทรซสุดท้ายของโปรเจกต์ลงจอดเมื่อใด และหน้าว่างภายใต้ source = "sdk" เริ่มต้นบอกวิธีดูแหล่งข้อมูลอื่น การสะกดผิดของ project_name กลับมาพร้อมกับชื่อที่มีอยู่ใกล้เคียงที่สุด

list(entity_type="trace", project_name="demo", since="1h",
     filters="error_info is_not_empty", sort="duration desc")
list(entity_type="trace", project_name="demo", search="order-42")

ปัญหาการวินิจฉัย agent_insights_issue คือหน้า Diagnostics ผ่าน MCP: ความล้มเหลวที่เกิดซ้ำซึ่งงาน Diagnostics ของ Opik จัดกลุ่มสำหรับโปรเจกต์ จัดอันดับตามที่ UI จัดอันดับ (เห็นล่าสุดก่อน) คอลัมน์คือ severity, status, total_occurrences (ผลรวมตลอดกาล), latest_count (วันรายงานล่าสุด ตัวเลขที่คำอธิบายของปัญหาอ้างถึง) และ last_seen ปัญหาที่เปิดอยู่จะถูกแสดงโดยค่าเริ่มต้น; ส่ง status="resolved" หรือ "closed" สำหรับ ส่วนที่เหลือ read และ list ยังตอบสนองต่อ issue ซึ่งเป็นสิ่งที่ UI เรียก สิ่งเหล่านี้; ชื่อยาวคือชื่อใน enum entity_type ดังนั้นเอนทิตีนั้น จะไม่ปรากฏสองครั้งที่นั่น จำนวนเป็นตลอดกาลเพื่อให้ตรงกับ UI; since / until เดียวกัน กับเทรซทำให้กรอบเวลาแคบลง ตัดทอนเป็นวันรายงาน UTC เพราะ Diagnostics รวมกลุ่มต่อวัน

รายการว่างบอกว่าทำไมมันว่าง เพราะ "ไม่มีอะไรเสีย" และ "ไม่มีใคร เปิด Diagnostics" อ่านเหมือนกัน มิฉะนั้น มีห้าสถานะ: Diagnostics ไม่พร้อมใช้งานบนดีพลอยเมนต์นี้ ไม่เปิดใช้งานสำหรับโปรเจกต์นี้ ปิดอยู่ เปิดใช้งานแต่ยังไม่สแกนเมื่อเร็ว ๆ นี้ หรือเปิดใช้งานและสะอาดพร้อมกับ เวลาของการสแกนครั้งล่าสุด สถานะที่คุณสามารถดำเนินการได้จะระบุการเรียกที่ต้องทำ และทุก สถานะเชื่อมโยงหน้า Diagnostics ของโปรเจกต์

รายการที่ไม่ว่างจะระบุวันที่ของตัวเอง ปัญหาคือสิ่งที่การสแกนครั้งล่าสุดจัดกลุ่ม ดังนั้นคำตอบจะจบด้วย Report covers data through <time> และเมื่อกรอบเวลา ที่คุณถามถึงเลยไปกว่านั้น มันจะระบุส่วนท้ายที่ไม่ครอบคลุมและวิธีปิด มัน: ทริกเกอร์เมื่อการสแกนใหม่ย้อนกลับไปไกลพอ มิฉะนั้นเทรสดิบพร้อมกับ since ที่มันให้คุณ ขอหนึ่งสัปดาห์บนโปรเจกต์ที่สแกนทุกคืนและ วันสุดท้ายจะหายไปจากคำตอบที่จัดกลุ่ม; นี่คือสิ่งที่บอกเช่นนั้น

write("agent_insights_job.enable", {"project_name": "demo"}) เปิด Diagnostics มันสแกนทุกวันตั้งแต่นั้นมา และการเรียกอีกครั้งปลอดภัย write("agent_insights_job.trigger", …) สแกน 24 ชั่วโมงที่ผ่านมาตอนนี้ โดยไม่ต้อง รอการรันรายคืน ทั้งสองรับสิทธิ์ที่การอ่านปัญหาต้องการ และทั้งสองปฏิเสธที่ดีพลอยเมนต์ที่ไม่มี Diagnostics

ปัญหาผ่านวงจรชีวิตด้วย write("agent_insights_issue.resolve", {"issue_id": "<uuid>", "project_name": "demo"}) — จัดการแล้ว — หรือ …close สำหรับปัญหาที่ไม่คุ้มค่าการดำเนินการ และ …reopen เพื่อนำ อย่างใดอย่างหนึ่งกลับไปยังรายการเปิด ทั้งสามรับสิทธิ์เดียวกันและตอบ ด้วยลิงก์ไปยังมุมมองที่ปัญหาย้ายไป เนื่องจากปัญหาที่แก้ไขแล้วไม่อยู่ บนหน้าเริ่มต้นอีกต่อไป ไม่ว่าความล้มเหลวจะได้รับการแก้ไขหรือไม่เป็นการตัดสินใจ ดังนั้นสิ่งเหล่านี้มีไว้เมื่อคุณถาม: ผู้ช่วยไม่มีหน้าที่จัดระเบียบรายการในขณะที่ คัดแยกมัน

เมตริกตามเวลา project_metric แผนภูมิหนึ่งเมตริกสำหรับโปรเจกต์เป็น ตารางของช่วงเวลา: จำนวนเทรซ, สแปนและเธรด, ระยะเวลา, อัตราข้อผิดพลาด, ต้นทุน, การใช้โทเค็นและคะแนนความคิดเห็น มันตอบคำถามที่ตามมา หลังภาพรวม ซึ่งคือเมื่อมีบางอย่างเปลี่ยนแปลง

list(entity_type="project_metric", project_name="demo", metric_type="trace_count")
list(entity_type="project_metric", project_name="demo", metric_type="trace_error_rate",
     since="14d", interval="daily")
list(entity_type="project_metric", project_name="demo", metric_type="span_count",
     breakdown="model")                      # one column per model
list(entity_type="project_metric", project_name="demo", metric_type="span_duration",
     breakdown="model", series="p99")        # the p99 of each model

แถวเป็นช่วงเวลา ไม่ใช่เรกคอร์ด ดังนั้น page, size และ sort จะถูกปฏิเสธ แทนที่จะถูกละเว้น interval คือ hourly, daily, weekly หรือ total; ถ้าละไว้ มันจะตามกรอบเวลาแบบที่แท็บ Metrics ทำ — รายชั่วโมงถึง 3 วัน, รายวันถึง 30, รายสัปดาห์เกินกว่านั้น — ดังนั้นแผนภูมิเริ่มต้นคือไม่กี่โหลแถว ไม่ว่าช่วงจะเป็นอะไร และเดือนรายชั่วโมง (721 แถว) คือสิ่งที่คุณต้องขอ since / until รับรูปแบบเดียวกันกับที่อื่นและเริ่มต้นเป็น 7 วันสุดท้าย filters ใช้ฟิลด์ของเอนทิตีที่เมตริกเกี่ยวกับ ดังนั้นเมตริกสแปนจึงถูกกรองด้วยฟิลด์สแปน

breakdown แบ่งแต่ละบัคเก็ตตาม tags, name, error_info, error_type, model, provider, span_type, guardrail_name หรือ metadata.<key> ไม่ใช่ทุก เมตริกที่ยอมรับทุกตัว และเจ็ดตัวไม่ยอมรับเลย; เครื่องมือ รู้ว่าอันไหนและบอกก่อนเรียกแบ็กเอนด์ โดยระบุเมตริกที่ ตอบคำถามเดียวกันเมื่อมีอยู่ สามตระกูลกลับมาเป็นหลายซีรีส์พร้อมกัน (ระยะเวลาเป็น p50/p90/p99, คะแนนความคิดเห็นต่อชื่อ, การใช้โทเค็น ต่อคีย์) และแบ็กเอนด์แผนภูมิหนึ่งในนั้นต่อครั้งเมื่อจัดกลุ่ม ดังนั้น series= เลือกมัน: เปอร์เซ็นไทล์, ชื่อคะแนน หรือคีย์การใช้งาน ระยะเวลา เริ่มต้นเป็น p50 และการใช้โทเค็นเป็น total_tokens และสิ่งที่ใช้จะถูก สะท้อนในบรรทัดแรก

บัคเก็ตว่างจะถูกตัดออกและนับด้านล่าง ดังนั้นเดือนที่เงียบคือไม่กี่ แถวแทนที่จะเป็นคอลัมน์ศูนย์ และอัตราเหนือบัคเก็ตที่ไม่มีเทรซคือ ไม่มีอยู่แทนที่จะรายงานเป็นศูนย์

ถาม schema("list.project_metric") สำหรับตารางเมตริก ช่วงเวลา และ เมทริกซ์การจัดกลุ่มต่อเมตริก

ชื่อของโปรเจกต์ score_name แสดงรายการชื่อคะแนนความคิดเห็นที่บันทึกใน โปรเจกต์และ online_rule ตัวประเมินกฎอัตโนมัติที่กำหนดค่าบนมัน ซึ่งเป็นที่มาของชื่อเหล่านั้นส่วนใหญ่ ทั้งสองเป็นรายการเดียวกันกับที่ read("project", …) มี อย่างเต็มรูปแบบและแบ่งหน้า สำหรับเมื่อ เวอร์ชันที่จำกัดในภาพรวมไม่เพียงพอ

list(entity_type="score_name", project_name="demo")
list(entity_type="online_rule", project_name="demo")

write

ตัวส่งการเขียนสากล ส่ง operation + data และตัวส่ง ตรวจสอบเพย์โหลด ใช้คำกริยา REST ที่ถูกต้อง และส่งคืน การตอบสนองของแบ็กเอนด์

การดำเนินการ:

การดำเนินการสิ่งที่มันทำ
trace.createบันทึกเทรซเดียว (หรือชุด) พาเรนต์สำหรับสแปน / คะแนน / ความคิดเห็น
trace.updateสรุปหรือแก้ไขเทรซที่มีอยู่
span.createบันทึกสแปนบนเทรซที่มีอยู่ (หรือชุด)
score.createแนบคะแนนความคิดเห็นตัวเลขกับเทรซ, สแปน หรือเธรด
comment.createแนบความคิดเห็นข้อความอิสระกับเทรซ, สแปน หรือเธรด
prompt_version.saveบันทึกเวอร์ชันพรอมพ์ใหม่ (สร้างพรอมพ์ตามชื่อถ้าหายไป)
dataset.createสร้างชุดข้อมูล — type: "test_suite" ทำให้เป็นชุดทดสอบการประเมิน
dataset_item.upsertอัปเซิร์ตรายการลงในชุดข้อมูล (เป็นรูปแบบซองจดหมายเสมอ)
experiment.createสร้างการทดลองที่จำกัดขอบเขตกับชุดข้อมูล
experiment_item.createแนบแถวเทรซ + dataset_item กับการทดลอง
thread.closeปิดเธรด (ทำเครื่องหมายว่าไม่ใช้งาน) ส่ง thread_id และโปรเจกต์
thread.openเปิดเธรดที่ปิดอีกครั้ง ส่ง thread_id และโปรเจกต์
agent_insights_job.enableเปิด Diagnostics สำหรับโปรเจกต์ (สแกนรายวัน ปลอดภัยที่จะทำซ้ำ)
agent_insights_job.triggerรันการสแกน Diagnostics ตอนนี้ ครอบคลุม 24 ชั่วโมงที่ผ่านมา
agent_insights_issue.resolveทำเครื่องหมายปัญห Diagnostics ว่าจัดการแล้ว (ถามผู้ใช้ก่อน)
agent_insights_issue.closeทำเครื่องหมายปัญห Diagnostics ว่าไม่คุ้มค่าการดำเนินการ (ถามผู้ใช้ก่อน)
agent_insights_issue.reopenนำปัญหาที่แก้ไขหรือปิดกลับไปยังรายการเปิด
write(operation="score.create", data={
  "target": "trace",
  "target_id": "7f2e3c8a-…",
  "name": "helpfulness",
  "value": 0.9,
  "reason": "great recovery"
})

schema

ตรวจสอบรูปร่าง JSON ที่แน่นอนและฟิลด์ที่จำเป็นของการดำเนินการเขียนใด ๆ ก่อน ที่คุณจะเรียกมัน — มีประโยชน์เมื่อคุณไม่แน่ใจว่า data ควรมีลักษณะอย่างไร ส่งคืน สคีมา, ขอบเขต OAuth และตัวอย่างที่ตรวจสอบแล้วหนึ่งตัวอย่าง การค้นหาล้วน ๆ ไม่มีการเรียกแบ็กเอนด์

schema(operation="score.create")
schema(operation="prompt_version.save")

เครื่องมือเดียวกันตอบ list.trace, list.span, list.thread และ list.experiment ด้วยข้อมูลอ้างอิงของเครื่องมือ list สำหรับเอนทิตีนั้น: ทุก ฟิลด์ที่กรองได้พร้อมกับประเภทและตัวดำเนินการที่ถูกต้อง ฟิลด์ที่เรียงลำดับได้ ไม่ว่า กรอบเวลาและการค้นหาข้อความอิสระใช้ได้หรือไม่ และตัวอย่างฟิลเตอร์สองตัวอย่าง

schema(operation="list.trace")

การกำหนดค่า

ทุกการตั้งค่าเป็นตัวแปรสภาพแวดล้อม ตัวที่จำเป็นอยู่ใน ตัวหนา

ข้อมูลประจำตัว / เอนด์พอยต์

ตัวแปรค่าเริ่มต้นหมายเหตุ
OPIK_API_KEY—จำเป็นสำหรับการอ่าน/เขียนที่ต้องมีการรับรองความถูกต้อง
OPIK_WORKSPACEไม่ได้ตั้งค่าชื่อเวิร์กสเปซ บนคลาวด์ที่มี API key การไม่ตั้งค่าจะส่ง default ซึ่งจะ resolve ไปยังเวิร์กสเปซ เริ่มต้น ของบัญชีคุณ — ตั้งค่าให้ชัดเจนหากคุณทำงานในเวิร์กสเปซอื่น มิฉะนั้นการอ่านจะมาจากเวิร์กสเปซที่ผิดโดยไม่มีการแจ้งเตือน ปล่อยว่างไว้เมื่อใช้ OAuth (token จะนำพาข้อมูลนี้ไปเอง) และบน local/OSS (default เป็นเวิร์กสเปซเดียวที่มีที่นั่น)
COMET_WORKSPACE—ชื่อเดิมที่เลิกใช้แล้วสำหรับ OPIK_WORKSPACE (เพื่อความเข้ากันได้ย้อนหลัง) OPIK_WORKSPACE จะมีผลเหนือกว่าหากตั้งค่าทั้งสอง
COMET_WORKSPACE_IDไม่ได้ตั้งค่าUUID ของเวิร์กสเปซ (ไม่บังคับ) จะถูกประทับลงในเหตุการณ์ analytics เมื่อตั้งค่า และจะมีความสำคัญเหนือกว่าค่าที่ resolve ได้ ไม่ค่อยจำเป็น — การติดตั้งผ่าน OAuth จะได้รับ UUID จาก token โดยอัตโนมัติ
COMET_URL_OVERRIDEhttps://www.comet.comตั้งค่าเป็นโฮสต์ Comet ที่คุณโฮสต์เอง หรือ https://dev.comet.com สำหรับ staging
OPIK_URLมาจาก COMET_URL_OVERRIDE + /opik/apiใช้แทนค่าเริ่มต้นก็ต่อเมื่อ Opik อยู่บนโฮสต์/พาธที่ต่างจาก Comet UI
OPIK_DEFAULT_PROJECT_NAMEไม่ได้ตั้งค่าเมื่อตั้งค่า blob instructions ต่อเซสชันจะบอกให้ LLM ส่งค่านี้เป็น project_name ในการเรียกใช้เครื่องมือทุกครั้ง เว้นแต่ผู้ใช้จะระบุโปรเจกต์อื่น

เซิร์ฟเวอร์ / การขนส่ง

ตัวแปรค่าเริ่มต้นหมายเหตุ
OPIK_MCP_TRANSPORTstdiostdio สำหรับการเปิดจากโฮสต์, streamable-http เพื่อฟังบนพอร์ต
OPIK_MCP_HOST127.0.0.1โฮสต์ที่ uvicorn ผูก (เฉพาะ streamable-http)
OPIK_MCP_PORT8080พอร์ตที่ uvicorn ผูก (เฉพาะ streamable-http)
OPIK_MCP_RELOADfalsetrue เพื่อเปิดใช้งาน uvicorn --reload (สำหรับการพัฒนาเท่านั้น)
OPIK_MCP_AS_URLไม่ได้ตั้งค่าURL ของ OAuth Authorization Server ประกาศใน /.well-known/oauth-protected-resource (RFC 9728) และใช้เป็น proxy target สำหรับการตรวจสอบ AS-discovery จำเป็นสำหรับโฮสต์ MCP ในการเริ่มต้น OAuth dance ผ่าน HTTP
OPIK_MCP_RESOURCE_URIไม่ได้ตั้งค่าURI สาธารณะหลักของเซิร์ฟเวอร์นี้ ประกาศเป็น resource ใน metadata ของทรัพยากรที่ได้รับการป้องกัน และใช้เพื่อหา WWW-Authenticate hint
OPIK_MCP_OAUTH_VALIDATION_CACHE_TTL_S30ระยะเวลาที่คำตอบที่ "ถูกต้อง" จากการตรวจสอบ token ของ opik-backend จะถูกเชื่อถือก่อนที่คำขอถัดไปบน OAuth token เดียวกันจะถามอีกครั้ง จำกัดโหลดที่เพิ่มให้กับ backend จากการตรวจสอบต่อคำขอ และหน้าต่างเวลาที่ token ที่หมดอายุยังถูกส่งต่อ (หน้าต่างนี้จะสิ้นสุดเมื่อ backend คืนค่า 401 ครั้งแรก) ถูกจำกัดด้วย expires_at ของ token เองเมื่อ backend รายงาน
OPIK_MCP_LOG_LEVELINFOระดับการบันทึกของ stderr logger

การเลือกการขนส่ง

bearer สองรูปแบบ สัญญาสองแบบบนการขนส่ง HTTP opik_mcp_at_… OAuth access token จะถูกตรวจสอบในทุกคำขอ กับ endpoint การตรวจสอบ token ของ opik-backend (มีการแคช ดู OPIK_MCP_OAUTH_VALIDATION_CACHE_TTL_S); token ที่หมดอายุหรือถูกเพิกถอนจะได้รับ HTTP 401 พร้อม WWW-Authenticate: Bearer error="invalid_token" ซึ่งเป็นสิ่งที่โฮสต์ MCP ใช้สำหรับการ silent refresh_token grant ของพวกเขา Opik API key จะไม่ถูกตรวจสอบในเครื่อง: มันจะถูกส่งต่อไปยัง opik-backend ตามที่เป็น ซึ่งเป็นจุดบังคับใช้เพียงจุดเดียว เลือกการขนส่งตามรูปแบบการติดตั้ง:

สถานการณ์การขนส่ง
MCP client และ Opik บนเครื่องเดียวกัน (การติดตั้ง OSS ในเครื่อง)stdio (แนะนำ — ง่ายที่สุด ไม่ต้องใช้พอร์ต ไม่ต้องตั้งค่า OAuth)
MCP client ในเครื่อง → Opik ระยะไกล (Comet cloud / โฮสต์เอง)stdio พร้อม OPIK_API_KEY หรือ HTTP พร้อม OAuth (OPIK_MCP_AS_URL ชี้ไปที่ backend)
opik-mcp ที่โฮสต์อยู่หลัง edge เดียวกับ opik-backendHTTP — bearer จะถูกตรวจสอบโดย backend ต่อคำขอ

หมายเหตุสำหรับการติดตั้ง OSS ในเครื่อง: backend OSS ไม่มีการตรวจสอบสิทธิ์คำขอ ดังนั้น HTTP opik-mcp ที่อยู่ข้างหน้าจะเปิดกว้างเท่ากับ REST API ของ OSS เอง เก็บค่าเริ่มต้น 127.0.0.1 bind ไว้ (และเลือกใช้ stdio) บนเครือข่ายที่ใช้ร่วมกัน

Telemetry

เหตุการณ์การใช้งานแบบไม่ระบุตัวตน (เฉพาะประเภทเหตุการณ์และเวลา — ไม่มีเนื้อหาคำค้นหา) มีการรวม SHA-256 digest ของ API key ของคุณเพื่อให้ฝ่ายสนับสนุนสามารถค้นหาบัญชีของคุณได้ key ดิบจะไม่ออกจากกระบวนการ เลือกไม่ใช้: OPIK_MCP_ANALYTICS_ENABLED=false

ตัวแปรค่าเริ่มต้นหมายเหตุ
OPIK_MCP_ANALYTICS_ENABLEDtrueตั้งค่าเป็น false เพื่อปิด telemetry ทั้งหมด
OPIK_MCP_ANALYTICS_URLhttps://stats.comet.com/notify/event/ค่าแทนสำหรับ staging
OPIK_MCP_ANALYTICS_ENVIRONMENTprodแท็กบนทุกเหตุการณ์ (prod / staging / dev)
OPIK_MCP_ANALYTICS_SOURCEcomet.comผู้รับใช้ค่านี้เพื่อทำเครื่องหมาย on_prem=False การติดตั้ง on-prem ควรแทนที่เป็น "" หรือโดเมนของตนเอง
OPIK_MCP_ANALYTICS_CONNECT_TIMEOUT_S5.0หมดเวลาเชื่อมต่อ HTTP
OPIK_MCP_ANALYTICS_TOTAL_TIMEOUT_S10.0หมดเวลารวมของคำขอ HTTP

ข้อจำกัดที่ทราบของโฮสต์

โฮสต์ต่างกันในระยะเวลาที่อนุญาตให้การเรียกใช้เครื่องมือหนึ่งครั้งทำงาน:

  • Claude Code — ไม่มีหมดเวลาการเรียกใช้เครื่องมือที่ระบุ แนะนำ
  • Cursor — หมดเวลา 60 วินาทีแบบตายตัวที่ไม่รีเซ็ตเมื่อมีความคืบหน้า (บั๊กต้นทาง)
  • MCP Inspector — MAX_TOTAL_TIMEOUT จำกัดระยะเวลาทั้งหมด (ค่าเริ่มต้น 60 วินาที) เพิ่มค่านี้ใน UI ของ Inspector สำหรับการทำงานที่ยาวนาน

หากการเรียกติดขัด ให้ตั้งค่า OPIK_MCP_LOG_LEVEL=DEBUG สำหรับบันทึกคำขอทั้งหมด


การแก้ไขปัญหา

OPIK_API_KEY ไม่ถูกนำมาใช้ — ตัวแปรไม่ถึงกระบวนการเซิร์ฟเวอร์ ใน Claude Code / Cursor / VS Code ตัวแปรสภาพแวดล้อมจะใช้ได้เฉพาะเมื่ออยู่ในบล็อก env ของการกำหนดค่า MCP server เท่านั้น ไม่ใช่ในเชลล์ของคุณ รีสตาร์ทโฮสต์หลังการแก้ไข

การเรียกใน Cursor หมดเวลาที่ 60 วินาที — บั๊กที่ทราบของ Cursor ไม่ใช่ opik-mcp จำกัดการเรียกให้แคบลง (size เล็กลง, กรอบเวลาที่แคบลง) หรือรันการทำงานเดียวกันบน Claude Code ซึ่งไม่มีขีดจำกัดตายตัว

เซิร์ฟเวอร์ไม่แสดง, การเข้าสู่ระบบไม่เปิด, เวิร์กสเปซผิด, ไม่พบ uvx สิ่งเหล่านี้ครอบคลุมใน ส่วนการแก้ไขปัญหาของเอกสาร opik mcp status (จาก uvx opik CLI เดียวกัน) แสดงรายการทุก client ที่กำหนดค่าเซิร์ฟเวอร์ไว้และว่าการกำหนดค่าของมันเบี่ยงเบนไปหรือไม่


การพัฒนา

git clone git@github.com:comet-ml/opik-mcp.git
cd opik-mcp
make install        # uv sync --extra dev
make check          # lint + typecheck + test
make run-dev        # uvicorn with --reload + DEBUG logs
make inspect        # MCP Inspector against the running server

เป้าหมายทั่วไป:

เป้าหมายสิ่งที่ทำ
make installuv sync --extra dev
make runรัน MCP server (stdio โดยค่าเริ่มต้น)
make run-devรันด้วยการบันทึก DEBUG + uvicorn --reload
make devรันผ่าน mcp dev (wrapper โหมด dev ของ Inspector)
make inspectเปิด MCP Inspector กับเซิร์ฟเวอร์ที่กำลังรันอยู่
make testuv run pytest -q
make lintruff check + การตรวจสอบรูปแบบ
make formatruff format + ruff check --fix
make typecheckmypy
make checklint + typecheck + test

โครงสร้าง repo:

opik-mcp/
├── src/opik_mcp/        ← server, tools, analytics
├── tests/               ← pytest suites
├── scripts/             ← live-BE smoke + MCP-session smoke
├── legacy/typescript/   ← migration guide for the deprecated v2 TS server (source: tag `legacy-typescript-final`)
├── pyproject.toml
└── Makefile

ขอความช่วยเหลือ


อัปเกรดจาก v2 หรือไม่? เซิร์ฟเวอร์ TypeScript รุ่นเก่ายังคงเผยแพร่บน npm เป็น opik-mcp@^2 (npx -y opik-mcp); ซอร์สโค้ดอยู่ที่ git tag legacy-typescript-final ดู legacy/typescript/DEPRECATED.md สำหรับนโยบายการสนับสนุน


สัญญาอนุญาต

Apache-2.0