Most developers have a "prompts.txt" file somewhere. It's usually a mess.
I wanted something better: a single source of truth for my best engineering prompts that I could access from anywhere—my terminal, my editor, or my AI chat app.
So I built the MCP Prompt Library, a standardized brain for AI interactions.
The "Three-Headed" Architecture
The core engineering challenge was building one system that works in three completely different contexts:
- As a Code Library:
npm install @esreekarreddy/ai-prompts - As a CLI Tool:
ai-lib get prd-generator - As an MCP Server: Connecting directly to Claude or Cursor.
To achieve this, I separated the "Brain" from the "Body".
The Brain (src/lib/Library.ts):
This class knows nothing about servers or consoles. It scans the file system, parses frontmatter using gray-matter, indexes tags, and runs fuzzy searches. It's pure logic.
The Bodies:
src/cli.ts: Wraps the Brain in acommanderinterface for the terminal.src/server.ts: Wraps the Brain in anMcpServerinstance for the protocol.
This separation means I can add a new feature (like "Smart Suggest") to the library, and it immediately works in both the terminal and Cursor.
Understanding MCP (Model Context Protocol)
MCP is a game-changer because it standardizes how AI tools ask for help. Instead of hardcoding "read file" logic into every app, the app just asks the MCP server: "What tools do you have?"
Here is the actual registration code from src/server.ts:
// server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
// 1. Create the server
const server = new McpServer({
name: "ai-library",
version: "1.0.0",
});
// 2. Register a tool
server.tool(
"get_prompt",
"Fetch a prompt by name (fuzzy matching works)",
{ name: z.string() },
async ({ name }) => {
// The server just delegates to the library "brain"
const item = library.getItem(name);
return toolSuccess(item.body);
},
);
Because of this standard, I didn't have to write a plugin for VS Code, and another for Claude, and another for Zee. I just wrote one MCP server, and it works everywhere.
Feature Spotlight: Smart Intent Detection
The coolest feature isn't just "getting" prompts—it's having the AI predict what you need.
I built a tool called enhance_prompt (src/tools/library.ts) that analyzes your raw request. If you say "I need to fix this bug," it doesn't just read the code. It:
- Detects the intent:
fix_bug - Loads the
deep-debuggerprompt framework. - Injects the
systematic-debuggingskill. - Returns a structured plan: Hypothesize → Verify → Fix.
This prevents "AI Slop"—lazy, meandering answers. The system forces the AI into a structured engineering workflow before it answers a single question.
Deep Dive: The Suggestion Engine
I didn't use an LLM for intent detection. I used a deterministic scoring algorithm.
Why? Speed. An LLM call takes 500ms+. My algorithm takes 2ms.
Here is the actual scoring logic from src/lib/library.ts:
// Calculate confidence score
const confidence = Math.min(
0.9,
0.3 + matchedKeywords.length * 0.2 + pattern.priority * 0.03,
);
It relies on three factors:
- Base Score (0.3): Every match starts with valid intent.
- Keyword Density (0.2): "fix bug" is better than just "bug".
- Heuristic Priority (0.03): "Security" patterns rank higher than "General".
This means enhance_prompt("fix critical security bug") will always outrank enhance_prompt("fix bug") because the keyword density is higher. It is predictable, testable, and instant.
Workflow Chains
For complex tasks like "New Feature" or "Security Hardening," a single prompt isn't enough.
I implemented a State Machine in src/lib/chains.ts. It manages multi-step interactions:
- Start:
start_chain("new-feature")→ Creates a session. - Step 1: "Draft PRD" (Waits for user input).
- Step 2: "Review Architecture" (Auto-loads context).
- Step 3: "Generate Tests".
The state persists in memory, allowing you to have a continuous, guided "pair programming" session that follows a strict quality standard.
What I Learned
Tools should meet you where you are.
Sometimes I'm in the terminal (ai-lib get git-commit). Sometimes I'm in Cursor (@Start New Feature Chain). By building a hybrid architecture, I didn't have to choose.
Structured prompts > Conversational drifting. The biggest productivity boost came from constraining the AI. By forcing it to use the "Architecture Review" template, I stop it from writing code before it understands the system.
Deep Dive: The "Zero-Dep" CLI
Most CLI tools use heavy frameworks like Oclif or Commander. They add 50ms to startup time. That sounds small, but for a tool you use 100 times a day, it adds up.
I built the CLI (src/cli.ts) with zero runtime dependencies for argument parsing.
// src/cli.ts
const args = process.argv.slice(2);
const command = args[0];
const commandArgs = args.slice(1);
switch (command) {
case "get":
await cmdGet(library, commandArgs);
break;
case "search":
await cmdSearch(library, commandArgs);
break;
// ...
}
It parses flags manually. It creates no extra objects. It boots instantly.
By sharing the same Library class as the MCP server, the CLI is just a thin, 500-line wrapper around the core logic. It has no "business logic" of its own—it just formats the output for the terminal.
Resources
Leave a Comment
Comments (0)
Be the first to comment on this post.
Comments are approved automatically.