<?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: Tehesherpa</title>
    <description>The latest articles on DEV Community by Tehesherpa (@telesherpa).</description>
    <link>https://dev.to/telesherpa</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%2F4147952%2Fed0a9f0d-2174-4de9-8940-66a89c245e24.png</url>
      <title>DEV Community: Tehesherpa</title>
      <link>https://dev.to/telesherpa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/telesherpa"/>
    <language>en</language>
    <item>
      <title>Giving a LangChain Agent Real-World Facility-Management Tools via MCP</title>
      <dc:creator>Tehesherpa</dc:creator>
      <pubDate>Mon, 28 Sep 2026 19:36:16 +0000</pubDate>
      <link>https://dev.to/telesherpa/giving-a-langchain-agent-real-world-facility-management-tools-via-mcp-4g1i</link>
      <guid>https://dev.to/telesherpa/giving-a-langchain-agent-real-world-facility-management-tools-via-mcp-4g1i</guid>
      <description>&lt;p&gt;Most "give your agent tools" tutorials hand it a calculator or a weather API. Useful for learning the mechanics, but it doesn't tell you what happens when an agent gets access to a real operational system — one with access control, multi-tenancy, and objects that map to actual physical things (buildings, vehicles, machines).&lt;/p&gt;

&lt;p&gt;This post walks through connecting a LangChain agent to &lt;a href="https://www.telesherpa.com" rel="noopener noreferrer"&gt;Telesherpa&lt;/a&gt;, an ontology-based platform for facility, fleet and field-service management, over the &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; (MCP). By the end, the agent can query and modify real ontology objects — not toy data — using nothing but its own reasoning and the tools MCP hands it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this pairing is interesting
&lt;/h2&gt;

&lt;p&gt;Two things make this a useful example rather than a marketing demo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The tool surface is large and role-gated.&lt;/strong&gt; Telesherpa exposes on the order of 170 MCP tools, but which ones a given agent sees depends on its role — a &lt;code&gt;public&lt;/code&gt; caller sees a handful of self-registration tools, an authenticated caller with the right scope sees object CRUD, reports, automation triggers, structured image filing, and more. That's a realistic shape for enterprise software, and a good stress test for whether an agent framework's tool-loading actually scales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding requires zero human intervention.&lt;/strong&gt; The platform is self-registering: &lt;code&gt;register()&lt;/code&gt;, &lt;code&gt;activate()&lt;/code&gt; (a 7-digit email code), and &lt;code&gt;login()&lt;/code&gt; are all public MCP tools. An agent can go from nothing to an authenticated session without a human ever opening a browser.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The connection
&lt;/h2&gt;

&lt;p&gt;LangChain's official &lt;a href="https://github.com/langchain-ai/langchain-mcp-adapters" rel="noopener noreferrer"&gt;&lt;code&gt;langchain-mcp-adapters&lt;/code&gt;&lt;/a&gt; package speaks MCP's Streamable HTTP transport natively, including custom headers — which is what you need for Bearer-token auth against a remote server:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_mcp_adapters.client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MultiServerMCPClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MultiServerMCPClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;telesherpa&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;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transport&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;http&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;url&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;https://mcp.telesherpa.com&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;headers&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;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="si"&gt;}&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;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_tools&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire integration surface. &lt;code&gt;tools&lt;/code&gt; is now a list of LangChain-compatible tools, generated directly from the server's live tool catalog — no manual schema mapping, no maintaining a wrapper per endpoint. If Telesherpa adds a tool next week, your agent sees it next week too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a token without a browser
&lt;/h2&gt;

&lt;p&gt;Before that snippet works you need &lt;code&gt;token&lt;/code&gt;. Since every step is itself an MCP tool call, an agent can do this on its own:&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;# 1. register — creates an account, requires accept_terms=true
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;call_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;register&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;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&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;...&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;accept_terms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;

&lt;span class="c1"&gt;# 2. activate — redeem the 7-digit code emailed to that address
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;call_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;activate&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;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&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;1234567&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# 3. login — exchange client credentials for a bearer token
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;call_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;login&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;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;client_id&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;...&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;client_secret&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;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;          &lt;span class="c1"&gt;# valid ~10h
&lt;/span&gt;&lt;span class="n"&gt;refresh_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refresh_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;auth_status&lt;/code&gt; is worth calling first in any new session — it tells you plainly whether your token is valid, which roles it carries, and how many of the total tools are currently visible to you. Cheaper than guessing from a 401.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it to work
&lt;/h2&gt;

&lt;p&gt;With tools loaded, a standard LangChain agent can now reason over real ontology objects:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_agent&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai:gpt-4.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&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;List the buildings in my current scope and flag any &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;that are missing a structured image category.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood this typically resolves to a couple of tool calls — something like &lt;code&gt;onto_type_show("building")&lt;/code&gt; to enumerate objects, then &lt;code&gt;onto_file_structured(object_id)&lt;/code&gt; per building to check which image categories are filled. The agent picks the sequence; you didn't hardcode it.&lt;/p&gt;

&lt;p&gt;What makes this more than a search-and-summarize demo is that the same tool surface supports &lt;em&gt;writes&lt;/em&gt;: creating objects, executing defined actions on them (check-in/check-out, service-order creation, form submission), setting properties, and — critically for anything touching real operations — a role-based access model that determines what an agent is even allowed to attempt. The interesting engineering problem isn't "can the agent call a tool," it's "does the permission boundary hold when the caller is non-human."&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond LangChain
&lt;/h2&gt;

&lt;p&gt;The same MCP server works the same way with CrewAI, LlamaIndex, and Microsoft's Agent Framework, since MCP is transport- and framework-agnostic by design — the tool definitions and auth flow don't change, only the client-side plumbing does. Working examples for each (some verified, some flagged as in-progress) are in &lt;a href="https://github.com/telesherpa/telesherpa-quickstarts" rel="noopener noreferrer"&gt;&lt;code&gt;telesherpa/telesherpa-quickstarts&lt;/code&gt;&lt;/a&gt;. The full capability reference — object model, scopes, automation, structured image filing, forms — is in &lt;a href="https://github.com/telesherpa/skill-telesherpa-com" rel="noopener noreferrer"&gt;&lt;code&gt;telesherpa/skill-telesherpa-com&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're building agents that need to do something in the physical world — not just answer questions about it — this is roughly the shape that "agent-ready" enterprise software needs to take: a documented, self-registering, role-scoped MCP surface, not a REST API with an OpenAPI spec bolted on after the fact.&lt;/p&gt;

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