AI · · 3 min read · Updated
Building Custom MCP Servers in TypeScript for Cursor
How to build a custom Model Context Protocol (MCP) server in TypeScript and wire it into multi-step Vercel AI SDK and Markdown publishing workflows.
Zayne Lovecraft
Software Engineer III

Out of the box, coding agents in Cursor and Claude Code can read files and run shell commands. Where they become exponentially more useful is when you give them domain-specific tools via the Model Context Protocol (MCP)—so turning external knowledge into shippable code or content happens in a single tool call.
Here is how I built three small open-source tools—yt-skill-mcp (case study), ai-content-workflow, and md-cover—and how they fit together inside an agent workflow.
1. Anatomy of a stdio MCP server (yt-skill-mcp)
Whenever I watch a great conference talk or deep-dive tutorial on YouTube, I want the architectural checklist saved as a reusable .cursor/skills/<slug>/SKILL.md file inside my Agent OS workspace.
Instead of copying transcripts by hand, yt-skill-mcp exposes two MCP tools over stdio using @modelcontextprotocol/sdk:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { buildSkillMarkdown, fetchTranscript } from "./transcript.js";
const server = new Server(
{ name: "yt-skill-mcp", version: "0.1.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "fetch_youtube_transcript",
description: "Fetch timestamped transcript segments from a YouTube URL or video ID.",
inputSchema: {
type: "object",
properties: {
url: { type: "string", description: "YouTube watch URL, youtu.be link, or 11-char ID" },
},
required: ["url"],
},
},
{
name: "compile_cursor_skill",
description: "Format extracted video frameworks into a Cursor Agent SKILL.md file.",
inputSchema: {
type: "object",
properties: {
skillName: { type: "string" },
description: { type: "string" },
videoId: { type: "string" },
title: { type: "string" },
steps: { type: "array", items: { type: "string" } },
},
required: ["skillName", "description", "videoId", "title", "steps"],
},
},
],
}));
Once registered in .cursor/mcp.json, dropping a YouTube URL into Cursor lets the agent pull the timestamped transcript ([141s] ...), extract the engineering rules, and write .cursor/skills/<name>/SKILL.md in seconds.
2. Schema-enforced editorial pipelines (ai-content-workflow)
When you move from interactive editor tools to automated publishing (like the multi-site pipeline I built for SynthPress), a single LLM prompt isn't enough. One-shot prompts produce generic prose and miss metadata constraints like 65-character title limits.
In ai-content-workflow, I open-sourced the three-stage pattern I use with the Vercel AI SDK (generateObject + generateText) and Zod:
| Stage | Function | Guardrail |
|---|---|---|
| 1. Brief | planArticleBrief() | Zod-enforced title (20–65 chars), meta description (80–160 chars), section outline, and FAQ schema |
| 2. Draft | draftArticleMarkdown() | Grounded technical prose with strict anti-filler system constraints |
| 3. Critic | verifyArticleQuality() | Structured quality gate that flags generic AI phrases and scores 0–100 before publish |
export const QualityGateSchema = z.object({
passed: z.boolean(),
score: z.number().min(0).max(100),
aiSlopDetected: z.array(z.string()),
missingEntities: z.array(z.string()),
revisedMetaDescription: z.string().optional(),
});
Separating the writer from the critic catches weak intros and missing technical specifics before a human ever reviews the draft.
3. Closing the last mile with md-cover
Even if an agent writes clean Markdown, publishing a blog post usually stalls on assets: finding a landscape photo, cropping it to Open Graph dimensions, saving it to public/blog/<slug>/cover.jpg, and crediting the photographer in the frontmatter.
I extracted the script that powers this blog into md-cover:
npx github:zaynelovecraft/md-cover building-custom-mcp-servers "server racks data center"
In one command, it queries the Pexels API, downloads a 1600×840 cropped JPEG, and writes cover, coverAlt, coverCredit, and coverSourceUrl straight into the Markdown frontmatter using gray-matter.
Takeaway
The best AI developer tools do one narrow job deterministically and expose clean inputs and outputs so an agent can chain them together. Check out the source for yt-skill-mcp, ai-content-workflow, and md-cover on GitHub—or read how I audit the finished pages in Generative Engine Optimization (GEO) & CWV Gates in Next.js.
- MCP
- TypeScript
- Cursor
- AI SDK
- AI Automation
Keep reading

AI · · 7 min read
Top 10 AI Tools to Build With Today (and How to Use Them)
The 10 AI tools I actually build with, from Cursor and Claude to the AI SDK, Vercel Workflow, and MCP, and how they fit into real automation pipelines.

Technical SEO · · 2 min read
Generative Engine Optimization (GEO) & CWV Gates in Next.js
How to audit Next.js apps for AI search citations (JSON-LD entity graphs, llms.txt, bot rules) and enforce Core Web Vitals client bundle budgets in CI.