Pre-submission Checklist
Affected Area
API (built-in MCP server)
Reproduced On
Demo site (v0.30.0-rc.1) and self-hosted v0.30.0-rc.2
Memos Version Tested
v0.30.0-rc.1 (demo.usememos.com) and v0.30.0-rc.2 (self-hosted Docker)
Previous Version
No response
Environment Details
This is the rewritten OpenAPI-driven MCP server from #6026. Reproduced unauthenticated against https://demo.usememos.com/mcp (Streamable HTTP) with plain curl — no MCP client involved.
Related issues: distinct from #6022 / #6037 / #6049 (list tools returning bare arrays), which are fixed in this build.
Reproduction Frequency
Always
Steps to Reproduce
SID=$(curl -sS -D - -o /dev/null -X POST https://demo.usememos.com/mcp \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"repro","version":"1.0"}}}' \
| grep -i mcp-session-id | tr -d '\r' | awk '{print $2}')
mcp() { curl -sS -X POST https://demo.usememos.com/mcp \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SID" -d "$1"; }
# 1. list_memos returns canonical resource names:
mcp '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"memo_list_memos","arguments":{"pageSize":1}}}'
# -> "name": "memos/webclipper0001"
# 2. Feed that name back to get_memo:
mcp '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"memo_get_memo","arguments":{"memo":"memos/webclipper0001"}}}'
# -> isError: true, structuredContent: {"error":{"message":"404 Not Found: Not Found"}}
# 3. Same call with the bare ID succeeds:
mcp '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"memo_get_memo","arguments":{"memo":"webclipper0001"}}}'
The same full-name → 404 / bare-ID → success behavior applies to memo_update_memo, memo_delete_memo, memo_create_memo_comment, and memo_list_memo_comments (verified update/delete on a self-hosted v0.30.0-rc.2 instance with a PAT; for memo_update_memo the 404 means the PATCH is silently never applied).
Current Behavior
1. Resource-name inconsistency. Every tool that maps to a /api/v1/memos/{memo} path substitutes the memo argument directly into the URL, so only bare IDs work (memos/<id> becomes /api/v1/memos/memos/<id> → 404). But the API returns name: "memos/<id>" in every memo object, and the tool's input schema describes the param only as "The memo id.". An MCP client (human or LLM) that round-trips the name it received from memo_create_memo/memo_list_memos gets a 404 on every follow-up operation. For memo_update_memo this is destructive-adjacent: the edit is silently lost.
2. Error results violate the declared outputSchema. On REST failure the tool returns structuredContent: {"error": {"message": "..."}}, while e.g. memo_get_memo declares an outputSchema with required: ["state","content","visibility"]. Spec-strict clients (Claude Code, LiteLLM, ChatGPT connector) reject the response with a schema-validation error (data must have required property 'state'…), masking the underlying 404 and making the tools appear completely broken.
Expected Behavior
- Tools accept the canonical
memos/{id} resource name (ideally both forms: strip a memos/ prefix before path substitution), matching the name values the API returns.
- On failure, tools either omit
structuredContent (relying on isError + text content, per MCP spec) or declare an output schema that admits the error shape — so strict clients surface the real error message.
Workarounds: pass bare IDs (strip the memos/ prefix) for any {memo} path parameter; read via memo_list_memos when a get fails validation.
Pre-submission Checklist
main, or the demo site, or this report is specifically about upgrading to the latest releaseAffected Area
API (built-in MCP server)
Reproduced On
Demo site (v0.30.0-rc.1) and self-hosted v0.30.0-rc.2
Memos Version Tested
v0.30.0-rc.1 (demo.usememos.com) and v0.30.0-rc.2 (self-hosted Docker)
Previous Version
No response
Environment Details
This is the rewritten OpenAPI-driven MCP server from #6026. Reproduced unauthenticated against
https://demo.usememos.com/mcp(Streamable HTTP) with plain curl — no MCP client involved.Related issues: distinct from #6022 / #6037 / #6049 (list tools returning bare arrays), which are fixed in this build.
Reproduction Frequency
Always
Steps to Reproduce
The same full-name → 404 / bare-ID → success behavior applies to
memo_update_memo,memo_delete_memo,memo_create_memo_comment, andmemo_list_memo_comments(verified update/delete on a self-hosted v0.30.0-rc.2 instance with a PAT; formemo_update_memothe 404 means the PATCH is silently never applied).Current Behavior
1. Resource-name inconsistency. Every tool that maps to a
/api/v1/memos/{memo}path substitutes thememoargument directly into the URL, so only bare IDs work (memos/<id>becomes/api/v1/memos/memos/<id>→ 404). But the API returnsname: "memos/<id>"in every memo object, and the tool's input schema describes the param only as"The memo id.". An MCP client (human or LLM) that round-trips thenameit received frommemo_create_memo/memo_list_memosgets a 404 on every follow-up operation. Formemo_update_memothis is destructive-adjacent: the edit is silently lost.2. Error results violate the declared outputSchema. On REST failure the tool returns
structuredContent: {"error": {"message": "..."}}, while e.g.memo_get_memodeclares anoutputSchemawithrequired: ["state","content","visibility"]. Spec-strict clients (Claude Code, LiteLLM, ChatGPT connector) reject the response with a schema-validation error (data must have required property 'state'…), masking the underlying 404 and making the tools appear completely broken.Expected Behavior
memos/{id}resource name (ideally both forms: strip amemos/prefix before path substitution), matching thenamevalues the API returns.structuredContent(relying onisError+ text content, per MCP spec) or declare an output schema that admits the error shape — so strict clients surface the real error message.Workarounds: pass bare IDs (strip the
memos/prefix) for any{memo}path parameter; read viamemo_list_memoswhen a get fails validation.