Why LLMs Need QR Code Generation
Users regularly ask AI assistants to create QR codes. "Make me a QR code for my WiFi network." "Generate a QR code I can put on my business card." "Create a QR code that links to my portfolio." Without a tool to call, the LLM can only describe how to make one. With the QR Gen API as a tool, it can actually produce the image.
The QR Gen API is ideal for LLM tool use because it requires no authentication, accepts simple parameters, and returns images directly. There is nothing to configure, no SDK to install, and no tokens to manage.
OpenAI Function Calling Tool Definition
Use this tool definition with OpenAI's Chat Completions API or Assistants API. The model will call this function when a user asks for a QR code.
{
"type": "function",
"function": {
"name": "generate_qr_code",
"description": "Generate a QR code image for the given data. Returns a URL that renders the QR code as a PNG image. Use this when the user asks you to create, make, or generate a QR code.",
"parameters": {
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "The content to encode. Can be a URL, plain text, WiFi config (WIFI:T:WPA;S:NetworkName;P:Password;;), vCard, email, phone number, or any string."
},
"size": {
"type": "integer",
"description": "Image size in pixels (32-2048). Default 512.",
"default": 512
},
"color": {
"type": "string",
"description": "Foreground color as 6-digit hex without #. Default 000000.",
"default": "000000"
},
"bg": {
"type": "string",
"description": "Background color as 6-digit hex without #. Default ffffff.",
"default": "ffffff"
},
"ec": {
"type": "string",
"enum": ["L", "M", "Q", "H"],
"description": "Error correction level. L=7%, M=15%, Q=25%, H=30%. Default M.",
"default": "M"
}
},
"required": ["data"]
}
}
}When the model calls this function, construct the URL and return it:
def handle_generate_qr_code(args):
params = urllib.parse.urlencode({
"data": args["data"],
"size": args.get("size", 512),
"color": args.get("color", "000000"),
"bg": args.get("bg", "ffffff"),
"ec": args.get("ec", "M"),
"format": "png"
})
url = f"https://qrgenapp.com/api/qr?{params}"
# Return the URL as the tool result
return json.dumps({"url": url, "alt": f"QR code for: {args['data']}"})Anthropic Tool Use Definition
For Anthropic's Messages API with tool use, define the tool like this:
{
"name": "generate_qr_code",
"description": "Generate a QR code image for the given data. Returns a URL that renders the QR code as a PNG. Call this when the user asks to create or generate a QR code for a URL, WiFi network, contact info, or any text.",
"input_schema": {
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "The content to encode in the QR code. URLs, plain text, WiFi strings (WIFI:T:WPA;S:Name;P:Pass;;), vCards, etc."
},
"size": {
"type": "integer",
"description": "Image size in pixels, 32-2048. Default 512."
},
"color": {
"type": "string",
"description": "Foreground hex color without #. Default 000000."
},
"bg": {
"type": "string",
"description": "Background hex color without #. Default ffffff."
},
"ec": {
"type": "string",
"enum": ["L", "M", "Q", "H"],
"description": "Error correction level. Default M."
},
"format": {
"type": "string",
"enum": ["png", "svg"],
"description": "Output format. Default png."
}
},
"required": ["data"]
}
}MCP Server (Model Context Protocol)
The Model Context Protocol allows you to expose tools to LLMs through a standardized server interface. Here is a complete MCP server that wraps the QR Gen API as a tool.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "qrgen",
version: "1.0.0",
});
server.tool(
"generate_qr_code",
"Generate a QR code image. Returns the image URL or raw SVG content.",
{
data: z.string().describe("Content to encode in the QR code"),
format: z.enum(["png", "svg"]).default("png").describe("Output format"),
size: z.number().min(32).max(2048).default(512).describe("Image size in pixels"),
color: z.string().default("000000").describe("Foreground hex color"),
bg: z.string().default("ffffff").describe("Background hex color"),
ec: z.enum(["L", "M", "Q", "H"]).default("M").describe("Error correction level"),
margin: z.number().min(0).max(10).default(4).describe("Quiet zone in modules"),
},
async ({ data, format, size, color, bg, ec, margin }) => {
const params = new URLSearchParams({
data, format, size: String(size),
color, bg, ec, margin: String(margin),
});
const url = `https://qrgenapp.com/api/qr?${params}`;
if (format === "svg") {
const res = await fetch(url);
if (!res.ok) throw new Error(`API error: ${res.status}`);
const svg = await res.text();
return { content: [{ type: "text", text: svg }] };
}
// For PNG, return the URL so the client can display or download it
return {
content: [
{
type: "text",
text: `QR code generated: ${url}`,
},
],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);Save this as qr-mcp-server.js and run it with node qr-mcp-server.js. Any MCP-compatible client (Claude Desktop, Claude Code, etc.) can connect to it.
Example Prompts and Expected Behavior
When you give an LLM the QR code generation tool, it should handle prompts like these:
- "Generate a QR code for my WiFi network. SSID: HomeNet, Password: secret123, WPA2" — The LLM constructs the WiFi string
WIFI:T:WPA;S:HomeNet;P:secret123;;and calls the tool. - "Create a QR code for https://mywebsite.com with a red foreground" — The LLM passes
color: "ff0000"along with the URL. - "Make me a QR code for my email address hello@example.com" — The LLM encodes
mailto:hello@example.comas the data. - "I need a large, high-quality QR code for printing" — The LLM uses
size: 2048andec: "H".
Returning the Image to the User
There are several ways an LLM can present the generated QR code to a user:
URL (simplest)
Return the API URL directly. The user can open it in a browser or download it. This is stateless and requires no storage.
https://qrgenapp.com/api/qr?data=https://example.com&size=512Markdown Image Embed
In chat interfaces that render Markdown, the LLM can embed the image inline:
This renders the QR code directly in the conversation. The image is loaded from the API on-demand; nothing is stored.
Base64 Data URI
If the LLM has the ability to fetch URLs (via a tool), it can download the image and return it as a base64 data URI:
import base64, requests
resp = requests.get("https://qrgenapp.com/api/qr?data=https://example.com&size=256")
b64 = base64.b64encode(resp.content).decode()
data_uri = f"data:image/png;base64,{b64}"Save to File
Coding agents (like Claude Code or Codex) can save the file directly to disk:
curl "https://qrgenapp.com/api/qr?data=https://example.com" -o qr-code.pngSystem Prompt Snippet
Add this to your system prompt to give any LLM QR code generation capabilities, even without formal tool definitions:
You have access to a free QR code generation API. To generate a QR code,
construct a URL in this format:
https://qrgenapp.com/api/qr?data=ENCODED_DATA&size=512&format=png
Parameters:
- data (required): URL-encoded content to put in the QR code
- size: 32-2048 pixels (default 256)
- format: png, svg, or json
- color: hex foreground color without # (default 000000)
- bg: hex background color without # (default ffffff)
- ec: error correction L/M/Q/H (default M)
- margin: 0-10 modules of quiet zone (default 4)
For WiFi QR codes, encode data as: WIFI:T:WPA;S:NetworkName;P:Password;;
For email: mailto:user@example.com
For phone: tel:+15551234567
For SMS: sms:+15551234567?body=Hello
When the user asks for a QR code, construct the URL and display it using
Markdown image syntax: 
This API requires no authentication and supports CORS.Full API Reference
See the complete parameter list, response formats, and code examples in multiple languages.
API Docs