Skip to main content
Glama

run_algorithm

Execute media protection algorithms to safeguard content from AI training and detect AI-generated material using the Sidearm MCP Server.

Instructions

Run one or more named algorithms on media. Provide algorithm IDs (from list_algorithms) and either a public media_url or base64-encoded media content. For text, use the text param. Returns a job_id for async processing — use check_job to poll for results. Requires credits.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
algorithmsYesAlgorithm IDs to run (e.g. ['nightshade', 'glaze']). Use list_algorithms to discover IDs.
media_urlNoPublic URL of the media file to process
mediaNoBase64-encoded media content (alternative to media_url)
textNoPlain text content (for text algorithms like spectra, textmark)
mimeNoMIME type of the media (e.g. image/png, audio/wav)
tagsNoTags for organizing and filtering
webhook_urlNoURL to receive a POST when the job completes
c2pa_wrapNoWrap output in C2PA provenance signing (default: true)
filenameNoOriginal filename for human-readable output naming

Implementation Reference

  • Main tool implementation: registers the 'run_algorithm' MCP tool with its Zod schema (lines 12-52) and async handler function (lines 53-93) that processes input parameters, builds the request body, calls the API client's post method, and returns the job_id and status_url or error response.
    export function register(server: McpServer, api: ApiClient): void {
      server.tool(
        "run_algorithm",
        "Run one or more named algorithms on media. Provide algorithm IDs (from list_algorithms) " +
          "and either a public media_url or base64-encoded media content. For text, use the text param. " +
          "Returns a job_id for async processing — use check_job to poll for results. Requires credits.",
        {
          algorithms: z
            .array(z.string())
            .min(1)
            .describe(
              "Algorithm IDs to run (e.g. ['nightshade', 'glaze']). Use list_algorithms to discover IDs.",
            ),
          media_url: z
            .string()
            .url()
            .optional()
            .describe("Public URL of the media file to process"),
          media: z
            .string()
            .optional()
            .describe("Base64-encoded media content (alternative to media_url)"),
          text: z
            .string()
            .optional()
            .describe("Plain text content (for text algorithms like spectra, textmark)"),
          mime: z
            .string()
            .optional()
            .describe("MIME type of the media (e.g. image/png, audio/wav)"),
          tags: z
            .array(z.string())
            .optional()
            .describe("Tags for organizing and filtering"),
          webhook_url: z
            .string()
            .url()
            .optional()
            .describe("URL to receive a POST when the job completes"),
          c2pa_wrap: z
            .boolean()
            .optional()
            .describe("Wrap output in C2PA provenance signing (default: true)"),
          filename: z
            .string()
            .optional()
            .describe("Original filename for human-readable output naming"),
        },
        async (params) => {
          try {
            const body: Record<string, unknown> = {
              algorithms: params.algorithms,
            };
            if (params.media_url) body.media_url = params.media_url;
            if (params.media) body.media = params.media;
            if (params.text) body.text = params.text;
            if (params.mime) body.mime = params.mime;
            if (params.tags) body.tags = params.tags;
            if (params.webhook_url) body.webhook_url = params.webhook_url;
            if (params.c2pa_wrap !== undefined) body.c2pa_wrap = params.c2pa_wrap;
            if (params.filename) body.filename = params.filename;
    
            const result = await api.post("/api/v1/run", body);
            const res = result as { job_id: string; status_url: string };
    
            return {
              content: [
                {
                  type: "text" as const,
                  text:
                    `Job created successfully.\n\n` +
                    `Job ID: ${res.job_id}\n` +
                    `Status URL: ${res.status_url}\n\n` +
                    `Use check_job with this job_id to poll for results.`,
                },
              ],
            };
          } catch (err) {
            return {
              content: [
                {
                  type: "text" as const,
                  text: `Error: ${err instanceof Error ? err.message : String(err)}`,
                },
              ],
              isError: true as const,
            };
          }
        },
      );
    }
  • src/index.ts:7-43 (registration)
    Tool registration: imports the register function from run-algorithm.ts as 'runAlgorithm' (line 7) and calls it with the server and api instances (line 43) to register the run_algorithm tool with the MCP server.
    import { register as runAlgorithm } from "./tools/run-algorithm.js";
    import { register as protectMedia } from "./tools/protect-media.js";
    import { register as checkJob } from "./tools/check-job.js";
    import { register as searchMedia } from "./tools/search-media.js";
    import { register as listSearches } from "./tools/list-searches.js";
    import { register as detectAi } from "./tools/detect-ai.js";
    import { register as detectFingerprint } from "./tools/detect-fingerprint.js";
    import { register as detectMembership } from "./tools/detect-membership.js";
    import { register as registerMedia } from "./tools/register-media.js";
    import { register as listMedia } from "./tools/list-media.js";
    import { register as getMedia } from "./tools/get-media.js";
    import { register as updateMedia } from "./tools/update-media.js";
    import { register as deleteMedia } from "./tools/delete-media.js";
    import { register as getRights } from "./tools/get-rights.js";
    import { register as getBilling } from "./tools/get-billing.js";
    
    const apiKey = process.env.SDRM_API_KEY;
    if (!apiKey) {
      process.stderr.write(
        "Error: SDRM_API_KEY environment variable is required.\n" +
          "Get your API key at https://sdrm.io/api-keys\n",
      );
      process.exit(1);
    }
    
    const api = new ApiClient(apiKey, process.env.SDRM_BASE_URL);
    
    const server = new McpServer({
      name: "sdrm",
      version: "0.1.0",
    });
    
    // Discovery
    listAlgorithms(server, api);
    
    // Protection
    runAlgorithm(server, api);
  • API client helper: the post method used by run_algorithm handler to send requests to the API endpoint (specifically /api/v1/run). Handles JSON serialization and authorization headers.
    async post<T = unknown>(path: string, body: unknown): Promise<T> {
      return this.request<T>(new URL(`${this.baseUrl}${path}`), {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
    }
  • Related helper tool: list_algorithms is used to discover valid algorithm IDs before calling run_algorithm, as mentioned in the run_algorithm description. It queries the /api/v1/algorithms endpoint.
    export function register(server: McpServer, api: ApiClient): void {
      server.tool(
        "list_algorithms",
        "List available algorithms for media protection, watermarking, and AI content disruption. " +
          "Returns algorithm IDs, names, supported media types, and descriptions. " +
          "Use this to discover valid algorithm IDs before calling run_algorithm. " +
          "Filter by category (open = research algorithms, proprietary = Sidearm bundles) " +
          "or media_type (image, video, audio, text, pdf, gif).",
        {
          category: z
            .enum(["open", "proprietary"])
            .optional()
            .describe("Filter by algorithm category"),
          media_type: z
            .enum(["image", "video", "audio", "text", "pdf", "gif"])
            .optional()
            .describe("Filter by supported media type"),
        },
        async ({ category, media_type }) => {
          try {
            const result = await api.get("/api/v1/algorithms", {
              category,
              media_type,
            });
            return {
              content: [
                { type: "text" as const, text: JSON.stringify(result, null, 2) },
              ],
            };
          } catch (err) {
            return {
              content: [
                {
                  type: "text" as const,
                  text: `Error: ${err instanceof Error ? err.message : String(err)}`,
                },
              ],
              isError: true as const,
            };
          }
        },
      );
    }
  • Related helper tool: check_job is used to poll for results of jobs created by run_algorithm, returning status, progress, and result data including download URLs when complete.
    export function register(server: McpServer, api: ApiClient): void {
      server.tool(
        "check_job",
        "Check the status of an asynchronous job (from run_algorithm, protect_media, or detect_ai). " +
          "Returns status (queued, processing, completed, failed), progress percentage, " +
          "and result data including download URLs when complete.",
        {
          job_id: z.string().describe("The job ID returned by a previous tool call"),
        },
        async ({ job_id }) => {
          try {
            const result = (await api.get(
              `/api/v1/jobs/${encodeURIComponent(job_id)}`,
            )) as JobResponse;
    
            const lines: string[] = [
              `Status: ${result.status}`,
            ];
    
            if (result.progress !== undefined) {
              lines.push(`Progress: ${result.progress}%`);
            }
            if (result.created_at) {
              lines.push(`Created: ${result.created_at}`);
            }
            if (result.completed_at) {
              lines.push(`Completed: ${result.completed_at}`);
            }
            if (result.error) {
              lines.push(`\nError: ${result.error}`);
            }
            if (result.result) {
              lines.push(`\nResult:\n${JSON.stringify(result.result, null, 2)}`);
            }
    
            if (result.status === "queued" || result.status === "processing") {
              lines.push(`\nJob is still running. Call check_job again in a few seconds.`);
            }
    
            return {
              content: [{ type: "text" as const, text: lines.join("\n") }],
            };
          } catch (err) {
            return {
              content: [
                {
                  type: "text" as const,
                  text: `Error: ${err instanceof Error ? err.message : String(err)}`,
                },
              ],
              isError: true as const,
            };
          }
        },
      );
    }

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/sidearmDRM/mcp-server'

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