DEV Community

Tehesherpa
Tehesherpa

Posted on

Giving a LangChain Agent Real-World Facility-Management Tools via MCP

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).

This post walks through connecting a LangChain agent to Telesherpa, an ontology-based platform for facility, fleet and field-service management, over the Model Context Protocol (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.

Why this pairing is interesting

Two things make this a useful example rather than a marketing demo:

  1. The tool surface is large and role-gated. Telesherpa exposes on the order of 170 MCP tools, but which ones a given agent sees depends on its role — a public 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.
  2. Onboarding requires zero human intervention. The platform is self-registering: register(), activate() (a 7-digit email code), and login() are all public MCP tools. An agent can go from nothing to an authenticated session without a human ever opening a browser.

The connection

LangChain's official langchain-mcp-adapters package speaks MCP's Streamable HTTP transport natively, including custom headers — which is what you need for Bearer-token auth against a remote server:

from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "telesherpa": {
        "transport": "http",
        "url": "https://mcp.telesherpa.com",
        "headers": {"Authorization": f"Bearer {token}"},
    }
})

tools = await client.get_tools()
Enter fullscreen mode Exit fullscreen mode

That's the entire integration surface. tools 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.

Getting a token without a browser

Before that snippet works you need token. Since every step is itself an MCP tool call, an agent can do this on its own:

# 1. register — creates an account, requires accept_terms=true
await call_tool("register", {"email": "...", "accept_terms": True, ...})

# 2. activate — redeem the 7-digit code emailed to that address
await call_tool("activate", {"code": "1234567"})

# 3. login — exchange client credentials for a bearer token
result = await call_tool("login", {"client_id": "...", "client_secret": "..."})
token = result["token"]          # valid ~10h
refresh_token = result["refresh_token"]
Enter fullscreen mode Exit fullscreen mode

auth_status 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.

Putting it to work

With tools loaded, a standard LangChain agent can now reason over real ontology objects:

from langchain.agents import create_agent

agent = create_agent("openai:gpt-4.1", tools)

response = await agent.ainvoke({
    "messages": "List the buildings in my current scope and flag any "
                "that are missing a structured image category."
})
Enter fullscreen mode Exit fullscreen mode

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

What makes this more than a search-and-summarize demo is that the same tool surface supports writes: 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."

Beyond LangChain

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 telesherpa/telesherpa-quickstarts. The full capability reference — object model, scopes, automation, structured image filing, forms — is in telesherpa/skill-telesherpa-com.

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.

Top comments (1)

Some comments have been hidden by the post's author - find out more