<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: J “jpLondon20” PLondon</title>
    <description>The latest articles on DEV Community by J “jpLondon20” PLondon (@j_jplondon20plondon_a9).</description>
    <link>https://dev.to/j_jplondon20plondon_a9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1873857%2F507e42d2-fc33-4c0d-ae90-d93a7509b778.png</url>
      <title>DEV Community: J “jpLondon20” PLondon</title>
      <link>https://dev.to/j_jplondon20plondon_a9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/j_jplondon20plondon_a9"/>
    <language>en</language>
    <item>
      <title>Building a Jira MCP server in TS</title>
      <dc:creator>J “jpLondon20” PLondon</dc:creator>
      <pubDate>Mon, 15 Jun 2026 21:27:29 +0000</pubDate>
      <link>https://dev.to/j_jplondon20plondon_a9/building-a-jira-mcp-server-in-ts-444f</link>
      <guid>https://dev.to/j_jplondon20plondon_a9/building-a-jira-mcp-server-in-ts-444f</guid>
      <description>&lt;h1&gt;
  
  
  LinkedIn Post — Jira MCP Server
&lt;/h1&gt;




&lt;p&gt;I built a Jira MCP server from scratch this week — starting from a Jira agent wrapped with a React UI, then pushed further. I wanted something reusable across any project, not just a one-off tool. Now I have my Jira MCP server creating tickets for itself — and my portfolio React 19 upgrade is fully tracked in Jira too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4958be1jt404pou6f4h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4958be1jt404pou6f4h.png" alt=" " width="799" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This taught me more about AI tooling than any tutorial ever could.&lt;/p&gt;

&lt;p&gt;As a mid-level frontend engineer, I've been deliberately pushing myself into AI integration territory. Not because it's trendy, but because the market is cutting pure UI roles and I want to be the developer who bridges both worlds.&lt;/p&gt;

&lt;p&gt;Here's what I built and what I learned:&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What is an MCP server?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MCP (Model Context Protocol) is an open standard that lets you expose tools to any AI client — Claude in VS Code, Claude Desktop, Cursor — without rewriting your integration for each one.&lt;/p&gt;

&lt;p&gt;The architecture is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLM (the brain) decides which tools to call&lt;/li&gt;
&lt;li&gt;MCP Client (built into VS Code) is the waiter — passes requests and responses&lt;/li&gt;
&lt;li&gt;MCP Server (what I built) is the kitchen — executes the actual work&lt;/li&gt;
&lt;li&gt;Jira REST API is the data source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: &lt;strong&gt;the MCP server has zero AI logic&lt;/strong&gt;. It just registers tools, executes them when called, and returns results. Claude does all the thinking.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What I built&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;jira-mcp&lt;/code&gt; server in TypeScript with four tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;search_jira_issues&lt;/code&gt; — JQL search across my Jira projects&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_jira_issue&lt;/code&gt; — fetch a single issue by key (e.g. AI-1)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create_jira_issue&lt;/code&gt; — create epics, stories, tasks with optional description&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_jira_issue&lt;/code&gt; — add comments or transition issue status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each tool is registered using the &lt;code&gt;@modelcontextprotocol/sdk&lt;/code&gt; with Zod for schema validation — which replaces hand-written JSON input schemas and gives full TypeScript type safety automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq3ooaa2mng2rpw660ezi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq3ooaa2mng2rpw660ezi.png" alt=" " width="799" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5e6raqn94qa2kp0uphu.png" alt=" " width="473" height="238"&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Things that tripped me up (and what I learned)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jira's deprecated search endpoint&lt;/strong&gt; — I was hitting &lt;code&gt;/rest/api/3/issue/search&lt;/code&gt; which has been removed. The new endpoint is &lt;code&gt;/rest/api/3/search/jql&lt;/code&gt; and it uses POST with the JQL in the body, not query params. Always check the API changelog: &lt;a href="https://developer.atlassian.com/changelog/#CHANGE-2046" rel="noopener noreferrer"&gt;https://developer.atlassian.com/changelog/#CHANGE-2046&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MCP return format&lt;/strong&gt; — you can't return a plain object. MCP requires &lt;code&gt;{ content: [{ type: "text", text: string }] }&lt;/code&gt;. Everything is serialized to a string because the LLM reads it as text over the wire.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jira transitions&lt;/strong&gt; — you can't set a status directly by name. You fetch the available transitions for an issue first, find the matching one, then POST its ID. Small detail, big debugging session if you don't know it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optional fields in request bodies&lt;/strong&gt; — used &lt;code&gt;...(value &amp;amp;&amp;amp; { key: value })&lt;/code&gt; to conditionally spread optional fields like &lt;code&gt;description&lt;/code&gt; without messy if/else blocks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;StdioServerTransport&lt;/strong&gt; — VS Code doesn't connect to your MCP server over HTTP. It spawns it as a child process and communicates through stdin/stdout. No server port, no HTTP — just pipes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript + &lt;code&gt;tsx&lt;/code&gt; (no compile step)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@modelcontextprotocol/sdk&lt;/code&gt; for tool registration and transport&lt;/li&gt;
&lt;li&gt;Zod for input schema validation&lt;/li&gt;
&lt;li&gt;Jira REST API v3&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dotenv&lt;/code&gt; for credentials&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Why this matters for my career&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most frontend engineers can build a UI. Far fewer can explain how an agentic loop works, build a protocol-compliant tool server, or debug a Jira API deprecation by reading changelogs.&lt;/p&gt;

&lt;p&gt;This project sits at the intersection of frontend engineering, API integration, and AI tooling — exactly where I want to be.&lt;/p&gt;

&lt;p&gt;If you're a frontend engineer wondering where to go next, I'd strongly recommend getting hands-on with MCP. The learning curve is low, the differentiation is high.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs35gshcfcs06fqq2lc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs35gshcfcs06fqq2lc6.png" alt=" " width="586" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built as part of my AI tooling portfolio. Next up: wiring this MCP server into a full agentic triage flow so Claude can plan Jira sprints from a plain English requirements doc.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  TypeScript #MCP #AIEngineering #Jira #ClaudeAI #SoftwareEngineering #FrontendDevelopment #AITooling
&lt;/h1&gt;

</description>
      <category>mcp</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
