<?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: Harshal Limaye</title>
    <description>The latest articles on DEV Community by Harshal Limaye (@harshallimaye).</description>
    <link>https://dev.to/harshallimaye</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F966610%2Ffc3f1b6b-010f-4f21-9e7d-e23d3b1d508a.jpg</url>
      <title>DEV Community: Harshal Limaye</title>
      <link>https://dev.to/harshallimaye</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshallimaye"/>
    <language>en</language>
    <item>
      <title>I got tired of vibe-testing my MCP servers, so I built a Bruno-style client for MCP</title>
      <dc:creator>Harshal Limaye</dc:creator>
      <pubDate>Tue, 14 Jul 2026 02:25:18 +0000</pubDate>
      <link>https://dev.to/harshallimaye/i-got-tired-of-vibe-testing-my-mcp-servers-so-i-built-a-bruno-style-client-for-mcp-fhd</link>
      <guid>https://dev.to/harshallimaye/i-got-tired-of-vibe-testing-my-mcp-servers-so-i-built-a-bruno-style-client-for-mcp-fhd</guid>
      <description>&lt;p&gt;I've been writing MCP servers for a few months now, and most of that time was spent staring at JSON. Hand-writing request payloads, eyeballing responses, mentally diffing nested objects to check if a tool call actually worked. My "testing" wasn't much better: point an LLM at the server, ask it to try some tool calls, read the vibes.&lt;/p&gt;

&lt;p&gt;That's not testing. That's hoping.&lt;/p&gt;

&lt;p&gt;Here's the thing — LLMs are non-deterministic by design. Your protocol layer isn't supposed to be. If your tool returns the wrong shape, a missing field, or a broken error response, you don't need a model's opinion about it. You need a failing assertion.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9s923kht1hejp51s4pkq.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9s923kht1hejp51s4pkq.png" alt="MCPFlo showing a passing assertion test against an MCP tool response" width="799" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;a href="https://mcpflo.com" rel="noopener noreferrer"&gt;MCPFlo&lt;/a&gt;&lt;/strong&gt; — an offline-first, open-source, MIT-licensed Electron app for testing and debugging MCP servers. The core idea is boring on purpose: deterministic assertions against real protocol responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it passes, it passes every time. If it fails, you know exactly where. No vibes involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Chai.js-style assertions against real tool responses. Write &lt;code&gt;expect().to.equal()&lt;/code&gt; tests for your tools, resources, and prompts. Run them against the actual server, not a mock.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto-generated forms from your schemas. MCPFlo renders your tool's input schema as a proper form — including nested objects and arrays — via RJSF. Stop hand-writing JSON payloads for every tool call. If your schema is deep and ugly, that's exactly when this matters most.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Token budget visualizer. See what your tools, resources, and prompts actually cost against different model context windows — before you find out the expensive way. An MCP server with 40 verbose tool descriptions is quietly eating someone's context budget. Now you can see it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OAuth 2.1 support, so you can test servers that actually require auth instead of stripping it out for local dev.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fully offline. No telemetry, no cloud dependency, no login, no server-side anything. Your requests and test data live on your machine as git-friendly JSON.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it deliberately doesn't do
&lt;/h2&gt;

&lt;p&gt;MCPFlo won't tell you whether an LLM uses your tools well — whether your descriptions are clear enough for a model to pick the right tool at the right time. That's behavioral evaluation, and it's a different layer of the stack. MCPFlo covers the layer below it: does your server actually do what the protocol says it does?&lt;/p&gt;

&lt;p&gt;Both layers matter. This tool is for the deterministic one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part
&lt;/h2&gt;

&lt;p&gt;It's early. There are rough edges. I'd rather ship it and get real feedback than keep polishing in private.&lt;/p&gt;

&lt;p&gt;If you're building or maintaining MCP servers, I'd genuinely like to know: is this useful, or am I solving a problem nobody has?&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/harshalslimaye/mcpflo" rel="noopener noreferrer"&gt;github.com/harshalslimaye/mcpflo&lt;/a&gt;&lt;br&gt;
Site: &lt;a href="https://mcpflo.com/" rel="noopener noreferrer"&gt;mcpflo.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions or get roasted in the comments.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>opensource</category>
      <category>claude</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>How to use APP_INITIALIZER token in Angular</title>
      <dc:creator>Harshal Limaye</dc:creator>
      <pubDate>Wed, 28 Dec 2022 03:28:12 +0000</pubDate>
      <link>https://dev.to/harshallimaye/how-to-use-appinitializer-token-in-angular-422f</link>
      <guid>https://dev.to/harshallimaye/how-to-use-appinitializer-token-in-angular-422f</guid>
      <description>&lt;p&gt;APP_INITIALIZER is a powerful feature in Angular that allows developers to perform tasks before the application starts. It is essentially a way to run code during the bootstrapping process of an Angular app. One common use case for APP_INITIALIZER is to load configuration data from a server or a local file. This data is often required for the application to function properly, and it is important to have it available as soon as possible.&lt;/p&gt;

