register_hook
Set up automated responses for secret changes in qring-mcp by executing shell commands, sending HTTP requests, or triggering process signals when secrets are updated, deleted, or rotated.
Instructions
Register a webhook/callback that fires when a secret is updated, deleted, or rotated. Supports shell commands, HTTP webhooks, and process signals.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Hook type | |
| key | No | Trigger on exact key match | |
| keyPattern | No | Trigger on key glob pattern (e.g. DB_*) | |
| tag | No | Trigger on secrets with this tag | |
| scope | No | Trigger only for this scope | |
| actions | No | Which actions trigger this hook | |
| command | No | Shell command to execute (for shell type) | |
| url | No | URL to POST to (for http type) | |
| signalTarget | No | Process name or PID (for signal type) | |
| signalName | No | Signal to send (for signal type) | SIGHUP |
| description | No | Human-readable description |
Implementation Reference
- src/core/hooks.ts:82-94 (handler)The 'registerHook' function handles adding a new hook entry to the registry (JSON file).
export function registerHook( entry: Omit<HookEntry, "id" | "createdAt">, ): HookEntry { const registry = loadRegistry(); const hook: HookEntry = { ...entry, id: randomUUID().slice(0, 8), createdAt: new Date().toISOString(), }; registry.hooks.push(hook); saveRegistry(registry); return hook; } - src/mcp/server.ts:916-955 (registration)The 'register_hook' MCP tool is registered here, which calls the 'registerHook' core function.
server.tool( "register_hook", "Register a webhook/callback that fires when a secret is updated, deleted, or rotated. Supports shell commands, HTTP webhooks, and process signals.", { type: z.enum(["shell", "http", "signal"]).describe("Hook type"), key: z.string().optional().describe("Trigger on exact key match"), keyPattern: z.string().optional().describe("Trigger on key glob pattern (e.g. DB_*)"), tag: z.string().optional().describe("Trigger on secrets with this tag"), scope: z.enum(["global", "project"]).optional().describe("Trigger only for this scope"), actions: z.array(z.enum(["write", "delete", "rotate"])).optional().default(["write", "delete", "rotate"]).describe("Which actions trigger this hook"), command: z.string().optional().describe("Shell command to execute (for shell type)"), url: z.string().optional().describe("URL to POST to (for http type)"), signalTarget: z.string().optional().describe("Process name or PID (for signal type)"), signalName: z.string().optional().default("SIGHUP").describe("Signal to send (for signal type)"), description: z.string().optional().describe("Human-readable description"), }, async (params) => { if (!params.key && !params.keyPattern && !params.tag) { return text("At least one match criterion required: key, keyPattern, or tag", true); } const entry = registerHook({ type: params.type as HookType, match: { key: params.key, keyPattern: params.keyPattern, tag: params.tag, scope: params.scope as "global" | "project" | undefined, action: params.actions as HookAction[], }, command: params.command, url: params.url, signal: params.signalTarget ? { target: params.signalTarget, signal: params.signalName } : undefined, description: params.description, enabled: true, }); return text(JSON.stringify(entry, null, 2)); }, );