Files
wehub-resource-sync 4cddfcf2f3
Backend Tests / Tests (other) (push) Failing after 1s
Backend Tests / Static Checks (push) Failing after 2s
Backend Tests / Tests (internal) (push) Failing after 2s
Backend Tests / Tests (server) (push) Failing after 1s
Backend Tests / Tests (store) (push) Failing after 1s
Build Canary Image / build-frontend (push) Failing after 1s
Frontend Tests / Lint (push) Failing after 1s
Build Canary Image / build-push (linux/amd64) (push) Has been skipped
Build Canary Image / build-push (linux/arm64) (push) Has been skipped
Build Canary Image / merge (push) Has been skipped
Frontend Tests / Build (push) Failing after 1s
Release Please / release-please (push) Failing after 0s
Proto Linter / Lint Protos (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:02:24 +08:00
..

MCP Evaluations

Task-level evaluations for the memos MCP server. Where the *_test.go files verify the server plumbing (schema resolution, tool naming, annotations), these check the thing that actually matters for an MCP server: can an LLM accomplish realistic tasks by composing the tools? They are the regression net for tool descriptions and discoverability — e.g. a bad filter description leaves the unit tests green but makes question 3/5/9 unanswerable.

memos_eval.xml holds 10 question/answer pairs in the format used by the mcp-builder skill. Each question is independent, read-only, requires multiple tool calls, and has a single string-comparable answer.

Why a fresh seeded instance (not the public demo)

Answers are pinned to the deterministic seed in store/seed/sqlite/01__dump.sql (10 memos — 7 top-level + 3 comments — 2 users, 12 reactions, no attachments, no shortcuts).

The public demo (demo.usememos.com) signs everyone into the same shared demo account, so visitors continually add/edit/delete memos and reactions. Its data has already diverged from the seed — do not evaluate against it.

The seed uses relative timestamps (strftime('now','-N days')), so the questions avoid absolute dates and rely only on relative ordering, counts, and content, all of which are stable across re-seeds.

Running an evaluation

  1. Launch a throwaway demo-mode instance (SQLite, auto-seeded) on a free port:

    go run ./cmd/memos --demo --driver sqlite \
      --port 8099 --data "$(mktemp -d)" \
      --instance-url http://localhost:8099
    
  2. The MCP endpoint is http://localhost:8099/mcp. Authenticate with the seed's demo personal access token:

    Authorization: Bearer memos_pat_demo
    
  3. Point an MCP client / eval harness at that endpoint and have the model answer each <question>, then string-compare against each <answer>.

    Quick manual check of a single tool call:

    curl -s -X POST http://localhost:8099/mcp \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json, text/event-stream' \
      -H 'Authorization: Bearer memos_pat_demo' \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"memo_list_memos","arguments":{"filter":"pinned == true"}}}'
    

Notes for whoever extends this

  • The CEL tag field does not support ==; filter tags with "work" in tags (or tags.exists(t, t == "work")), not tag == "work".
  • memo_list_memos returns only top-level memos; comments are reached via memo_list_memo_comments.
  • The seed defines no shortcuts and no attachments, so shortcut_list_shortcuts and the attachment tools return empty sets against a fresh seed. Add seed rows before writing questions that depend on them.