&lt;p&gt;To use APP_INITIALIZER, you need to import the APP_INITIALIZER token from the @angular/core module and use it to provide a factory function. This factory function should return a Promise that resolves when the initialization is complete.&lt;/p&gt;

&lt;p&gt;Let's understand this in detail using an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APP_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClientModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;HttpClientModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APP_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;useFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;multi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the loadConfig function uses the HttpClient to make a request to a server to retrieve the configuration data. The function returns a Promise that resolves when the data has been retrieved.&lt;/p&gt;

&lt;p&gt;It is important to note that the APP_INITIALIZER factory function should be marked as multi: true, as this allows multiple initializers to be run. If you do not mark the factory function as multi: true, only the last initializer registered will be run.&lt;/p&gt;

&lt;p&gt;And that's it! I hope you found this post useful. Incase you have any questions or queries, feel free to drop a comment.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>career</category>
      <category>productivity</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>How to Create a Custom Assets Folder in Angular</title>
      <dc:creator>Harshal Limaye</dc:creator>
      <pubDate>Wed, 09 Nov 2022 16:07:37 +0000</pubDate>
      <link>https://dev.to/harshallimaye/how-to-create-a-custom-assets-folder-in-angular-1dbl</link>
      <guid>https://dev.to/harshallimaye/how-to-create-a-custom-assets-folder-in-angular-1dbl</guid>
      <description>&lt;p&gt;Every Angular app generated with &lt;a href="https://angular.io/cli" rel="noopener noreferrer"&gt;@angular/cli&lt;/a&gt; comes bundled with an &lt;em&gt;assets&lt;/em&gt; folder located inside the &lt;em&gt;src&lt;/em&gt; directory. And any file or folder created inside the &lt;em&gt;assets&lt;/em&gt; folder becomes publicly accessible. However, your options are not limited to this folder. You can easily create more &lt;em&gt;assets&lt;/em&gt; like folders by adding their paths in the &lt;em&gt;angular.json&lt;/em&gt; file. Let's understand this in detail with an example.&lt;/p&gt;

&lt;p&gt;Let's say I want to create another folder inside &lt;em&gt;src&lt;/em&gt; directory called &lt;strong&gt;users&lt;/strong&gt; and add following json file to this folder.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rambo_was_real"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"occupation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mall Santa"&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;We'll name the file &lt;code&gt;profile.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you've created the folder and added the file, you need to make Angular aware of this folder.&lt;/p&gt;

&lt;p&gt;This can be done by simply dropping following line of code in your &lt;em&gt;angular.json&lt;/em&gt; file under the &lt;em&gt;assets&lt;/em&gt; array key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0k9jw0sh9v7p0cd5m9zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0k9jw0sh9v7p0cd5m9zz.png" alt="Assets option inside angular.json" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! After doing this you can simply restart your Angular application and try to access the file via the web browser. If you've done everything as expected, you'll see following output in the web browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjl7xh5j3b5tls0zn8d1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjl7xh5j3b5tls0zn8d1u.png" alt="Accessing custom assets folder via web browser" width="582" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also query the &lt;em&gt;profile.json&lt;/em&gt; file using the HttpClient Service.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/profile.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I hope you enjoyed this post. In case you've any queries or feedback, feel free to drop a comment or reach out to me on Twitter &lt;a href="https://twitter.com/harshalslimaye" rel="noopener noreferrer"&gt;@harshalslimaye&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, I would like to recommend another article I've written which talks about the technique called &lt;a href="https://harshal.dev/how-to-implement-virtual-scroll-in-angular" rel="noopener noreferrer"&gt;Virtual Scrolling in Angular&lt;/a&gt; which allows the developers to display subset of large lists within small viewports and change the subset data as user continues to scroll through the list.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
