@ampless/backend 1.0.0-alpha.70 → 1.0.0-alpha.72
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/functions/mcp-handler.js +112 -14
- package/package.json +3 -3
|
@@ -4,6 +4,7 @@ import { DynamoDBDocumentClient, GetCommand, UpdateCommand } from "@aws-sdk/lib-
|
|
|
4
4
|
import { createHash } from "crypto";
|
|
5
5
|
|
|
6
6
|
// ../mcp-server/dist/index.js
|
|
7
|
+
import { filterSortPostSummaries } from "ampless";
|
|
7
8
|
import {
|
|
8
9
|
decodeAwsJson
|
|
9
10
|
} from "ampless";
|
|
@@ -53,11 +54,28 @@ var POST_FIELDS = (
|
|
|
53
54
|
body
|
|
54
55
|
status
|
|
55
56
|
publishedAt
|
|
57
|
+
updatedAt
|
|
56
58
|
tags
|
|
57
59
|
metadata
|
|
58
60
|
}
|
|
59
61
|
`
|
|
60
62
|
);
|
|
63
|
+
var POST_SUMMARY_FIELDS = (
|
|
64
|
+
/* GraphQL */
|
|
65
|
+
`
|
|
66
|
+
fragment PostSummaryFields on Post {
|
|
67
|
+
postId
|
|
68
|
+
slug
|
|
69
|
+
title
|
|
70
|
+
excerpt
|
|
71
|
+
format
|
|
72
|
+
status
|
|
73
|
+
publishedAt
|
|
74
|
+
updatedAt
|
|
75
|
+
tags
|
|
76
|
+
}
|
|
77
|
+
`
|
|
78
|
+
);
|
|
61
79
|
function toCorePost(p) {
|
|
62
80
|
const metadata = decodeAwsJson(p.metadata);
|
|
63
81
|
return {
|
|
@@ -69,18 +87,32 @@ function toCorePost(p) {
|
|
|
69
87
|
body: decodeAwsJson(p.body),
|
|
70
88
|
status: p.status ?? "draft",
|
|
71
89
|
publishedAt: p.publishedAt ?? void 0,
|
|
90
|
+
updatedAt: p.updatedAt ?? void 0,
|
|
72
91
|
tags: (p.tags ?? []).filter((t) => typeof t === "string"),
|
|
73
92
|
metadata: metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : void 0
|
|
74
93
|
};
|
|
75
94
|
}
|
|
95
|
+
function toPostSummary(p) {
|
|
96
|
+
return {
|
|
97
|
+
postId: p.postId,
|
|
98
|
+
slug: p.slug,
|
|
99
|
+
title: p.title,
|
|
100
|
+
excerpt: p.excerpt ?? void 0,
|
|
101
|
+
format: p.format ?? "markdown",
|
|
102
|
+
status: p.status ?? "draft",
|
|
103
|
+
publishedAt: p.publishedAt ?? void 0,
|
|
104
|
+
updatedAt: p.updatedAt ?? void 0,
|
|
105
|
+
tags: (p.tags ?? []).filter((t) => typeof t === "string")
|
|
106
|
+
};
|
|
107
|
+
}
|
|
76
108
|
var QUERY = (
|
|
77
109
|
/* GraphQL */
|
|
78
110
|
`
|
|
79
|
-
${
|
|
111
|
+
${POST_SUMMARY_FIELDS}
|
|
80
112
|
query ListPosts($filter: ModelPostFilterInput, $limit: Int, $nextToken: String) {
|
|
81
113
|
listPosts(filter: $filter, limit: $limit, nextToken: $nextToken) {
|
|
82
114
|
items {
|
|
83
|
-
...
|
|
115
|
+
...PostSummaryFields
|
|
84
116
|
}
|
|
85
117
|
nextToken
|
|
86
118
|
}
|
|
@@ -90,29 +122,95 @@ var QUERY = (
|
|
|
90
122
|
var listPostsSchema = {
|
|
91
123
|
type: "object",
|
|
92
124
|
properties: {
|
|
125
|
+
query: {
|
|
126
|
+
type: "string",
|
|
127
|
+
description: "Case-insensitive substring match over title / slug / tags"
|
|
128
|
+
},
|
|
129
|
+
tag: {
|
|
130
|
+
type: "string",
|
|
131
|
+
description: "Exact tag filter"
|
|
132
|
+
},
|
|
93
133
|
status: {
|
|
94
134
|
type: "string",
|
|
95
135
|
enum: ["draft", "published", "all"],
|
|
96
136
|
description: 'Filter by status (default "all")'
|
|
97
137
|
},
|
|
98
|
-
|
|
99
|
-
|
|
138
|
+
sort: {
|
|
139
|
+
type: "string",
|
|
140
|
+
enum: [
|
|
141
|
+
"updated-desc",
|
|
142
|
+
"updated-asc",
|
|
143
|
+
"published-desc",
|
|
144
|
+
"published-asc",
|
|
145
|
+
"title-asc",
|
|
146
|
+
"title-desc"
|
|
147
|
+
],
|
|
148
|
+
description: 'Sort order (default "updated-desc" \u2014 most recently edited first)'
|
|
149
|
+
},
|
|
150
|
+
limit: {
|
|
151
|
+
type: "integer",
|
|
152
|
+
minimum: 1,
|
|
153
|
+
maximum: 100,
|
|
154
|
+
description: "Max results per page (default 20)"
|
|
155
|
+
},
|
|
156
|
+
offset: {
|
|
157
|
+
type: "integer",
|
|
158
|
+
minimum: 0,
|
|
159
|
+
description: "Zero-based offset into the filtered result set (default 0)"
|
|
160
|
+
}
|
|
100
161
|
}
|
|
101
162
|
};
|
|
163
|
+
var VALID_STATUS = /* @__PURE__ */ new Set(["draft", "published", "all"]);
|
|
164
|
+
var VALID_SORT = /* @__PURE__ */ new Set([
|
|
165
|
+
"updated-desc",
|
|
166
|
+
"updated-asc",
|
|
167
|
+
"published-desc",
|
|
168
|
+
"published-asc",
|
|
169
|
+
"title-asc",
|
|
170
|
+
"title-desc"
|
|
171
|
+
]);
|
|
172
|
+
function asString(v) {
|
|
173
|
+
return typeof v === "string" ? v : void 0;
|
|
174
|
+
}
|
|
175
|
+
function asInt(v, fallback) {
|
|
176
|
+
const n = Number(v);
|
|
177
|
+
return Number.isFinite(n) ? Math.trunc(n) : fallback;
|
|
178
|
+
}
|
|
102
179
|
async function listPosts(client, args = {}) {
|
|
103
|
-
const
|
|
180
|
+
const limit = Math.min(100, Math.max(1, asInt(args.limit, 20)));
|
|
181
|
+
const offset = Math.max(0, asInt(args.offset, 0));
|
|
182
|
+
const rawStatus = asString(args.status);
|
|
183
|
+
const status = rawStatus && VALID_STATUS.has(rawStatus) ? rawStatus : "all";
|
|
184
|
+
const rawSort = asString(args.sort);
|
|
185
|
+
const sort = rawSort && VALID_SORT.has(rawSort) ? rawSort : void 0;
|
|
186
|
+
const query = asString(args.query);
|
|
187
|
+
const tag = asString(args.tag);
|
|
104
188
|
const filter = {};
|
|
105
189
|
if (status !== "all") filter.status = { eq: status };
|
|
106
190
|
const hasFilter = Object.keys(filter).length > 0;
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
191
|
+
const allItems = [];
|
|
192
|
+
let cursor = null;
|
|
193
|
+
do {
|
|
194
|
+
const data = await client.query(QUERY, {
|
|
195
|
+
filter: hasFilter ? filter : void 0,
|
|
196
|
+
limit: 200,
|
|
197
|
+
nextToken: cursor
|
|
198
|
+
});
|
|
199
|
+
for (const item of data.listPosts.items) {
|
|
200
|
+
allItems.push(toPostSummary(item));
|
|
201
|
+
}
|
|
202
|
+
cursor = data.listPosts.nextToken;
|
|
203
|
+
} while (cursor);
|
|
204
|
+
const filtered = filterSortPostSummaries(allItems, {
|
|
205
|
+
query,
|
|
206
|
+
tag,
|
|
207
|
+
sort,
|
|
208
|
+
// status already applied server-side; pass 'all' to avoid double-filter
|
|
209
|
+
status: "all"
|
|
111
210
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
};
|
|
211
|
+
const total = filtered.length;
|
|
212
|
+
const posts = filtered.slice(offset, offset + limit);
|
|
213
|
+
return { posts, total, offset, limit };
|
|
116
214
|
}
|
|
117
215
|
var GET_BY_ID = (
|
|
118
216
|
/* GraphQL */
|
|
@@ -1547,7 +1645,7 @@ async function commitStaticPost(graphql, storage, args) {
|
|
|
1547
1645
|
var tools = [
|
|
1548
1646
|
{
|
|
1549
1647
|
name: "list_posts",
|
|
1550
|
-
description: "
|
|
1648
|
+
description: "Returns lightweight post summaries (no body \u2014 use get_post for content) with search / sort / filters. `total` reflects the filtered count. Supports query (substring over title/slug/tags), tag (exact), status, sort, limit (1\u2013100, default 20), offset (default 0).",
|
|
1551
1649
|
inputSchema: listPostsSchema,
|
|
1552
1650
|
handler: (args, ctx) => listPosts(ctx.graphql, args)
|
|
1553
1651
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ampless/backend",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.72",
|
|
4
4
|
"description": "Amplify Gen 2 backend factories for ampless: auth, data, storage, event processors, API key renewer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"@smithy/protocol-http": "^5.4.4",
|
|
70
70
|
"@smithy/signature-v4": "^5.4.4",
|
|
71
71
|
"fflate": "^0.8.3",
|
|
72
|
-
"@ampless/mcp-server": "1.0.0-alpha.
|
|
73
|
-
"ampless": "1.0.0-alpha.
|
|
72
|
+
"@ampless/mcp-server": "1.0.0-alpha.56",
|
|
73
|
+
"ampless": "1.0.0-alpha.50"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@aws-amplify/backend": "^1",
|