Skip to main content
Glama
benswel

QR for Agent

update_qr_destination

Update the destination URL of an existing QR code without changing its image. Fix broken links, modify campaign targets, or test new URLs dynamically.

Instructions

Change where an existing QR code redirects to. This is the key 'dynamic link' feature: the QR image stays the same, but scanning it will now go to the new URL. Ideal for updating campaigns, fixing broken links, or A/B testing.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
short_idYesThe short ID of the QR code to update.
target_urlYesThe new destination URL.
labelNoOptionally update the label too.
expires_atNoISO 8601 expiration date. Set to null to remove expiration.
scheduled_urlNoScheduled replacement URL. Set to null to cancel.
scheduled_atNoISO 8601 activation date for scheduled_url. Set to null to cancel.
gtm_container_idNoGoogle Tag Manager container ID. Set to null to remove GTM tracking.

Implementation Reference

  • The handler function for update_qr_destination. It constructs a body with the target_url and optional fields (label, expires_at, scheduled_url, scheduled_at, gtm_container_id), then sends a PATCH request to /api/qr/{short_id}.
    handler: async (input: { short_id: string; target_url: string; label?: string; expires_at?: string | null; scheduled_url?: string | null; scheduled_at?: string | null; gtm_container_id?: string | null }) => {
      const body: Record<string, unknown> = { target_url: input.target_url, label: input.label };
      if (input.expires_at !== undefined) body.expires_at = input.expires_at;
      if (input.scheduled_url !== undefined) body.scheduled_url = input.scheduled_url;
      if (input.scheduled_at !== undefined) body.scheduled_at = input.scheduled_at;
      if (input.gtm_container_id !== undefined) body.gtm_container_id = input.gtm_container_id;
      return apiRequest(`/api/qr/${input.short_id}`, {
        method: "PATCH",
        body,
      });
    },
  • The input schema for update_qr_destination using Zod. Validates short_id (string), target_url (valid URL), label (optional string), expires_at (optional nullable ISO string), scheduled_url (optional nullable URL), scheduled_at (optional nullable ISO string), and gtm_container_id (optional nullable string matching GTM-[A-Z0-9]+ pattern).
    update_qr_destination: {
      description:
        "Change where an existing QR code redirects to. This is the key 'dynamic link' feature: the QR image stays the same, but scanning it will now go to the new URL. Ideal for updating campaigns, fixing broken links, or A/B testing.",
      inputSchema: z.object({
        short_id: z.string().describe("The short ID of the QR code to update."),
        target_url: z
          .string()
          .url()
          .describe("The new destination URL."),
        label: z
          .string()
          .optional()
          .describe("Optionally update the label too."),
        expires_at: z
          .string()
          .nullable()
          .optional()
          .describe("ISO 8601 expiration date. Set to null to remove expiration."),
        scheduled_url: z
          .string()
          .url()
          .nullable()
          .optional()
          .describe("Scheduled replacement URL. Set to null to cancel."),
        scheduled_at: z
          .string()
          .nullable()
          .optional()
          .describe("ISO 8601 activation date for scheduled_url. Set to null to cancel."),
        gtm_container_id: z
          .string()
          .regex(/^GTM-[A-Z0-9]+$/)
          .nullable()
          .optional()
          .describe("Google Tag Manager container ID. Set to null to remove GTM tracking."),
      }),
  • Tools are dynamically registered on the MCP server by iterating over all entries in the tools object (including update_qr_destination). The server.tool() method is called with the name, description, input schema shape, and a wrapper async handler that calls tool.handler and formats the response.
    for (const [name, tool] of Object.entries(tools)) {
      server.tool(
        name,
        tool.description,
        tool.inputSchema.shape,
        async (input: Record<string, unknown>) => {
          try {
            const result = await tool.handler(input as any);
            return {
              content: [
                {
                  type: "text" as const,
                  text: JSON.stringify(result, null, 2),
                },
              ],
            };
          } catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            return {
              content: [
                {
                  type: "text" as const,
                  text: JSON.stringify({
                    error: message,
                    hint: "Check the input parameters and try again. Use list_qr_codes to verify available QR codes.",
                  }),
                },
              ],
              isError: true,
            };
          }
        }
      );
    }
  • The apiRequest helper function used by the handler. It makes HTTP requests to the backend API with the configured BASE_URL, API_KEY, and optional query params or JSON body. For update_qr_destination, it sends a PATCH request to /api/qr/{short_id}.
    export async function apiRequest(path: string, options: RequestOptions = {}) {
      const { method = "GET", body, query } = options;
    
      let url = `${BASE_URL}${path}`;
      if (query) {
        const params = new URLSearchParams();
        for (const [key, value] of Object.entries(query)) {
          params.set(key, String(value));
        }
        url += `?${params.toString()}`;
      }
    
      const headers: Record<string, string> = {
        "X-API-Key": API_KEY,
      };
    
      if (body) {
        headers["Content-Type"] = "application/json";
      }
    
      const res = await fetch(url, {
        method,
        headers,
        body: body ? JSON.stringify(body) : undefined,
      });
    
      return res.json();
    }
Behavior3/5

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

With no annotations, the description discloses the key behavior (QR image unchanged, URL updated) but lacks information on side effects, permissions, or rate limits. Adequate but not comprehensive.

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

Conciseness5/5

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

Three sentences: purpose, behavior, use cases. Front-loaded, no redundant words, perfectly scoped for quick understanding.

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?

Describes only destination update but the tool also updates label, expiration, scheduling, and GTM container. No output schema exists; description should at least hint at additional capabilities.

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% and its descriptions are already clear. The tool description adds no new parameter-level meaning beyond summarizing the core action.

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?

Clearly states the tool changes the destination URL of an existing QR code. Uses specific verb+resource ('change where an existing QR code redirects to') and highlights the dynamic link feature, distinguishing it from creation and other update tools.

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?

Describes when to use: updating campaigns, fixing broken links, A/B testing. Implies context (dynamic vs. static QR codes) but does not explicitly exclude alternative tools or mention prerequisites.

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/benswel/qr-agent-core'

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