<?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: Dialog Brain</title>
    <description>The latest articles on DEV Community by Dialog Brain (@dialogbrain).</description>
    <link>https://dev.to/dialogbrain</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%2F4104153%2Fd605cd82-26c7-48fe-aabd-1f01469fc643.png</url>
      <title>DEV Community: Dialog Brain</title>
      <link>https://dev.to/dialogbrain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dialogbrain"/>
    <language>en</language>
    <item>
      <title>How to publish an MCP server in the Claude connectors directory</title>
      <dc:creator>Dialog Brain</dc:creator>
      <pubDate>Thu, 15 Oct 2026 07:58:41 +0000</pubDate>
      <link>https://dev.to/dialogbrain/how-to-publish-an-mcp-server-in-the-claude-connectors-directory-2oek</link>
      <guid>https://dev.to/dialogbrain/how-to-publish-an-mcp-server-in-the-claude-connectors-directory-2oek</guid>
      <description>&lt;p&gt;&lt;em&gt;On 30 September 2026 we submitted DialogBrain to Anthropic's connectors directory and it went live the same day. This is what the portal asks for, which rules quietly hold a submission, and why running every one of your own tools before you submit is the step that actually pays.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a listing is, and what it is not
&lt;/h2&gt;

&lt;p&gt;A connector listing puts your remote MCP server in the directory people browse inside Claude. They add it in one click, sign in with your OAuth, and your tools are in their conversation. It is not a plugin: a plugin is a bundle of skills and configuration that comes from a GitHub repository and is a separate submission. If you have both, you submit both.&lt;/p&gt;

&lt;p&gt;The listing is published as a Community connector by default. An automated policy scan runs first; some submissions also get a human reviewer. Ours went from submitted to approved to published inside a day, but the portal says review can take weeks, so do not plan a launch around a date.&lt;/p&gt;

&lt;p&gt;Everything below follows the portal at &lt;a href="https://claude.ai/directory/manage" rel="noopener noreferrer"&gt;claude.ai/directory/manage&lt;/a&gt;, which any paid Claude plan can open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide which tools you are submitting
&lt;/h2&gt;

&lt;p&gt;This is the decision that matters, and it comes before the form. A reviewer reads every tool your listing exposes. Our full MCP catalogue carries raw SQL, a Python sandbox, an Android device farm and browser-session capture, all legitimate for the engineers who connect it themselves, and all wrong for a listing anyone can install. OpenAI had already rejected exactly that surface for the same reason.&lt;/p&gt;

&lt;p&gt;So the server answers on two paths. The full catalogue stays where it was; a second path serves a curated set: read and answer conversations, search, contacts, tasks, notes, reminders, knowledge, agent drafts, call transcripts. The paths cannot be merged, because the resource value a client reads back from the protected-resource document has to be the URL it registered: one shared path breaks one of the two listings.&lt;/p&gt;

&lt;p&gt;If your server was built for your own users, assume you will need this split. It is a dozen lines and it is the difference between a listing a reviewer can approve and a conversation about why you expose a SQL console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# One tool set, one path per directory. The resource a client reads back
# must be the URL it registered, so the paths cannot be merged.
&lt;/span&gt;&lt;span class="n"&gt;PROFILES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;directory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DIRECTORY_TOOLS&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;PROFILE_PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/mcp/chatgpt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;directory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/mcp/claude-directory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;directory&lt;/span&gt;&lt;span class="sh"&gt;"&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;h2&gt;
  
  
  Check the four things the portal reads automatically
&lt;/h2&gt;

&lt;p&gt;Remote and reachable over HTTPS. A local server cannot be submitted on its own; it belongs in a plugin.&lt;/p&gt;

&lt;p&gt;OAuth 2.0 with dynamic client registration, or no authentication at all for public data. The portal detects which you have. Ours advertises a registration endpoint in /.well-known/oauth-authorization-server, and the 401 your server returns without a token has to point at the protected-resource document for the exact path being submitted.&lt;/p&gt;

&lt;p&gt;Every tool carries a title and the applicable readOnlyHint or destructiveHint. The portal flags the ones that do not, and a wrong label is a common rejection: anything that sends or deletes is destructive, anything that writes is not read-only.&lt;/p&gt;

&lt;p&gt;Documentation URL, privacy policy URL, support contact and an icon. All four are public links a reviewer will open.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.dialogbrain.com/mcp/claude-directory &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt;

&lt;span class="c"&gt;# HTTP/2 401&lt;/span&gt;
&lt;span class="c"&gt;# www-authenticate: Bearer error="invalid_token",&lt;/span&gt;
&lt;span class="c"&gt;#   resource_metadata="https://api.dialogbrain.com/&lt;/span&gt;
&lt;span class="c"&gt;#   .well-known/oauth-protected-resource/mcp/claude-directory"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run every tool before you submit: this is where the bugs are
&lt;/h2&gt;

&lt;p&gt;The portal asks you to confirm you have run each tool, and it is tempting to tick that box because the tools obviously work. We ran them instead: added the server as a custom connector in Claude, signed in as the reviewer account, and asked Claude to call each tool in turn and report the result. It took twenty minutes and found three real defects, two of which had been shipped for weeks.&lt;/p&gt;

