<?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: lucas noah</title>
    <description>The latest articles on DEV Community by lucas noah (@lucas_noah_31e58c33025074).</description>
    <link>https://dev.to/lucas_noah_31e58c33025074</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%2F3801747%2F7ccf0353-a8a2-4904-9050-03108df9777f.png</url>
      <title>DEV Community: lucas noah</title>
      <link>https://dev.to/lucas_noah_31e58c33025074</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucas_noah_31e58c33025074"/>
    <language>en</language>
    <item>
      <title>Building an MCP Server for a Niche Local Service: Philadelphia Restoration</title>
      <dc:creator>lucas noah</dc:creator>
      <pubDate>Mon, 02 Mar 2026 13:08:34 +0000</pubDate>
      <link>https://dev.to/lucas_noah_31e58c33025074/building-an-mcp-server-for-a-niche-local-service-philadelphia-restoration-4a3e</link>
      <guid>https://dev.to/lucas_noah_31e58c33025074/building-an-mcp-server-for-a-niche-local-service-philadelphia-restoration-4a3e</guid>
      <description>&lt;h1&gt;
  
  
  Building an MCP Server for a Niche Local Service: Philadelphia Restoration
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;How we built a Model Context Protocol server to make Philadelphia's water and fire damage restoration expertise available to every AI agent.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Build an MCP Server for a Local Service?
&lt;/h2&gt;

&lt;p&gt;Most MCP servers expose general-purpose tools — file systems, databases, code interpreters. We built one for a very specific use case: helping Philadelphia homeowners deal with water and fire damage.&lt;/p&gt;

&lt;p&gt;Philadelphia Restoration started as a concierge service connecting homeowners with vetted restoration professionals. We had a REST API with 7 tools covering damage assessment, insurance coverage analysis, cost estimation, emergency guidance, neighborhood-specific risk profiles, a deep knowledge base, and professional callback scheduling.&lt;/p&gt;

&lt;p&gt;The question was: how do we make this expertise accessible to AI agents — Claude, ChatGPT, LangChain agents, custom assistants — so they can help homeowners directly during conversations?&lt;/p&gt;

&lt;p&gt;The answer: MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: Go + mcp-go, Dual-Port, Single Binary
&lt;/h2&gt;

&lt;p&gt;We chose Go for the MCP server because our REST API was already written in Go. The &lt;a href="https://github.com/mark3labs/mcp-go" rel="noopener noreferrer"&gt;&lt;code&gt;mark3labs/mcp-go&lt;/code&gt;&lt;/a&gt; library made it straightforward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Binary, Two Ports
&lt;/h3&gt;

&lt;p&gt;Our API binary serves both REST and MCP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Port 8080&lt;/strong&gt;: REST API (existing)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port 8081&lt;/strong&gt;: MCP server (new)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both share the same store, embedder, and notification services. This keeps deployment simple — one container, one process, two protocols.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Create MCP server sharing the same dependencies&lt;/span&gt;
&lt;span class="n"&gt;mcpSrv&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mcpserver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMCPServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;discordNotifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;httpSrv&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStreamableHTTPServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mcpSrv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithStateLess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use stateless mode (&lt;code&gt;WithStateLess(true)&lt;/code&gt;) because our tools are request/response — no session state needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Proxy Pattern: MCP Tools Delegate to REST Handlers
&lt;/h3&gt;

&lt;p&gt;The key architectural decision was how MCP tool handlers relate to REST handlers. We had two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate logic&lt;/strong&gt; — write separate MCP handlers with the same business logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy pattern&lt;/strong&gt; — MCP handlers call REST handlers internally&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We chose the proxy pattern. Each MCP tool handler marshals its arguments as a JSON body, creates an &lt;code&gt;httptest.Request&lt;/code&gt;, calls the existing REST handler, and returns the response as MCP text content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;makeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToolHandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CallToolRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CallToolResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;httpReq&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;httptest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;httpReq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;httptest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRecorder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpReq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewToolResultText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we maintain business logic in exactly one place. When we update a REST handler, the MCP tool automatically gets the same update.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool Design: Optimized for Registry Search
&lt;/h2&gt;

&lt;p&gt;MCP tool descriptions matter — they're how registries and agents decide whether to use your tools. We optimized ours to be specific and searchable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; (generic):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Assess damage and return results"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt; (registry-optimized):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Returns structured damage assessment for water and fire damage in Philadelphia residential properties. Classifies 13 damage types (burst pipe, roof leak, sewage backup, flooding, appliance leak, structural fire, kitchen fire, electrical fire, smoke damage, arson, and more) with severity grading, immediate safety steps, timeline risks, cost estimates, and Philadelphia-specific context including rowhouse and pre-1978 home considerations."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Key principles for tool descriptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Be specific about data returned&lt;/strong&gt; — not just "assess damage" but what the assessment includes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State geographic focus&lt;/strong&gt; — "Philadelphia residential properties"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List concrete values&lt;/strong&gt; — "13 damage types", "$64–$183/hr"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include keywords&lt;/strong&gt; — the damage types, standards (IICRC), policy types (HO-3)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reasoning Kits: Structured Data for AI Agents
&lt;/h2&gt;

