<?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: Rostery Team</title>
    <description>The latest articles on DEV Community by Rostery Team (@rostery).</description>
    <link>https://dev.to/rostery</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%2F4170736%2F5ddb616e-634c-4a90-b486-2b11440ee017.png</url>
      <title>DEV Community: Rostery Team</title>
      <link>https://dev.to/rostery</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rostery"/>
    <language>en</language>
    <item>
      <title>Connecting AI assistants to care-sector software with MCP: lessons from Rostery's MCP server</title>
      <dc:creator>Rostery Team</dc:creator>
      <pubDate>Thu, 08 Oct 2026 08:59:29 +0000</pubDate>
      <link>https://dev.to/rostery/connecting-ai-assistants-to-care-sector-software-with-mcp-lessons-from-rosterys-mcp-server-1a7g</link>
      <guid>https://dev.to/rostery/connecting-ai-assistants-to-care-sector-software-with-mcp-lessons-from-rosterys-mcp-server-1a7g</guid>
      <description>&lt;p&gt;Most people who run a disability or aged care service ask their software the same small questions every day. Who is unrostered tomorrow? Which participants have no progress notes this week? What incidents were logged at a particular house last month? Each of those is either a report someone has to build or a screen someone has to know about.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol (MCP) gives AI assistants a standard way to ask those questions of a live system. This post looks at how MCP works, why care-sector data changes the design, and how to connect a client to a remote server. Our examples come from &lt;a href="https://rostery.com.au" rel="noopener noreferrer"&gt;Rostery&lt;/a&gt;, Australian software for NDIS and aged care providers, which runs a remote MCP server at &lt;code&gt;https://app.rostery.com.au/api/mcp&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MCP actually is
&lt;/h2&gt;

&lt;p&gt;MCP is an open protocol for connecting an AI client (Claude, ChatGPT, an IDE agent, and so on) to an external system. The server publishes a set of &lt;strong&gt;tools&lt;/strong&gt;. Each tool has a name, a description and a JSON Schema for its inputs. The client lists those tools, the model decides when to call one, and the server returns structured results the model can reason over.&lt;/p&gt;

&lt;p&gt;Under the hood it is JSON-RPC 2.0. A session starts with an &lt;code&gt;initialize&lt;/code&gt; request, the client calls &lt;code&gt;tools/list&lt;/code&gt; to discover what is available, and &lt;code&gt;tools/call&lt;/code&gt; runs a tool. Remote servers usually speak the Streamable HTTP transport, which means a single HTTPS endpoint that accepts JSON-RPC over POST.&lt;/p&gt;

&lt;p&gt;The useful idea is the split of responsibilities. The model is good at turning "who hasn't had a visit this week?" into a sensible sequence of calls. The server stays the system of record and decides what can be read, by whom, and in what shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why care data changes the design
&lt;/h2&gt;

&lt;p&gt;A connector for a to-do app can expose almost everything. A connector for care software can't. NDIS and aged care records hold health information, behaviour support details, incident reports and funding data, and Australian providers work under the Privacy Act and the requirements of their regulators. Three design questions come up before you write a single tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. What should the assistant be able to reach at all?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is tempting to expose the whole API and rely on permissions. Rostery took the narrower route. The connector covers operational data (clients, rosters, progress notes and incidents) and leaves money out entirely. Timesheets, invoices, payments and payroll aren't behind a permission check in the MCP tool set. They are simply absent.&lt;/p&gt;

&lt;p&gt;That difference matters. A permission-gated tool can be misconfigured, and a role can be granted too broadly. A tool that doesn't exist can't be called. If your question is "could an assistant ever read a pay run?", "there is no tool for it" is an easier answer to defend than "only if the role allows it".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Whose data is this, and who agreed to share it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In multi-tenant SaaS the worst failure is one organisation's assistant reading another organisation's records. So the connection is per-organisation, authorised with OAuth by a user from that organisation, and it acts within that user's role and permissions. Nobody pastes a long-lived API key into a chat app. It is also revocable: disconnect it in Settings and the access ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Where does the data go after the tool returns it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once a result reaches the model, it is part of a conversation governed by the agreement between the provider and their AI vendor. The server can't control that, so the honest thing is to say so plainly. Rostery's documentation states that the connector answers queries when asked, doesn't send data unprompted and doesn't store conversations, and it points providers to the business terms their AI vendor offers. If you are building something similar, put this in writing early. It is usually the first question a privacy officer asks.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the authorisation flow looks from the outside
&lt;/h2&gt;

