@topgunbuild/mcp-server 0.9.0 → 0.10.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/cli.js +33 -39
- package/dist/cli.js.map +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +33 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -17,7 +17,7 @@ var QueryArgsSchema = z.object({
|
|
|
17
17
|
order: z.enum(["asc", "desc"]).describe("Sort order: ascending or descending")
|
|
18
18
|
}).optional().describe("Sort configuration"),
|
|
19
19
|
limit: z.number().optional().default(10).describe("Maximum number of results to return"),
|
|
20
|
-
|
|
20
|
+
cursor: z.string().optional().describe("Opaque cursor for pagination (from previous response nextCursor)")
|
|
21
21
|
});
|
|
22
22
|
var MutateArgsSchema = z.object({
|
|
23
23
|
map: z.string().describe("Name of the map to modify (e.g., 'tasks', 'users')"),
|
|
@@ -71,7 +71,7 @@ var toolSchemas = {
|
|
|
71
71
|
description: "Sort configuration"
|
|
72
72
|
},
|
|
73
73
|
limit: { type: "number", description: "Maximum number of results to return", default: 10 },
|
|
74
|
-
|
|
74
|
+
cursor: { type: "string", description: "Opaque cursor for pagination (from previous response nextCursor)" }
|
|
75
75
|
},
|
|
76
76
|
required: ["map"]
|
|
77
77
|
},
|
|
@@ -161,7 +161,7 @@ var toolSchemas = {
|
|
|
161
161
|
// src/tools/query.ts
|
|
162
162
|
var queryTool = {
|
|
163
163
|
name: "topgun_query",
|
|
164
|
-
description: "Query data from a TopGun map with filters and sorting. Use this to read data from the database. Supports filtering by field values
|
|
164
|
+
description: "Query data from a TopGun map with filters and sorting. Use this to read data from the database. Supports filtering by field values, sorting, and cursor-based pagination.",
|
|
165
165
|
inputSchema: toolSchemas.query
|
|
166
166
|
};
|
|
167
167
|
async function handleQuery(rawArgs, ctx) {
|
|
@@ -173,7 +173,7 @@ async function handleQuery(rawArgs, ctx) {
|
|
|
173
173
|
isError: true
|
|
174
174
|
};
|
|
175
175
|
}
|
|
176
|
-
const { map, filter, sort, limit,
|
|
176
|
+
const { map, filter, sort, limit, cursor } = parseResult.data;
|
|
177
177
|
if (ctx.config.allowedMaps && !ctx.config.allowedMaps.includes(map)) {
|
|
178
178
|
return {
|
|
179
179
|
content: [
|
|
@@ -186,39 +186,26 @@ async function handleQuery(rawArgs, ctx) {
|
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
188
|
const effectiveLimit = Math.min(limit ?? ctx.config.defaultLimit, ctx.config.maxLimit);
|
|
189
|
-
const effectiveOffset = offset ?? 0;
|
|
190
189
|
try {
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
let matches = true;
|
|
196
|
-
if (filter) {
|
|
197
|
-
for (const [filterKey, filterValue] of Object.entries(filter)) {
|
|
198
|
-
if (value[filterKey] !== filterValue) {
|
|
199
|
-
matches = false;
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (matches) {
|
|
205
|
-
allEntries.push({ key: String(key), value });
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
190
|
+
const queryFilter = {
|
|
191
|
+
where: filter,
|
|
192
|
+
limit: effectiveLimit
|
|
193
|
+
};
|
|
209
194
|
if (sort?.field) {
|
|
210
|
-
|
|
211
|
-
const aVal = a.value[sort.field];
|
|
212
|
-
const bVal = b.value[sort.field];
|
|
213
|
-
if (aVal === bVal) return 0;
|
|
214
|
-
if (aVal === void 0 || aVal === null) return 1;
|
|
215
|
-
if (bVal === void 0 || bVal === null) return -1;
|
|
216
|
-
const comparison = aVal < bVal ? -1 : 1;
|
|
217
|
-
return sort.order === "desc" ? -comparison : comparison;
|
|
218
|
-
});
|
|
195
|
+
queryFilter.sort = { [sort.field]: sort.order };
|
|
219
196
|
}
|
|
220
|
-
|
|
221
|
-
|
|
197
|
+
if (cursor) {
|
|
198
|
+
queryFilter.cursor = cursor;
|
|
199
|
+
}
|
|
200
|
+
const handle = ctx.client.query(map, queryFilter);
|
|
201
|
+
const results = await new Promise((resolve) => {
|
|
202
|
+
const unsubscribe = handle.subscribe((data) => {
|
|
203
|
+
unsubscribe();
|
|
204
|
+
resolve(data);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
const paginationInfo = handle.getPaginationInfo();
|
|
208
|
+
if (results.length === 0) {
|
|
222
209
|
return {
|
|
223
210
|
content: [
|
|
224
211
|
{
|
|
@@ -228,17 +215,24 @@ async function handleQuery(rawArgs, ctx) {
|
|
|
228
215
|
]
|
|
229
216
|
};
|
|
230
217
|
}
|
|
231
|
-
const formatted =
|
|
232
|
-
|
|
218
|
+
const formatted = results.map((entry, idx) => {
|
|
219
|
+
const { _key, ...value } = entry;
|
|
220
|
+
return `${idx + 1}. [${_key}]: ${JSON.stringify(value, null, 2)}`;
|
|
221
|
+
}).join("\n\n");
|
|
222
|
+
let paginationText = "";
|
|
223
|
+
if (paginationInfo.hasMore && paginationInfo.nextCursor) {
|
|
224
|
+
paginationText = `
|
|
233
225
|
|
|
234
|
-
|
|
226
|
+
---
|
|
227
|
+
More results available. Use cursor: "${paginationInfo.nextCursor}" to fetch next page.`;
|
|
228
|
+
}
|
|
235
229
|
return {
|
|
236
230
|
content: [
|
|
237
231
|
{
|
|
238
232
|
type: "text",
|
|
239
|
-
text: `Found ${
|
|
233
|
+
text: `Found ${results.length} result(s) in map '${map}':
|
|
240
234
|
|
|
241
|
-
${formatted}${
|
|
235
|
+
${formatted}${paginationText}`
|
|
242
236
|
}
|
|
243
237
|
]
|
|
244
238
|
};
|