&lt;p&gt;A read tool that answered "agent_id is required. Pass it as a parameter when calling from MCP." A person asking "what reminders are set?" has no agent id and cannot get one, so that tool could not answer for anyone connecting over MCP. It had been in our ChatGPT listing since September.&lt;/p&gt;

&lt;p&gt;A tool whose error message pointed at another tool the listing did not expose: files.read refuses a binary file and tells you to use files.get_base64, which was outside the curated set. The advice led nowhere and a customer's photo could not be opened.&lt;/p&gt;

&lt;p&gt;A tool that reported success for work it had not done: removing a tag that was never on the conversation answered success: true, indistinguishable from a real removal.&lt;/p&gt;

&lt;p&gt;None of these would have been caught by a reviewer in the first five minutes, and all three would have been found by a user in the first week. Twenty minutes of your own time is a cheap way to not learn about them from a stranger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Call each of these tools exactly once, in order, and do not ask me
anything in between: workspace_current, channels_list, search_threads,
contacts_find, messages_read_history, tasks_create, tasks_update,
notes_save, reminder_set, reminder_list, reminder_cancel, files_read.
Then print one line per tool: the name, OK or FAILED, and for a failure
the exact error text.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The ten steps, and what each one actually wants
&lt;/h2&gt;

&lt;p&gt;Connection. Paste the URL and authorise. The portal reads your tool list live. If your server hides tools for channels a workspace has not connected, the count here is what that account can see, not your full set: say so in the notes rather than letting a reviewer wonder.&lt;/p&gt;

&lt;p&gt;Tools. Your tools and their annotations, synced from the live connection. Anything flagged here is fixed on your server, not in the form.&lt;/p&gt;

&lt;p&gt;Listing. Name, slug, a one-liner up to 200 characters, a description up to 2,000, categories, documentation, privacy, support, icon. The slug is permanent once published: ours is dialogbrain, and that is the one field you cannot take back.&lt;/p&gt;

&lt;p&gt;Use cases. Three things people will do, each with an example prompt, plus what they need before connecting, and whether the connector reads, writes, or both.&lt;/p&gt;

&lt;p&gt;Company, Authentication, Data handling. Company name and a contact a reviewer can reach; the authentication mode, which is detected; and whether the API is your own, whether personal health data is involved, whether any content is sponsored.&lt;/p&gt;

&lt;p&gt;Test &amp;amp; launch. Access instructions detailed enough for a reviewer to connect and run the tools: the URL, real credentials for a populated account, and what to try. Say plainly which tools reach real people: ours deliver messages to actual customers, so the instructions ask reviewers to read and not send.&lt;/p&gt;

&lt;p&gt;Compliance. Seven acknowledgements, including prompt injection and conversation-data collection. Read them. If your product stores other people's private messages, as an inbox does, say so in the notes instead of hoping the checkbox covers it.&lt;/p&gt;

&lt;p&gt;Review and submit. A summary and the button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two traps worth knowing
&lt;/h2&gt;

&lt;p&gt;Reconnecting the server resets fields you already filled. We reconnected on the Connection step to pick up two newly added tools, and the portal silently put the listing name and slug back to the auto-derived api.dialogbrain.com and api-dialogbrain-com. The slug is permanent after publishing. Check the Listing step again after any reconnect.&lt;/p&gt;

&lt;p&gt;A draft lives in the browser tab. The form says "Draft saved in this tab". Leave that tab and the draft is not in your submissions list; come back to the same tab and it is still there, on the step you left. Do not close it.&lt;/p&gt;

&lt;h2&gt;
  
  
  After it is live
&lt;/h2&gt;

&lt;p&gt;The listing appears in the directory within about an hour, with Community and New badges. Health, rank and usage start about a day after the first calls.&lt;/p&gt;

&lt;p&gt;Edits after publishing go through review before they replace what is live, so the listing you publish is the one people see for a while. Edits before publishing send the submission back to draft for another review, which is why, if you are staring at an approved submission and a small copy change, publish first and edit after.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions and answers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need a separate submission for a plugin?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. A connector is one remote MCP server submitted by URL. A plugin is a bundle of skills, commands and MCP configuration read from a GitHub repository, submitted as "Plugin bundle". If your plugin references a server you run, submit the server as a connector too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I submit while another submission is in review?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. Unlike Meta's app review, the portal is open for new submissions at any time, and an organisation can create up to ten in 24 hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if a tool fails while a reviewer is testing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It becomes a question you answer by email, and the listing waits. That is the argument for running every tool yourself first: a failure you find is a commit, a failure a reviewer finds is a week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the listing cost anything?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Any paid Claude plan can submit, and a Community listing is free. What it costs you is the work of making the tool surface defensible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I change the name or slug later?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The name follows the listing and can be edited through review. The slug is permanent once the listing is published, so decide it before you press publish.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://dialogbrain.com/articles/publish-mcp-server-claude-directory" rel="noopener noreferrer"&gt;dialogbrain.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>claude</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>The call transfer that reported success and rang nobody</title>
      <dc:creator>Dialog Brain</dc:creator>
      <pubDate>Wed, 02 Sep 2026 04:21:46 +0000</pubDate>
      <link>https://dev.to/dialogbrain/the-call-transfer-that-reported-success-and-rang-nobody-1c01</link>
      <guid>https://dev.to/dialogbrain/the-call-transfer-that-reported-success-and-rang-nobody-1c01</guid>
      <description>&lt;p&gt;Our voice agents can hand a live phone call to a human. Getting there took two rewrites, and the first one shipped without ever delivering a single call — while our own logs said it worked. This is what the feature does now, and what the failure taught us.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the caller hears