&lt;p&gt;You can see most of the auth design without any credentials. An unauthenticated &lt;code&gt;initialize&lt;/code&gt; request to Rostery's endpoint returns &lt;code&gt;401&lt;/code&gt; with a &lt;code&gt;WWW-Authenticate&lt;/code&gt; header pointing at protected resource metadata:&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://app.rostery.com.au/api/mcp &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="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Accept: application/json, text/event-stream'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0.1"}}}'&lt;/span&gt;

&lt;span class="c"&gt;# HTTP/2 401&lt;/span&gt;
&lt;span class="c"&gt;# www-authenticate: Bearer resource_metadata="https://app.rostery.com.au/.well-known/oauth-protected-resource"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That metadata document names the authorisation server, the supported scope (&lt;code&gt;mcp&lt;/code&gt;) and that bearer tokens go in the &lt;code&gt;Authorization&lt;/code&gt; header. The authorisation server metadata at &lt;code&gt;/.well-known/oauth-authorization-server&lt;/code&gt; then advertises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the authorisation code grant with refresh tokens&lt;/li&gt;
&lt;li&gt;PKCE with &lt;code&gt;S256&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a dynamic client registration endpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;token_endpoint_auth_methods_supported: ["none"]&lt;/code&gt;, meaning public clients with no client secret&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the pattern the MCP authorisation spec describes, and it is why "add a URL" is all the user has to do. The client discovers the auth server, registers itself, sends the user to log in and approve access, and gets back a token tied to that user's organisation. No secret ever sits in a config file.&lt;/p&gt;

&lt;p&gt;If you are building your own server, it is worth getting this 401 response right. A bare &lt;code&gt;401&lt;/code&gt; with no &lt;code&gt;WWW-Authenticate&lt;/code&gt; header leaves clients with no way to discover how to log in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a remote MCP server to a client
&lt;/h2&gt;

&lt;p&gt;The details differ between clients and change often, so check each client's current docs. The general shapes are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude (web or desktop):&lt;/strong&gt; add a custom connector in the connector settings, paste the server URL, then complete the OAuth sign-in when prompted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http rostery https://app.rostery.com.au/api/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;VS Code and other clients that use a JSON config:&lt;/strong&gt;&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;"servers"&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;"rostery"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://app.rostery.com.au/api/mcp"&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;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;&lt;strong&gt;ChatGPT:&lt;/strong&gt; connectors to remote MCP servers are added from the app's connector settings. Availability depends on the plan and workspace settings.&lt;/p&gt;

&lt;p&gt;On first use the client opens a browser window to sign in. For Rostery, that means signing in with an existing Rostery account and approving access for your organisation. The connector is part of the product, not a public data source, so it is only useful to providers who already use Rostery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design notes if you're building one
&lt;/h2&gt;

&lt;p&gt;A few things we'd suggest to anyone putting an MCP server in front of sensitive data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start from questions, not endpoints.&lt;/strong&gt; List the ten questions coordinators actually ask, then design tools around those. A small set of well-described tools beats a thin wrapper around every REST route, both for safety and for how reliably the model picks the right tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write tool descriptions for the model.&lt;/strong&gt; The description is the prompt. Say what the tool returns, what it doesn't, and when to use it instead of a neighbouring tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return less.&lt;/strong&gt; Page results, trim fields, and leave out identifiers the model doesn't need to answer the question. Every field you return ends up in a conversation transcript somewhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce tenancy below the application layer.&lt;/strong&gt; Database-level isolation, such as row-level security, means a bug in a tool handler still can't return another tenant's rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclude rather than gate when the risk is high.&lt;/strong&gt; If a category of data would change the risk conversation, leave it out of the tool set and say so in your docs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make revocation obvious.&lt;/strong&gt; Users should be able to find the disconnect button without asking support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log tool calls like any other access.&lt;/strong&gt; Care providers already keep audit logs for access to participant records, and an assistant reading those records is no different.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;MCP makes it cheap to connect an assistant to a system of record. In regulated sectors, though, the protocol is the easy part. The real work is deciding what the assistant should never be able to reach, making consent explicit per organisation, and being clear about where data goes once it leaves your server.&lt;/p&gt;

&lt;p&gt;If you work on software for NDIS or aged care providers and want to compare notes on connector design, you can find more about how &lt;a href="https://rostery.com.au" rel="noopener noreferrer"&gt;Rostery&lt;/a&gt; approaches it on our site.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— Rostery Team&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>saas</category>
      <category>healthtech</category>
    </item>
  </channel>
</rss>
