Skip to main content
Glama
burkeholland

VS Code MCP Button Generator

by burkeholland
index.ts6.44 kB
#!/usr/bin/env node import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { generateButtonsMarkdown, fromMcpConfigObject, generateCopilotInstallButtons, generateCopilotInstallButtonsFromGithub } from "./lib/buttons.js"; type Kind = 'chat-instructions' | 'chat-prompt' | 'chat-mode'; function printCliUsage() { console.error(`Usage: mcp-vsc-button-gen --kind <chat-instructions|chat-prompt|chat-mode> --raw <url> mcp-vsc-button-gen --kind <chat-instructions|chat-prompt|chat-mode> --owner <owner> --repo <repo> --path <path> [--branch <branch>] Examples: mcp-vsc-button-gen --kind chat-instructions --raw https://raw.githubusercontent.com/github/awesome-copilot/main/instructions/markdown.instructions.md mcp-vsc-button-gen --kind chat-prompt --owner github --repo awesome-copilot --path prompts/readme-blueprint-generator.prompt.md `); } function getArg(flag: string, argv: string[]): string | undefined { const idx = argv.indexOf(flag); if (idx !== -1 && idx + 1 < argv.length) return argv[idx + 1]; return undefined; } function hasFlag(flag: string, argv: string[]): boolean { return argv.includes(flag); } async function maybeHandleCli(argv: string[]): Promise<boolean> { if (hasFlag('--help', argv) || hasFlag('-h', argv)) { printCliUsage(); process.exit(0); } const kind = getArg('--kind', argv) as Kind | undefined; const raw = getArg('--raw', argv); const owner = getArg('--owner', argv); const repo = getArg('--repo', argv); const path = getArg('--path', argv); const branch = getArg('--branch', argv) ?? 'main'; const usingRaw = !!raw; const usingGh = !!(owner && repo && path); if (!kind || (!usingRaw && !usingGh) || (usingRaw && usingGh)) { // Not a valid CLI invocation; if some flags present, show usage and exit 1. if (kind || usingRaw || usingGh) { printCliUsage(); process.exit(1); } return false; // fall through to server mode } try { const md = usingRaw ? generateCopilotInstallButtons(kind, raw!) : generateCopilotInstallButtonsFromGithub(kind, owner!, repo!, path!, branch); console.log(md); process.exit(0); } catch (err) { console.error((err as Error).message || String(err)); process.exit(1); } return true; } // Types const InputSchema = z.object({ type: z.string(), // "promptString" supported for now id: z.string(), description: z.string().optional(), password: z.boolean().optional(), }); const ConfigSchema = z.object({ command: z.string().default("npx"), args: z.array(z.string()).default([]), env: z.record(z.string()).optional(), }); const MakeButtonsParams = z.object({ name: z.string().min(1, "name is required"), inputs: z.array(InputSchema).default([]), config: ConfigSchema.default({ command: "npx", args: [] }), }); function encode(value: unknown): string { return encodeURIComponent(JSON.stringify(value)); } // moved generation helpers to lib/buttons async function main() { // CLI mode: if args match, print buttons and exit early. const handled = await maybeHandleCli(process.argv.slice(2)); if (handled) return; const transport = new StdioServerTransport(); const server = new McpServer({ name: "mcp-vsc-button-gen", version: "0.1.0", }); server.registerTool( "make_install_buttons", { title: "Generate install buttons", description: "Generate VS Code Stable and Insiders MCP install button markdown for an NPX-based server.", inputSchema: { name: z.string().describe("Server display name (e.g., 'supabase')."), inputs: z.array(z.object({ type: z.string(), id: z.string(), description: z.string().optional(), password: z.boolean().optional(), })).default([]), config: z.object({ command: z.string().default("npx"), args: z.array(z.string()).default([]), env: z.record(z.string()).optional(), }).default({ command: "npx", args: [] }), } }, async ({ name, inputs, config }) => { const markdown = generateButtonsMarkdown(name, inputs, config); return { content: [{ type: "text", text: markdown }] }; } ); server.registerTool( "from_mcp_config", { title: "Buttons from MCP config", description: "Generate install buttons from a raw MCP JSON-like config object and a server name.", inputSchema: { name: z.string().describe("Server display name."), mcp: z.any(), } }, async ({ name, mcp }) => { const { inputs, config } = fromMcpConfigObject(name, mcp ?? {}); const markdown = generateButtonsMarkdown(name, inputs, config); return { content: [{ type: "text", text: markdown }] }; } ); // Awesome Copilot style buttons for Instructions/Prompts/Chat Modes server.registerTool( "copilot_buttons_from_raw", { title: "Copilot install buttons (raw URL)", description: "Generate VS Code install buttons for a raw URL to chat instructions, prompts, or chat modes.", inputSchema: { kind: z.enum(["chat-instructions", "chat-prompt", "chat-mode"]).describe("Install kind"), url: z.string().url().describe("Raw GitHub URL or any public raw URL to the file."), } }, async ({ kind, url }) => { const markdown = generateCopilotInstallButtons(kind, url); return { content: [{ type: "text", text: markdown }] }; } ); server.registerTool( "copilot_buttons_from_github", { title: "Copilot install buttons (GitHub)", description: "Generate VS Code install buttons for a GitHub file using owner/repo/path and optional branch.", inputSchema: { kind: z.enum(["chat-instructions", "chat-prompt", "chat-mode"]).describe("Install kind"), owner: z.string(), repo: z.string(), path: z.string().describe("Path within the repo"), branch: z.string().default("main"), } }, async ({ kind, owner, repo, path, branch }) => { const markdown = generateCopilotInstallButtonsFromGithub(kind, owner, repo, path, branch ?? 'main'); return { content: [{ type: "text", text: markdown }] }; } ); await server.connect(transport); } main().catch((err) => { console.error(err); process.exit(1); });

Implementation Reference

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/burkeholland/mcp-vsc-button-gen'

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