@daylight-labs/sharedb-mcp 0.1.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/dist/api-client.d.ts +175 -0
- package/dist/api-client.js +65 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +61 -0
- package/dist/resources/index.d.ts +13 -0
- package/dist/resources/index.js +638 -0
- package/dist/tools/auth.d.ts +31 -0
- package/dist/tools/auth.js +126 -0
- package/dist/tools/data.d.ts +127 -0
- package/dist/tools/data.js +290 -0
- package/dist/tools/migrations.d.ts +114 -0
- package/dist/tools/migrations.js +272 -0
- package/dist/tools/schema.d.ts +83 -0
- package/dist/tools/schema.js +289 -0
- package/package.json +38 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { api } from '../api-client.js';
|
|
2
|
+
export const migrationTools = [
|
|
3
|
+
{
|
|
4
|
+
name: 'stage_change',
|
|
5
|
+
description: 'Stage a schema change to be applied later. Supports: CREATE_TABLE, DROP_TABLE, ADD_COLUMN, DROP_COLUMN, RENAME_COLUMN, ADD_INDEX, ADD_RLS_POLICY',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
database_id: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'The database ID or name',
|
|
12
|
+
},
|
|
13
|
+
operation: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
enum: [
|
|
16
|
+
'CREATE_TABLE',
|
|
17
|
+
'DROP_TABLE',
|
|
18
|
+
'RENAME_TABLE',
|
|
19
|
+
'ADD_COLUMN',
|
|
20
|
+
'DROP_COLUMN',
|
|
21
|
+
'RENAME_COLUMN',
|
|
22
|
+
'ADD_INDEX',
|
|
23
|
+
'ADD_RLS_POLICY',
|
|
24
|
+
],
|
|
25
|
+
description: 'The type of schema change',
|
|
26
|
+
},
|
|
27
|
+
params: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
description: `Parameters for the operation:
|
|
30
|
+
- CREATE_TABLE: { tableName, columns: [{ name, type, nullable?, defaultValue?, primaryKey? }], enableRls?: true, userIdColumn?: "user_id" }
|
|
31
|
+
- ADD_COLUMN: { tableName, columnName, type, nullable?, defaultValue? }
|
|
32
|
+
- ADD_INDEX: { tableName, indexName, columns: [...], unique? }
|
|
33
|
+
- ADD_RLS_POLICY: Row Level Security policy. Two role types exist:
|
|
34
|
+
* Regular users: authenticated app users
|
|
35
|
+
* Admins: app builders who manage reference data
|
|
36
|
+
|
|
37
|
+
Common patterns:
|
|
38
|
+
1. User-owned data (e.g., user's workouts): { tableName, policyName, userIdColumn: "user_id" }
|
|
39
|
+
2. Admin-managed reference data (e.g., exercise library): Users can READ, only admins can INSERT/UPDATE/DELETE:
|
|
40
|
+
- First: { tableName, policyName: "table_read", command: "SELECT", using: "true" }
|
|
41
|
+
- Then: { tableName, policyName: "table_admin_write", command: "INSERT", using: "public.current_user_is_admin()" }
|
|
42
|
+
- And: { tableName, policyName: "table_admin_update", command: "UPDATE", using: "public.current_user_is_admin()" }
|
|
43
|
+
- And: { tableName, policyName: "table_admin_delete", command: "DELETE", using: "public.current_user_is_admin()" }
|
|
44
|
+
3. Custom: { tableName, policyName, command: "ALL"|"SELECT"|"INSERT"|"UPDATE"|"DELETE", using: "SQL expression", withCheck?: "SQL expression" }`,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
required: ['database_id', 'operation', 'params'],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'list_staged_changes',
|
|
52
|
+
description: 'List all staged (pending) schema changes for a database',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
database_id: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'The database ID or name',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
required: ['database_id'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'preview_changes',
|
|
66
|
+
description: 'Preview the DDL statements that will be executed when applying staged changes',
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
database_id: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
description: 'The database ID or name',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
required: ['database_id'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'apply_changes',
|
|
80
|
+
description: 'Apply all staged changes as a migration. This executes the DDL on the database.',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {
|
|
84
|
+
database_id: {
|
|
85
|
+
type: 'string',
|
|
86
|
+
description: 'The database ID or name',
|
|
87
|
+
},
|
|
88
|
+
description: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
description: 'Optional description for the migration',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
required: ['database_id'],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'unstage_change',
|
|
98
|
+
description: 'Remove a staged change before it is applied',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
database_id: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
description: 'The database ID or name',
|
|
105
|
+
},
|
|
106
|
+
change_id: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
description: 'The ID of the staged change to remove',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
required: ['database_id', 'change_id'],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'get_migration_history',
|
|
116
|
+
description: 'List all applied migrations for a database',
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
database_id: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
description: 'The database ID or name',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
required: ['database_id'],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'rollback_migration',
|
|
130
|
+
description: 'Roll back a migration if it is reversible. Only the most recent migration can be rolled back.',
|
|
131
|
+
inputSchema: {
|
|
132
|
+
type: 'object',
|
|
133
|
+
properties: {
|
|
134
|
+
database_id: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
description: 'The database ID or name',
|
|
137
|
+
},
|
|
138
|
+
migration_id: {
|
|
139
|
+
type: 'string',
|
|
140
|
+
description: 'The ID of the migration to roll back',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
required: ['database_id', 'migration_id'],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
export async function handleMigrationTool(name, args) {
|
|
148
|
+
try {
|
|
149
|
+
switch (name) {
|
|
150
|
+
case 'stage_change': {
|
|
151
|
+
const databaseId = args.database_id;
|
|
152
|
+
const operation = args.operation;
|
|
153
|
+
const params = args.params;
|
|
154
|
+
const { staged } = await api.changes.stage(databaseId, operation, params);
|
|
155
|
+
return {
|
|
156
|
+
content: [
|
|
157
|
+
{
|
|
158
|
+
type: 'text',
|
|
159
|
+
text: `Staged ${staged.length} change(s):\n${JSON.stringify(staged, null, 2)}`,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
case 'list_staged_changes': {
|
|
165
|
+
const databaseId = args.database_id;
|
|
166
|
+
const { changes } = await api.changes.list(databaseId);
|
|
167
|
+
if (changes.length === 0) {
|
|
168
|
+
return {
|
|
169
|
+
content: [{ type: 'text', text: 'No staged changes' }],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
content: [
|
|
174
|
+
{
|
|
175
|
+
type: 'text',
|
|
176
|
+
text: JSON.stringify(changes, null, 2),
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
case 'preview_changes': {
|
|
182
|
+
const databaseId = args.database_id;
|
|
183
|
+
const result = await api.changes.preview(databaseId);
|
|
184
|
+
if (!result.preview) {
|
|
185
|
+
return {
|
|
186
|
+
content: [{ type: 'text', text: result.message || 'No staged changes to preview' }],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
content: [
|
|
191
|
+
{
|
|
192
|
+
type: 'text',
|
|
193
|
+
text: `Preview of ${result.preview.changeCount} changes:\n\nDDL to execute:\n${result.preview.ddlStatements.join(';\n\n')};\n\nHas irreversible changes: ${result.preview.hasIrreversibleChanges}`,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
case 'apply_changes': {
|
|
199
|
+
const databaseId = args.database_id;
|
|
200
|
+
const description = args.description;
|
|
201
|
+
const { migration } = await api.changes.apply(databaseId, description);
|
|
202
|
+
return {
|
|
203
|
+
content: [
|
|
204
|
+
{
|
|
205
|
+
type: 'text',
|
|
206
|
+
text: `Migration v${migration.version} applied successfully!\n\n${JSON.stringify(migration, null, 2)}`,
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
case 'unstage_change': {
|
|
212
|
+
const databaseId = args.database_id;
|
|
213
|
+
const changeId = args.change_id;
|
|
214
|
+
const { deleted } = await api.changes.unstage(databaseId, changeId);
|
|
215
|
+
return {
|
|
216
|
+
content: [
|
|
217
|
+
{
|
|
218
|
+
type: 'text',
|
|
219
|
+
text: `Unstaged change: ${deleted.change_type} on ${deleted.table_name}`,
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
case 'get_migration_history': {
|
|
225
|
+
const databaseId = args.database_id;
|
|
226
|
+
const { migrations } = await api.migrations.list(databaseId);
|
|
227
|
+
if (migrations.length === 0) {
|
|
228
|
+
return {
|
|
229
|
+
content: [{ type: 'text', text: 'No migrations applied yet' }],
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
content: [
|
|
234
|
+
{
|
|
235
|
+
type: 'text',
|
|
236
|
+
text: JSON.stringify(migrations, null, 2),
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
case 'rollback_migration': {
|
|
242
|
+
const databaseId = args.database_id;
|
|
243
|
+
const migrationId = args.migration_id;
|
|
244
|
+
const { rolledBack } = await api.migrations.rollback(databaseId, migrationId);
|
|
245
|
+
return {
|
|
246
|
+
content: [
|
|
247
|
+
{
|
|
248
|
+
type: 'text',
|
|
249
|
+
text: `Rolled back migration v${rolledBack.version}, reverted ${rolledBack.changesReverted} changes`,
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
default:
|
|
255
|
+
return {
|
|
256
|
+
content: [{ type: 'text', text: `Unknown migration tool: ${name}` }],
|
|
257
|
+
isError: true,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
return {
|
|
263
|
+
content: [
|
|
264
|
+
{
|
|
265
|
+
type: 'text',
|
|
266
|
+
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
isError: true,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export declare const schemaTools: ({
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
name: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
display_name: {
|
|
12
|
+
type: string;
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
environment: {
|
|
16
|
+
type: string;
|
|
17
|
+
enum: string[];
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
database_id?: undefined;
|
|
21
|
+
table_name?: undefined;
|
|
22
|
+
};
|
|
23
|
+
required: string[];
|
|
24
|
+
};
|
|
25
|
+
} | {
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: "object";
|
|
30
|
+
properties: {
|
|
31
|
+
name?: undefined;
|
|
32
|
+
display_name?: undefined;
|
|
33
|
+
environment?: undefined;
|
|
34
|
+
database_id?: undefined;
|
|
35
|
+
table_name?: undefined;
|
|
36
|
+
};
|
|
37
|
+
required: never[];
|
|
38
|
+
};
|
|
39
|
+
} | {
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: "object";
|
|
44
|
+
properties: {
|
|
45
|
+
database_id: {
|
|
46
|
+
type: string;
|
|
47
|
+
description: string;
|
|
48
|
+
};
|
|
49
|
+
name?: undefined;
|
|
50
|
+
display_name?: undefined;
|
|
51
|
+
environment?: undefined;
|
|
52
|
+
table_name?: undefined;
|
|
53
|
+
};
|
|
54
|
+
required: string[];
|
|
55
|
+
};
|
|
56
|
+
} | {
|
|
57
|
+
name: string;
|
|
58
|
+
description: string;
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: "object";
|
|
61
|
+
properties: {
|
|
62
|
+
database_id: {
|
|
63
|
+
type: string;
|
|
64
|
+
description: string;
|
|
65
|
+
};
|
|
66
|
+
table_name: {
|
|
67
|
+
type: string;
|
|
68
|
+
description: string;
|
|
69
|
+
};
|
|
70
|
+
name?: undefined;
|
|
71
|
+
display_name?: undefined;
|
|
72
|
+
environment?: undefined;
|
|
73
|
+
};
|
|
74
|
+
required: string[];
|
|
75
|
+
};
|
|
76
|
+
})[];
|
|
77
|
+
export declare function handleSchemaTool(name: string, args: Record<string, unknown>): Promise<{
|
|
78
|
+
content: Array<{
|
|
79
|
+
type: 'text';
|
|
80
|
+
text: string;
|
|
81
|
+
}>;
|
|
82
|
+
isError?: boolean;
|
|
83
|
+
}>;
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { api } from '../api-client.js';
|
|
2
|
+
import { config } from '../config.js';
|
|
3
|
+
export const schemaTools = [
|
|
4
|
+
{
|
|
5
|
+
name: 'create_database',
|
|
6
|
+
description: 'Create a new app database in ShareDB. THIS IS THE FIRST STEP when building any app that needs a backend - from personal single-user apps to multi-user platforms. ShareDB provides PostgreSQL + Auth + REST API. After creating, use stage_change to add tables.',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
name: {
|
|
11
|
+
type: 'string',
|
|
12
|
+
description: 'The database name (lowercase, underscores allowed, e.g., "my_app" or "todo_list")',
|
|
13
|
+
},
|
|
14
|
+
display_name: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'A human-readable display name (e.g., "My App" or "Todo List")',
|
|
17
|
+
},
|
|
18
|
+
environment: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
enum: ['development', 'staging', 'production'],
|
|
21
|
+
description: 'The environment for this database (default: development)',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
required: ['name', 'display_name'],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'list_databases',
|
|
29
|
+
description: 'List all app databases in ShareDB',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {},
|
|
33
|
+
required: [],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'get_database_schema',
|
|
38
|
+
description: 'Get the full schema for a database, including all tables, columns, indexes, constraints, RLS policies, and functions',
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
database_id: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description: 'The database ID or name',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
required: ['database_id'],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'get_table_details',
|
|
52
|
+
description: 'Get detailed information about a specific table, including columns, indexes, constraints, and RLS policies',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
database_id: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'The database ID or name',
|
|
59
|
+
},
|
|
60
|
+
table_name: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
description: 'The name of the table',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ['database_id', 'table_name'],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'get_rls_policies',
|
|
70
|
+
description: 'List all RLS (Row Level Security) policies for a database',
|
|
71
|
+
inputSchema: {
|
|
72
|
+
type: 'object',
|
|
73
|
+
properties: {
|
|
74
|
+
database_id: {
|
|
75
|
+
type: 'string',
|
|
76
|
+
description: 'The database ID or name',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
required: ['database_id'],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'start_postgrest',
|
|
84
|
+
description: 'Start the PostgREST API server for a database. This enables the REST API endpoints for data access. Required before using insert_rows, query_rows, etc.',
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
database_id: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
description: 'The database ID or name',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
required: ['database_id'],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'restart_postgrest',
|
|
98
|
+
description: 'Restart the PostgREST API server for a database. Use this after schema changes to refresh the API, or if PostgREST is in a bad state.',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
database_id: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
description: 'The database ID or name',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
required: ['database_id'],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
export async function handleSchemaTool(name, args) {
|
|
112
|
+
try {
|
|
113
|
+
switch (name) {
|
|
114
|
+
case 'create_database': {
|
|
115
|
+
const dbName = args.name;
|
|
116
|
+
const displayName = args.display_name;
|
|
117
|
+
const environment = args.environment || 'development';
|
|
118
|
+
const { database } = await api.databases.create({
|
|
119
|
+
name: dbName,
|
|
120
|
+
displayName,
|
|
121
|
+
environment,
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
content: [
|
|
125
|
+
{
|
|
126
|
+
type: 'text',
|
|
127
|
+
text: `Database "${database.display_name}" created successfully!
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
**IMPORTANT: Store this database reference for future use in this project:**
|
|
131
|
+
- Database ID: ${database.id}
|
|
132
|
+
- Database Name: ${database.name}
|
|
133
|
+
- Display Name: ${database.display_name}
|
|
134
|
+
- Environment: ${database.environment}
|
|
135
|
+
- Auth API: ${config.authApiUrl}
|
|
136
|
+
|
|
137
|
+
Use the Database ID for all subsequent ShareDB operations (stage_change, apply_changes, insert_rows, etc.)
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## API Endpoints for your app
|
|
141
|
+
|
|
142
|
+
**Auth API** (${config.authApiUrl}):
|
|
143
|
+
- POST /auth/register - Register new user
|
|
144
|
+
- POST /auth/login - Login, returns { accessToken, refreshToken, user }
|
|
145
|
+
- POST /auth/refresh - Refresh access token
|
|
146
|
+
- GET /auth/me - Get current user (requires auth header)
|
|
147
|
+
|
|
148
|
+
**PostgREST API** (per-database, unique URL):
|
|
149
|
+
- Use start_postgrest tool to start the API server
|
|
150
|
+
- GET /<table> - List rows
|
|
151
|
+
- GET /<table>?id=eq.<uuid> - Get single row
|
|
152
|
+
- POST /<table> - Create row
|
|
153
|
+
- PATCH /<table>?id=eq.<uuid> - Update row
|
|
154
|
+
- DELETE /<table>?id=eq.<uuid> - Delete row
|
|
155
|
+
- Include header: Authorization: Bearer <accessToken>
|
|
156
|
+
|
|
157
|
+
## Next steps
|
|
158
|
+
1. Use stage_change to add tables
|
|
159
|
+
2. Use apply_changes to create them
|
|
160
|
+
3. Use start_postgrest to start the REST API
|
|
161
|
+
4. Implement auth in your app using the Auth API
|
|
162
|
+
5. Query data using the PostgREST API`,
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
case 'list_databases': {
|
|
168
|
+
const { databases } = await api.databases.list();
|
|
169
|
+
const dbList = databases.map(db => `- **${db.display_name}** (${db.environment})\n - ID: ${db.id}\n - Name: ${db.name}`).join('\n');
|
|
170
|
+
return {
|
|
171
|
+
content: [
|
|
172
|
+
{
|
|
173
|
+
type: 'text',
|
|
174
|
+
text: `## ShareDB Databases
|
|
175
|
+
|
|
176
|
+
${databases.length === 0 ? '_No databases yet. Use create_database to create one._' : dbList}
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
**IMPORTANT: When working with a specific database, store its ID and name for future operations.**
|
|
180
|
+
Use the Database ID for all ShareDB tools (stage_change, apply_changes, insert_rows, query_rows, etc.)
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## API Endpoints
|
|
184
|
+
|
|
185
|
+
**Auth API**: ${config.authApiUrl}
|
|
186
|
+
**PostgREST API**: Each database has its own PostgREST instance (use start_postgrest to get the URL).
|
|
187
|
+
|
|
188
|
+
Use get_api_endpoints with database_id for full endpoint documentation.`,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
case 'get_database_schema': {
|
|
194
|
+
const databaseId = args.database_id;
|
|
195
|
+
const schema = await api.databases.schema(databaseId);
|
|
196
|
+
return {
|
|
197
|
+
content: [
|
|
198
|
+
{
|
|
199
|
+
type: 'text',
|
|
200
|
+
text: JSON.stringify(schema, null, 2),
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
case 'get_table_details': {
|
|
206
|
+
const databaseId = args.database_id;
|
|
207
|
+
const tableName = args.table_name;
|
|
208
|
+
const details = await api.databases.tableDetails(databaseId, tableName);
|
|
209
|
+
return {
|
|
210
|
+
content: [
|
|
211
|
+
{
|
|
212
|
+
type: 'text',
|
|
213
|
+
text: JSON.stringify(details, null, 2),
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
case 'get_rls_policies': {
|
|
219
|
+
const databaseId = args.database_id;
|
|
220
|
+
const { policies } = await api.databases.rlsPolicies(databaseId);
|
|
221
|
+
return {
|
|
222
|
+
content: [
|
|
223
|
+
{
|
|
224
|
+
type: 'text',
|
|
225
|
+
text: JSON.stringify(policies, null, 2),
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
case 'start_postgrest': {
|
|
231
|
+
const databaseId = args.database_id;
|
|
232
|
+
const result = await api.databases.startPostgrest(databaseId);
|
|
233
|
+
return {
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
236
|
+
type: 'text',
|
|
237
|
+
text: `${result.message}
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
**Store this PostgREST URL for this database:**
|
|
241
|
+
- PostgREST URL: ${result.postgrestUrl}
|
|
242
|
+
- Port: ${result.port}
|
|
243
|
+
- Status: ${result.status}
|
|
244
|
+
|
|
245
|
+
This URL is used for direct REST API access to the database tables.
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
You can now use insert_rows, query_rows, update_rows, and delete_rows with this database.`,
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
case 'restart_postgrest': {
|
|
254
|
+
const databaseId = args.database_id;
|
|
255
|
+
const result = await api.databases.restartPostgrest(databaseId);
|
|
256
|
+
return {
|
|
257
|
+
content: [
|
|
258
|
+
{
|
|
259
|
+
type: 'text',
|
|
260
|
+
text: `${result.message}
|
|
261
|
+
|
|
262
|
+
PostgREST URL: ${result.postgrestUrl}
|
|
263
|
+
Port: ${result.port}
|
|
264
|
+
Status: ${result.status}
|
|
265
|
+
|
|
266
|
+
The PostgREST API has been restarted and should now reflect any recent schema changes.`,
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
default:
|
|
272
|
+
return {
|
|
273
|
+
content: [{ type: 'text', text: `Unknown schema tool: ${name}` }],
|
|
274
|
+
isError: true,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
return {
|
|
280
|
+
content: [
|
|
281
|
+
{
|
|
282
|
+
type: 'text',
|
|
283
|
+
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
isError: true,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@daylight-labs/sharedb-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for ShareDB schema management and development",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"sharedb-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"dev": "tsx watch src/index.ts",
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"sharedb",
|
|
22
|
+
"postgresql",
|
|
23
|
+
"database",
|
|
24
|
+
"schema"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20.14.10",
|
|
35
|
+
"tsx": "^4.16.2",
|
|
36
|
+
"typescript": "^5.5.3"
|
|
37
|
+
}
|
|
38
|
+
}
|