{"record":{"id":"4101a31d49e0222f","repo":"siyuan-note/siyuan","slug":"tools-list-repeated-cursor-q","errorCode":null,"errorMessage":"tools/list repeated cursor %q","messagePattern":"tools/list repeated cursor %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/mcp.go","lineNumber":363,"sourceCode":"\tvar (\n\t\tallTools []*mcp.Tool\n\t\tparams   *mcp.ListToolsParams\n\t)\n\tseenCursors := map[string]struct{}{}\n\tfor page := 0; page < maxMCPToolListPages; page++ {\n\t\tresult, err := listPage(ctx, params)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif result == nil {\n\t\t\treturn nil, fmt.Errorf(\"tools/list returned an empty response\")\n\t\t}\n\t\tallTools = append(allTools, result.Tools...)\n\t\tif result.NextCursor == \"\" {\n\t\t\treturn allTools, nil\n\t\t}\n\t\tif _, exists := seenCursors[result.NextCursor]; exists {\n\t\t\treturn nil, fmt.Errorf(\"tools/list repeated cursor %q\", result.NextCursor)\n\t\t}\n\t\tseenCursors[result.NextCursor] = struct{}{}\n\t\tparams = &mcp.ListToolsParams{Cursor: result.NextCursor}\n\t}\n\treturn nil, fmt.Errorf(\"tools/list exceeded %d pages\", maxMCPToolListPages)\n}\n\nfunc sanitizedServerNameCollision(server conf.MCPServer) bool {\n\tmcpMu.Lock()\n\tdefer mcpMu.Unlock()\n\tsanitizedName := sanitize(server.Name)\n\tfor _, configured := range mcpServers {\n\t\tif configured.ID != server.ID && sanitize(configured.Name) == sanitizedName {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/client/mcp.go#L345-L381","documentation":"listAllMCPTools paginates a remote MCP server's tools/list results, tracking every NextCursor it has already followed. When the server returns a cursor identical to one already seen, pagination would loop forever, so the client aborts with this error. It indicates a buggy or non-conformant MCP server implementation rather than a client configuration problem.","triggerScenarios":"connectOneServer calls listAllMCPTools; the server returns a tools/list page whose NextCursor equals a previously returned cursor (including returning the first page's cursor again).","commonSituations":"An MCP server with a broken cursor implementation (always returns the same cursor), a server that ignores the requested cursor parameter, a cached/stale middleware replaying the first page, or a mocked/test server misbehaving.","solutions":["Upgrade or fix the MCP server so each page returns a distinct NextCursor and empty string terminates the list","Verify the server actually advances its cursor when the request carries a Cursor parameter (test with a raw tools/list call)","Check for proxies/caches between client and server that replay responses","If a third-party server cannot be fixed, reduce the tool count so it fits one page, or use a corrected server build"],"exampleFix":"// before: server always returns NextCursor \"abc\"\n// after: server returns empty NextCursor on the last page\nif hasMorePages {\n    result.NextCursor = nextCursorToken // unique per page\n} else {\n    result.NextCursor = \"\"\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"conn, err := listAllMCPTools(ctx, listPage)\nif err != nil {\n    if strings.Contains(err.Error(), \"repeated cursor\") {\n        logging.LogWarnf(\"mcp: server cursor bug: %v\", err)\n        return // mark server unhealthy, skip tool registration\n    }\n    return err\n}","preventionTips":["Test new MCP server integrations against a known-good reference client first","Pin and regularly update third-party MCP server versions","Monitor logs for repeated-cursor errors to identify broken server builds early"],"tags":["mcp","pagination","cursor","protocol"],"backgroundTag":"unexpected-response-shape","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}