<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://blog.jztan.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.jztan.com/" rel="alternate" type="text/html" /><updated>2026-09-05T23:27:25+00:00</updated><id>https://blog.jztan.com/feed.xml</id><title type="html">Kevin Tan</title><subtitle>Thoughts on cloud architecture, AWS, and engineering leadership. By Kevin Tan, Cloud Solutions Architect &amp; Engineering Leader.</subtitle><author><name>Kevin Tan</name></author><entry><title type="html">How to Test and Debug a Python MCP Server</title><link href="https://blog.jztan.com/how-to-test-and-debug-a-python-mcp-server/" rel="alternate" type="text/html" title="How to Test and Debug a Python MCP Server" /><published>2026-09-05T21:00:00+00:00</published><updated>2026-09-05T21:00:00+00:00</updated><id>https://blog.jztan.com/how-to-test-and-debug-a-python-mcp-server</id><author><name>Kevin Tan</name></author><category term="mcp" /><category term="python" /><category term="ai-agents" /><category term="observability" /><summary type="html"><![CDATA[How to test and debug a Python MCP server: the Inspector, in-process pytest, the stdio traps that fail silently, and a CI job that catches regressions.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/mcp-server-test-debug.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/mcp-server-test-debug.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Claude Code Can’t Read Vertical Japanese PDFs: How I Fixed Tategaki Extraction</title><link href="https://blog.jztan.com/vertical-japanese-pdf-reading-order/" rel="alternate" type="text/html" title="Claude Code Can’t Read Vertical Japanese PDFs: How I Fixed Tategaki Extraction" /><published>2026-08-29T21:00:00+00:00</published><updated>2026-08-29T21:00:00+00:00</updated><id>https://blog.jztan.com/vertical-japanese-pdf-reading-order</id><author><name>Kevin Tan</name></author><category term="rag" /><category term="ai-agents" /><category term="llm" /><summary type="html"><![CDATA[Vertical Japanese PDFs extract as scrambled glyphs because reading order is not stored. Here is how I rebuilt tategaki order from glyph geometry, no OCR.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/vertical-japanese-pdf-reading-order.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/vertical-japanese-pdf-reading-order.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">WebMCP in Production: What I Shipped and What I Removed</title><link href="https://blog.jztan.com/webmcp-on-a-real-website/" rel="alternate" type="text/html" title="WebMCP in Production: What I Shipped and What I Removed" /><published>2026-08-22T21:00:00+00:00</published><updated>2026-08-22T21:00:00+00:00</updated><id>https://blog.jztan.com/webmcp-on-a-real-website</id><author><name>Kevin Tan</name></author><category term="ai-agents" /><category term="llm" /><category term="security" /><summary type="html"><![CDATA[I shipped six WebMCP tools on a live site, then removed three. On honeypots vs invited agents, spec gaps, and where agent-ready websites draw the line.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/webmcp-on-a-real-website.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/webmcp-on-a-real-website.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cross-Document RAG Without a Vector Database: SQLite + RRF</title><link href="https://blog.jztan.com/rag-without-vector-database/" rel="alternate" type="text/html" title="Cross-Document RAG Without a Vector Database: SQLite + RRF" /><published>2026-08-15T21:00:00+00:00</published><updated>2026-08-15T21:00:00+00:00</updated><id>https://blog.jztan.com/rag-without-vector-database</id><author><name>Kevin Tan</name></author><category term="rag" /><category term="ai-agents" /><category term="mcp" /><category term="llm" /><summary type="html"><![CDATA[Merging search results across 100 PDFs breaks quietly: BM25 scores aren't comparable between documents. How SQLite FTS5 plus RRF fixed it, with benchmarks.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/rag-without-vector-database-hero.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/rag-without-vector-database-hero.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Redmine MCP Server: Give AI Agents Live Project Data</title><link href="https://blog.jztan.com/redmine-mcp-server-for-ai-agents/" rel="alternate" type="text/html" title="Redmine MCP Server: Give AI Agents Live Project Data" /><published>2026-08-08T21:00:00+00:00</published><updated>2026-08-08T21:00:00+00:00</updated><id>https://blog.jztan.com/redmine-mcp-server-for-ai-agents</id><author><name>Kevin Tan</name></author><category term="mcp" /><category term="ai-agents" /><category term="llm" /><category term="production-systems" /><summary type="html"><![CDATA[Redmine holds your project data and your AI agent cannot see it. This open-source MCP server exposes 51 curated tools for issues, time tracking, and wiki.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/redmine-mcp-server-hero.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/redmine-mcp-server-hero.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Turn a Folder of PDFs Into an AI Agent Knowledge Base</title><link href="https://blog.jztan.com/ai-agent-pdf-knowledge-base/" rel="alternate" type="text/html" title="Turn a Folder of PDFs Into an AI Agent Knowledge Base" /><published>2026-08-01T21:00:00+00:00</published><updated>2026-08-22T13:00:00+00:00</updated><id>https://blog.jztan.com/ai-agent-pdf-knowledge-base</id><author><name>Kevin Tan</name></author><category term="mcp" /><category term="ai-agents" /><category term="rag" /><category term="llm" /><summary type="html"><![CDATA[Your AI agent does not need a vector database to search your PDFs. Turn any folder into a knowledge base with zero ingestion: warm, catalog, query, read.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/ai-agent-pdf-knowledge-base-hero.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/ai-agent-pdf-knowledge-base-hero.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">AI Agent Cloudflare 403: Two Libraries That Fix It and Cut Tokens 90%</title><link href="https://blog.jztan.com/ai-agent-web-fetch-403-and-token-fix/" rel="alternate" type="text/html" title="AI Agent Cloudflare 403: Two Libraries That Fix It and Cut Tokens 90%" /><published>2026-07-25T21:00:00+00:00</published><updated>2026-07-25T21:00:00+00:00</updated><id>https://blog.jztan.com/ai-agent-web-fetch-403-and-token-fix</id><author><name>Kevin Tan</name></author><category term="ai-agents" /><category term="llm" /><category term="blueclaw" /><category term="python" /><summary type="html"><![CDATA[Your AI agent's web tool returns 403 on Medium and burns tokens on HTML noise. Here's the two-library fix that solves both, with real trace numbers.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/ai-agent-cloudflare-bypass.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/ai-agent-cloudflare-bypass.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Why Multi-Column PDFs Scramble Reading Order in RAG</title><link href="https://blog.jztan.com/multi-column-pdf-reading-order/" rel="alternate" type="text/html" title="Why Multi-Column PDFs Scramble Reading Order in RAG" /><published>2026-07-18T21:00:00+00:00</published><updated>2026-07-18T21:00:00+00:00</updated><id>https://blog.jztan.com/multi-column-pdf-reading-order</id><author><name>Kevin Tan</name></author><category term="rag" /><category term="ai-agents" /><category term="llm" /><summary type="html"><![CDATA[Multi-column PDFs silently scramble reading order, poisoning the text your RAG pipeline searches and embeds. Here's the bug that renamed a paper's author.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/multi-column-pdf-reading-order.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/multi-column-pdf-reading-order.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to Evaluate LLM Agents: 5 Patterns That Catch Failures</title><link href="https://blog.jztan.com/how-to-evaluate-llm-agents/" rel="alternate" type="text/html" title="How to Evaluate LLM Agents: 5 Patterns That Catch Failures" /><published>2026-07-11T21:00:00+00:00</published><updated>2026-07-11T21:00:00+00:00</updated><id>https://blog.jztan.com/how-to-evaluate-llm-agents</id><author><name>Kevin Tan</name></author><category term="ai-agents" /><category term="llm" /><category term="observability" /><category term="blueclaw" /><summary type="html"><![CDATA[Most LLM agent eval shortcuts break on honesty-trained models. Five assertion patterns that survived production, when to use each, and how to derive your own.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/agent-eval-refusal.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/agent-eval-refusal.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">RAG for AI Agents: 6 Decisions That Make or Break Retrieval</title><link href="https://blog.jztan.com/rag-for-ai-agents-decision-guide/" rel="alternate" type="text/html" title="RAG for AI Agents: 6 Decisions That Make or Break Retrieval" /><published>2026-07-10T12:30:00+00:00</published><updated>2026-07-10T12:30:00+00:00</updated><id>https://blog.jztan.com/rag-for-ai-agents-decision-guide</id><author><name>Kevin Tan</name></author><category term="rag" /><category term="ai-agents" /><category term="llm" /><summary type="html"><![CDATA[Six decisions determine RAG quality for AI agents: search mode, fusion vs routing, chunk granularity, and more. Benchmark-backed defaults for each one.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jztan.com/assets/images/rag-for-ai-agents-decision-guide.webp" /><media:content medium="image" url="https://blog.jztan.com/assets/images/rag-for-ai-agents-decision-guide.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>