Skip to main content
Glama
benswel

QR for Agent

create_vcard_qr

Generate a QR code that encodes a contact card (vCard) for instant saving when scanned. Supports all standard vCard fields and customizable styling like colors, logo, and frame.

Instructions

Create a QR code that encodes a contact card (vCard). When scanned by a phone camera, it prompts the user to save the contact. Supports all standard vCard fields and custom QR styling.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
first_nameYesContact first name.
last_nameYesContact last name.
organizationNoCompany or organization.
titleNoJob title.
emailNoEmail address.
phoneNoPhone number.
urlNoWebsite URL.
addressNoStreet address.
noteNoAdditional notes.
labelNoLabel for this QR code.
formatNoImage format.svg
foreground_colorNoHex color for dots.
background_colorNoHex color for background.
dot_styleNoDot shape.
corner_styleNoCorner shape.
logo_urlNoLogo URL or data URI.
frame_styleNoFrame style around QR.
frame_textNoCTA text on frame (max 30 chars).
frame_colorNoFrame background color.
frame_text_colorNoFrame text color.

Implementation Reference

  • Handler function that extracts vCard fields from input and sends a POST request to /api/qr with type='vcard' and vcard_data.
    handler: async (input: Record<string, unknown>) => {
      const { first_name, last_name, organization, title, email, phone, url, address, note, ...rest } = input;
      return apiRequest("/api/qr", {
        method: "POST",
        body: {
          type: "vcard",
          vcard_data: { first_name, last_name, organization, title, email, phone, url, address, note },
          ...rest,
        },
      });
    },
  • Input schema definition using Zod for create_vcard_qr tool, defining all vCard fields (first_name, last_name, organization, title, email, phone, url, address, note) and QR styling options.
    inputSchema: z.object({
      first_name: z.string().describe("Contact first name."),
      last_name: z.string().describe("Contact last name."),
      organization: z.string().optional().describe("Company or organization."),
      title: z.string().optional().describe("Job title."),
      email: z.string().optional().describe("Email address."),
      phone: z.string().optional().describe("Phone number."),
      url: z.string().optional().describe("Website URL."),
      address: z.string().optional().describe("Street address."),
      note: z.string().optional().describe("Additional notes."),
      label: z.string().optional().describe("Label for this QR code."),
      format: z.enum(["svg", "png"]).default("svg").describe("Image format."),
      foreground_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Hex color for dots."),
      background_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Hex color for background."),
      dot_style: z.enum(["square", "rounded", "dots", "classy-rounded"]).optional().describe("Dot shape."),
      corner_style: z.enum(["square", "extra-rounded", "dot"]).optional().describe("Corner shape."),
      logo_url: z.string().optional().describe("Logo URL or data URI."),
      frame_style: z.enum(["none", "banner_bottom", "banner_top", "rounded"]).optional().describe("Frame style around QR."),
      frame_text: z.string().max(30).optional().describe("CTA text on frame (max 30 chars)."),
      frame_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Frame background color."),
      frame_text_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Frame text color."),
    }),
  • Tool definition registered in the tools object with description, inputSchema, and handler.
    create_vcard_qr: {
      description:
        "Create a QR code that encodes a contact card (vCard). When scanned by a phone camera, it prompts the user to save the contact. Supports all standard vCard fields and custom QR styling.",
      inputSchema: z.object({
        first_name: z.string().describe("Contact first name."),
        last_name: z.string().describe("Contact last name."),
        organization: z.string().optional().describe("Company or organization."),
        title: z.string().optional().describe("Job title."),
        email: z.string().optional().describe("Email address."),
        phone: z.string().optional().describe("Phone number."),
        url: z.string().optional().describe("Website URL."),
        address: z.string().optional().describe("Street address."),
        note: z.string().optional().describe("Additional notes."),
        label: z.string().optional().describe("Label for this QR code."),
        format: z.enum(["svg", "png"]).default("svg").describe("Image format."),
        foreground_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Hex color for dots."),
        background_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Hex color for background."),
        dot_style: z.enum(["square", "rounded", "dots", "classy-rounded"]).optional().describe("Dot shape."),
        corner_style: z.enum(["square", "extra-rounded", "dot"]).optional().describe("Corner shape."),
        logo_url: z.string().optional().describe("Logo URL or data URI."),
        frame_style: z.enum(["none", "banner_bottom", "banner_top", "rounded"]).optional().describe("Frame style around QR."),
        frame_text: z.string().max(30).optional().describe("CTA text on frame (max 30 chars)."),
        frame_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Frame background color."),
        frame_text_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Frame text color."),
      }),
      handler: async (input: Record<string, unknown>) => {
        const { first_name, last_name, organization, title, email, phone, url, address, note, ...rest } = input;
        return apiRequest("/api/qr", {
          method: "POST",
          body: {
            type: "vcard",
            vcard_data: { first_name, last_name, organization, title, email, phone, url, address, note },
            ...rest,
          },
        });
      },
    },
  • MCP server registration loop that iterates over all tools (including create_vcard_qr) and registers them with the McpServer instance.
    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 to make HTTP POST requests to the backend API.
    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();
    }
Behavior2/5

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

No annotations provided, so description must fully convey behavior. Only states that it creates a QR prompting contact save, but omits details on output format, action on creation, or potential side effects.

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?

Two efficient sentences with no extraneous information, front-loaded with purpose and key behavior.

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?

For a tool with 20 parameters and no output schema, the description is brief and does not explain output or distinguish styling options. It covers core purpose but lacks depth on response and usage details.

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 has 100% parameter description coverage with clear fields. Description adds 'supports all standard vCard fields' which reassures mapping but does not enrich beyond existing 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?

Clearly states the tool creates a QR code encoding a vCard contact card, with specific verb and resource. Differentiates from sibling QR tools by explicitly mentioning vCard format and use case.

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

Usage Guidelines3/5

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

Implies use when needing a contact card QR, but does not provide explicit when-to-use or when-not-to-use, nor contrasts with other create_qr variants or update_vcard_qr.

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