&lt;/h2&gt;

&lt;p&gt;Someone asks to speak to a person, or the agent decides the question is not its own: a complaint, a payment, something outside its instructions. The agent says one short line, and from there the caller hears real ringing — the second number is being dialled.&lt;/p&gt;

&lt;p&gt;When the phone is answered, the agent goes quiet. Two people are on the line and nothing else is on it with them. If nobody answers, nothing happens: the caller stays with the agent, which knows the dial failed and can offer a callback or take a message.&lt;/p&gt;

&lt;h2&gt;
  
  
  The route a transfer takes
&lt;/h2&gt;

&lt;p&gt;A transfer here is not "hand the line to the carrier". It is a second call, dialled into the same conversation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Is the number on the agent's approved list?&lt;/strong&gt; If not, refused — and the agent is still on the line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is this a phone call at all?&lt;/strong&gt; A messenger chat or a web voice widget has no second line to connect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dial the second number into the same call.&lt;/strong&gt; The caller hears ringing; the agent is still there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Did they pick up within 45 seconds?&lt;/strong&gt; If not, the dial is cancelled and the caller stays with the agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They picked up&lt;/strong&gt; — the agent loses the right to speak, and the two of them talk.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both gates sit &lt;em&gt;before&lt;/em&gt; anything is dialled, so a refusal never costs the caller a single ring. The pickup fork is the only place where a call becomes a transferred one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not SIP REFER
&lt;/h2&gt;

&lt;p&gt;Telephony has a cheaper way: a &lt;code&gt;REFER&lt;/code&gt;, after which the carrier connects the two parties itself and you leave the call — the minutes stop flowing through you.&lt;/p&gt;

&lt;p&gt;We built that first. It never delivered a call. Telnyx answered every REFER with &lt;code&gt;200 OK&lt;/code&gt; and did nothing: no progress NOTIFY, no ring at the destination. Meanwhile our own bookkeeping recorded &lt;code&gt;outcome = transferred&lt;/code&gt;, so the dashboards were green while the caller was simply dropped.&lt;/p&gt;

&lt;p&gt;The documentation explains it. REFER-based external transfer on a SIP trunk requires an &lt;strong&gt;active inbound call to your own number&lt;/strong&gt; to match against, plus a &lt;code&gt;Diversion&lt;/code&gt; header carrying that number. We were sending REFER on calls &lt;em&gt;we&lt;/em&gt; originated — the one shape it cannot work on. And LiveKit's &lt;code&gt;TransferSIPParticipant&lt;/code&gt; has no field for a custom header, so the requirement is unreachable from there anyway.&lt;/p&gt;

&lt;p&gt;Two other explanations were tested and disproved rather than assumed: enabling third-party call control on the connection changed nothing, and neither did a &lt;code&gt;sip:&lt;/code&gt; URI instead of &lt;code&gt;tel:&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things measurement changed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Presence in the room is not a pickup signal.&lt;/strong&gt; The dialled participant appears in the media room the moment dialling starts — measured at 310 ms, with no call at the destination. Only &lt;code&gt;wait_until_answered&lt;/code&gt; tells you a human lifted the handset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Removing the agent takes the call with it.&lt;/strong&gt; Measured in isolation on a live call: &lt;code&gt;RemoveParticipant&lt;/code&gt;, and within five seconds the room was empty, carrier leg included. The room does not outlive its agent job. So the agent is silenced, not removed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Silencing alone is not enough.&lt;/strong&gt; Revoking publish stops the agent being &lt;em&gt;heard&lt;/em&gt;. Its job keeps running: nine seconds after one handover it composed and "spoke" a line that went into the call history, while it carried on transcribing two people who had just been handed to each other. It now gets an explicit stand-down.&lt;/p&gt;

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

&lt;p&gt;Bridging means the conversation runs over our media path, and minutes are billed on both legs — exactly what a REFER avoids. In exchange it works identically on inbound and outbound calls, on any carrier, with nothing to configure on the telephony side.&lt;/p&gt;

&lt;p&gt;If your logs can say "transferred" without anyone's phone ringing, that is the bug worth looking for first.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://dialogbrain.com/articles/call-transfer-to-human" rel="noopener noreferrer"&gt;dialogbrain.com&lt;/a&gt;, where the same piece has a flow diagram.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
