@instantdb/mcp 0.22.171 → 0.22.172
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/index.js +49 -161
- package/dist/index.js.map +1 -1
- package/dist/tools.d.ts +12 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +72 -0
- package/dist/tools.js.map +1 -0
- package/package.json +9 -7
package/dist/index.js
CHANGED
|
@@ -15,9 +15,11 @@ import { pino } from 'pino';
|
|
|
15
15
|
import { init } from '@instantdb/admin';
|
|
16
16
|
import schema from "./db/instant.schema.js";
|
|
17
17
|
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
|
|
18
|
-
import { addOAuthRoutes, ServiceProvider, tokensOfBearerToken, } from "./oauth-service-provider.js";
|
|
18
|
+
import { addOAuthRoutes, makeApiAuth, ServiceProvider, tokensOfBearerToken, } from "./oauth-service-provider.js";
|
|
19
|
+
import { PlatformApi } from '@instantdb/platform';
|
|
19
20
|
import indexHtml from "./index.html.js";
|
|
20
21
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
22
|
+
import { handleQuery, handleTransact } from "./tools.js";
|
|
21
23
|
// Helpers
|
|
22
24
|
// -----------
|
|
23
25
|
function createMCPServer() {
|
|
@@ -60,7 +62,7 @@ function wrapServerWithTracing(server, tracer, attrs) {
|
|
|
60
62
|
};
|
|
61
63
|
return server;
|
|
62
64
|
}
|
|
63
|
-
function registerTools(server) {
|
|
65
|
+
function registerTools(server, api) {
|
|
64
66
|
server.tool('learn', "If you don't have any context provided about InstantDB, use this tool to learn about it!", {}, async () => {
|
|
65
67
|
const instructions = `
|
|
66
68
|
You can learn about InstantDB by fetching our rules file for agents:
|
|
@@ -78,19 +80,15 @@ function registerTools(server) {
|
|
|
78
80
|
});
|
|
79
81
|
server.tool('get-schema', 'Fetch schema for an app by its ID!', {
|
|
80
82
|
appId: z.string().uuid().describe('UUID of the app'),
|
|
81
|
-
|
|
82
|
-
.string()
|
|
83
|
-
.uuid()
|
|
84
|
-
.describe('UUID of the admin token for the app'),
|
|
85
|
-
}, async ({ appId, adminToken }) => {
|
|
83
|
+
}, async ({ appId }) => {
|
|
86
84
|
const instructions = `
|
|
87
85
|
You can fetch the schema for the app by using the instant-cli tool:
|
|
88
86
|
|
|
89
87
|
\`\`\`
|
|
90
|
-
npx instant-cli pull schema --app ${appId} --
|
|
88
|
+
npx instant-cli pull schema --app ${appId} --yes
|
|
91
89
|
\`\`\`
|
|
92
90
|
|
|
93
|
-
We supply the --yes flag to skip confirmation prompts. Now 'instant.schema.ts'
|
|
91
|
+
We supply the --yes flag to skip confirmation prompts. Now 'instant.schema.ts' will contain the schema for the app.
|
|
94
92
|
`;
|
|
95
93
|
return {
|
|
96
94
|
content: [
|
|
@@ -103,16 +101,12 @@ function registerTools(server) {
|
|
|
103
101
|
});
|
|
104
102
|
server.tool('get-perms', 'Fetch permissions for an app by its ID', {
|
|
105
103
|
appId: z.string().uuid().describe('UUID of the app'),
|
|
106
|
-
|
|
107
|
-
.string()
|
|
108
|
-
.uuid()
|
|
109
|
-
.describe('UUID of the admin token for the app'),
|
|
110
|
-
}, async ({ appId, adminToken }) => {
|
|
104
|
+
}, async ({ appId }) => {
|
|
111
105
|
const instructions = `
|
|
112
106
|
You fetch the permissions for the app by using the instant-cli tool:
|
|
113
107
|
|
|
114
108
|
\`\`\`
|
|
115
|
-
npx instant-cli pull perms --app ${appId} --
|
|
109
|
+
npx instant-cli pull perms --app ${appId} --yes
|
|
116
110
|
\`\`\`
|
|
117
111
|
|
|
118
112
|
We supply the --yes flag to skip confirmation prompts. Now 'instant.perms.ts' will contain the permissions for the app.
|
|
@@ -129,17 +123,12 @@ function registerTools(server) {
|
|
|
129
123
|
server.tool('push-schema', `Push local schema changes for an app to the server. Do this after updating your local 'instant.schema.ts' file.
|
|
130
124
|
If you don't have an instant.schema.ts file yet, use the get-schema tool to learn how to get this file.`, {
|
|
131
125
|
appId: z.string().uuid().describe('UUID of the app'),
|
|
132
|
-
|
|
133
|
-
.string()
|
|
134
|
-
.uuid()
|
|
135
|
-
.describe('UUID of the admin token for the app'),
|
|
136
|
-
}, async ({ appId, adminToken }) => {
|
|
126
|
+
}, async ({ appId }) => {
|
|
137
127
|
const instructions = `
|
|
138
128
|
Push schema changes by using the instant-cli tool:
|
|
139
129
|
|
|
140
|
-
|
|
141
130
|
\`\`\`
|
|
142
|
-
npx instant-cli push schema --app ${appId} --
|
|
131
|
+
npx instant-cli push schema --app ${appId} --yes
|
|
143
132
|
\`\`\`
|
|
144
133
|
|
|
145
134
|
We supply the --yes flag to skip confirmation prompts.
|
|
@@ -148,7 +137,7 @@ function registerTools(server) {
|
|
|
148
137
|
If you want to rename fields as part of your schema changes you can use the --rename flag to specify renames.
|
|
149
138
|
|
|
150
139
|
\`\`\`
|
|
151
|
-
npx instant-cli push schema --app ${appId} --
|
|
140
|
+
npx instant-cli push schema --app ${appId} --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes
|
|
152
141
|
\`\`\`
|
|
153
142
|
`;
|
|
154
143
|
return {
|
|
@@ -163,16 +152,12 @@ function registerTools(server) {
|
|
|
163
152
|
server.tool('push-perms', `Push local permissions changes for an app to the server. Do this after updating your local instant.perms.ts file.
|
|
164
153
|
If you don't have an instant.perms.ts file yet, use the get-perms tool to learn how to get this file.`, {
|
|
165
154
|
appId: z.string().uuid().describe('UUID of the app'),
|
|
166
|
-
|
|
167
|
-
.string()
|
|
168
|
-
.uuid()
|
|
169
|
-
.describe('UUID of the admin token for the app'),
|
|
170
|
-
}, async ({ appId, adminToken }) => {
|
|
155
|
+
}, async ({ appId }) => {
|
|
171
156
|
const instructions = `
|
|
172
157
|
Push permission changes by using the instant-cli tool:
|
|
173
158
|
|
|
174
159
|
\`\`\`
|
|
175
|
-
npx instant-cli push
|
|
160
|
+
npx instant-cli push perms --app ${appId} --yes
|
|
176
161
|
\`\`\`
|
|
177
162
|
|
|
178
163
|
We supply the --yes flag to skip confirmation prompts.
|
|
@@ -186,142 +171,38 @@ function registerTools(server) {
|
|
|
186
171
|
],
|
|
187
172
|
};
|
|
188
173
|
});
|
|
189
|
-
server.tool('query',
|
|
190
|
-
const instructions = `
|
|
191
|
-
You can query data for an app by writing and executing a script using the
|
|
192
|
-
Admin SDK. Here's an example script for fetching a habit and its completions:
|
|
193
|
-
|
|
194
|
-
\`\`\`typescript
|
|
195
|
-
import { init } from "@instantdb/admin";
|
|
196
|
-
import "dotenv/config";
|
|
197
|
-
|
|
198
|
-
const adminDb = init({
|
|
199
|
-
appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
|
|
200
|
-
adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
async function fetchHabit(habitName: string) {
|
|
204
|
-
const { habits } = await adminDb.query({
|
|
205
|
-
habits: {
|
|
206
|
-
$: { where: { name: habitName } },
|
|
207
|
-
completions: {},
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
console.log(habits);
|
|
211
|
-
}
|
|
174
|
+
server.tool('query', `Execute an InstaQL query against an app. Returns the query results as JSON.
|
|
212
175
|
|
|
213
|
-
|
|
214
|
-
|
|
176
|
+
Example query to fetch all goals and their todos:
|
|
177
|
+
{"goals": {"todos": {}}}
|
|
215
178
|
|
|
216
|
-
|
|
179
|
+
Example query with a where clause:
|
|
180
|
+
{"goals": {"$": {"where": {"status": "active"}}, "todos": {}}}
|
|
217
181
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
text: instructions,
|
|
225
|
-
},
|
|
226
|
-
],
|
|
227
|
-
};
|
|
182
|
+
If you're unsure how to write queries, refer to the documentation:
|
|
183
|
+
https://instantdb.com/docs/instaql`, {
|
|
184
|
+
appId: z.string().uuid().describe('UUID of the app'),
|
|
185
|
+
query: z.record(z.string(), z.any()).describe('InstaQL query object'),
|
|
186
|
+
}, async ({ appId, query }) => {
|
|
187
|
+
return handleQuery(api, appId, query);
|
|
228
188
|
});
|
|
229
|
-
server.tool('transact',
|
|
230
|
-
const instructions = `
|
|
231
|
-
You can transact data for an app by writing and executing a script using the
|
|
232
|
-
Admin SDK. Here's an example script for seeding a microblog app with some posts:
|
|
233
|
-
|
|
234
|
-
\`\`\`typescript
|
|
235
|
-
import { init, id } from "@instantdb/admin";
|
|
236
|
-
import "dotenv/config";
|
|
237
|
-
|
|
238
|
-
const adminDb = init({
|
|
239
|
-
appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
|
|
240
|
-
adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
|
|
241
|
-
});
|
|
189
|
+
server.tool('transact', `Execute a transaction against an app. Useful for creating, updating, or deleting data.
|
|
242
190
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
content: string;
|
|
249
|
-
timestamp: string;
|
|
250
|
-
likes: number;
|
|
251
|
-
liked: boolean;
|
|
252
|
-
}
|
|
191
|
+
Steps use the internal transaction format:
|
|
192
|
+
- Create/update: ["update", "namespace", "entity-id", {"attr": "value"}]
|
|
193
|
+
- Link: ["link", "namespace", "entity-id", {"linkAttr": "target-id"}]
|
|
194
|
+
- Unlink: ["unlink", "namespace", "entity-id", {"linkAttr": "target-id"}]
|
|
195
|
+
- Delete: ["delete", "namespace", "entity-id"]
|
|
253
196
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
author: 'Sarah Chen',
|
|
257
|
-
handle: 'sarahchen',
|
|
258
|
-
color: 'bg-blue-100',
|
|
259
|
-
content: 'Just launched my new project! Really excited to share it with everyone.',
|
|
260
|
-
timestamp: '2h ago',
|
|
261
|
-
likes: 12,
|
|
262
|
-
liked: false,
|
|
263
|
-
},
|
|
264
|
-
{
|
|
265
|
-
author: 'Alex Rivera',
|
|
266
|
-
handle: 'alexrivera',
|
|
267
|
-
color: 'bg-purple-100',
|
|
268
|
-
content: 'Beautiful sunset today. Nature never stops amazing me.',
|
|
269
|
-
timestamp: '4h ago',
|
|
270
|
-
likes: 19,
|
|
271
|
-
liked: true,
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
author: 'Jordan Lee',
|
|
275
|
-
handle: 'jordanlee',
|
|
276
|
-
color: 'bg-pink-100',
|
|
277
|
-
content: 'Working on something cool with Next.js and TypeScript. Updates coming soon!',
|
|
278
|
-
timestamp: '6h ago',
|
|
279
|
-
likes: 7,
|
|
280
|
-
liked: false,
|
|
281
|
-
},
|
|
282
|
-
];
|
|
283
|
-
|
|
284
|
-
function friendlyTimeToTimestamp(friendlyTime: string) {
|
|
285
|
-
const hours = parseInt(friendlyTime);
|
|
286
|
-
const now = Date.now();
|
|
287
|
-
return now - (hours * 60 * 60 * 1000);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
function seed() {
|
|
291
|
-
console.log("Seeding db...");
|
|
292
|
-
mockPosts.forEach(post => {
|
|
293
|
-
const userId = id();
|
|
294
|
-
const postId = id();
|
|
295
|
-
const user = adminDb.tx.$users[userId].create({});
|
|
296
|
-
const profile = adminDb.tx.profiles[userId].create({
|
|
297
|
-
displayName: post.author,
|
|
298
|
-
handle: post.handle,
|
|
299
|
-
}).link({ user: userId });
|
|
300
|
-
const postEntity = adminDb.tx.posts[postId].create({
|
|
301
|
-
color: post.color,
|
|
302
|
-
content: post.content,
|
|
303
|
-
timestamp: friendlyTimeToTimestamp(post.timestamp),
|
|
304
|
-
}).link({ author: userId });
|
|
305
|
-
const likes = Array.from({ length: post.likes }, () => adminDb.tx.likes[id()].create({ postId, userId }).link({ post: postId, user: userId }));
|
|
306
|
-
adminDb.transact([user, profile, postEntity, ...likes]);
|
|
307
|
-
})
|
|
308
|
-
}
|
|
197
|
+
Example steps to create a todo:
|
|
198
|
+
[["update", "todos", "a-uuid", {"title": "Get fit", "done": false}]]
|
|
309
199
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
`;
|
|
317
|
-
return {
|
|
318
|
-
content: [
|
|
319
|
-
{
|
|
320
|
-
type: 'text',
|
|
321
|
-
text: instructions,
|
|
322
|
-
},
|
|
323
|
-
],
|
|
324
|
-
};
|
|
200
|
+
If you're unsure how to make transactions, refer to the documentation:
|
|
201
|
+
https://instantdb.com/docs/instaml`, {
|
|
202
|
+
appId: z.string().uuid().describe('UUID of the app'),
|
|
203
|
+
steps: z.array(z.array(z.any())).describe('Array of transaction steps'),
|
|
204
|
+
}, async ({ appId, steps }) => {
|
|
205
|
+
return handleTransact(api, appId, steps);
|
|
325
206
|
});
|
|
326
207
|
}
|
|
327
208
|
async function startStdio() {
|
|
@@ -340,8 +221,9 @@ async function startStdio() {
|
|
|
340
221
|
console.error('Provide an access token using --token or set INSTANT_ACCESS_TOKEN environment variable');
|
|
341
222
|
process.exit(1);
|
|
342
223
|
}
|
|
224
|
+
const api = new PlatformApi({ auth: { token: accessToken } });
|
|
343
225
|
const server = createMCPServer();
|
|
344
|
-
registerTools(server);
|
|
226
|
+
registerTools(server, api);
|
|
345
227
|
const transport = new StdioServerTransport();
|
|
346
228
|
await server.connect(transport);
|
|
347
229
|
console.error('Instant Platform MCP Server running on stdio');
|
|
@@ -443,6 +325,9 @@ async function startSse() {
|
|
|
443
325
|
const server = createMCPServer();
|
|
444
326
|
try {
|
|
445
327
|
const tokens = await tokensOfBearerToken(db, req.auth.token);
|
|
328
|
+
const api = new PlatformApi({
|
|
329
|
+
auth: makeApiAuth(oauthConfig, keyConfig, db, tokens.instantToken),
|
|
330
|
+
});
|
|
446
331
|
wrapServerWithTracing(server, tracer, {
|
|
447
332
|
'client.client_id': tokens.mcpToken.client?.client_id,
|
|
448
333
|
'client.name': tokens.mcpToken.client?.client_name,
|
|
@@ -451,7 +336,7 @@ async function startSse() {
|
|
|
451
336
|
'client.uri': tokens.mcpToken.client?.client_uri,
|
|
452
337
|
'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,
|
|
453
338
|
});
|
|
454
|
-
registerTools(server);
|
|
339
|
+
registerTools(server, api);
|
|
455
340
|
const transport = new StreamableHTTPServerTransport({
|
|
456
341
|
sessionIdGenerator: undefined,
|
|
457
342
|
});
|
|
@@ -501,6 +386,9 @@ async function startSse() {
|
|
|
501
386
|
});
|
|
502
387
|
try {
|
|
503
388
|
const tokens = await tokensOfBearerToken(db, req.auth.token);
|
|
389
|
+
const api = new PlatformApi({
|
|
390
|
+
auth: makeApiAuth(oauthConfig, keyConfig, db, tokens.instantToken),
|
|
391
|
+
});
|
|
504
392
|
wrapServerWithTracing(server, tracer, {
|
|
505
393
|
'client.client_id': tokens.mcpToken.client?.client_id,
|
|
506
394
|
'client.name': tokens.mcpToken.client?.client_name,
|
|
@@ -509,7 +397,7 @@ async function startSse() {
|
|
|
509
397
|
'client.uri': tokens.mcpToken.client?.client_uri,
|
|
510
398
|
'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,
|
|
511
399
|
});
|
|
512
|
-
registerTools(server);
|
|
400
|
+
registerTools(server, api);
|
|
513
401
|
transports.sse[transport.sessionId] = transport;
|
|
514
402
|
}
|
|
515
403
|
catch (e) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport 'dotenv/config';\nimport express, { Request, Response } from 'express';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { parseArgs } from 'node:util';\nimport version from './version.ts';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { HoneycombSDK } from '@honeycombio/opentelemetry-node';\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n Tracer,\n Attributes,\n} from '@opentelemetry/api';\n\nimport {\n createOAuthMetadata,\n mcpAuthRouter,\n} from '@modelcontextprotocol/sdk/server/auth/router.js';\nimport { pinoHttp } from 'pino-http';\nimport { pino } from 'pino';\nimport { init } from '@instantdb/admin';\n\nimport schema from './db/instant.schema.ts';\nimport { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';\nimport {\n addOAuthRoutes,\n OAuthConfig,\n ServiceProvider,\n tokensOfBearerToken,\n} from './oauth-service-provider.ts';\nimport { KeyConfig } from './crypto.ts';\nimport indexHtml from './index.html.ts';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\n\n// Helpers\n// -----------\nfunction createMCPServer(): McpServer {\n return new McpServer({\n name: '@instantdb/mcp',\n version,\n });\n}\n\n// Tool Registration\n// -----------\n\n// Adds tracing to server.tool\nfunction wrapServerWithTracing(\n server: McpServer,\n tracer: Tracer,\n attrs: Attributes,\n): McpServer {\n const originalTool = server.tool.bind(server);\n\n server.tool = function (name: string, ...args: any[]): any {\n // Find the callback (it's always the last argument)\n const callback = args[args.length - 1];\n const otherArgs = args.slice(0, -1);\n\n // Wrap the callback with tracing\n const wrappedCallback = async (...callbackArgs: any[]) => {\n const span = tracer.startSpan(`tool.${name}`, {\n attributes: attrs,\n });\n try {\n const result = await callback(...callbackArgs);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n span.recordException(error as Error);\n throw error;\n } finally {\n span.end();\n }\n };\n\n return originalTool(\n name,\n // @ts-expect-error: not sure how to type this\n ...otherArgs,\n wrappedCallback,\n );\n } as any;\n\n return server;\n}\n\nfunction registerTools(server: McpServer) {\n server.tool(\n 'learn',\n \"If you don't have any context provided about InstantDB, use this tool to learn about it!\",\n {},\n async () => {\n const instructions = `\n You can learn about InstantDB by fetching our rules file for agents:\n\n https://www.instantdb.com/llm-rules/AGENTS.md\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'get-schema',\n 'Fetch schema for an app by its ID!',\n {\n appId: z.string().uuid().describe('UUID of the app'),\n adminToken: z\n .string()\n .uuid()\n .describe('UUID of the admin token for the app'),\n },\n async ({ appId, adminToken }) => {\n const instructions = `\n You can fetch the schema for the app by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli pull schema --app ${appId} --token ${adminToken} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts. Now 'instant.schema.ts' with contain the schema for the app.\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'get-perms',\n 'Fetch permissions for an app by its ID',\n {\n appId: z.string().uuid().describe('UUID of the app'),\n adminToken: z\n .string()\n .uuid()\n .describe('UUID of the admin token for the app'),\n },\n async ({ appId, adminToken }) => {\n const instructions = `\n You fetch the permissions for the app by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli pull perms --app ${appId} --token ${adminToken} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts. Now 'instant.perms.ts' will contain the permissions for the app.\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'push-schema',\n `Push local schema changes for an app to the server. Do this after updating your local 'instant.schema.ts' file.\n If you don't have an instant.schema.ts file yet, use the get-schema tool to learn how to get this file.`,\n {\n appId: z.string().uuid().describe('UUID of the app'),\n adminToken: z\n .string()\n .uuid()\n .describe('UUID of the admin token for the app'),\n },\n async ({ appId, adminToken }) => {\n const instructions = `\n Push schema changes by using the instant-cli tool:\n\n\n \\`\\`\\`\n npx instant-cli push schema --app ${appId} --token ${adminToken} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts.\n\n By default the instant-cli tool will assume new fields from the previous schema are additions and missing fields are deletions.\n If you want to rename fields as part of your schema changes you can use the --rename flag to specify renames.\n\n \\`\\`\\`\n npx instant-cli push schema --app ${appId} --token ${adminToken} --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes\n \\`\\`\\`\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'push-perms',\n `Push local permissions changes for an app to the server. Do this after updating your local instant.perms.ts file.\n If you don't have an instant.perms.ts file yet, use the get-perms tool to learn how to get this file.`,\n {\n appId: z.string().uuid().describe('UUID of the app'),\n adminToken: z\n .string()\n .uuid()\n .describe('UUID of the admin token for the app'),\n },\n async ({ appId, adminToken }) => {\n const instructions = `\n Push permission changes by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli push schema --app ${appId} --token ${adminToken} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts.\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'query',\n 'Execute a query againt an app. Useful for inspecting data in the app.',\n {},\n async () => {\n const instructions = `\n You can query data for an app by writing and executing a script using the\n Admin SDK. Here's an example script for fetching a habit and its completions:\n\n \\`\\`\\`typescript\n import { init } from \"@instantdb/admin\";\n import \"dotenv/config\";\n\n const adminDb = init({\n appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,\n adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,\n });\n\n async function fetchHabit(habitName: string) {\n const { habits } = await adminDb.query({\n habits: {\n $: { where: { name: habitName } },\n completions: {},\n },\n });\n console.log(habits);\n }\n\n fetchHabit(\"Read\");\n \\`\\`\\`\n\n If you're unsure how to write queries, refer to the documentation:\n\n https://instantdb.com/docs/instaql.md\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'transact',\n 'Execute a transaction against an app. Useful for seeding or modifying data in the app.',\n {},\n async () => {\n const instructions = `\n You can transact data for an app by writing and executing a script using the\n Admin SDK. Here's an example script for seeding a microblog app with some posts:\n\n \\`\\`\\`typescript\n import { init, id } from \"@instantdb/admin\";\n import \"dotenv/config\";\n\n const adminDb = init({\n appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,\n adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,\n });\n\n interface Post {\n id: number;\n author: string;\n handle: string;\n color: string;\n content: string;\n timestamp: string;\n likes: number;\n liked: boolean;\n }\n\n const mockPosts: Post[] = [\n {\n author: 'Sarah Chen',\n handle: 'sarahchen',\n color: 'bg-blue-100',\n content: 'Just launched my new project! Really excited to share it with everyone.',\n timestamp: '2h ago',\n likes: 12,\n liked: false,\n },\n {\n author: 'Alex Rivera',\n handle: 'alexrivera',\n color: 'bg-purple-100',\n content: 'Beautiful sunset today. Nature never stops amazing me.',\n timestamp: '4h ago',\n likes: 19,\n liked: true,\n },\n {\n author: 'Jordan Lee',\n handle: 'jordanlee',\n color: 'bg-pink-100',\n content: 'Working on something cool with Next.js and TypeScript. Updates coming soon!',\n timestamp: '6h ago',\n likes: 7,\n liked: false,\n },\n ];\n\n function friendlyTimeToTimestamp(friendlyTime: string) {\n const hours = parseInt(friendlyTime);\n const now = Date.now();\n return now - (hours * 60 * 60 * 1000);\n }\n\n function seed() {\n console.log(\"Seeding db...\");\n mockPosts.forEach(post => {\n const userId = id();\n const postId = id();\n const user = adminDb.tx.$users[userId].create({});\n const profile = adminDb.tx.profiles[userId].create({\n displayName: post.author,\n handle: post.handle,\n }).link({ user: userId });\n const postEntity = adminDb.tx.posts[postId].create({\n color: post.color,\n content: post.content,\n timestamp: friendlyTimeToTimestamp(post.timestamp),\n }).link({ author: userId });\n const likes = Array.from({ length: post.likes }, () => adminDb.tx.likes[id()].create({ postId, userId }).link({ post: postId, user: userId }));\n adminDb.transact([user, profile, postEntity, ...likes]);\n })\n }\n\n seed();\n \\`\\`\\`\n\n If you're unsure how to make transactions, refer to the documentation:\n\n https://instantdb.com/docs/instaml.md\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n}\n\nasync function startStdio() {\n const {\n values: { token, ['api-url']: apiUrl },\n } = parseArgs({\n options: {\n token: {\n type: 'string',\n },\n ['api-url']: {\n type: 'string',\n },\n },\n });\n\n const accessToken = token || process.env.INSTANT_ACCESS_TOKEN;\n if (!accessToken) {\n console.error(\n 'Provide an access token using --token or set INSTANT_ACCESS_TOKEN environment variable',\n );\n process.exit(1);\n }\n\n const server = createMCPServer();\n registerTools(server);\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Instant Platform MCP Server running on stdio');\n}\n\nfunction ensureEnv(key: string): string {\n const v = process.env[key];\n if (!v) {\n throw new Error(`Missing environment variable ${key}`);\n }\n return v;\n}\n\nasync function startSse() {\n const honeycomb = new HoneycombSDK({\n apiKey: process.env.HONEYCOMB_API_KEY,\n serviceName: 'mcp-server',\n });\n\n if (process.env.HONEYCOMB_API_KEY) {\n honeycomb.start();\n }\n\n const tracer = trace.getTracer('mcp-server');\n\n const db = init({\n adminToken: ensureEnv('INSTANT_ADMIN_TOKEN'),\n appId: ensureEnv('INSTANT_APP_ID'),\n schema,\n disableValidation: true,\n });\n\n const oauthConfig: OAuthConfig = {\n clientId: ensureEnv('INSTANT_OAUTH_CLIENT_ID'),\n clientSecret: ensureEnv('INSTANT_OAUTH_CLIENT_SECRET'),\n serverOrigin: ensureEnv('SERVER_ORIGIN'),\n };\n\n const keyConfig: KeyConfig = JSON.parse(ensureEnv('INSTANT_AES_KEY'));\n\n const app = express();\n const logger = pino({ level: 'info' });\n\n app.use((req, res, next) => {\n const span = tracer.startSpan('http-req', {\n kind: SpanKind.SERVER,\n attributes: {\n 'http.method': req.method,\n 'http.url': req.url,\n 'http.target': req.path,\n 'http.host': req.get('host'),\n 'http.scheme': req.protocol,\n },\n });\n\n const originalEnd = res.end.bind(res);\n res.end = function (this: typeof res, ...args: any[]): typeof res {\n span.setAttribute('http.status_code', res.statusCode);\n span.setStatus({\n code: res.statusCode >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK,\n });\n span.end();\n return originalEnd(...args);\n };\n\n next();\n });\n\n app.use(\n pinoHttp({\n logger,\n autoLogging: {\n ignore(req) {\n return req.url === '/health';\n },\n },\n }),\n );\n app.use(express.json());\n\n const proxyProvider = new ServiceProvider(db, oauthConfig, keyConfig);\n\n const authRouterOptions = {\n scopesSupported: ['apps-read', 'apps-write'],\n provider: proxyProvider,\n issuerUrl: new URL(oauthConfig.serverOrigin),\n baseUrl: new URL(oauthConfig.serverOrigin),\n serviceDocumentationUrl: new URL('https://instantdb.com/docs'),\n };\n\n const oauthMetadata = createOAuthMetadata(authRouterOptions);\n\n app.use(mcpAuthRouter(authRouterOptions));\n\n addOAuthRoutes(app, db, oauthConfig);\n\n app.get('/.well-known/oauth-protected-resource/mcp', (_req, res) => {\n res.json({\n resource: `${oauthConfig.serverOrigin}/mcp`,\n authorization_servers: [oauthMetadata.issuer],\n scopes_supported: oauthMetadata.scopes_supported,\n resource_documentation: 'https://instantdb.com/docs',\n });\n });\n\n app.get('/.well-known/oauth-protected-resource/sse', (_req, res) => {\n res.json({\n resource: `${oauthConfig.serverOrigin}/mcp`,\n authorization_servers: [oauthMetadata.issuer],\n scopes_supported: oauthMetadata.scopes_supported,\n resource_documentation: 'https://instantdb.com/docs',\n });\n });\n\n const requireTokenMiddleware = (path: string) =>\n requireBearerAuth({\n verifier: proxyProvider,\n resourceMetadataUrl: `${oauthConfig.serverOrigin}/.well-known/oauth-protected-resource/${path}`,\n });\n\n // Handle POST requests for client-to-server communication\n app.post(\n '/mcp',\n requireTokenMiddleware('mcp'),\n async (req: Request, res: Response) => {\n const server = createMCPServer();\n try {\n const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n wrapServerWithTracing(server, tracer, {\n 'client.client_id': tokens.mcpToken.client?.client_id,\n 'client.name': tokens.mcpToken.client?.client_name,\n 'client.id': tokens.mcpToken.client?.id,\n 'client.scope': tokens.mcpToken.client?.scope,\n 'client.uri': tokens.mcpToken.client?.client_uri,\n 'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n });\n registerTools(server);\n const transport: StreamableHTTPServerTransport =\n new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n });\n\n req.on('close', () => {\n transport.close();\n server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n } catch (e) {\n console.error('Error handling MCP request:', e);\n if (!res.headersSent) {\n res.status(500).json({\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: 'Internal server error',\n },\n id: null,\n });\n }\n }\n },\n );\n\n // We're a stateless server, so disallow these\n const handleSessionRequest = async (\n _req: express.Request,\n res: express.Response,\n ) => {\n res.writeHead(405).end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: {\n code: -32000,\n message: 'Method not allowed.',\n },\n id: null,\n }),\n );\n };\n\n app.get('/mcp', handleSessionRequest);\n app.delete('/mcp', handleSessionRequest);\n\n // SSE for older clients\n const transports = {\n sse: {} as Record<string, SSEServerTransport>,\n };\n\n app.get(\n '/sse',\n requireTokenMiddleware('sse'),\n async (req: Request, res: Response) => {\n const server = createMCPServer();\n const transport = new SSEServerTransport('/messages', res);\n res.on('close', () => {\n delete transports.sse[transport.sessionId];\n });\n\n try {\n const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n wrapServerWithTracing(server, tracer, {\n 'client.client_id': tokens.mcpToken.client?.client_id,\n 'client.name': tokens.mcpToken.client?.client_name,\n 'client.id': tokens.mcpToken.client?.id,\n 'client.scope': tokens.mcpToken.client?.scope,\n 'client.uri': tokens.mcpToken.client?.client_uri,\n 'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n });\n\n registerTools(server);\n transports.sse[transport.sessionId] = transport;\n } catch (e) {\n console.error('Error handling MCP SSE request:', e);\n if (!res.headersSent) {\n res.status(500).json({\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: 'Internal server error',\n },\n id: null,\n });\n }\n return;\n }\n\n await server.connect(transport);\n },\n );\n\n // Legacy message endpoint for older clients\n app.post('/messages', async (req, res) => {\n const sessionId = req.query.sessionId as string;\n const transport = transports.sse[sessionId];\n if (transport) {\n await transport.handlePostMessage(req, res, req.body);\n } else {\n res.status(400).send('No transport found for sessionId');\n }\n });\n\n app.get('/', (_req, res: Response) => {\n res\n .status(200)\n .set('Content-Type', 'text/html; charset=UTF-8')\n .send(indexHtml(oauthConfig.serverOrigin));\n });\n\n app.get('/health', (_req, res: Response) => {\n res.status(200).send('Tip top!');\n });\n\n const port = parseInt(process.env.PORT || '3123');\n const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';\n\n if (process.env.IN_FLY) {\n app.set('trust proxy', 2);\n }\n\n app.listen(port, host, () => console.log(`listening on port ${port}`));\n}\n\nasync function main() {\n if (process.env.SERVER_TYPE === 'http') {\n return startSse();\n }\n return startStdio();\n}\n\nmain().catch((error) => {\n console.error('Fatal error in main():', error);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport 'dotenv/config';\nimport express, { Request, Response } from 'express';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { parseArgs } from 'node:util';\nimport version from './version.ts';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { HoneycombSDK } from '@honeycombio/opentelemetry-node';\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n Tracer,\n Attributes,\n} from '@opentelemetry/api';\n\nimport {\n createOAuthMetadata,\n mcpAuthRouter,\n} from '@modelcontextprotocol/sdk/server/auth/router.js';\nimport { pinoHttp } from 'pino-http';\nimport { pino } from 'pino';\nimport { init } from '@instantdb/admin';\n\nimport schema from './db/instant.schema.ts';\nimport { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';\nimport {\n addOAuthRoutes,\n makeApiAuth,\n OAuthConfig,\n ServiceProvider,\n tokensOfBearerToken,\n} from './oauth-service-provider.ts';\nimport { KeyConfig } from './crypto.ts';\nimport { PlatformApi } from '@instantdb/platform';\nimport indexHtml from './index.html.ts';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\nimport { handleQuery, handleTransact } from './tools.ts';\n\n// Helpers\n// -----------\nfunction createMCPServer(): McpServer {\n return new McpServer({\n name: '@instantdb/mcp',\n version,\n });\n}\n\n// Tool Registration\n// -----------\n\n// Adds tracing to server.tool\nfunction wrapServerWithTracing(\n server: McpServer,\n tracer: Tracer,\n attrs: Attributes,\n): McpServer {\n const originalTool = server.tool.bind(server);\n\n server.tool = function (name: string, ...args: any[]): any {\n // Find the callback (it's always the last argument)\n const callback = args[args.length - 1];\n const otherArgs = args.slice(0, -1);\n\n // Wrap the callback with tracing\n const wrappedCallback = async (...callbackArgs: any[]) => {\n const span = tracer.startSpan(`tool.${name}`, {\n attributes: attrs,\n });\n try {\n const result = await callback(...callbackArgs);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n span.recordException(error as Error);\n throw error;\n } finally {\n span.end();\n }\n };\n\n return originalTool(\n name,\n // @ts-expect-error: not sure how to type this\n ...otherArgs,\n wrappedCallback,\n );\n } as any;\n\n return server;\n}\n\nfunction registerTools(server: McpServer, api: PlatformApi) {\n server.tool(\n 'learn',\n \"If you don't have any context provided about InstantDB, use this tool to learn about it!\",\n {},\n async () => {\n const instructions = `\n You can learn about InstantDB by fetching our rules file for agents:\n\n https://www.instantdb.com/llm-rules/AGENTS.md\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'get-schema',\n 'Fetch schema for an app by its ID!',\n {\n appId: z.string().uuid().describe('UUID of the app'),\n },\n async ({ appId }) => {\n const instructions = `\n You can fetch the schema for the app by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli pull schema --app ${appId} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts. Now 'instant.schema.ts' will contain the schema for the app.\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'get-perms',\n 'Fetch permissions for an app by its ID',\n {\n appId: z.string().uuid().describe('UUID of the app'),\n },\n async ({ appId }) => {\n const instructions = `\n You fetch the permissions for the app by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli pull perms --app ${appId} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts. Now 'instant.perms.ts' will contain the permissions for the app.\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'push-schema',\n `Push local schema changes for an app to the server. Do this after updating your local 'instant.schema.ts' file.\n If you don't have an instant.schema.ts file yet, use the get-schema tool to learn how to get this file.`,\n {\n appId: z.string().uuid().describe('UUID of the app'),\n },\n async ({ appId }) => {\n const instructions = `\n Push schema changes by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli push schema --app ${appId} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts.\n\n By default the instant-cli tool will assume new fields from the previous schema are additions and missing fields are deletions.\n If you want to rename fields as part of your schema changes you can use the --rename flag to specify renames.\n\n \\`\\`\\`\n npx instant-cli push schema --app ${appId} --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes\n \\`\\`\\`\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'push-perms',\n `Push local permissions changes for an app to the server. Do this after updating your local instant.perms.ts file.\n If you don't have an instant.perms.ts file yet, use the get-perms tool to learn how to get this file.`,\n {\n appId: z.string().uuid().describe('UUID of the app'),\n },\n async ({ appId }) => {\n const instructions = `\n Push permission changes by using the instant-cli tool:\n\n \\`\\`\\`\n npx instant-cli push perms --app ${appId} --yes\n \\`\\`\\`\n\n We supply the --yes flag to skip confirmation prompts.\n `;\n\n return {\n content: [\n {\n type: 'text',\n text: instructions,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'query',\n `Execute an InstaQL query against an app. Returns the query results as JSON.\n\n Example query to fetch all goals and their todos:\n {\"goals\": {\"todos\": {}}}\n\n Example query with a where clause:\n {\"goals\": {\"$\": {\"where\": {\"status\": \"active\"}}, \"todos\": {}}}\n\n If you're unsure how to write queries, refer to the documentation:\n https://instantdb.com/docs/instaql`,\n {\n appId: z.string().uuid().describe('UUID of the app'),\n query: z.record(z.string(), z.any()).describe('InstaQL query object'),\n },\n async ({ appId, query }) => {\n return handleQuery(api, appId, query);\n },\n );\n\n server.tool(\n 'transact',\n `Execute a transaction against an app. Useful for creating, updating, or deleting data.\n\n Steps use the internal transaction format:\n - Create/update: [\"update\", \"namespace\", \"entity-id\", {\"attr\": \"value\"}]\n - Link: [\"link\", \"namespace\", \"entity-id\", {\"linkAttr\": \"target-id\"}]\n - Unlink: [\"unlink\", \"namespace\", \"entity-id\", {\"linkAttr\": \"target-id\"}]\n - Delete: [\"delete\", \"namespace\", \"entity-id\"]\n\n Example steps to create a todo:\n [[\"update\", \"todos\", \"a-uuid\", {\"title\": \"Get fit\", \"done\": false}]]\n\n If you're unsure how to make transactions, refer to the documentation:\n https://instantdb.com/docs/instaml`,\n {\n appId: z.string().uuid().describe('UUID of the app'),\n steps: z.array(z.array(z.any())).describe('Array of transaction steps'),\n },\n async ({ appId, steps }) => {\n return handleTransact(api, appId, steps);\n },\n );\n}\n\nasync function startStdio() {\n const {\n values: { token, ['api-url']: apiUrl },\n } = parseArgs({\n options: {\n token: {\n type: 'string',\n },\n ['api-url']: {\n type: 'string',\n },\n },\n });\n\n const accessToken = token || process.env.INSTANT_ACCESS_TOKEN;\n if (!accessToken) {\n console.error(\n 'Provide an access token using --token or set INSTANT_ACCESS_TOKEN environment variable',\n );\n process.exit(1);\n }\n\n const api = new PlatformApi({ auth: { token: accessToken } });\n\n const server = createMCPServer();\n registerTools(server, api);\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Instant Platform MCP Server running on stdio');\n}\n\nfunction ensureEnv(key: string): string {\n const v = process.env[key];\n if (!v) {\n throw new Error(`Missing environment variable ${key}`);\n }\n return v;\n}\n\nasync function startSse() {\n const honeycomb = new HoneycombSDK({\n apiKey: process.env.HONEYCOMB_API_KEY,\n serviceName: 'mcp-server',\n });\n\n if (process.env.HONEYCOMB_API_KEY) {\n honeycomb.start();\n }\n\n const tracer = trace.getTracer('mcp-server');\n\n const db = init({\n adminToken: ensureEnv('INSTANT_ADMIN_TOKEN'),\n appId: ensureEnv('INSTANT_APP_ID'),\n schema,\n disableValidation: true,\n });\n\n const oauthConfig: OAuthConfig = {\n clientId: ensureEnv('INSTANT_OAUTH_CLIENT_ID'),\n clientSecret: ensureEnv('INSTANT_OAUTH_CLIENT_SECRET'),\n serverOrigin: ensureEnv('SERVER_ORIGIN'),\n };\n\n const keyConfig: KeyConfig = JSON.parse(ensureEnv('INSTANT_AES_KEY'));\n\n const app = express();\n const logger = pino({ level: 'info' });\n\n app.use((req, res, next) => {\n const span = tracer.startSpan('http-req', {\n kind: SpanKind.SERVER,\n attributes: {\n 'http.method': req.method,\n 'http.url': req.url,\n 'http.target': req.path,\n 'http.host': req.get('host'),\n 'http.scheme': req.protocol,\n },\n });\n\n const originalEnd = res.end.bind(res);\n res.end = function (this: typeof res, ...args: any[]): typeof res {\n span.setAttribute('http.status_code', res.statusCode);\n span.setStatus({\n code: res.statusCode >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK,\n });\n span.end();\n return originalEnd(...args);\n };\n\n next();\n });\n\n app.use(\n pinoHttp({\n logger,\n autoLogging: {\n ignore(req) {\n return req.url === '/health';\n },\n },\n }),\n );\n app.use(express.json());\n\n const proxyProvider = new ServiceProvider(db, oauthConfig, keyConfig);\n\n const authRouterOptions = {\n scopesSupported: ['apps-read', 'apps-write'],\n provider: proxyProvider,\n issuerUrl: new URL(oauthConfig.serverOrigin),\n baseUrl: new URL(oauthConfig.serverOrigin),\n serviceDocumentationUrl: new URL('https://instantdb.com/docs'),\n };\n\n const oauthMetadata = createOAuthMetadata(authRouterOptions);\n\n app.use(mcpAuthRouter(authRouterOptions));\n\n addOAuthRoutes(app, db, oauthConfig);\n\n app.get('/.well-known/oauth-protected-resource/mcp', (_req, res) => {\n res.json({\n resource: `${oauthConfig.serverOrigin}/mcp`,\n authorization_servers: [oauthMetadata.issuer],\n scopes_supported: oauthMetadata.scopes_supported,\n resource_documentation: 'https://instantdb.com/docs',\n });\n });\n\n app.get('/.well-known/oauth-protected-resource/sse', (_req, res) => {\n res.json({\n resource: `${oauthConfig.serverOrigin}/mcp`,\n authorization_servers: [oauthMetadata.issuer],\n scopes_supported: oauthMetadata.scopes_supported,\n resource_documentation: 'https://instantdb.com/docs',\n });\n });\n\n const requireTokenMiddleware = (path: string) =>\n requireBearerAuth({\n verifier: proxyProvider,\n resourceMetadataUrl: `${oauthConfig.serverOrigin}/.well-known/oauth-protected-resource/${path}`,\n });\n\n // Handle POST requests for client-to-server communication\n app.post(\n '/mcp',\n requireTokenMiddleware('mcp'),\n async (req: Request, res: Response) => {\n const server = createMCPServer();\n try {\n const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n const api = new PlatformApi({\n auth: makeApiAuth(oauthConfig, keyConfig, db, tokens.instantToken),\n });\n\n wrapServerWithTracing(server, tracer, {\n 'client.client_id': tokens.mcpToken.client?.client_id,\n 'client.name': tokens.mcpToken.client?.client_name,\n 'client.id': tokens.mcpToken.client?.id,\n 'client.scope': tokens.mcpToken.client?.scope,\n 'client.uri': tokens.mcpToken.client?.client_uri,\n 'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n });\n registerTools(server, api);\n const transport: StreamableHTTPServerTransport =\n new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n });\n\n req.on('close', () => {\n transport.close();\n server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n } catch (e) {\n console.error('Error handling MCP request:', e);\n if (!res.headersSent) {\n res.status(500).json({\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: 'Internal server error',\n },\n id: null,\n });\n }\n }\n },\n );\n\n // We're a stateless server, so disallow these\n const handleSessionRequest = async (\n _req: express.Request,\n res: express.Response,\n ) => {\n res.writeHead(405).end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: {\n code: -32000,\n message: 'Method not allowed.',\n },\n id: null,\n }),\n );\n };\n\n app.get('/mcp', handleSessionRequest);\n app.delete('/mcp', handleSessionRequest);\n\n // SSE for older clients\n const transports = {\n sse: {} as Record<string, SSEServerTransport>,\n };\n\n app.get(\n '/sse',\n requireTokenMiddleware('sse'),\n async (req: Request, res: Response) => {\n const server = createMCPServer();\n const transport = new SSEServerTransport('/messages', res);\n res.on('close', () => {\n delete transports.sse[transport.sessionId];\n });\n\n try {\n const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n const api = new PlatformApi({\n auth: makeApiAuth(oauthConfig, keyConfig, db, tokens.instantToken),\n });\n\n wrapServerWithTracing(server, tracer, {\n 'client.client_id': tokens.mcpToken.client?.client_id,\n 'client.name': tokens.mcpToken.client?.client_name,\n 'client.id': tokens.mcpToken.client?.id,\n 'client.scope': tokens.mcpToken.client?.scope,\n 'client.uri': tokens.mcpToken.client?.client_uri,\n 'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n });\n\n registerTools(server, api);\n transports.sse[transport.sessionId] = transport;\n } catch (e) {\n console.error('Error handling MCP SSE request:', e);\n if (!res.headersSent) {\n res.status(500).json({\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: 'Internal server error',\n },\n id: null,\n });\n }\n return;\n }\n\n await server.connect(transport);\n },\n );\n\n // Legacy message endpoint for older clients\n app.post('/messages', async (req, res) => {\n const sessionId = req.query.sessionId as string;\n const transport = transports.sse[sessionId];\n if (transport) {\n await transport.handlePostMessage(req, res, req.body);\n } else {\n res.status(400).send('No transport found for sessionId');\n }\n });\n\n app.get('/', (_req, res: Response) => {\n res\n .status(200)\n .set('Content-Type', 'text/html; charset=UTF-8')\n .send(indexHtml(oauthConfig.serverOrigin));\n });\n\n app.get('/health', (_req, res: Response) => {\n res.status(200).send('Tip top!');\n });\n\n const port = parseInt(process.env.PORT || '3123');\n const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';\n\n if (process.env.IN_FLY) {\n app.set('trust proxy', 2);\n }\n\n app.listen(port, host, () => console.log(`listening on port ${port}`));\n}\n\nasync function main() {\n if (process.env.SERVER_TYPE === 'http') {\n return startSse();\n }\n return startStdio();\n}\n\nmain().catch((error) => {\n console.error('Fatal error in main():', error);\n process.exit(1);\n});\n"]}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PlatformApi } from '@instantdb/platform';
|
|
2
|
+
type ToolResult = {
|
|
3
|
+
isError?: boolean;
|
|
4
|
+
content: {
|
|
5
|
+
type: 'text';
|
|
6
|
+
text: string;
|
|
7
|
+
}[];
|
|
8
|
+
};
|
|
9
|
+
export declare function handleQuery(api: PlatformApi, appId: string, query: Record<string, any>): Promise<ToolResult>;
|
|
10
|
+
export declare function handleTransact(api: PlatformApi, appId: string, steps: any[][]): Promise<ToolResult>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIlD,KAAK,UAAU,GAAG;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C,CAAC;AA8CF,wBAAsB,WAAW,CAC/B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC,UAAU,CAAC,CAiBrB;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,GAAG,EAAE,EAAE,GACb,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const API_URL = process.env.INSTANT_API_URL || 'https://api.instantdb.com';
|
|
2
|
+
async function adminQuery(apiURI, token, appId, query) {
|
|
3
|
+
const res = await fetch(`${apiURI}/admin/query`, {
|
|
4
|
+
method: 'POST',
|
|
5
|
+
headers: {
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
Authorization: `Bearer ${token}`,
|
|
8
|
+
'App-Id': appId,
|
|
9
|
+
},
|
|
10
|
+
body: JSON.stringify({ query }),
|
|
11
|
+
});
|
|
12
|
+
const data = await res.json();
|
|
13
|
+
if (!res.ok) {
|
|
14
|
+
throw new Error(JSON.stringify(data));
|
|
15
|
+
}
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
async function adminTransact(apiURI, token, appId, steps) {
|
|
19
|
+
const res = await fetch(`${apiURI}/admin/transact`, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
Authorization: `Bearer ${token}`,
|
|
24
|
+
'App-Id': appId,
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify({ steps }),
|
|
27
|
+
});
|
|
28
|
+
const data = await res.json();
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
throw new Error(JSON.stringify(data));
|
|
31
|
+
}
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
export async function handleQuery(api, appId, query) {
|
|
35
|
+
try {
|
|
36
|
+
const data = await api.withRetry(adminQuery, [
|
|
37
|
+
API_URL,
|
|
38
|
+
api.token(),
|
|
39
|
+
appId,
|
|
40
|
+
query,
|
|
41
|
+
]);
|
|
42
|
+
return {
|
|
43
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
return {
|
|
48
|
+
isError: true,
|
|
49
|
+
content: [{ type: 'text', text: `Error querying app: ${e.message}` }],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export async function handleTransact(api, appId, steps) {
|
|
54
|
+
try {
|
|
55
|
+
const data = await api.withRetry(adminTransact, [
|
|
56
|
+
API_URL,
|
|
57
|
+
api.token(),
|
|
58
|
+
appId,
|
|
59
|
+
steps,
|
|
60
|
+
]);
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
return {
|
|
67
|
+
isError: true,
|
|
68
|
+
content: [{ type: 'text', text: `Error transacting: ${e.message}` }],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { PlatformApi } from '@instantdb/platform';\n\nconst API_URL = process.env.INSTANT_API_URL || 'https://api.instantdb.com';\n\ntype ToolResult = {\n isError?: boolean;\n content: { type: 'text'; text: string }[];\n};\n\nasync function adminQuery(\n apiURI: string,\n token: string,\n appId: string,\n query: Record<string, any>,\n) {\n const res = await fetch(`${apiURI}/admin/query`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n 'App-Id': appId,\n },\n body: JSON.stringify({ query }),\n });\n const data = await res.json();\n if (!res.ok) {\n throw new Error(JSON.stringify(data));\n }\n return data;\n}\n\nasync function adminTransact(\n apiURI: string,\n token: string,\n appId: string,\n steps: any[][],\n) {\n const res = await fetch(`${apiURI}/admin/transact`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n 'App-Id': appId,\n },\n body: JSON.stringify({ steps }),\n });\n const data = await res.json();\n if (!res.ok) {\n throw new Error(JSON.stringify(data));\n }\n return data;\n}\n\nexport async function handleQuery(\n api: PlatformApi,\n appId: string,\n query: Record<string, any>,\n): Promise<ToolResult> {\n try {\n const data = await api.withRetry(adminQuery, [\n API_URL,\n api.token(),\n appId,\n query,\n ]);\n return {\n content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],\n };\n } catch (e: any) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error querying app: ${e.message}` }],\n };\n }\n}\n\nexport async function handleTransact(\n api: PlatformApi,\n appId: string,\n steps: any[][],\n): Promise<ToolResult> {\n try {\n const data = await api.withRetry(adminTransact, [\n API_URL,\n api.token(),\n appId,\n steps,\n ]);\n return {\n content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],\n };\n } catch (e: any) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error transacting: ${e.message}` }],\n };\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instantdb/mcp",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.172",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for managing Instant apps, schemas, and permissions!",
|
|
5
5
|
"homepage": "https://github.com/instantdb/instant/tree/main/client/packages/mcp",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"pino-pretty": "^13.0.0",
|
|
24
24
|
"tsx": "^4.7.0",
|
|
25
25
|
"typescript": "^5.9.3",
|
|
26
|
-
"vitest": "^
|
|
26
|
+
"vitest": "^3.2.4"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@honeycombio/opentelemetry-node": "^0.7.2",
|
|
@@ -36,16 +36,18 @@
|
|
|
36
36
|
"pino": "^9.7.0",
|
|
37
37
|
"pino-http": "^10.5.0",
|
|
38
38
|
"zod": "^3.25.39",
|
|
39
|
-
"@instantdb/
|
|
40
|
-
"@instantdb/
|
|
41
|
-
"@instantdb/platform": "0.22.
|
|
42
|
-
"@instantdb/
|
|
39
|
+
"@instantdb/core": "0.22.172",
|
|
40
|
+
"@instantdb/version": "0.22.172",
|
|
41
|
+
"@instantdb/platform": "0.22.172",
|
|
42
|
+
"@instantdb/admin": "0.22.172"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=18"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"test": "vitest",
|
|
48
|
+
"test": "vitest --project unit",
|
|
49
|
+
"test:e2e": "vitest --project e2e",
|
|
50
|
+
"test:ci": "vitest run",
|
|
49
51
|
"dev": "tsc --watch --preserveWatchOutput -p tsconfig.dev.json",
|
|
50
52
|
"clean": "rm -rf dist",
|
|
51
53
|
"build": "rm -rf dist && tsc",
|