@daylight-labs/sharedb-mcp 0.1.0 → 0.1.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/dist/api-client.d.ts +28 -0
- package/dist/api-client.js +18 -0
- package/dist/config.js +3 -2
- package/dist/index.js +6 -1
- package/dist/tools/auth.js +35 -0
- package/dist/tools/logs.d.ts +66 -0
- package/dist/tools/logs.js +132 -0
- package/dist/tools/schema.js +28 -4
- package/package.json +1 -1
package/dist/api-client.d.ts
CHANGED
|
@@ -75,6 +75,23 @@ export interface PostgRESTInfo {
|
|
|
75
75
|
containerName?: string;
|
|
76
76
|
startedAt?: string;
|
|
77
77
|
}
|
|
78
|
+
export interface LogEntry {
|
|
79
|
+
id: string;
|
|
80
|
+
database_id: string;
|
|
81
|
+
level: 'error' | 'debug';
|
|
82
|
+
message: string;
|
|
83
|
+
metadata: Record<string, unknown>;
|
|
84
|
+
source: 'admin-api' | 'admin-ui' | 'user-app' | 'postgrest';
|
|
85
|
+
request_id: string | null;
|
|
86
|
+
created_at: string;
|
|
87
|
+
}
|
|
88
|
+
export interface LogQueryOptions {
|
|
89
|
+
level?: string;
|
|
90
|
+
source?: string;
|
|
91
|
+
since?: string;
|
|
92
|
+
until?: string;
|
|
93
|
+
limit?: number;
|
|
94
|
+
}
|
|
78
95
|
export declare const api: {
|
|
79
96
|
databases: {
|
|
80
97
|
list: () => Promise<{
|
|
@@ -172,4 +189,15 @@ export declare const api: {
|
|
|
172
189
|
helperFunction: string;
|
|
173
190
|
}>;
|
|
174
191
|
};
|
|
192
|
+
logs: {
|
|
193
|
+
query: (dbId: string, options?: LogQueryOptions) => Promise<{
|
|
194
|
+
logs: LogEntry[];
|
|
195
|
+
total: number;
|
|
196
|
+
limit: number;
|
|
197
|
+
offset: number;
|
|
198
|
+
}>;
|
|
199
|
+
get: (dbId: string, logId: string) => Promise<{
|
|
200
|
+
log: LogEntry;
|
|
201
|
+
}>;
|
|
202
|
+
};
|
|
175
203
|
};
|
package/dist/api-client.js
CHANGED
|
@@ -62,4 +62,22 @@ export const api = {
|
|
|
62
62
|
auth: {
|
|
63
63
|
config: () => request('/admin/auth/config'),
|
|
64
64
|
},
|
|
65
|
+
logs: {
|
|
66
|
+
query: (dbId, options = {}) => {
|
|
67
|
+
const params = new URLSearchParams();
|
|
68
|
+
if (options.level)
|
|
69
|
+
params.append('level', options.level);
|
|
70
|
+
if (options.source)
|
|
71
|
+
params.append('source', options.source);
|
|
72
|
+
if (options.since)
|
|
73
|
+
params.append('since', options.since);
|
|
74
|
+
if (options.until)
|
|
75
|
+
params.append('until', options.until);
|
|
76
|
+
if (options.limit)
|
|
77
|
+
params.append('limit', options.limit.toString());
|
|
78
|
+
const query = params.toString();
|
|
79
|
+
return request(`/admin/databases/${dbId}/logs${query ? `?${query}` : ''}`);
|
|
80
|
+
},
|
|
81
|
+
get: (dbId, logId) => request(`/admin/databases/${dbId}/logs/${logId}`),
|
|
82
|
+
},
|
|
65
83
|
};
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
const domain = process.env.SHAREDB_DOMAIN;
|
|
1
2
|
export const config = {
|
|
2
|
-
adminApiUrl: process.env.SHAREDB_API_URL || 'http://localhost:3002',
|
|
3
|
-
authApiUrl: process.env.SHAREDB_AUTH_URL || 'http://localhost:3000',
|
|
3
|
+
adminApiUrl: process.env.SHAREDB_API_URL || (domain ? `https://${domain}/api` : 'http://localhost:3002'),
|
|
4
|
+
authApiUrl: process.env.SHAREDB_AUTH_URL || (domain ? `https://${domain}/api` : 'http://localhost:3000'),
|
|
4
5
|
token: process.env.SHAREDB_TOKEN || '',
|
|
5
6
|
};
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { schemaTools, handleSchemaTool } from './tools/schema.js';
|
|
|
6
6
|
import { migrationTools, handleMigrationTool } from './tools/migrations.js';
|
|
7
7
|
import { authTools, handleAuthTool } from './tools/auth.js';
|
|
8
8
|
import { dataTools, handleDataTool } from './tools/data.js';
|
|
9
|
+
import { logsTools, handleLogsTool } from './tools/logs.js';
|
|
9
10
|
import { resources, readResource } from './resources/index.js';
|
|
10
11
|
const server = new Server({
|
|
11
12
|
name: 'sharedb',
|
|
@@ -16,7 +17,7 @@ const server = new Server({
|
|
|
16
17
|
resources: {},
|
|
17
18
|
},
|
|
18
19
|
});
|
|
19
|
-
const allTools = [...schemaTools, ...migrationTools, ...authTools, ...dataTools];
|
|
20
|
+
const allTools = [...schemaTools, ...migrationTools, ...authTools, ...dataTools, ...logsTools];
|
|
20
21
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
21
22
|
return { tools: allTools };
|
|
22
23
|
});
|
|
@@ -38,6 +39,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
38
39
|
if (dataTool) {
|
|
39
40
|
return handleDataTool(name, args || {});
|
|
40
41
|
}
|
|
42
|
+
const logsTool = logsTools.find((t) => t.name === name);
|
|
43
|
+
if (logsTool) {
|
|
44
|
+
return handleLogsTool(name, args || {});
|
|
45
|
+
}
|
|
41
46
|
return {
|
|
42
47
|
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
43
48
|
isError: true,
|
package/dist/tools/auth.js
CHANGED
|
@@ -69,6 +69,11 @@ export async function handleAuthTool(name, args) {
|
|
|
69
69
|
logout: `POST ${config.authApiUrl}/auth/logout`,
|
|
70
70
|
me: `GET ${config.authApiUrl}/auth/me`,
|
|
71
71
|
},
|
|
72
|
+
importantNotes: [
|
|
73
|
+
'After login, store the accessToken and user object (contains user.id)',
|
|
74
|
+
'Include accessToken in all API requests: Authorization: Bearer <accessToken>',
|
|
75
|
+
'Use GET /auth/me to fetch current user if needed (returns { user: { id, email, name } })',
|
|
76
|
+
],
|
|
72
77
|
},
|
|
73
78
|
postgrest: {
|
|
74
79
|
baseUrl: postgrestUrl,
|
|
@@ -83,6 +88,36 @@ export async function handleAuthTool(name, args) {
|
|
|
83
88
|
delete: `DELETE ${postgrestUrl}/<table>?id=eq.<uuid>`,
|
|
84
89
|
},
|
|
85
90
|
},
|
|
91
|
+
importantNotes: [
|
|
92
|
+
'CRITICAL: user_id is NOT automatically set! When creating records with a user_id column, the client MUST include user_id in the request body.',
|
|
93
|
+
'Get the user ID from login response (user.id) or GET /auth/me, then include it: POST /todos { "title": "...", "user_id": "<user-id-from-auth>" }',
|
|
94
|
+
'RLS policies filter BY user_id but do not SET it - the client must always send user_id explicitly.',
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
logging: {
|
|
98
|
+
description: 'DEVELOPER DEBUGGING ONLY - Error and debug logging for app development. Use this to catch and debug errors during development. Logs are stored for 7 days and viewable in the admin UI. NOT for end-user analytics or production user tracking.',
|
|
99
|
+
endpoint: `POST ${config.adminApiUrl}/logs`,
|
|
100
|
+
authentication: 'None required (public endpoint, rate limited to 100/min per database)',
|
|
101
|
+
requestBody: {
|
|
102
|
+
database_id: '<your-database-uuid> (required)',
|
|
103
|
+
level: '"error" | "debug" (required)',
|
|
104
|
+
message: 'string (required)',
|
|
105
|
+
metadata: 'object (optional) - additional context like stack traces, component names, etc.',
|
|
106
|
+
source: '"user-app" (required for client apps)',
|
|
107
|
+
request_id: 'string (optional) - for correlating related logs',
|
|
108
|
+
},
|
|
109
|
+
example: `fetch('${config.adminApiUrl}/logs', {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers: { 'Content-Type': 'application/json' },
|
|
112
|
+
body: JSON.stringify({
|
|
113
|
+
database_id: '<your-database-uuid>',
|
|
114
|
+
level: 'error',
|
|
115
|
+
message: 'Failed to load user data',
|
|
116
|
+
metadata: { component: 'UserProfile', error: err.message, stack: err.stack },
|
|
117
|
+
source: 'user-app'
|
|
118
|
+
})
|
|
119
|
+
})`,
|
|
120
|
+
recommendation: 'Add to your global error handler (window.onerror, React error boundaries) during development to catch unhandled errors.',
|
|
86
121
|
},
|
|
87
122
|
};
|
|
88
123
|
return {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export declare const logsTools: ({
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
database_id: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
level: {
|
|
12
|
+
type: string;
|
|
13
|
+
enum: string[];
|
|
14
|
+
description: string;
|
|
15
|
+
};
|
|
16
|
+
source: {
|
|
17
|
+
type: string;
|
|
18
|
+
enum: string[];
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
since: {
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
|
+
until: {
|
|
26
|
+
type: string;
|
|
27
|
+
description: string;
|
|
28
|
+
};
|
|
29
|
+
limit: {
|
|
30
|
+
type: string;
|
|
31
|
+
description: string;
|
|
32
|
+
};
|
|
33
|
+
log_id?: undefined;
|
|
34
|
+
};
|
|
35
|
+
required: string[];
|
|
36
|
+
};
|
|
37
|
+
} | {
|
|
38
|
+
name: string;
|
|
39
|
+
description: string;
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: "object";
|
|
42
|
+
properties: {
|
|
43
|
+
database_id: {
|
|
44
|
+
type: string;
|
|
45
|
+
description: string;
|
|
46
|
+
};
|
|
47
|
+
log_id: {
|
|
48
|
+
type: string;
|
|
49
|
+
description: string;
|
|
50
|
+
};
|
|
51
|
+
level?: undefined;
|
|
52
|
+
source?: undefined;
|
|
53
|
+
since?: undefined;
|
|
54
|
+
until?: undefined;
|
|
55
|
+
limit?: undefined;
|
|
56
|
+
};
|
|
57
|
+
required: string[];
|
|
58
|
+
};
|
|
59
|
+
})[];
|
|
60
|
+
export declare function handleLogsTool(name: string, args: Record<string, unknown>): Promise<{
|
|
61
|
+
content: Array<{
|
|
62
|
+
type: 'text';
|
|
63
|
+
text: string;
|
|
64
|
+
}>;
|
|
65
|
+
isError?: boolean;
|
|
66
|
+
}>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { api } from '../api-client.js';
|
|
2
|
+
export const logsTools = [
|
|
3
|
+
{
|
|
4
|
+
name: 'query_logs',
|
|
5
|
+
description: 'Query error and debug logs for a database. FOR DEVELOPER DEBUGGING ONLY - helps you debug issues during app development. View client-side errors, PostgREST API errors, or backend failures. Logs are retained for 7 days. Filter by source: "user-app" for client app errors, "postgrest" for API errors, "admin-api" for backend errors.',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
database_id: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'The database ID or name to query logs for',
|
|
12
|
+
},
|
|
13
|
+
level: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
enum: ['error', 'debug'],
|
|
16
|
+
description: 'Filter by log level',
|
|
17
|
+
},
|
|
18
|
+
source: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
enum: ['admin-api', 'admin-ui', 'user-app', 'postgrest'],
|
|
21
|
+
description: 'Filter by log source: user-app (client apps), postgrest (API errors), admin-api (backend), admin-ui (admin dashboard)',
|
|
22
|
+
},
|
|
23
|
+
since: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'ISO 8601 datetime to filter logs after (e.g., "2024-01-01T00:00:00Z")',
|
|
26
|
+
},
|
|
27
|
+
until: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
description: 'ISO 8601 datetime to filter logs before',
|
|
30
|
+
},
|
|
31
|
+
limit: {
|
|
32
|
+
type: 'number',
|
|
33
|
+
description: 'Maximum number of logs to return (default: 100, max: 1000)',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ['database_id'],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'get_log_details',
|
|
41
|
+
description: 'Get full details of a specific log entry including all metadata (stack traces, request context, etc.).',
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
database_id: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'The database ID or name',
|
|
48
|
+
},
|
|
49
|
+
log_id: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'The log entry ID',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
required: ['database_id', 'log_id'],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
export async function handleLogsTool(name, args) {
|
|
59
|
+
try {
|
|
60
|
+
switch (name) {
|
|
61
|
+
case 'query_logs': {
|
|
62
|
+
const databaseId = args.database_id;
|
|
63
|
+
const level = args.level;
|
|
64
|
+
const source = args.source;
|
|
65
|
+
const since = args.since;
|
|
66
|
+
const until = args.until;
|
|
67
|
+
const limit = args.limit;
|
|
68
|
+
const result = await api.logs.query(databaseId, {
|
|
69
|
+
level,
|
|
70
|
+
source,
|
|
71
|
+
since,
|
|
72
|
+
until,
|
|
73
|
+
limit,
|
|
74
|
+
});
|
|
75
|
+
if (result.logs.length === 0) {
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
text: `No logs found for database "${databaseId}" with the specified filters.`,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const summary = result.logs.map((log) => ({
|
|
86
|
+
id: log.id,
|
|
87
|
+
level: log.level,
|
|
88
|
+
source: log.source,
|
|
89
|
+
message: log.message.substring(0, 200) + (log.message.length > 200 ? '...' : ''),
|
|
90
|
+
created_at: log.created_at,
|
|
91
|
+
}));
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: 'text',
|
|
96
|
+
text: `Found ${result.total} logs (showing ${result.logs.length}):\n\n${JSON.stringify(summary, null, 2)}`,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case 'get_log_details': {
|
|
102
|
+
const databaseId = args.database_id;
|
|
103
|
+
const logId = args.log_id;
|
|
104
|
+
const result = await api.logs.get(databaseId, logId);
|
|
105
|
+
return {
|
|
106
|
+
content: [
|
|
107
|
+
{
|
|
108
|
+
type: 'text',
|
|
109
|
+
text: `Log details:\n\n${JSON.stringify(result.log, null, 2)}`,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
default:
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: 'text', text: `Unknown logs tool: ${name}` }],
|
|
117
|
+
isError: true,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{
|
|
125
|
+
type: 'text',
|
|
126
|
+
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
isError: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
package/dist/tools/schema.js
CHANGED
|
@@ -149,17 +149,32 @@ Use the Database ID for all subsequent ShareDB operations (stage_change, apply_c
|
|
|
149
149
|
- Use start_postgrest tool to start the API server
|
|
150
150
|
- GET /<table> - List rows
|
|
151
151
|
- GET /<table>?id=eq.<uuid> - Get single row
|
|
152
|
-
- POST /<table> - Create row
|
|
152
|
+
- POST /<table> - Create row (IMPORTANT: include user_id in body if table has user_id column!)
|
|
153
153
|
- PATCH /<table>?id=eq.<uuid> - Update row
|
|
154
154
|
- DELETE /<table>?id=eq.<uuid> - Delete row
|
|
155
155
|
- Include header: Authorization: Bearer <accessToken>
|
|
156
156
|
|
|
157
|
+
**CRITICAL - user_id handling:**
|
|
158
|
+
- user_id is NOT automatically set by auth or RLS
|
|
159
|
+
- After login, store the user object: { id, email, name }
|
|
160
|
+
- When creating records, the client MUST send user_id in the request body
|
|
161
|
+
- Example: POST /todos { "title": "Buy milk", "user_id": "<id-from-login>" }
|
|
162
|
+
- RLS policies filter BY user_id but don't SET it
|
|
163
|
+
|
|
157
164
|
## Next steps
|
|
158
165
|
1. Use stage_change to add tables
|
|
159
166
|
2. Use apply_changes to create them
|
|
160
167
|
3. Use start_postgrest to start the REST API
|
|
161
168
|
4. Implement auth in your app using the Auth API
|
|
162
|
-
5. Query data using the PostgREST API
|
|
169
|
+
5. Query data using the PostgREST API
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
**NOTE FOR ASSISTANT:** ShareDB users are often non-technical builders who need guidance through technical steps. When helping them:
|
|
173
|
+
- Proactively offer to run commands for them (npm install, npm run dev, etc.)
|
|
174
|
+
- Explain what each step does in simple terms
|
|
175
|
+
- Don't assume they know how to start dev servers, install dependencies, or debug errors
|
|
176
|
+
- Guide them step-by-step through running their app locally
|
|
177
|
+
- If something fails, check logs with query_logs and explain the issue clearly`,
|
|
163
178
|
},
|
|
164
179
|
],
|
|
165
180
|
};
|
|
@@ -185,7 +200,10 @@ Use the Database ID for all ShareDB tools (stage_change, apply_changes, insert_r
|
|
|
185
200
|
**Auth API**: ${config.authApiUrl}
|
|
186
201
|
**PostgREST API**: Each database has its own PostgREST instance (use start_postgrest to get the URL).
|
|
187
202
|
|
|
188
|
-
Use get_api_endpoints with database_id for full endpoint documentation
|
|
203
|
+
Use get_api_endpoints with database_id for full endpoint documentation.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
**NOTE FOR ASSISTANT:** ShareDB users are often non-technical builders. Proactively help them with technical tasks like running commands, starting dev servers, and debugging. Explain things in simple terms.`,
|
|
189
207
|
},
|
|
190
208
|
],
|
|
191
209
|
};
|
|
@@ -245,7 +263,13 @@ Use get_api_endpoints with database_id for full endpoint documentation.`,
|
|
|
245
263
|
This URL is used for direct REST API access to the database tables.
|
|
246
264
|
---
|
|
247
265
|
|
|
248
|
-
You can now use insert_rows, query_rows, update_rows, and delete_rows with this database
|
|
266
|
+
You can now use insert_rows, query_rows, update_rows, and delete_rows with this database.
|
|
267
|
+
|
|
268
|
+
**NOTE FOR ASSISTANT:** The backend is now ready. If the user has a frontend app, help them start it:
|
|
269
|
+
- For React/Vite: \`npm install\` then \`npm run dev\`
|
|
270
|
+
- For Next.js: \`npm install\` then \`npm run dev\`
|
|
271
|
+
- Offer to run these commands for them and explain what's happening
|
|
272
|
+
- If errors occur, help debug and check query_logs for backend issues`,
|
|
249
273
|
},
|
|
250
274
|
],
|
|
251
275
|
};
|