opik-mcp

writes

Purpose

write(operation, data) is the only tool that changes anything in Opik; schema(operation) returns an operation’s input. This doc answers what a write promises, what comes back on success and failure, and where to change or add an operation.

What it does now

Inputs

Success

{"ok": true, "operation": "thread.close", "method": "PUT", "path": "/v1/private/traces/threads/close",
 "status": 204, "batch": false, "item_count": 1, "backend_body": "...", "url": "..."}

Failure

dispatch.run_write raises every failure as a WriteError; write_tool.run_write turns it into a ToolError whose text is compact JSON.

{"error": "validation_failed", "operation": "thread.close",
 "message": "data does not fit 'thread.close'; retry write('thread.close', data=…) shaped like example, and schema('thread.close') returns the full schema.",
 "issues": [{"field": "", "message": "thread_project_missing: ...", "code": "thread_project_missing"}],
 "example": {"thread_id": "...", "project_name": "..."}}
{"error": "backend_error", "operation": "trace.create",
 "message": "Opik rejected the data for 'trace.create' (400); fix it and retry write('trace.create', data=…).",
 "backend_error": {"status": 400}, "backend_message": "project not found"}

Each code is a plain exception class in src/opik_mcp/writes/errors.py, whose args rebuild it when pickled or copied. Other codes: unknown_operation (with valid_operations, did_you_mean), batch_too_large (over BATCH_LIMIT) and authorization_denied (required_scope). The OAuth 401 hint is in hosted-auth.

Scopes

Each operation declares a scope, and the dispatcher compares it with the scopes it is given. The write tool in src/opik_mcp/server/tools/write.py gives none, so the default ALL_WRITE_SCOPES applies and every call passes today.

How it works

server.write                  src/opik_mcp/server/tools/write.py
  -> write_tool.run_write     src/opik_mcp/writes/write_tool.py  (WriteError -> ToolError)
  -> dispatch.run_write       src/opik_mcp/writes/dispatch.py
     lookup, validate, authorize, prepare, build, send, retry, finalize, decorate
  -> OpikClient.write_json    src/opik_mcp/client/base.py

Evaluation hooks: experiment-flows. Diagnostics hooks: diagnostics. write_json: runtime. Error kinds: analytics. Every write against a real Opik: live-e2e.

Adding an operation

Add a model and an example in its writes/operations/ module, and a registry entry that names both; the enum, description and schema follow. Also:

Decisions

Traps

Proven by

Log