Skip to main content
Glama
shatrunjaysingh

indicus-ai-mcp-tools

indicus-ai-mcp-tools

Demo services for the IndicusAI platform, served two ways at once:

  • REST, at /soc, /utility, /payer, /iam — registered as built-in custom HTTP tools, one tool per endpoint

  • MCP, at /mcp — one connector carrying every tool on the server

Both surfaces call the same functions over the same fixtures. That is the point: a demo comparing built-in tools against MCP proves nothing if the two run on different data, because any difference could be blamed on the data.

Run it

python3 -m venv .venv && .venv/bin/pip install -e .
.venv/bin/uvicorn mcp_server:app --port 8304
curl -s localhost:8304/health | python3 -m json.tool

Or docker compose up -d, which joins the platform's network so the platform reaches it as http://mcp-tools:8304.

Related MCP server: Http-tools Universal MCP Server

Adding a tool

One edit:

@app.get("/widgets/{widget_id}", operation_id="getWidget",
         summary="Fetch one widget")
def get_widget(widget_id: str) -> dict:
    """What the model reads to decide whether to call this."""
    ...

It is now a REST endpoint and an MCP tool called soc_getWidget. Nothing else to register — mcp_server walks the routes and every one carrying an operation_id becomes a tool. A route without one is skipped, which is how the audio download stays out of the tool list.

Three things the wrapper handles, each learned by hitting it:

  • Names are {service}_{operationId}. MCP names are flat across a server while operation_ids are unique only per service. SOC and IAM both define getIdentity; unprefixed, the second silently replaced the first and an agent asking for a SOC identity got IAM's answer.

  • HTTPException becomes a value, not a protocol error. Over REST a 404 is the response; over MCP there are no status codes, so an uncaught one reads as a broken server. {"error": "No alert ALT-9999.", "status": 404} is a fact the model can act on.

  • Annotations are resolved eagerly. from __future__ import annotations makes them strings, which pydantic resolves through the handler's own module globals — not something a wrapper can inherit.

A new service

Write the FastAPI app in services/, then add it to SERVICES in mcp_server.py. That is the whole procedure.

Onboarding these tools into IndicusAI

What a tool is on that platform, the three ways one gets there, and how to build both demos' agents and pipelines in the UI: demo-data-setup.md, in the platform repository — that side of it is all IndicusAI, and this repository only supplies the endpoints.

Testing the DISCOM agents

discom-agent-tests.md, in the platform repository — the walkthrough is done in that UI, and sits with the other platform documents. It takes all ten through the browser one input at a time, with what a correct answer contains and the wrong answer each case is designed to catch.

The expected figures in it come from services/discom_data.py here, so a change to a fixture means a change to that document.

Seeding a demo

seeds/ builds the workspace, skills, agents and pipeline in the platform. They log in as demo@example.com, so scripts/seed.py in the platform repo runs first.

On a deployment, run them inside the container — it already has the code and its dependencies, and the compose file sets both hostnames:

docker compose exec mcp-tools python seeds/soc.py
docker compose exec mcp-tools python seeds/utility.py

On a laptop, where the platform and these services are both on localhost:

.venv/bin/python seeds/soc.py
.venv/bin/python seeds/utility.py

Two hostnames decide where a seed points, and both default to 127.0.0.1, which is correct only on a laptop — inside a container it is the container:

  • PLATFORM_API_URL — the platform being seeded, http://api:8000/api/v1 over the compose network

  • DEMO_HOST — what goes into the registered tool URLs and their allowed_hosts pin, mcp-tools over the compose network

The recordings

services/generate_visit_recordings.py uses macOS say and cannot run on Linux. Generate on a Mac, copy data/recordings/ to the deployment. data/ is gitignored — the fixtures are derived, not source.

Only the utility demo needs them, and only to run a visit end to end; seeding works without.

Related MCP Connectors

Related MCP Servers