@ampless/mcp-server 0.2.0-alpha.9 → 1.0.0-alpha.10

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.
@@ -8,7 +8,6 @@ var POST_FIELDS = (
8
8
  /* GraphQL */
9
9
  `
10
10
  fragment PostFields on Post {
11
- siteId
12
11
  postId
13
12
  slug
14
13
  title
@@ -25,7 +24,6 @@ var POST_FIELDS = (
25
24
  function toCorePost(p) {
26
25
  const metadata = decodeAwsJson(p.metadata);
27
26
  return {
28
- siteId: p.siteId,
29
27
  postId: p.postId,
30
28
  slug: p.slug,
31
29
  title: p.title,
@@ -57,7 +55,6 @@ var QUERY = (
57
55
  var listPostsSchema = {
58
56
  type: "object",
59
57
  properties: {
60
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
61
58
  status: {
62
59
  type: "string",
63
60
  enum: ["draft", "published", "all"],
@@ -67,12 +64,16 @@ var listPostsSchema = {
67
64
  nextToken: { type: "string", description: "Pagination cursor from a previous call" }
68
65
  }
69
66
  };
70
- async function listPosts(client, defaultSiteId, args = {}) {
71
- const siteId = args.siteId ?? defaultSiteId;
67
+ async function listPosts(client, args = {}) {
72
68
  const status = args.status ?? "all";
73
- const filter = { siteId: { eq: siteId } };
69
+ const filter = {};
74
70
  if (status !== "all") filter.status = { eq: status };
75
- const data = await client.query(QUERY, { filter, limit: args.limit ?? 20, nextToken: args.nextToken });
71
+ const hasFilter = Object.keys(filter).length > 0;
72
+ const data = await client.query(QUERY, {
73
+ filter: hasFilter ? filter : void 0,
74
+ limit: args.limit ?? 20,
75
+ nextToken: args.nextToken
76
+ });
76
77
  return {
77
78
  posts: data.listPosts.items.map(toCorePost),
78
79
  nextToken: data.listPosts.nextToken
@@ -84,8 +85,8 @@ var GET_BY_ID = (
84
85
  /* GraphQL */
85
86
  `
86
87
  ${POST_FIELDS}
87
- query GetPost($siteId: String!, $postId: ID!) {
88
- getPost(siteId: $siteId, postId: $postId) {
88
+ query GetPost($postId: ID!) {
89
+ getPost(postId: $postId) {
89
90
  ...PostFields
90
91
  }
91
92
  }
@@ -107,22 +108,20 @@ var LIST_BY_SLUG = (
107
108
  var getPostSchema = {
108
109
  type: "object",
109
110
  properties: {
110
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
111
111
  slug: { type: "string", description: "Post slug" },
112
112
  postId: { type: "string", description: "Post id (used when slug is omitted)" }
113
113
  }
114
114
  };
115
- async function getPost(client, defaultSiteId, args) {
115
+ async function getPost(client, args) {
116
116
  if (!args.slug && !args.postId) {
117
117
  throw new Error("get_post requires either `slug` or `postId`");
118
118
  }
119
- const siteId = args.siteId ?? defaultSiteId;
120
119
  if (args.postId) {
121
- const data2 = await client.query(GET_BY_ID, { siteId, postId: args.postId });
120
+ const data2 = await client.query(GET_BY_ID, { postId: args.postId });
122
121
  return data2.getPost ? toCorePost(data2.getPost) : null;
123
122
  }
124
123
  const data = await client.query(LIST_BY_SLUG, {
125
- filter: { siteId: { eq: siteId }, slug: { eq: args.slug } }
124
+ filter: { slug: { eq: args.slug } }
126
125
  });
127
126
  const item = data.listPosts.items[0];
128
127
  return item ? toCorePost(item) : null;
@@ -130,8 +129,6 @@ async function getPost(client, defaultSiteId, args) {
130
129
 
131
130
  // src/tools/create-post.ts
132
131
  import {
133
- composeSiteIdStatus,
134
- composeSiteIdSlug,
135
132
  encodeAwsJson
136
133
  } from "ampless";
137
134
 
@@ -139,19 +136,19 @@ import {
139
136
  function entries(post) {
140
137
  if (post.status !== "published" || !post.publishedAt || !post.tags?.length) return [];
141
138
  return post.tags.map((tag) => ({
142
- siteIdTag: `${post.siteId}#${tag}`,
139
+ tag,
143
140
  publishedAtPostId: `${post.publishedAt}#${post.postId}`
144
141
  }));
145
142
  }
146
143
  function entryKey(e) {
147
- return `${e.siteIdTag}|${e.publishedAtPostId}`;
144
+ return `${e.tag}|${e.publishedAtPostId}`;
148
145
  }
149
146
  var CREATE_POST_TAG = (
150
147
  /* GraphQL */
151
148
  `
152
149
  mutation CreatePostTag($input: CreatePostTagInput!) {
153
150
  createPostTag(input: $input) {
154
- siteIdTag
151
+ tag
155
152
  publishedAtPostId
156
153
  }
157
154
  }
@@ -162,7 +159,7 @@ var UPDATE_POST_TAG = (
162
159
  `
163
160
  mutation UpdatePostTag($input: UpdatePostTagInput!) {
164
161
  updatePostTag(input: $input) {
165
- siteIdTag
162
+ tag
166
163
  publishedAtPostId
167
164
  }
168
165
  }
@@ -173,7 +170,7 @@ var DELETE_POST_TAG = (
173
170
  `
174
171
  mutation DeletePostTag($input: DeletePostTagInput!) {
175
172
  deletePostTag(input: $input) {
176
- siteIdTag
173
+ tag
177
174
  publishedAtPostId
178
175
  }
179
176
  }
@@ -187,7 +184,7 @@ async function syncPostTags(client, post, oldPost) {
187
184
  await Promise.all(
188
185
  oldEntries.filter((e) => !newKeys.has(entryKey(e))).map(
189
186
  (e) => client.query(DELETE_POST_TAG, {
190
- input: { siteIdTag: e.siteIdTag, publishedAtPostId: e.publishedAtPostId }
187
+ input: { tag: e.tag, publishedAtPostId: e.publishedAtPostId }
191
188
  })
192
189
  )
193
190
  );
@@ -195,10 +192,8 @@ async function syncPostTags(client, post, oldPost) {
195
192
  newEntries.filter((e) => !oldKeys.has(entryKey(e))).map(
196
193
  (e) => client.query(CREATE_POST_TAG, {
197
194
  input: {
198
- siteIdTag: e.siteIdTag,
195
+ tag: e.tag,
199
196
  publishedAtPostId: e.publishedAtPostId,
200
- siteId: post.siteId,
201
- tag: e.siteIdTag.slice(post.siteId.length + 1),
202
197
  postId: post.postId,
203
198
  publishedAt: post.publishedAt,
204
199
  slug: post.slug,
@@ -213,7 +208,7 @@ async function syncPostTags(client, post, oldPost) {
213
208
  newEntries.filter((e) => oldKeys.has(entryKey(e))).map(
214
209
  (e) => client.query(UPDATE_POST_TAG, {
215
210
  input: {
216
- siteIdTag: e.siteIdTag,
211
+ tag: e.tag,
217
212
  publishedAtPostId: e.publishedAtPostId,
218
213
  slug: post.slug,
219
214
  title: post.title,
@@ -241,7 +236,6 @@ var createPostSchema = {
241
236
  type: "object",
242
237
  required: ["slug", "title", "format", "body"],
243
238
  properties: {
244
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
245
239
  postId: { type: "string", description: "Optional explicit id; auto-generated if omitted" },
246
240
  slug: { type: "string" },
247
241
  title: { type: "string" },
@@ -259,7 +253,7 @@ var createPostSchema = {
259
253
  tags: { type: "array", items: { type: "string" } },
260
254
  metadata: {
261
255
  type: "object",
262
- description: "Free-form per-post metadata. Reserved well-known keys: `no_layout` (boolean) \u2014 when true, the public page is served as bare HTML with no theme chrome (the route redirects to /raw/<slug>); meaningful only with format=html. Other keys pass through unchanged for themes/plugins.",
256
+ description: "Free-form per-post metadata. Reserved well-known keys: `no_layout` (boolean) \u2014 when true, the public page is served as bare HTML with no theme chrome (the route redirects to /_/<slug>); meaningful only with format=html. Other keys pass through unchanged for themes/plugins.",
263
257
  properties: {
264
258
  no_layout: {
265
259
  type: "boolean",
@@ -270,14 +264,12 @@ var createPostSchema = {
270
264
  }
271
265
  }
272
266
  };
273
- async function createPost(client, defaultSiteId, args) {
274
- const siteId = args.siteId ?? defaultSiteId;
267
+ async function createPost(client, args) {
275
268
  const postId = args.postId ?? `post-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
276
269
  const status = args.status ?? "draft";
277
270
  const publishedAt = args.publishedAt ?? (status === "published" ? (/* @__PURE__ */ new Date()).toISOString() : void 0);
278
271
  const data = await client.query(MUTATION, {
279
272
  input: {
280
- siteId,
281
273
  postId,
282
274
  slug: args.slug,
283
275
  title: args.title,
@@ -287,10 +279,7 @@ async function createPost(client, defaultSiteId, args) {
287
279
  status,
288
280
  publishedAt,
289
281
  tags: args.tags,
290
- metadata: args.metadata !== void 0 ? encodeAwsJson(args.metadata) : void 0,
291
- // Denormalized GSI keys.
292
- siteIdStatus: composeSiteIdStatus(siteId, status),
293
- siteIdSlug: composeSiteIdSlug(siteId, args.slug)
282
+ metadata: args.metadata !== void 0 ? encodeAwsJson(args.metadata) : void 0
294
283
  }
295
284
  });
296
285
  const created = toCorePost(data.createPost);
@@ -300,8 +289,6 @@ async function createPost(client, defaultSiteId, args) {
300
289
 
301
290
  // src/tools/update-post.ts
302
291
  import {
303
- composeSiteIdStatus as composeSiteIdStatus2,
304
- composeSiteIdSlug as composeSiteIdSlug2,
305
292
  encodeAwsJson as encodeAwsJson2
306
293
  } from "ampless";
307
294
  var MUTATION2 = (
@@ -320,7 +307,6 @@ var updatePostSchema = {
320
307
  required: ["postId"],
321
308
  properties: {
322
309
  postId: { type: "string" },
323
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
324
310
  slug: { type: "string" },
325
311
  title: { type: "string" },
326
312
  excerpt: { type: "string" },
@@ -335,7 +321,7 @@ var updatePostSchema = {
335
321
  tags: { type: "array", items: { type: "string" } },
336
322
  metadata: {
337
323
  type: "object",
338
- description: "Free-form per-post metadata. Reserved well-known keys: `no_layout` (boolean) \u2014 when true, the public page is served as bare HTML with no theme chrome (the route redirects to /raw/<slug>); meaningful only with format=html. Passing metadata replaces the existing metadata object \u2014 read the current post first if you only want to add a key.",
324
+ description: "Free-form per-post metadata. Reserved well-known keys: `no_layout` (boolean) \u2014 when true, the public page is served as bare HTML with no theme chrome (the route redirects to /_/<slug>); meaningful only with format=html. Passing metadata replaces the existing metadata object \u2014 read the current post first if you only want to add a key.",
339
325
  properties: {
340
326
  no_layout: {
341
327
  type: "boolean",
@@ -346,10 +332,9 @@ var updatePostSchema = {
346
332
  }
347
333
  }
348
334
  };
349
- async function updatePost(client, defaultSiteId, args) {
350
- const siteId = args.siteId ?? defaultSiteId;
351
- const oldPost = await getPost(client, defaultSiteId, { postId: args.postId, siteId });
352
- const input = { siteId, postId: args.postId };
335
+ async function updatePost(client, args) {
336
+ const oldPost = await getPost(client, { postId: args.postId });
337
+ const input = { postId: args.postId };
353
338
  if (args.slug !== void 0) input.slug = args.slug;
354
339
  if (args.title !== void 0) input.title = args.title;
355
340
  if (args.excerpt !== void 0) input.excerpt = args.excerpt;
@@ -359,12 +344,6 @@ async function updatePost(client, defaultSiteId, args) {
359
344
  if (args.publishedAt !== void 0) input.publishedAt = args.publishedAt;
360
345
  if (args.tags !== void 0) input.tags = args.tags;
361
346
  if (args.metadata !== void 0) input.metadata = encodeAwsJson2(args.metadata);
362
- if (args.status !== void 0) {
363
- input.siteIdStatus = composeSiteIdStatus2(siteId, args.status);
364
- }
365
- if (args.slug !== void 0) {
366
- input.siteIdSlug = composeSiteIdSlug2(siteId, args.slug);
367
- }
368
347
  const data = await client.query(MUTATION2, { input });
369
348
  const updated = toCorePost(data.updatePost);
370
349
  await syncPostTags(client, updated, oldPost);
@@ -377,7 +356,6 @@ var MUTATION3 = (
377
356
  `
378
357
  mutation DeletePost($input: DeletePostInput!) {
379
358
  deletePost(input: $input) {
380
- siteId
381
359
  postId
382
360
  }
383
361
  }
@@ -387,17 +365,15 @@ var deletePostSchema = {
387
365
  type: "object",
388
366
  required: ["postId"],
389
367
  properties: {
390
- postId: { type: "string" },
391
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' }
368
+ postId: { type: "string" }
392
369
  }
393
370
  };
394
- async function deletePost(client, defaultSiteId, args) {
395
- const siteId = args.siteId ?? defaultSiteId;
396
- const oldPost = await getPost(client, defaultSiteId, { postId: args.postId, siteId });
371
+ async function deletePost(client, args) {
372
+ const oldPost = await getPost(client, { postId: args.postId });
397
373
  if (oldPost) {
398
374
  await syncPostTags(client, { ...oldPost, status: "draft" }, oldPost);
399
375
  }
400
- const data = await client.query(MUTATION3, { input: { siteId, postId: args.postId } });
376
+ const data = await client.query(MUTATION3, { input: { postId: args.postId } });
401
377
  return { deleted: data.deletePost };
402
378
  }
403
379
 
@@ -418,7 +394,6 @@ var MUTATION4 = (
418
394
  `
419
395
  mutation CreateMedia($input: CreateMediaInput!) {
420
396
  createMedia(input: $input) {
421
- siteId
422
397
  mediaId
423
398
  src
424
399
  mimeType
@@ -432,7 +407,6 @@ var uploadMediaSchema = {
432
407
  type: "object",
433
408
  required: ["filename", "mimeType", "base64Data"],
434
409
  properties: {
435
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
436
410
  filename: { type: "string", description: "Original filename; sanitized server-side" },
437
411
  mimeType: {
438
412
  type: "string",
@@ -444,15 +418,13 @@ var uploadMediaSchema = {
444
418
  }
445
419
  }
446
420
  };
447
- async function uploadMedia(graphql, storage, defaultSiteId, args) {
448
- const siteId = args.siteId ?? defaultSiteId;
421
+ async function uploadMedia(graphql, storage, args) {
449
422
  const body = Buffer.from(args.base64Data, "base64");
450
423
  const key = buildMediaKey(args.filename);
451
424
  const url = await storage.putObject(key, body, args.mimeType);
452
425
  const mediaId = `media-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
453
426
  const data = await graphql.query(MUTATION4, {
454
427
  input: {
455
- siteId,
456
428
  mediaId,
457
429
  src: key,
458
430
  mimeType: args.mimeType,
@@ -473,11 +445,10 @@ function getSchema() {
473
445
  contentTypes: [
474
446
  {
475
447
  name: "post",
476
- identifier: ["siteId", "postId"],
448
+ identifier: ["postId"],
477
449
  fields: {
478
- siteId: { type: "string", required: true },
479
450
  postId: { type: "string", required: true, description: "auto-generated if omitted on create" },
480
- slug: { type: "string", required: true, description: "URL slug, unique per site" },
451
+ slug: { type: "string", required: true, description: "URL slug, unique" },
481
452
  title: { type: "string", required: true },
482
453
  excerpt: { type: "string" },
483
454
  format: { type: "enum", values: ["tiptap", "markdown", "html"], required: true },
@@ -496,9 +467,8 @@ function getSchema() {
496
467
  },
497
468
  {
498
469
  name: "page",
499
- identifier: ["siteId", "pageId"],
470
+ identifier: ["pageId"],
500
471
  fields: {
501
- siteId: { type: "string", required: true },
502
472
  pageId: { type: "string", required: true },
503
473
  slug: { type: "string", required: true },
504
474
  title: { type: "string", required: true },
@@ -510,9 +480,8 @@ function getSchema() {
510
480
  },
511
481
  {
512
482
  name: "media",
513
- identifier: ["siteId", "mediaId"],
483
+ identifier: ["mediaId"],
514
484
  fields: {
515
- siteId: { type: "string", required: true },
516
485
  mediaId: { type: "string", required: true },
517
486
  src: { type: "string", required: true, description: "S3 key" },
518
487
  mimeType: { type: "string", required: true },
@@ -525,8 +494,8 @@ function getSchema() {
525
494
  notes: {
526
495
  editorTrust: 'editor stores arbitrary HTML/JS verbatim \u2014 same trust shape as WordPress unfiltered_html capability. See docs/architecture/04-access-layer-mcp.md \xA7"editor \u306E\u4FE1\u983C\u30E2\u30C7\u30EB".',
527
496
  tiptapBody: 'When format=tiptap, body is the tiptap document JSON: { type: "doc", content: [...] }. The renderer expects this shape.',
528
- noLayout: "metadata.no_layout=true serves the post as bare HTML with no theme chrome \u2014 the public route at /<slug> 302-redirects to /raw/<slug>, and that route renders the body verbatim with no wrapping <html>/<head>/layout. Use this for landing pages, embeds, or any post whose body is a full HTML document. Only meaningful with format=html (the other formats need the theme renderer).",
529
- staticFormat: "A fourth format value `static` exists on the underlying data model for posts whose body is a JSON manifest pointing to a pre-uploaded HTML/CSS/JS bundle in S3 at public/static/<siteId>/<slug>/. Static posts are created/edited through the dedicated tools `upload_static_bundle` (zip in one shot), `upload_static_file` / `delete_static_file` (incremental per-file ops), and `commit_static_post` (rebuild the manifest from the current S3 prefix). `create_post` / `update_post` intentionally do NOT accept format=static \u2014 the bundle tools are the only supported entry point so the Post manifest stays in sync with the S3 prefix."
497
+ noLayout: "metadata.no_layout=true serves the post as bare HTML with no theme chrome \u2014 the public route at /<slug> 308-redirects to /_/<slug>, and that route renders the body verbatim with no wrapping <html>/<head>/layout. Use this for landing pages, embeds, or any post whose body is a full HTML document. Only meaningful with format=html (the other formats need the theme renderer).",
498
+ staticFormat: "A fourth format value `static` exists on the underlying data model for posts whose body is a JSON manifest pointing to a pre-uploaded HTML/CSS/JS bundle in S3 at public/static/<slug>/. Public URL pattern: /_/<slug>/ for the entrypoint and /_/<slug>/<file> for every bundle file (308 redirect from /<slug> via the post dispatcher). Static posts are created/edited through the dedicated tools `upload_static_bundle` (zip in one shot), `upload_static_file` / `delete_static_file` (incremental per-file ops), and `commit_static_post` (rebuild the manifest from the current S3 prefix). `create_post` / `update_post` intentionally do NOT accept format=static \u2014 the bundle tools are the only supported entry point so the Post manifest stays in sync with the S3 prefix."
530
499
  }
531
500
  };
532
501
  }
@@ -576,8 +545,6 @@ function decodeUtf8(data) {
576
545
 
577
546
  // src/tools/upsert-static-post.ts
578
547
  import {
579
- composeSiteIdStatus as composeSiteIdStatus3,
580
- composeSiteIdSlug as composeSiteIdSlug3,
581
548
  encodeAwsJson as encodeAwsJson3
582
549
  } from "ampless";
583
550
  var CREATE_MUTATION = (
@@ -602,21 +569,17 @@ var UPDATE_MUTATION = (
602
569
  }
603
570
  `
604
571
  );
605
- async function upsertStaticPost(graphql, siteId, slug, body, fields) {
606
- const existing = await getPost(graphql, siteId, { siteId, slug });
572
+ async function upsertStaticPost(graphql, slug, body, fields) {
573
+ const existing = await getPost(graphql, { slug });
607
574
  if (existing) {
608
575
  const input2 = {
609
- siteId,
610
576
  postId: existing.postId,
611
577
  format: "static",
612
578
  body: encodeAwsJson3(body)
613
579
  };
614
580
  if (fields.title !== void 0) input2.title = fields.title;
615
581
  if (fields.excerpt !== void 0) input2.excerpt = fields.excerpt;
616
- if (fields.status !== void 0) {
617
- input2.status = fields.status;
618
- input2.siteIdStatus = composeSiteIdStatus3(siteId, fields.status);
619
- }
582
+ if (fields.status !== void 0) input2.status = fields.status;
620
583
  if (fields.publishedAt !== void 0) input2.publishedAt = fields.publishedAt;
621
584
  if (fields.tags !== void 0) input2.tags = fields.tags;
622
585
  if (fields.metadata !== void 0) {
@@ -636,15 +599,12 @@ async function upsertStaticPost(graphql, siteId, slug, body, fields) {
636
599
  const publishedAt = fields.publishedAt ?? (status === "published" ? (/* @__PURE__ */ new Date()).toISOString() : void 0);
637
600
  const postId = fields.postId ?? `post-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
638
601
  const input = {
639
- siteId,
640
602
  postId,
641
603
  slug,
642
604
  title: fields.title,
643
605
  format: "static",
644
606
  body: encodeAwsJson3(body),
645
- status,
646
- siteIdStatus: composeSiteIdStatus3(siteId, status),
647
- siteIdSlug: composeSiteIdSlug3(siteId, slug)
607
+ status
648
608
  };
649
609
  if (fields.excerpt !== void 0) input.excerpt = fields.excerpt;
650
610
  if (publishedAt !== void 0) input.publishedAt = publishedAt;
@@ -661,7 +621,6 @@ var uploadStaticBundleSchema = {
661
621
  type: "object",
662
622
  required: ["slug", "title", "zipBase64"],
663
623
  properties: {
664
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
665
624
  postId: {
666
625
  type: "string",
667
626
  description: "Optional explicit Post id when creating a new post. Ignored if a post at this slug already exists."
@@ -687,8 +646,7 @@ var uploadStaticBundleSchema = {
687
646
  }
688
647
  }
689
648
  };
690
- async function uploadStaticBundle(graphql, storage, defaultSiteId, args) {
691
- const siteId = args.siteId ?? defaultSiteId;
649
+ async function uploadStaticBundle(graphql, storage, args) {
692
650
  const slug = args.slug;
693
651
  const zipBytes = Buffer.from(args.zipBase64, "base64");
694
652
  if (zipBytes.length === 0) {
@@ -715,7 +673,7 @@ async function uploadStaticBundle(graphql, storage, defaultSiteId, args) {
715
673
  `upload_static_bundle: entrypoint "${entrypoint}" is not present in the bundle.`
716
674
  );
717
675
  }
718
- const prefix = bundlePrefix(siteId, slug);
676
+ const prefix = bundlePrefix(slug);
719
677
  const existing = await storage.listObjects(prefix).catch((err) => {
720
678
  console.error("[upload_static_bundle] listObjects failed (proceeding)", err);
721
679
  return [];
@@ -733,7 +691,7 @@ async function uploadStaticBundle(graphql, storage, defaultSiteId, args) {
733
691
  files: files.map((f) => f.path).sort(),
734
692
  uploadedAt: (/* @__PURE__ */ new Date()).toISOString()
735
693
  };
736
- const { post } = await upsertStaticPost(graphql, siteId, slug, body, {
694
+ const { post } = await upsertStaticPost(graphql, slug, body, {
737
695
  title: args.title,
738
696
  postId: args.postId,
739
697
  status: args.status,
@@ -757,8 +715,7 @@ var uploadStaticFileSchema = {
757
715
  type: "object",
758
716
  required: ["slug", "filename", "base64Data"],
759
717
  properties: {
760
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
761
- slug: { type: "string", description: "Bundle slug. Files land at public/static/<siteId>/<slug>/<filename>." },
718
+ slug: { type: "string", description: "Bundle slug. Files land at public/static/<slug>/<filename>." },
762
719
  filename: {
763
720
  type: "string",
764
721
  description: "Relative path inside the bundle. Must NOT start with `/`, contain `..`, or include null bytes. macOS / Windows zip junk (`.DS_Store`, `__MACOSX/*`, `Thumbs.db`) is also rejected."
@@ -773,8 +730,7 @@ var uploadStaticFileSchema = {
773
730
  }
774
731
  }
775
732
  };
776
- async function uploadStaticFile(storage, defaultSiteId, args) {
777
- const siteId = args.siteId ?? defaultSiteId;
733
+ async function uploadStaticFile(storage, args) {
778
734
  const filename = args.filename;
779
735
  const reason = validateBundlePath2(filename);
780
736
  if (reason) {
@@ -795,7 +751,7 @@ async function uploadStaticFile(storage, defaultSiteId, args) {
795
751
  }
796
752
  }
797
753
  const contentType = args.contentType ?? mimeTypeFor2(filename);
798
- const key = `${bundlePrefix2(siteId, args.slug)}${filename}`;
754
+ const key = `${bundlePrefix2(args.slug)}${filename}`;
799
755
  const url = await storage.putObject(key, body, contentType);
800
756
  return { key, url, size: body.length };
801
757
  }
@@ -806,7 +762,6 @@ var deleteStaticFileSchema = {
806
762
  type: "object",
807
763
  required: ["slug", "filename"],
808
764
  properties: {
809
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
810
765
  slug: { type: "string" },
811
766
  filename: {
812
767
  type: "string",
@@ -814,13 +769,12 @@ var deleteStaticFileSchema = {
814
769
  }
815
770
  }
816
771
  };
817
- async function deleteStaticFile(storage, defaultSiteId, args) {
818
- const siteId = args.siteId ?? defaultSiteId;
772
+ async function deleteStaticFile(storage, args) {
819
773
  const reason = validateBundlePath3(args.filename);
820
774
  if (reason) {
821
775
  throw new Error(`delete_static_file: invalid filename "${args.filename}" (${reason})`);
822
776
  }
823
- const prefix = bundlePrefix3(siteId, args.slug);
777
+ const prefix = bundlePrefix3(args.slug);
824
778
  const key = `${prefix}${args.filename}`;
825
779
  const existing = await storage.listObjects(key);
826
780
  const found = existing.some((o) => o.key === key);
@@ -840,7 +794,6 @@ var commitStaticPostSchema = {
840
794
  type: "object",
841
795
  required: ["slug"],
842
796
  properties: {
843
- siteId: { type: "string", description: 'Site identifier (defaults to "default")' },
844
797
  slug: { type: "string" },
845
798
  title: {
846
799
  type: "string",
@@ -865,10 +818,9 @@ var commitStaticPostSchema = {
865
818
  }
866
819
  }
867
820
  };
868
- async function commitStaticPost(graphql, storage, defaultSiteId, args) {
869
- const siteId = args.siteId ?? defaultSiteId;
821
+ async function commitStaticPost(graphql, storage, args) {
870
822
  const slug = args.slug;
871
- const prefix = bundlePrefix4(siteId, slug);
823
+ const prefix = bundlePrefix4(slug);
872
824
  const objects = await storage.listObjects(prefix);
873
825
  if (objects.length === 0) {
874
826
  throw new Error(
@@ -887,7 +839,7 @@ async function commitStaticPost(graphql, storage, defaultSiteId, args) {
887
839
  files: relPaths,
888
840
  uploadedAt: (/* @__PURE__ */ new Date()).toISOString()
889
841
  };
890
- const { post, created } = await upsertStaticPost(graphql, siteId, slug, body, {
842
+ const { post, created } = await upsertStaticPost(graphql, slug, body, {
891
843
  title: args.title,
892
844
  postId: args.postId,
893
845
  excerpt: args.excerpt,
@@ -905,37 +857,37 @@ var tools = [
905
857
  name: "list_posts",
906
858
  description: "List posts in the CMS with optional filters by status. Returns up to `limit` posts (default 20) plus a `nextToken` cursor for pagination.",
907
859
  inputSchema: listPostsSchema,
908
- handler: (args, ctx) => listPosts(ctx.graphql, ctx.defaultSiteId, args)
860
+ handler: (args, ctx) => listPosts(ctx.graphql, args)
909
861
  },
910
862
  {
911
863
  name: "get_post",
912
864
  description: "Fetch a single post by slug or postId. Returns null if not found.",
913
865
  inputSchema: getPostSchema,
914
- handler: (args, ctx) => getPost(ctx.graphql, ctx.defaultSiteId, args)
866
+ handler: (args, ctx) => getPost(ctx.graphql, args)
915
867
  },
916
868
  {
917
869
  name: "create_post",
918
- description: "Create a new post. Title and slug are required. Body shape depends on format: tiptap=JSON node tree, markdown=source string, html=raw HTML string. Defaults to status=draft. Pass `metadata: { no_layout: true }` alongside format=html to publish the body as a bare HTML page with no theme chrome (the public route redirects to /raw/<slug>).",
870
+ description: "Create a new post. Title and slug are required. Body shape depends on format: tiptap=JSON node tree, markdown=source string, html=raw HTML string. Defaults to status=draft. Pass `metadata: { no_layout: true }` alongside format=html to publish the body as a bare HTML page with no theme chrome (the public route redirects to /_/<slug>).",
919
871
  inputSchema: createPostSchema,
920
- handler: (args, ctx) => createPost(ctx.graphql, ctx.defaultSiteId, args)
872
+ handler: (args, ctx) => createPost(ctx.graphql, args)
921
873
  },
922
874
  {
923
875
  name: "update_post",
924
876
  description: "Update an existing post by postId. Only the fields you pass are changed. Tag list / publishedAt changes also update the PostTag denormalized index. Passing `metadata` REPLACES the existing object \u2014 call get_post first if you only want to add or change one key.",
925
877
  inputSchema: updatePostSchema,
926
- handler: (args, ctx) => updatePost(ctx.graphql, ctx.defaultSiteId, args)
878
+ handler: (args, ctx) => updatePost(ctx.graphql, args)
927
879
  },
928
880
  {
929
881
  name: "delete_post",
930
882
  description: "Delete a post by postId. Also drops associated PostTag index entries.",
931
883
  inputSchema: deletePostSchema,
932
- handler: (args, ctx) => deletePost(ctx.graphql, ctx.defaultSiteId, args)
884
+ handler: (args, ctx) => deletePost(ctx.graphql, args)
933
885
  },
934
886
  {
935
887
  name: "upload_media",
936
888
  description: "Upload a file to the site's media S3 bucket. Pass base64-encoded bytes; the server stores them verbatim under public/media/YYYY/MM/. Returns the public URL and Media record. The server does not transcode \u2014 pre-process (e.g. resize/webp) on the client.",
937
889
  inputSchema: uploadMediaSchema,
938
- handler: (args, ctx) => uploadMedia(ctx.graphql, ctx.storage(), ctx.defaultSiteId, args)
890
+ handler: (args, ctx) => uploadMedia(ctx.graphql, ctx.storage(), args)
939
891
  },
940
892
  {
941
893
  name: "get_schema",
@@ -945,12 +897,11 @@ var tools = [
945
897
  },
946
898
  {
947
899
  name: "upload_static_bundle",
948
- description: "Create or replace a `format: 'static'` post in one shot. Pass a base64-encoded zip; the server unpacks it, validates every path + lints HTML/CSS/SVG for absolute path refs (bundles must be self-contained via relative paths), wipes the existing S3 prefix at public/static/<siteId>/<slug>/, uploads every file, and upserts the Post row with a manifest pointing at the entrypoint. Use this when you have the whole bundle to submit at once. For incremental edits use upload_static_file / delete_static_file followed by commit_static_post.",
900
+ description: "Create or replace a `format: 'static'` post in one shot. Pass a base64-encoded zip; the server unpacks it, validates every path + lints HTML/CSS/SVG for absolute path refs (bundles must be self-contained via relative paths), wipes the existing S3 prefix at public/static/<slug>/, uploads every file, and upserts the Post row with a manifest pointing at the entrypoint. Use this when you have the whole bundle to submit at once. For incremental edits use upload_static_file / delete_static_file followed by commit_static_post.",
949
901
  inputSchema: uploadStaticBundleSchema,
950
902
  handler: (args, ctx) => uploadStaticBundle(
951
903
  ctx.graphql,
952
904
  ctx.storage(),
953
- ctx.defaultSiteId,
954
905
  args
955
906
  )
956
907
  },
@@ -960,7 +911,6 @@ var tools = [
960
911
  inputSchema: uploadStaticFileSchema,
961
912
  handler: (args, ctx) => uploadStaticFile(
962
913
  ctx.storage(),
963
- ctx.defaultSiteId,
964
914
  args
965
915
  )
966
916
  },
@@ -970,18 +920,16 @@ var tools = [
970
920
  inputSchema: deleteStaticFileSchema,
971
921
  handler: (args, ctx) => deleteStaticFile(
972
922
  ctx.storage(),
973
- ctx.defaultSiteId,
974
923
  args
975
924
  )
976
925
  },
977
926
  {
978
927
  name: "commit_static_post",
979
- description: 'Rebuild a static post\'s Post row from whatever is currently in its S3 prefix. Scans `public/static/<siteId>/<slug>/`, picks the entrypoint (default `index.html` or override), and upserts the Post with a fresh manifest (sorted file list + uploadedAt timestamp). Use this as the "save" step after a series of `upload_static_file` / `delete_static_file` calls. `title` is required when creating a brand-new post; on update, existing fields are preserved unless explicitly overridden.',
928
+ description: 'Rebuild a static post\'s Post row from whatever is currently in its S3 prefix. Scans `public/static/<slug>/`, picks the entrypoint (default `index.html` or override), and upserts the Post with a fresh manifest (sorted file list + uploadedAt timestamp). Use this as the "save" step after a series of `upload_static_file` / `delete_static_file` calls. `title` is required when creating a brand-new post; on update, existing fields are preserved unless explicitly overridden.',
980
929
  inputSchema: commitStaticPostSchema,
981
930
  handler: (args, ctx) => commitStaticPost(
982
931
  ctx.graphql,
983
932
  ctx.storage(),
984
- ctx.defaultSiteId,
985
933
  args
986
934
  )
987
935
  }
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-IW52OUIR.js";
8
8
  import {
9
9
  tools
10
- } from "./chunk-4PTNHZO4.js";
10
+ } from "./chunk-DAR6AHSX.js";
11
11
  import {
12
12
  AwsCrc32,
13
13
  __awaiter,
@@ -10895,10 +10895,6 @@ function parseArgs(argv) {
10895
10895
  out.outputs = argv[++i2];
10896
10896
  } else if (arg.startsWith("--outputs=")) {
10897
10897
  out.outputs = arg.slice("--outputs=".length);
10898
- } else if (arg === "--site-id") {
10899
- out.defaultSiteId = argv[++i2];
10900
- } else if (arg.startsWith("--site-id=")) {
10901
- out.defaultSiteId = arg.slice("--site-id=".length);
10902
10898
  }
10903
10899
  }
10904
10900
  return out;
@@ -10938,8 +10934,7 @@ async function loadConfig2(argv = process.argv.slice(2)) {
10938
10934
  return {
10939
10935
  outputs,
10940
10936
  email: requireEnv("AMPLESS_MCP_EMAIL"),
10941
- password: requireEnv("AMPLESS_MCP_PASSWORD"),
10942
- defaultSiteId: args.defaultSiteId ?? process.env.AMPLESS_MCP_SITE_ID ?? "default"
10937
+ password: requireEnv("AMPLESS_MCP_PASSWORD")
10943
10938
  };
10944
10939
  }
10945
10940
 
@@ -32181,8 +32176,7 @@ async function startServer(config2) {
32181
32176
  };
32182
32177
  const ctx = {
32183
32178
  graphql,
32184
- storage,
32185
- defaultSiteId: config2.defaultSiteId
32179
+ storage
32186
32180
  };
32187
32181
  const server = new Server(
32188
32182
  { name: "@ampless/mcp-server", version: "0.0.1" },
@@ -48,7 +48,6 @@ interface StorageClient {
48
48
  interface ToolContext {
49
49
  graphql: GraphqlClient;
50
50
  storage: () => StorageClient;
51
- defaultSiteId: string;
52
51
  }
53
52
 
54
53
  /**
@@ -5,7 +5,7 @@ import {
5
5
  extractZipFromBuffer,
6
6
  getTools,
7
7
  tools
8
- } from "../chunk-4PTNHZO4.js";
8
+ } from "../chunk-DAR6AHSX.js";
9
9
  import "../chunk-LMMQX4CK.js";
10
10
  export {
11
11
  decodeUtf8,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ampless/mcp-server",
3
- "version": "0.2.0-alpha.9",
3
+ "version": "1.0.0-alpha.10",
4
4
  "description": "MCP server for ampless — lets AI agents (Claude Desktop, Cursor, Claude Code) read and write posts and media via AppSync",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,7 +36,7 @@
36
36
  "@aws-sdk/client-s3": "^3.1048.0",
37
37
  "amazon-cognito-identity-js": "^6.3.12",
38
38
  "fflate": "^0.8.2",
39
- "ampless": "0.2.0-alpha.8"
39
+ "ampless": "1.0.0-alpha.9"
40
40
  },
41
41
  "keywords": [
42
42
  "ampless",