@mtcsistemas/appflowy-mcp-server 1.0.0
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/LICENSE +21 -0
- package/README.md +324 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/appflowy-prompts.d.ts +7 -0
- package/dist/prompts/appflowy-prompts.d.ts.map +1 -0
- package/dist/prompts/appflowy-prompts.js +115 -0
- package/dist/prompts/appflowy-prompts.js.map +1 -0
- package/dist/resources/workspace-resources.d.ts +7 -0
- package/dist/resources/workspace-resources.d.ts.map +1 -0
- package/dist/resources/workspace-resources.js +86 -0
- package/dist/resources/workspace-resources.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +31 -0
- package/dist/server.js.map +1 -0
- package/dist/services/appflowy-client.d.ts +65 -0
- package/dist/services/appflowy-client.d.ts.map +1 -0
- package/dist/services/appflowy-client.js +303 -0
- package/dist/services/appflowy-client.js.map +1 -0
- package/dist/services/auth.d.ts +26 -0
- package/dist/services/auth.d.ts.map +1 -0
- package/dist/services/auth.js +89 -0
- package/dist/services/auth.js.map +1 -0
- package/dist/tools/databases.d.ts +7 -0
- package/dist/tools/databases.d.ts.map +1 -0
- package/dist/tools/databases.js +199 -0
- package/dist/tools/databases.js.map +1 -0
- package/dist/tools/documents.d.ts +7 -0
- package/dist/tools/documents.d.ts.map +1 -0
- package/dist/tools/documents.js +197 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/files.d.ts +7 -0
- package/dist/tools/files.d.ts.map +1 -0
- package/dist/tools/files.js +196 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/search.d.ts +7 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +60 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/workspaces.d.ts +7 -0
- package/dist/tools/workspaces.d.ts.map +1 -0
- package/dist/tools/workspaces.js +66 -0
- package/dist/tools/workspaces.js.map +1 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/services/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppFlowy MCP Server - Database Tools
|
|
3
|
+
* MCP tools for database/table operations
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
export declare function registerDatabaseTools(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=databases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../src/tools/databases.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QAmMtD"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppFlowy MCP Server - Database Tools
|
|
3
|
+
* MCP tools for database/table operations
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { appflowyClient } from '../services/appflowy-client.js';
|
|
7
|
+
export function registerDatabaseTools(server) {
|
|
8
|
+
// Tool: List databases
|
|
9
|
+
server.tool('appflowy_list_databases', `List all databases (Grid, Board, Calendar, Gallery) in a workspace.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
- workspace_id: The workspace ID`, {
|
|
13
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
14
|
+
}, async ({ workspace_id }) => {
|
|
15
|
+
try {
|
|
16
|
+
const databases = await appflowyClient.listDatabases(workspace_id);
|
|
17
|
+
if (databases.length === 0) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: 'text', text: 'No databases found in this workspace.' }],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const lines = ['# Databases\n'];
|
|
23
|
+
for (const db of databases) {
|
|
24
|
+
const icon = getLayoutIcon(db.layout);
|
|
25
|
+
lines.push(`${icon} **${db.name}** (${db.layout})`);
|
|
26
|
+
lines.push(` ID: ${db.view_id}`);
|
|
27
|
+
if (db.last_edited_time)
|
|
28
|
+
lines.push(` Last edited: ${db.last_edited_time}`);
|
|
29
|
+
lines.push('');
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: 'text', text: `ā Error listing databases: ${error.message}` }],
|
|
38
|
+
isError: true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
// Tool: Read database
|
|
43
|
+
server.tool('appflowy_read_database', `Read all rows from a database (table/kanban/calendar).
|
|
44
|
+
|
|
45
|
+
Returns a markdown table with all data.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
- workspace_id: The workspace ID
|
|
49
|
+
- database_id: The database/view ID`, {
|
|
50
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
51
|
+
database_id: z.string().describe('The database/view ID'),
|
|
52
|
+
}, async ({ workspace_id, database_id }) => {
|
|
53
|
+
try {
|
|
54
|
+
const [dbInfo, rows] = await Promise.all([
|
|
55
|
+
appflowyClient.getDatabase(workspace_id, database_id),
|
|
56
|
+
appflowyClient.getDatabaseRows(workspace_id, database_id),
|
|
57
|
+
]);
|
|
58
|
+
const lines = [`# ${dbInfo.name}\n`];
|
|
59
|
+
lines.push(`**Type**: ${dbInfo.views?.[0]?.layout || 'Grid'}\n`);
|
|
60
|
+
// Headers
|
|
61
|
+
const headers = dbInfo.fields.map((f) => f.name).join(' | ');
|
|
62
|
+
lines.push(`| ${headers} |`);
|
|
63
|
+
lines.push(`|${dbInfo.fields.map(() => '---').join('|')}|`);
|
|
64
|
+
// Rows
|
|
65
|
+
for (const row of rows) {
|
|
66
|
+
const cells = dbInfo.fields.map((f) => {
|
|
67
|
+
const cell = row.cells[f.id];
|
|
68
|
+
return formatCellValue(cell);
|
|
69
|
+
});
|
|
70
|
+
lines.push(`| ${cells.join(' | ')} |`);
|
|
71
|
+
}
|
|
72
|
+
lines.push(`\n*Total rows: ${rows.length}*`);
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: 'text', text: `ā Error reading database: ${error.message}` }],
|
|
80
|
+
isError: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Tool: Create database row
|
|
85
|
+
server.tool('appflowy_create_database_row', `Create a new row/entry in a database.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
- workspace_id: The workspace ID
|
|
89
|
+
- database_id: The database/view ID
|
|
90
|
+
- cells: Object with field IDs as keys and values
|
|
91
|
+
|
|
92
|
+
Example cells:
|
|
93
|
+
{\"field_abc123\": \"Task name\", \"field_def456\": \"In Progress\"}`, {
|
|
94
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
95
|
+
database_id: z.string().describe('The database/view ID'),
|
|
96
|
+
cells: z.record(z.any()).describe('Cell values { field_id: value }'),
|
|
97
|
+
}, async ({ workspace_id, database_id, cells }) => {
|
|
98
|
+
try {
|
|
99
|
+
const row = await appflowyClient.createDatabaseRow(workspace_id, database_id, cells);
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: 'text',
|
|
104
|
+
text: `ā
Row created successfully.\n\n- Row ID: ${row.id}\n- Created: ${row.created_at}`,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: 'text', text: `ā Error creating row: ${error.message}` }],
|
|
112
|
+
isError: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
// Tool: Update database row
|
|
117
|
+
server.tool('appflowy_update_database_row', `Update an existing row in a database.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
- workspace_id: The workspace ID
|
|
121
|
+
- database_id: The database/view ID
|
|
122
|
+
- row_id: The row ID to update
|
|
123
|
+
- cells: Object with field IDs and new values`, {
|
|
124
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
125
|
+
database_id: z.string().describe('The database/view ID'),
|
|
126
|
+
row_id: z.string().describe('The row ID to update'),
|
|
127
|
+
cells: z.record(z.any()).describe('Cell values to update { field_id: value }'),
|
|
128
|
+
}, async ({ workspace_id, database_id, row_id, cells }) => {
|
|
129
|
+
try {
|
|
130
|
+
const row = await appflowyClient.updateDatabaseRow(workspace_id, database_id, row_id, cells);
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: 'text',
|
|
135
|
+
text: `ā
Row updated successfully.\n\n- Row ID: ${row.id}\n- Last modified: ${row.last_modified}`,
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: 'text', text: `ā Error updating row: ${error.message}` }],
|
|
143
|
+
isError: true,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
// Tool: Delete database row
|
|
148
|
+
server.tool('appflowy_delete_database_row', `ā ļø Delete a row from a database. This action cannot be undone!
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
- workspace_id: The workspace ID
|
|
152
|
+
- database_id: The database/view ID
|
|
153
|
+
- row_id: The row ID to delete`, {
|
|
154
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
155
|
+
database_id: z.string().describe('The database/view ID'),
|
|
156
|
+
row_id: z.string().describe('The row ID to delete'),
|
|
157
|
+
}, async ({ workspace_id, database_id, row_id }) => {
|
|
158
|
+
try {
|
|
159
|
+
await appflowyClient.deleteDatabaseRow(workspace_id, database_id, row_id);
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: 'text', text: 'šļø Row deleted successfully.' }],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
return {
|
|
166
|
+
content: [{ type: 'text', text: `ā Error deleting row: ${error.message}` }],
|
|
167
|
+
isError: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// Helper: Get icon for layout
|
|
173
|
+
function getLayoutIcon(layout) {
|
|
174
|
+
const icons = {
|
|
175
|
+
Grid: 'š',
|
|
176
|
+
Board: 'š',
|
|
177
|
+
Calendar: 'š
',
|
|
178
|
+
Gallery: 'š¼ļø',
|
|
179
|
+
};
|
|
180
|
+
return icons[layout] || 'š';
|
|
181
|
+
}
|
|
182
|
+
// Helper: Format cell value for display
|
|
183
|
+
function formatCellValue(cell) {
|
|
184
|
+
if (!cell)
|
|
185
|
+
return '-';
|
|
186
|
+
if (cell.text)
|
|
187
|
+
return cell.text;
|
|
188
|
+
if (cell.value !== undefined) {
|
|
189
|
+
if (Array.isArray(cell.value))
|
|
190
|
+
return cell.value.join(', ');
|
|
191
|
+
if (typeof cell.value === 'boolean')
|
|
192
|
+
return cell.value ? 'ā
' : 'ā';
|
|
193
|
+
if (cell.value === null || cell.value === '')
|
|
194
|
+
return '-';
|
|
195
|
+
return String(cell.value);
|
|
196
|
+
}
|
|
197
|
+
return '-';
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=databases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databases.js","sourceRoot":"","sources":["../../src/tools/databases.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGhE,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,uBAAuB;IACvB,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB;;;mCAG+B,EAC/B;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;KACtD,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,EAAyB,EAAE;QAChD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YAEnE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAC;iBAC3E,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,eAAe,CAAC,CAAC;YAChC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;gBACtC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,MAAM,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;gBACpD,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnC,IAAI,EAAE,CAAC,gBAAgB;oBAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,gBAAgB,EAAE,CAAC,CAAC;gBAC9E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;aACpD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAChF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB;;;;;;sCAMkC,EAClC;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACzD,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,EAAyB,EAAE;QAC7D,IAAI,CAAC;YACH,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACvC,cAAc,CAAC,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC;gBACrD,cAAc,CAAC,eAAe,CAAC,YAAY,EAAE,WAAW,CAAC;aAC1D,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,CAAC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,MAAM,IAAI,CAAC,CAAC;YAEjE,UAAU;YACV,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7D,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAE5D,OAAO;YACP,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACpC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC7B,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC,CAAC,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAE7C,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;aACpD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,6BAA6B,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC/E,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B;;;;;;;;uEAQmE,EACnE;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;KACrE,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,EAAyB,EAAE;QACpE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,iBAAiB,CAAC,YAAY,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACrF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,4CAA4C,GAAG,CAAC,EAAE,gBAAgB,GAAG,CAAC,UAAU,EAAE;qBACzF;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC3E,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B;;;;;;gDAM4C,EAC5C;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACnD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KAC/E,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,EAAyB,EAAE;QAC5E,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,iBAAiB,CAAC,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7F,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,4CAA4C,GAAG,CAAC,EAAE,sBAAsB,GAAG,CAAC,aAAa,EAAE;qBAClG;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC3E,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B;;;;;iCAK6B,EAC7B;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACpD,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,EAAyB,EAAE;QACrE,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,iBAAiB,CAAC,YAAY,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAC1E,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,EAAE,CAAC;aACnE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC3E,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED,8BAA8B;AAC9B,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,KAAK,GAA2B;QACpC,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;QACX,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,KAAK;KACf,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED,wCAAwC;AACxC,SAAS,eAAe,CAAC,IAAS;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC;IACtB,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IAChC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACnE,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE;YAAE,OAAO,GAAG,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppFlowy MCP Server - Document Tools
|
|
3
|
+
* MCP tools for document/page management
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
export declare function registerDocumentTools(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/tools/documents.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QA4LtD"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppFlowy MCP Server - Document Tools
|
|
3
|
+
* MCP tools for document/page management
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { appflowyClient } from '../services/appflowy-client.js';
|
|
7
|
+
export function registerDocumentTools(server) {
|
|
8
|
+
// Tool: List documents
|
|
9
|
+
server.tool('appflowy_list_documents', `List all documents/pages in a workspace or folder.
|
|
10
|
+
|
|
11
|
+
Can list root-level documents or documents inside a specific folder (parent_view_id).
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
- workspace_id: The workspace ID
|
|
15
|
+
- parent_view_id (optional): Folder ID to list contents inside`, {
|
|
16
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
17
|
+
parent_view_id: z.string().optional().describe('Parent folder/view ID (optional)'),
|
|
18
|
+
}, async ({ workspace_id, parent_view_id }) => {
|
|
19
|
+
try {
|
|
20
|
+
const docs = await appflowyClient.listDocuments(workspace_id, parent_view_id);
|
|
21
|
+
if (docs.length === 0) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: 'text', text: 'No documents found.' }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const lines = [`# Documents${parent_view_id ? ' in folder' : ''}\n`];
|
|
27
|
+
for (const doc of docs) {
|
|
28
|
+
const icon = doc.icon || getLayoutIcon(doc.layout);
|
|
29
|
+
lines.push(`${icon} **${doc.name}**`);
|
|
30
|
+
lines.push(` ID: ${doc.view_id} | Type: ${doc.layout}`);
|
|
31
|
+
if (doc.last_edited_time) {
|
|
32
|
+
lines.push(` Last edited: ${doc.last_edited_time}`);
|
|
33
|
+
}
|
|
34
|
+
lines.push('');
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: 'text', text: `ā Error listing documents: ${error.message}` }],
|
|
43
|
+
isError: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// Tool: Read document
|
|
48
|
+
server.tool('appflowy_read_document', `Read the full content of a document/page from AppFlowy.
|
|
49
|
+
|
|
50
|
+
Returns the document metadata and text content extracted from blocks.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
- workspace_id: The workspace ID
|
|
54
|
+
- document_id: The document/view ID`, {
|
|
55
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
56
|
+
document_id: z.string().describe('The document/view ID'),
|
|
57
|
+
}, async ({ workspace_id, document_id }) => {
|
|
58
|
+
try {
|
|
59
|
+
const [docMeta, content] = await Promise.all([
|
|
60
|
+
appflowyClient.getDocument(workspace_id, document_id),
|
|
61
|
+
appflowyClient.getDocumentContent(workspace_id, document_id),
|
|
62
|
+
]);
|
|
63
|
+
let textContent = '';
|
|
64
|
+
if (content?.blocks) {
|
|
65
|
+
textContent = extractTextFromBlocks(content.blocks);
|
|
66
|
+
}
|
|
67
|
+
const lines = [`# ${docMeta.name}\n`];
|
|
68
|
+
lines.push(`**ID**: ${docMeta.view_id}`);
|
|
69
|
+
lines.push(`**Type**: ${docMeta.layout}`);
|
|
70
|
+
lines.push(`**Created**: ${docMeta.created_at}`);
|
|
71
|
+
if (docMeta.last_edited_time)
|
|
72
|
+
lines.push(`**Last edited**: ${docMeta.last_edited_time}`);
|
|
73
|
+
lines.push('');
|
|
74
|
+
lines.push('---');
|
|
75
|
+
lines.push('');
|
|
76
|
+
lines.push(textContent || '*Document is empty or contains unsupported content.*');
|
|
77
|
+
return {
|
|
78
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: 'text', text: `ā Error reading document: ${error.message}` }],
|
|
84
|
+
isError: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
// Tool: Create document
|
|
89
|
+
server.tool('appflowy_create_document', `Create a new document/page in AppFlowy.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
- workspace_id: The workspace ID
|
|
93
|
+
- name: Document name/title
|
|
94
|
+
- parent_view_id (optional): Folder ID to place document inside`, {
|
|
95
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
96
|
+
name: z.string().min(1).max(200).describe('Document name/title'),
|
|
97
|
+
parent_view_id: z.string().optional().describe('Parent folder ID (optional)'),
|
|
98
|
+
}, async ({ workspace_id, name, parent_view_id }) => {
|
|
99
|
+
try {
|
|
100
|
+
const doc = await appflowyClient.createDocument(workspace_id, name, parent_view_id);
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{
|
|
104
|
+
type: 'text',
|
|
105
|
+
text: `ā
Document created: **${doc.name}**\n\n- ID: ${doc.view_id}\n- Type: ${doc.layout}\n- Created: ${doc.created_at}`,
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: 'text', text: `ā Error creating document: ${error.message}` }],
|
|
113
|
+
isError: true,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// Tool: Delete document
|
|
118
|
+
server.tool('appflowy_delete_document', `ā ļø Delete a document/page from AppFlowy. This action cannot be undone!
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
- workspace_id: The workspace ID
|
|
122
|
+
- document_id: The document/view ID to delete`, {
|
|
123
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
124
|
+
document_id: z.string().describe('The document/view ID to delete'),
|
|
125
|
+
}, async ({ workspace_id, document_id }) => {
|
|
126
|
+
try {
|
|
127
|
+
await appflowyClient.deleteDocument(workspace_id, document_id);
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: 'text', text: 'šļø Document deleted successfully.' }],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return {
|
|
134
|
+
content: [{ type: 'text', text: `ā Error deleting document: ${error.message}` }],
|
|
135
|
+
isError: true,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// Tool: Duplicate document
|
|
140
|
+
server.tool('appflowy_duplicate_document', `Duplicate/clone an existing document/page.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
- workspace_id: The workspace ID
|
|
144
|
+
- document_id: The document/view ID to duplicate`, {
|
|
145
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
146
|
+
document_id: z.string().describe('The document/view ID to duplicate'),
|
|
147
|
+
}, async ({ workspace_id, document_id }) => {
|
|
148
|
+
try {
|
|
149
|
+
const doc = await appflowyClient.duplicateDocument(workspace_id, document_id);
|
|
150
|
+
return {
|
|
151
|
+
content: [
|
|
152
|
+
{
|
|
153
|
+
type: 'text',
|
|
154
|
+
text: `š Document duplicated: **${doc.name}**\n\n- New ID: ${doc.view_id}\n- Original ID: ${document_id}`,
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: 'text', text: `ā Error duplicating document: ${error.message}` }],
|
|
162
|
+
isError: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// Helper: Get icon for document layout
|
|
168
|
+
function getLayoutIcon(layout) {
|
|
169
|
+
const icons = {
|
|
170
|
+
Document: 'š',
|
|
171
|
+
Grid: 'š',
|
|
172
|
+
Board: 'š',
|
|
173
|
+
Calendar: 'š
',
|
|
174
|
+
Gallery: 'š¼ļø',
|
|
175
|
+
Chat: 'š¬',
|
|
176
|
+
};
|
|
177
|
+
return icons[layout] || 'š';
|
|
178
|
+
}
|
|
179
|
+
// Helper: Extract text from document blocks recursively
|
|
180
|
+
function extractTextFromBlocks(blocks) {
|
|
181
|
+
const texts = [];
|
|
182
|
+
for (const block of blocks) {
|
|
183
|
+
if (block.data?.text) {
|
|
184
|
+
texts.push(block.data.text);
|
|
185
|
+
}
|
|
186
|
+
if (block.data?.url && block.type === 'file') {
|
|
187
|
+
texts.push(`[File: ${block.data.name || 'attachment'} (${block.data.file_type || 'unknown'})]`);
|
|
188
|
+
}
|
|
189
|
+
if (block.children?.length) {
|
|
190
|
+
const childTexts = extractTextFromBlocks(block.children);
|
|
191
|
+
if (childTexts)
|
|
192
|
+
texts.push(childTexts);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return texts.join('\n');
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=documents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/tools/documents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppFlowy MCP Server - File/Attachment Tools
|
|
3
|
+
* MCP tools for uploading, downloading, and managing file attachments
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
export declare function registerFileTools(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/tools/files.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QAmNlD"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppFlowy MCP Server - File/Attachment Tools
|
|
3
|
+
* MCP tools for uploading, downloading, and managing file attachments
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { appflowyClient } from '../services/appflowy-client.js';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { writeFileSync } from 'fs';
|
|
9
|
+
import { resolve } from 'path';
|
|
10
|
+
export function registerFileTools(server) {
|
|
11
|
+
// Tool: Upload file
|
|
12
|
+
server.tool('appflowy_upload_file', `Upload a file from your local machine to AppFlowy Cloud storage.
|
|
13
|
+
|
|
14
|
+
The file will be stored in your workspace and can be attached to documents.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
- workspace_id: The workspace ID
|
|
18
|
+
- file_path: Absolute path to the local file
|
|
19
|
+
- parent_dir (optional): Storage directory (default: 'attachments')
|
|
20
|
+
|
|
21
|
+
Supported file types: images, documents, PDFs, code files, etc.
|
|
22
|
+
Max file size: configurable via APPFLOWY_MAX_FILE_SIZE_MB env var (default: 50MB)`, {
|
|
23
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
24
|
+
file_path: z.string().describe('Absolute path to the local file'),
|
|
25
|
+
parent_dir: z.string().default('attachments').describe('Storage directory name'),
|
|
26
|
+
}, async ({ workspace_id, file_path, parent_dir }) => {
|
|
27
|
+
try {
|
|
28
|
+
const resolvedPath = resolve(file_path);
|
|
29
|
+
if (!existsSync(resolvedPath)) {
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: 'text', text: `ā File not found: ${resolvedPath}` }],
|
|
32
|
+
isError: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const result = await appflowyClient.uploadFile(workspace_id, resolvedPath, parent_dir);
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: 'text',
|
|
40
|
+
text: `ā
File uploaded successfully!\n\nš **${result.name}**\n- File ID: ${result.file_id}\n- Size: ${formatFileSize(result.size)}\n- Type: ${result.mime_type}\n- URL: ${result.url}\n- Storage: ${parent_dir}/`,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: 'text', text: `ā Upload error: ${error.message}` }],
|
|
48
|
+
isError: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
// Tool: Download file
|
|
53
|
+
server.tool('appflowy_download_file', `Download a file from AppFlowy Cloud storage to your local machine.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
- workspace_id: The workspace ID
|
|
57
|
+
- file_id: The file ID (from upload or list_files)
|
|
58
|
+
- output_path: Absolute path where to save the file
|
|
59
|
+
- parent_dir (optional): Storage directory (default: 'attachments')`, {
|
|
60
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
61
|
+
file_id: z.string().describe('The file ID'),
|
|
62
|
+
output_path: z.string().describe('Absolute path to save the file'),
|
|
63
|
+
parent_dir: z.string().default('attachments').describe('Storage directory name'),
|
|
64
|
+
}, async ({ workspace_id, file_id, output_path, parent_dir }) => {
|
|
65
|
+
try {
|
|
66
|
+
const buffer = await appflowyClient.downloadFile(workspace_id, file_id, parent_dir);
|
|
67
|
+
const resolvedPath = resolve(output_path);
|
|
68
|
+
writeFileSync(resolvedPath, buffer);
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: 'text',
|
|
73
|
+
text: `ā
File downloaded successfully!\n\nš„ Saved to: ${resolvedPath}\n- Size: ${formatFileSize(buffer.length)}`,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return {
|
|
80
|
+
content: [{ type: 'text', text: `ā Download error: ${error.message}` }],
|
|
81
|
+
isError: true,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
// Tool: List files
|
|
86
|
+
server.tool('appflowy_list_files', `List all files in a workspace storage directory.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
- workspace_id: The workspace ID
|
|
90
|
+
- parent_dir (optional): Storage directory (default: 'attachments')`, {
|
|
91
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
92
|
+
parent_dir: z.string().default('attachments').describe('Storage directory name'),
|
|
93
|
+
}, async ({ workspace_id, parent_dir }) => {
|
|
94
|
+
try {
|
|
95
|
+
const files = await appflowyClient.listFiles(workspace_id, parent_dir);
|
|
96
|
+
if (files.length === 0) {
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: 'text', text: `No files found in ${parent_dir}/` }],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const lines = [`# Files in ${parent_dir}/\n`];
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
lines.push(`š **${file.file_id}**`);
|
|
104
|
+
lines.push(` URL: ${file.url}`);
|
|
105
|
+
lines.push('');
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
return {
|
|
113
|
+
content: [{ type: 'text', text: `ā Error listing files: ${error.message}` }],
|
|
114
|
+
isError: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
// Tool: Delete file
|
|
119
|
+
server.tool('appflowy_delete_file', `ā ļø Delete a file from AppFlowy Cloud storage. This action cannot be undone!
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
- workspace_id: The workspace ID
|
|
123
|
+
- file_id: The file ID to delete
|
|
124
|
+
- parent_dir (optional): Storage directory (default: 'attachments')`, {
|
|
125
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
126
|
+
file_id: z.string().describe('The file ID to delete'),
|
|
127
|
+
parent_dir: z.string().default('attachments').describe('Storage directory name'),
|
|
128
|
+
}, async ({ workspace_id, file_id, parent_dir }) => {
|
|
129
|
+
try {
|
|
130
|
+
await appflowyClient.deleteFile(workspace_id, file_id, parent_dir);
|
|
131
|
+
return {
|
|
132
|
+
content: [{ type: 'text', text: `šļø File ${file_id} deleted successfully.` }],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
return {
|
|
137
|
+
content: [{ type: 'text', text: `ā Error deleting file: ${error.message}` }],
|
|
138
|
+
isError: true,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
// Tool: Attach file to document
|
|
143
|
+
server.tool('appflowy_attach_file_to_document', `Attach an uploaded file to a specific document/page in AppFlowy.
|
|
144
|
+
|
|
145
|
+
This inserts a file block into the document so the file appears inline.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
- workspace_id: The workspace ID
|
|
149
|
+
- document_id: The document/view ID
|
|
150
|
+
- file_id: The uploaded file ID
|
|
151
|
+
- parent_dir (optional): Storage directory (default: 'attachments')`, {
|
|
152
|
+
workspace_id: z.string().describe('The workspace ID'),
|
|
153
|
+
document_id: z.string().describe('The document/view ID'),
|
|
154
|
+
file_id: z.string().describe('The uploaded file ID'),
|
|
155
|
+
parent_dir: z.string().default('attachments').describe('Storage directory name'),
|
|
156
|
+
}, async ({ workspace_id, document_id, file_id, parent_dir }) => {
|
|
157
|
+
try {
|
|
158
|
+
// Get file metadata
|
|
159
|
+
const metadata = await appflowyClient.getFileMetadata(workspace_id, file_id, parent_dir);
|
|
160
|
+
// Create upload result object
|
|
161
|
+
const uploadResult = {
|
|
162
|
+
file_id,
|
|
163
|
+
url: metadata.url || '',
|
|
164
|
+
name: metadata.file_name,
|
|
165
|
+
size: metadata.file_size,
|
|
166
|
+
mime_type: metadata.mime_type,
|
|
167
|
+
created_at: metadata.created_at,
|
|
168
|
+
};
|
|
169
|
+
await appflowyClient.attachFileToDocument(workspace_id, document_id, uploadResult, parent_dir);
|
|
170
|
+
return {
|
|
171
|
+
content: [
|
|
172
|
+
{
|
|
173
|
+
type: 'text',
|
|
174
|
+
text: `ā
File attached to document!\n\nš **${metadata.file_name}**\n- Document ID: ${document_id}\n- File ID: ${file_id}\n- Size: ${formatFileSize(metadata.file_size)}`,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
return {
|
|
181
|
+
content: [{ type: 'text', text: `ā Error attaching file: ${error.message}` }],
|
|
182
|
+
isError: true,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// Helper: Format file size
|
|
188
|
+
function formatFileSize(bytes) {
|
|
189
|
+
if (bytes === 0)
|
|
190
|
+
return '0 B';
|
|
191
|
+
const k = 1024;
|
|
192
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
193
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
194
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=files.js.map
|