Skip to main content
Glama
Mike25app

scaleforge-mcp-meta-ads

upload_image

Upload an image to a Meta Ads ad account. Returns a hash ({images: {filename: {hash}}}) for use in ad creatives. Image hashes are scoped to the ad account; upload separately for each account.

Instructions

WRITE: Upload an image to an ad account. Returns {images: {filename: {hash}}}. The hash is what you pass to create_ad_creative as image_hash.

IMPORTANT: Meta image hashes are SCOPED TO THE AD ACCOUNT — a hash uploaded on account A cannot be used on account B. If you need the same image across multiple accounts, call this once per account. (ScaleForge's backend caches hashes per account to avoid re-uploads within the same account.)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ad_account_idYes'act_123' or '123'
urlNoRemote URL (recommended)
filenameNoDescriptive filename (Meta keys the response by this)

Implementation Reference

  • Handler function that uploads an image by POSTing to Meta's /act_{id}/adimages endpoint with the image URL. Returns {images: {filename: {hash}}}.
      handler: async (args) => {
        if (!args.url) {
          throw new Error(
            "upload_image needs `url` (remote image URL). Local file uploads are not supported from MCP stdio.",
          );
        }
        const body: Record<string, unknown> = { url: args.url };
        if (args.filename) body.filename = args.filename;
        return metaPost(
          `/${toAdAccountPath(String(args.ad_account_id))}/adimages`,
          body,
        );
      },
    },
  • Zod schema defining the input parameters: ad_account_id (required), url (optional remote URL), filename (optional descriptive name).
    inputSchema: {
      ad_account_id: z.string().describe("'act_123' or '123'"),
      url: z.string().url().optional().describe("Remote URL (recommended)"),
      filename: z
        .string()
        .optional()
        .describe("Descriptive filename (Meta keys the response by this)"),
    },
  • src/index.ts:65-66 (registration)
    Registration of all tools (including upload_image) via McpServer.registerTool() in the stdio entrypoint. The loop iterates over allToolDefs and registers each one with their name, description, inputSchema, and handler.
    for (const tool of allTools) {
      server.registerTool(
  • src/http.ts:48-67 (registration)
    Registration of all tools (including upload_image) via McpServer.registerTool() in the HTTP entrypoint. Same pattern as stdio index.ts.
    for (const tool of allTools) {
      server.registerTool(
        tool.name,
        { description: tool.description, inputSchema: tool.inputSchema },
        async (args: unknown) => {
          try {
            const result = await tool.handler(args as Record<string, unknown>);
            return {
              content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
            };
          } catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            return {
              content: [{ type: "text" as const, text: `Error: ${message}` }],
              isError: true,
            };
          }
        },
      );
    }
  • Helper function that normalizes ad account IDs to the 'act_' prefixed format used by Meta's Graph API.
    function toAdAccountPath(idOrActId: string): string {
      return idOrActId.startsWith("act_") ? idOrActId : `act_${idOrActId}`;
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since no annotations are provided, the description covers key behavioral aspects: it is a write operation, returns a hash, scoped per account, and mentions backend caching. It does not cover file size limits or supported formats but is sufficient for a simple upload.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with 'WRITE:' and the main purpose, then return format and important note. Each sentence adds value, though minor redundancy could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the return format and provides cross-account advice. However, it lacks details on error cases, file size limits, or supported image types. Given no output schema, it covers the essentials but could be more complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds context like 'Recommended' for url and explains how filename is used by Meta, but does not significantly expand beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'Upload an image to an ad account' and details the return format. It distinguishes this tool from siblings like create_ad_creative and upload_video by explaining how the returned hash is used in creative creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on when to use this tool, especially the note about hash scoping and cross-account usage. However, it does not explicitly mention alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mike25app/scaleforge-mcp-meta-ads'

If you have feedback or need assistance with the MCP directory API, please join our Discord server