@ampless/mcp-server 1.0.0-alpha.23 → 1.0.0-alpha.25

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/README.ja.md CHANGED
@@ -68,6 +68,7 @@ import type { ToolDefinition, ToolContext, ResolvedSite } from '@ampless/mcp-ser
68
68
  | `update_post` | editor | 既存の投稿のフィールドをパッチ更新 |
69
69
  | `delete_post` | editor | 投稿を削除しタグインデックスをクリーンアップ |
70
70
  | `upload_media` | editor | Base64 エンコードされたバイト列を S3 にアップロードし Media レコードを作成 |
71
+ | `delete_media` | editor | メディアファイルを削除(S3 オブジェクト + Media 行)。`mediaId` または `src` で指定 |
71
72
  | `get_schema` | reader | CMS コンテンツスキーマを返す |
72
73
  | `upload_static_bundle` | editor | ビルド済み静的バンドルを S3 にアップロード |
73
74
  | `list_static_files` | reader | 静的バンドルファイルを一覧表示 |
package/README.md CHANGED
@@ -68,6 +68,7 @@ import type { ToolDefinition, ToolContext, ResolvedSite } from '@ampless/mcp-ser
68
68
  | `update_post` | editor | Patch fields on an existing post |
69
69
  | `delete_post` | editor | Delete a post and clean up its tag index |
70
70
  | `upload_media` | editor | Upload base64-encoded bytes to S3 and create a Media record |
71
+ | `delete_media` | editor | Delete a media file (S3 object + Media row). Pass `mediaId` or `src` |
71
72
  | `get_schema` | reader | Return the CMS content schema |
72
73
  | `upload_static_bundle` | editor | Upload a pre-built static bundle to S3 |
73
74
  | `list_static_files` | reader | List static bundle files |
package/dist/index.js CHANGED
@@ -353,6 +353,92 @@ async function uploadMedia(graphql, storage, args) {
353
353
  return { media: data.createMedia, url: putResult.url };
354
354
  }
355
355
 
356
+ // src/tools/delete-media.ts
357
+ var GET_BY_ID2 = (
358
+ /* GraphQL */
359
+ `
360
+ query GetMedia($mediaId: ID!) {
361
+ getMedia(mediaId: $mediaId) {
362
+ mediaId
363
+ src
364
+ }
365
+ }
366
+ `
367
+ );
368
+ var GET_BY_SRC = (
369
+ /* GraphQL */
370
+ `
371
+ query GetMediaBySrc($src: String!) {
372
+ getMediaBySrc(src: $src) {
373
+ mediaId
374
+ src
375
+ }
376
+ }
377
+ `
378
+ );
379
+ var DELETE = (
380
+ /* GraphQL */
381
+ `
382
+ mutation DeleteMedia($input: DeleteMediaInput!) {
383
+ deleteMedia(input: $input) {
384
+ mediaId
385
+ }
386
+ }
387
+ `
388
+ );
389
+ var deleteMediaSchema = {
390
+ type: "object",
391
+ properties: {
392
+ mediaId: {
393
+ type: "string",
394
+ description: "Media row primary key (e.g. 'media-1714400000000-abc123' as returned by `upload_media`). Provide either `mediaId` or `src`; mediaId is the direct path."
395
+ },
396
+ src: {
397
+ type: "string",
398
+ description: "Full S3 key including `public/` (e.g. 'public/media/2026/05/1714400000000-photo.jpg'). Use when you only have the public URL \u2014 strip `/api/media/` and prepend `public/`. Provide either `mediaId` or `src`."
399
+ }
400
+ }
401
+ };
402
+ async function deleteMedia(graphql, storage, args) {
403
+ if (!args.mediaId && !args.src) {
404
+ throw new Error("delete_media: provide `mediaId` or `src`");
405
+ }
406
+ let mediaId;
407
+ let src;
408
+ if (args.mediaId) {
409
+ const data = await graphql.query(GET_BY_ID2, { mediaId: args.mediaId });
410
+ if (data.getMedia) {
411
+ mediaId = data.getMedia.mediaId;
412
+ src = data.getMedia.src;
413
+ }
414
+ } else {
415
+ const data = await graphql.query(GET_BY_SRC, { src: args.src });
416
+ if (data.getMediaBySrc) {
417
+ mediaId = data.getMediaBySrc.mediaId;
418
+ src = data.getMediaBySrc.src;
419
+ }
420
+ }
421
+ if (!mediaId) {
422
+ if (args.src) {
423
+ await storage.deleteObject(args.src);
424
+ return {
425
+ deleted: false,
426
+ reason: "media row not found; S3 object delete attempted (idempotent)",
427
+ src: args.src
428
+ };
429
+ }
430
+ return {
431
+ deleted: false,
432
+ reason: "media row not found for mediaId"
433
+ };
434
+ }
435
+ await storage.deleteObject(src);
436
+ await graphql.query(DELETE, {
437
+ input: { mediaId }
438
+ });
439
+ return { deleted: true, mediaId, src };
440
+ }
441
+
356
442
  // src/tools/get-schema.ts
357
443
  var getSchemaSchema = {
358
444
  type: "object",
@@ -1309,6 +1395,17 @@ var tools = [
1309
1395
  inputSchema: uploadMediaSchema,
1310
1396
  handler: (args, ctx) => uploadMedia(ctx.graphql, ctx.storage(), args)
1311
1397
  },
1398
+ {
1399
+ name: "delete_media",
1400
+ description: "Delete a media file: removes the S3 object and the Media row. Pass `mediaId` (from `upload_media`'s response) or `src` (full S3 key like `public/media/2026/05/...`). When only `src` is given, looks up the Media row via `getMediaBySrc`. S3 delete runs first, then the DDB row delete \u2014 both are idempotent so re-running converges on missing-key cases. Returns `{ deleted: false }` instead of throwing when no Media row matches; if `src` was supplied directly the S3 object is still removed (use this to sweep orphan files).",
1401
+ inputSchema: deleteMediaSchema,
1402
+ handler: (args, ctx) => deleteMedia(
1403
+ ctx.graphql,
1404
+ ctx.storage(),
1405
+ args
1406
+ ),
1407
+ destructive: true
1408
+ },
1312
1409
  {
1313
1410
  name: "get_schema",
1314
1411
  description: "Returns the CMS content schema (Post/Page/Media field shapes, format enum, notes). Useful as the first call to understand what fields are available.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ampless/mcp-server",
3
- "version": "1.0.0-alpha.23",
3
+ "version": "1.0.0-alpha.25",
4
4
  "description": "MCP tool registry shared by @ampless/backend mcp-handler Lambda. Installed transitively via @ampless/admin / @ampless/backend; no direct install needed.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -26,7 +26,7 @@
26
26
  "bugs": "https://github.com/heavymoons/ampless/issues",
27
27
  "dependencies": {
28
28
  "fflate": "^0.8.3",
29
- "ampless": "1.0.0-alpha.19"
29
+ "ampless": "1.0.0-alpha.20"
30
30
  },
31
31
  "keywords": [
32
32
  "ampless",