&lt;p&gt;Every tool returns a "reasoning kit" — structured data designed for an AI agent to reason over, not just pass through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_instructions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Present severity assessment first..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"related_tools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"check_insurance_coverage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"estimate_cost"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_sources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"IICRC S500 §12.3"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Connect with a vetted restoration professional"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"request_callback"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;_meta.reasoning_instructions&lt;/code&gt; field tells the agent how to interpret and present the data. The &lt;code&gt;related_tools&lt;/code&gt; array creates natural workflow chains. Sources provide attribution for IICRC standards and other references.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow Specification: Arazzo 1.0.1
&lt;/h2&gt;

&lt;p&gt;We publish an &lt;a href="https://spec.openapis.org/arazzo/latest.html" rel="noopener noreferrer"&gt;Arazzo&lt;/a&gt; workflow specification describing optimal tool sequences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;workflowId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;primary-damage-assessment&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stepId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assess&lt;/span&gt;
        &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assessDamage&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stepId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;insurance&lt;/span&gt;
        &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;checkInsuranceCoverage&lt;/span&gt;
        &lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;damage_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$steps.assess.outputs.damage_type&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stepId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;costs&lt;/span&gt;
        &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;estimateCost&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stepId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;knowledge&lt;/span&gt;
        &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;searchRestorationKnowledge&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stepId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;callback&lt;/span&gt;
        &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;requestCallback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data flows between steps via runtime expressions — the damage type from the assessment step feeds into insurance, cost, and knowledge searches automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Discovery: Meeting Agents Where They Are
&lt;/h2&gt;

&lt;p&gt;We publish discovery files so agents can find us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/.well-known/mcp.json&lt;/code&gt; — MCP server manifest&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/.well-known/agent.json&lt;/code&gt; — Agent discovery (v2.0.0 with transports)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/.well-known/ai-plugin.json&lt;/code&gt; — ChatGPT plugin manifest&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/openapi.yaml&lt;/code&gt; — OpenAPI 3.1 specification&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/arazzo.yaml&lt;/code&gt; — Workflow specification&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/llms.txt&lt;/code&gt; — LLM-optimized site summary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each file serves a different discovery channel, but they all point to the same 7 tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring: Understanding Agent Behavior
&lt;/h2&gt;

&lt;p&gt;We track tool usage with Prometheus metrics and a custom dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool calls by type and transport (REST vs MCP)&lt;/li&gt;
&lt;li&gt;Agent identification from User-Agent strings (Claude, ChatGPT, LangChain, etc.)&lt;/li&gt;
&lt;li&gt;Knowledge search analytics (query patterns, zero-result rate)&lt;/li&gt;
&lt;li&gt;Conversion tracking (tool calls → callback requests)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets us understand how agents actually use our tools and where to improve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The proxy pattern works well&lt;/strong&gt; for adding MCP to existing REST services. Zero business logic duplication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tool descriptions are marketing copy&lt;/strong&gt; for AI registries. Spend time on them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stateless transport simplifies everything&lt;/strong&gt; — no session management, no reconnection logic, each request stands alone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reasoning kits beat raw data&lt;/strong&gt; — &lt;code&gt;_meta.reasoning_instructions&lt;/code&gt; and &lt;code&gt;related_tools&lt;/code&gt; help agents chain tools effectively without hardcoded workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple discovery channels matter&lt;/strong&gt; — different agents discover tools through different mechanisms. Publish everywhere.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Connect to our MCP server — no auth, no signup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server: mcp.philadelphiarestoration.org
Transport: Streamable HTTP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philadelphiarestoration.org/developers" rel="noopener noreferrer"&gt;Developer Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/phillyrestore/mcp-client-example" rel="noopener noreferrer"&gt;Example Code (Python + TypeScript)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philadelphiarestoration.org/openapi.yaml" rel="noopener noreferrer"&gt;OpenAPI Spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://philadelphiarestoration.org/arazzo.yaml" rel="noopener noreferrer"&gt;Arazzo Workflows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Philadelphia Restoration is a free concierge service for Philadelphia homeowners dealing with water and fire damage. Our knowledge base is grounded in IICRC S500/S520/S540 standards and real restoration company experience.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>api</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
