// src/tools/mediaTools.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import {
// TODO: Add these imports as you implement the functions in wordpress/api.js
uploadMedia,
listMedia,
searchMedia,
editMediaMetadata,
deleteMedia,
setFeaturedImage,
optimizeMedia,
getMediaDetails,
bulkDeleteMedia
} from "../wordpress/api.js";
/**
* Register all media-related tools with the MCP server
*/
export function registerMediaTools(server: McpServer) {
// Upload Media Tool
server.tool(
"upload-media",
"Upload media files to WordPress from local paths or URLs",
{
source: z.string().describe("Local file path or URL to upload"),
title: z.string().optional().describe("Media title"),
caption: z.string().optional().describe("Media caption"),
altText: z.string().optional().describe("Alt text for accessibility"),
description: z.string().optional().describe("Media description")
},
async ({ source, title, caption, altText, description }) => {
try {
// TODO: Implement uploadMedia in wordpress/api.js
const result = await uploadMedia(source, { title, caption, altText, description });
return {
content: [{
type: "text",
text: "⚠️ upload-media tool not yet implemented. Please add uploadMedia function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.error("Error uploading media:", error);
return {
content: [{
type: "text",
text: `Error uploading media: ${errorMessage}`
}],
isError: true
};
}
}
);
// List Media Tool
server.tool(
"list-media",
"List WordPress media library with pagination and filters",
{
page: z.number().default(1).describe("Page number (default: 1)"),
perPage: z.number().max(100).default(20).describe("Items per page (max: 100)"),
mediaType: z.enum(["image", "video", "audio", "application", "any"]).default("any").describe("Filter by media type"),
mimeType: z.string().optional().describe("Specific MIME type (e.g., 'image/jpeg')"),
orderBy: z.enum(["date", "id", "title", "slug"]).default("date").describe("Order media by"),
order: z.enum(["asc", "desc"]).default("desc").describe("Sort order"),
parent: z.number().optional().describe("Filter by parent post ID")
},
async ({ page, perPage, mediaType, mimeType, orderBy, order, parent }) => {
try {
// TODO: Implement listMedia in wordpress/api.js
const result = await listMedia({ page, perPage, mediaType, mimeType, orderBy, order, parent });
return {
content: [{
type: "text",
text: "⚠️ list-media tool not yet implemented. Please add listMedia function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error listing media: ${errorMessage}`
}],
isError: true
};
}
}
);
// Search Media Tool
server.tool(
"search-media",
"Search WordPress media library by keyword, type, or date",
{
query: z.string().describe("Search query for title, caption, or filename"),
mediaType: z.enum(["image", "video", "audio", "application", "any"]).default("any").describe("Filter by media type"),
dateAfter: z.string().optional().describe("Find media after this date (ISO format)"),
dateBefore: z.string().optional().describe("Find media before this date (ISO format)"),
limit: z.number().max(50).default(20).describe("Maximum results to return")
},
async ({ query, mediaType, dateAfter, dateBefore, limit }) => {
try {
// TODO: Implement searchMedia in wordpress/api.js
const result = await searchMedia({ query, mediaType, dateAfter, dateBefore, limit });
return {
content: [{
type: "text",
text: "⚠️ search-media tool not yet implemented. Please add searchMedia function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error searching media: ${errorMessage}`
}],
isError: true
};
}
}
);
// Edit Media Metadata Tool
server.tool(
"edit-media-metadata",
"Update title, caption, alt text, and description of media files",
{
mediaId: z.number().describe("ID of the media item to edit"),
title: z.string().optional().describe("New media title"),
caption: z.string().optional().describe("New media caption"),
altText: z.string().optional().describe("New alt text for accessibility"),
description: z.string().optional().describe("New media description")
},
async ({ mediaId, title, caption, altText, description }) => {
try {
// TODO: Implement editMediaMetadata in wordpress/api.js
const result = await editMediaMetadata(mediaId, { title, caption, altText, description });
return {
content: [{
type: "text",
text: "⚠️ edit-media-metadata tool not yet implemented. Please add editMediaMetadata function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error editing media metadata: ${errorMessage}`
}],
isError: true
};
}
}
);
// Delete Media Tool
server.tool(
"delete-media",
"Permanently delete media files from WordPress library",
{
mediaId: z.number().describe("ID of the media item to delete"),
force: z.boolean().default(true).describe("Force delete (bypass trash for media)")
},
async ({ mediaId, force }) => {
try {
// TODO: Implement deleteMedia in wordpress/api.js
const result = await deleteMedia(mediaId, force);
return {
content: [{
type: "text",
text: "⚠️ delete-media tool not yet implemented. Please add deleteMedia function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error deleting media: ${errorMessage}`
}],
isError: true
};
}
}
);
// Set Featured Image Tool
server.tool(
"set-featured-image",
"Assign a featured image to a WordPress post",
{
postId: z.number().describe("ID of the post to update"),
mediaId: z.number().describe("ID of the media item to set as featured image")
},
async ({ postId, mediaId }) => {
try {
// TODO: Implement setFeaturedImage in wordpress/api.js
const result = await setFeaturedImage(postId, mediaId);
return {
content: [{
type: "text",
text: "⚠️ set-featured-image tool not yet implemented. Please add setFeaturedImage function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error setting featured image: ${errorMessage}`
}],
isError: true
};
}
}
);
// Optimize Media Tool
server.tool(
"optimize-media",
"Compress and optimize images using external API (e.g., TinyPNG)",
{
mediaId: z.number().describe("ID of the media item to optimize"),
quality: z.number().min(10).max(100).default(80).describe("Compression quality (10-100)"),
replaceOriginal: z.boolean().default(false).describe("Replace original file or create new version")
},
async ({ mediaId, quality, replaceOriginal }) => {
try {
// TODO: Implement optimizeMedia in wordpress/api.js
const result = await optimizeMedia(mediaId, { quality, replaceOriginal });
return {
content: [{
type: "text",
text: "⚠️ optimize-media tool not yet implemented. Please add optimizeMedia function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error optimizing media: ${errorMessage}`
}],
isError: true
};
}
}
);
// Get Media Details Tool
server.tool(
"get-media-details",
"Retrieve detailed information about a media file",
{
mediaId: z.number().describe("ID of the media item to retrieve")
},
async ({ mediaId }) => {
try {
// TODO: Implement getMediaDetails in wordpress/api.js
const result = await getMediaDetails(mediaId);
return {
content: [{
type: "text",
text: "⚠️ get-media-details tool not yet implemented. Please add getMediaDetails function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error retrieving media details: ${errorMessage}`
}],
isError: true
};
}
}
);
// Bulk Delete Media Tool
server.tool(
"bulk-delete-media",
"Delete multiple media files at once",
{
mediaIds: z.array(z.number()).describe("Array of media IDs to delete"),
force: z.boolean().default(true).describe("Force delete (bypass trash)")
},
async ({ mediaIds, force }) => {
try {
if (mediaIds.length === 0) {
return {
content: [{
type: "text",
text: "No media IDs provided for bulk deletion"
}],
isError: true
};
}
// TODO: Implement bulkDeleteMedia in wordpress/api.js
const result = await bulkDeleteMedia(mediaIds, force);
return {
content: [{
type: "text",
text: "⚠️ bulk-delete-media tool not yet implemented. Please add bulkDeleteMedia function to wordpress/api.js"
}],
isError: true
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [{
type: "text",
text: `Error bulk deleting media: ${errorMessage}`
}],
isError: true
};
}
}
);
}