affine-mcp-server 1.11.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A Model Context Protocol (MCP) server that integrates with AFFiNE (self‑hosted or cloud). It exposes AFFiNE workspaces and documents to AI assistants over stdio (default) or HTTP (`/mcp`).
4
4
 
5
- [![Version](https://img.shields.io/badge/version-1.11.0-blue)](https://github.com/dawncr0w/affine-mcp-server/releases)
5
+ [![Version](https://img.shields.io/badge/version-1.11.1-blue)](https://github.com/dawncr0w/affine-mcp-server/releases)
6
6
  [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-1.17.2-green)](https://github.com/modelcontextprotocol/typescript-sdk)
7
7
  [![CI](https://github.com/dawncr0w/affine-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/dawncr0w/affine-mcp-server/actions/workflows/ci.yml)
8
8
  [![License](https://img.shields.io/badge/license-MIT-yellow)](LICENSE)
@@ -19,7 +19,7 @@ A Model Context Protocol (MCP) server that integrates with AFFiNE (self‑hosted
19
19
  - Tools: 76 focused tools with WebSocket-based document editing
20
20
  - Status: Active
21
21
 
22
- > New in v1.11.0: Added sidebar organize tools, configurable tool filtering, `delete_database_row`, and richer markdown import formatting for lists and table cells.
22
+ > New in v1.11.1: Corrected stale `list_docs` count and cursor metadata after `delete_doc` removes a document.
23
23
 
24
24
  ## Features
25
25
 
@@ -1985,6 +1985,7 @@ export function registerDocTools(server, gql, defaults) {
1985
1985
  const docs = data.workspace.docs;
1986
1986
  const tagsByDocId = new Map();
1987
1987
  const titlesByDocId = new Map();
1988
+ let workspacePageCount = null;
1988
1989
  try {
1989
1990
  const { endpoint, cookie, bearer } = await getCookieAndEndpoint();
1990
1991
  const wsUrl = wsUrlFromGraphQLEndpoint(endpoint);
@@ -1997,6 +1998,7 @@ export function registerDocTools(server, gql, defaults) {
1997
1998
  Y.applyUpdate(wsDoc, Buffer.from(snapshot.missing, "base64"));
1998
1999
  const meta = wsDoc.getMap("meta");
1999
2000
  const pages = getWorkspacePageEntries(meta);
2001
+ workspacePageCount = pages.length;
2000
2002
  const { byId } = getWorkspaceTagOptionMaps(meta);
2001
2003
  for (const page of pages) {
2002
2004
  if (page.title) {
@@ -2014,24 +2016,43 @@ export function registerDocTools(server, gql, defaults) {
2014
2016
  catch {
2015
2017
  // Keep list_docs available even when workspace snapshot fetch fails.
2016
2018
  }
2019
+ const mergedEdges = Array.isArray(docs?.edges)
2020
+ ? docs.edges.map((edge) => {
2021
+ const node = edge?.node;
2022
+ if (!node || typeof node.id !== "string") {
2023
+ return edge;
2024
+ }
2025
+ return {
2026
+ ...edge,
2027
+ node: {
2028
+ ...node,
2029
+ title: titlesByDocId.get(node.id) || node.title,
2030
+ tags: tagsByDocId.get(node.id) || [],
2031
+ },
2032
+ };
2033
+ })
2034
+ : [];
2035
+ // The workspace snapshot reflects deletions before GraphQL count metadata catches up.
2036
+ // Clamp downward only so create/index lag does not inflate counts from partial snapshot state.
2037
+ const correctedTotalCount = typeof docs?.totalCount === "number" &&
2038
+ typeof workspacePageCount === "number" &&
2039
+ workspacePageCount < docs.totalCount
2040
+ ? workspacePageCount
2041
+ : docs?.totalCount;
2042
+ const correctedPageInfo = docs?.pageInfo
2043
+ ? {
2044
+ ...docs.pageInfo,
2045
+ endCursor: mergedEdges.length > 0 ? mergedEdges[mergedEdges.length - 1]?.cursor ?? null : null,
2046
+ hasNextPage: typeof correctedTotalCount === "number" && !parsed.after
2047
+ ? (parsed.offset ?? 0) + mergedEdges.length < correctedTotalCount
2048
+ : docs.pageInfo.hasNextPage,
2049
+ }
2050
+ : docs?.pageInfo;
2017
2051
  const mergedDocs = {
2018
2052
  ...docs,
2019
- edges: Array.isArray(docs?.edges)
2020
- ? docs.edges.map((edge) => {
2021
- const node = edge?.node;
2022
- if (!node || typeof node.id !== "string") {
2023
- return edge;
2024
- }
2025
- return {
2026
- ...edge,
2027
- node: {
2028
- ...node,
2029
- title: titlesByDocId.get(node.id) || node.title,
2030
- tags: tagsByDocId.get(node.id) || [],
2031
- },
2032
- };
2033
- })
2034
- : [],
2053
+ totalCount: correctedTotalCount,
2054
+ pageInfo: correctedPageInfo,
2055
+ edges: mergedEdges,
2035
2056
  };
2036
2057
  return text(mergedDocs);
2037
2058
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "affine-mcp-server",
3
- "version": "1.11.0",
3
+ "version": "1.11.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Model Context Protocol server for AFFiNE - enables AI assistants to interact with AFFiNE workspaces, documents, and collaboration features.",