cd /news/ai-agents/build-your-first-flasktrack-mcp-agen… · home topics ai-agents article
[ARTICLE · art-102706] src=flasktrack.com ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Build your first FlaskTrack MCP agent

FlaskTrack released a walkthrough for building an MCP agent that gives AI models controlled access to laboratory operations, using dynamic tool discovery from the /mcp/tools endpoint and schema-valid execution via /mcp/call. The agent, written in Python 3.10+ with the requests library, reads the live tool catalog, selects a read operation, and uses structured results with record IDs to continue multi-step work, with all actions scoped to the authenticated FlaskTrack organization and subject to roles, validation, and compliance controls.

read6 min views1 publishedAug 19, 2026

Give an AI agent controlled access to real laboratory operations with FlaskTrack's organization-scoped MCP tool interface.

In this walkthrough, you will create a small Python agent that discovers FlaskTrack tools, searches laboratory records, executes a tool, and uses structured results to continue safely.

Dynamic tool discovery Read the live MCP registry instead of hard-coding the API surface

Typed laboratory records Work with workflows, protocols, batches, samples, species, and more

Organization scoped Every action is evaluated in the authenticated FlaskTrack organization

Permission aware Agent calls remain subject to roles, validation, and compliance controls

Structured results Use returned record IDs and metadata to safely continue multi-step work

What you are building #

The agent will discover the tools exposed by your FlaskTrack deployment, choose a read operation, execute it through the MCP interface, and use the structured result as context for the next decision.

Discover tools Load the current FlaskTrack tool catalog from

/mcp/tools

.Choose a tool Give the model names, descriptions, schemas, and semantic record metadata.

Execute through FlaskTrack Send one registered tool name and schema-valid input to

/mcp/call

.Continue from the result Use the concrete returned record ID instead of guessing or inventing identifiers.

Before you start #

Create a FlaskTrack API credential for the integration and keep it outside your prompt, source code, browser JavaScript, and model context.

API key Use a dedicated machine credential for the agent.

Organization Every request includes the FlaskTrack organization context.

Python 3.10+ The example uses Python,

requests

, and any model client you prefer.LLM provider OpenAI, Anthropic, a local model, or another provider can drive the decision loop.

Configure FlaskTrack credentials #

Keep credentials in environment variables so the model never sees them.

export FLASKTRACK_URL="https://flasktrack.com"
export FLASKTRACK_ORGANIZATION="YOUR_ORGANIZATION_ID"
export FLASKTRACK_API_KEY="YOUR_API_KEY"

Install the tiny client #

python -m pip install requests

Connect to FlaskTrack #

Keep credentials in the HTTP layer rather than the prompt.

import os
import requests

BASE_URL = os.environ["FLASKTRACK_URL"].rstrip("/")

HEADERS = {
    "x-organization": os.environ["FLASKTRACK_ORGANIZATION"],
    "x-api-key": os.environ["FLASKTRACK_API_KEY"],
    "accept": "application/json",
}

def flasktrack_get(path):
    response = requests.get(
        f"{BASE_URL}{path}",
        headers=HEADERS,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()

def flasktrack_post(path, payload):
    response = requests.post(
        f"{BASE_URL}{path}",
        headers={**HEADERS, "content-type": "application/json"},
        json=payload,
        timeout=60,
    )
    response.raise_for_status()
    return response.json()

Discover the live MCP tool catalog #

Do not hard-code every FlaskTrack action. Ask the running deployment what tools are currently registered.

tools = flasktrack_get("/mcp/tools")

for tool in tools:
    print(
        tool["name"],
        tool["effect"],
        tool.get("output_entity"),
    )

Why discovery matters FlaskTrack's tool surface evolves with the platform. Runtime discovery lets an agent adapt to the deployed version instead of relying on a stale list copied into a prompt.

Give the model a compact tool list #

def compact_tools(tools):
    return [
        {
            "name": tool["name"],
            "description": tool["description"],
            "effect": tool["effect"],
            "input_schema": tool["input_schema"],
            "entity_fields": tool.get("entity_fields", []),
            "output_entity": tool.get("output_entity"),
        }
        for tool in tools
    ]

agent_tools = compact_tools(tools)

Keep authentication headers, API keys, cookies, and unrelated organization data outside model-visible context.

Ask the model for one tool call #

Keep the first agent intentionally simple: the model returns one registered tool name and one JSON input object.

import json

SYSTEM_PROMPT = """
You are a FlaskTrack laboratory assistant.

Choose exactly one FlaskTrack tool for the user's request.

Rules:
- Use only tool names supplied to you.
- Match the tool input schema exactly.
- Never invent FlaskTrack UUIDs.
- Treat Workflow, Protocol, Batch, Sample, Species, Tool,
  Ingredient, Plasmid, and other entity IDs as distinct types.
- Prefer read tools when you still need to identify a record.
- Return JSON only:

{
  "name": "tool_name",
  "input": {}
}
"""

def choose_tool(llm, user_request, tools):
    raw = llm(
        system=SYSTEM_PROMPT,
        user=json.dumps({
            "request": user_request,
            "tools": tools,
        }),
    )

    return json.loads(raw)

The llm

function is provider-agnostic. Wrap your preferred model SDK and make it return the model's text response.

Execute the selected FlaskTrack tool #

def call_tool(tool_call):
    return flasktrack_post(
        "/mcp/call",
        {
            "name": tool_call["name"],
            "input": tool_call["input"],
        },
    )

FlaskTrack resolves the registered tool and applies its normal input validation, organization scope, permissions, route, and operation semantics.

Put the pieces together #

def run_agent_once(llm, request):
    tools = flasktrack_get("/mcp/tools")

    tool_call = choose_tool(
        llm,
        request,
        compact_tools(tools),
    )

    print("Selected tool:", tool_call["name"])
    print("Input:", json.dumps(tool_call["input"], indent=2))

    result = call_tool(tool_call)

    print("Result:")
    print(json.dumps(result, indent=2))

    return result

run_agent_once(
    llm,
    "Find the workflow used for banana multiplication.",
)

That is the core FlaskTrack agent loop: discover, decide, execute, inspect.

Use real results for multi-step work #

If one action creates a record needed by the next action, use the concrete ID returned by FlaskTrack.

workflow = call_tool({
    "name": "create_workflow",
    "input": workflow_input,
})

workflow_id = workflow["result"]["primary_id"]

batch = call_tool({
    "name": "create_batch",
    "input": {
        "name": "Agent-created batch",
        "workflow_id": workflow_id,
        "species_id": species_id,
        "planned_quantity": 24,
    },
})

Never invent future IDs Do not use strings such as

workflow_id_placeholder

. Execute the first operation, capture its authoritative result, and use that value in the next direct MCP call.

Optional: preview a mutation before execution #

Use /mcp/prepare

when your integration wants a validation or review step before direct execution.

def prepare_tool(tool_call):
    return flasktrack_post(
        "/mcp/prepare",
        {
            "name": tool_call["name"],
            "input": tool_call["input"],
        },
    )

Preparation does not execute the underlying operation. Use it for policy checks, logging, or a human confirmation surface.

Three rules that make agents dramatically safer #

Search before mutation If the agent does not know an exact record, use a FlaskTrack read tool first.

Respect entity types A Protocol UUID is not a Workflow UUID. Use the semantic type declared by the tool.

Stop on control failures Authorization, compliance, validation, and signature failures are authoritative. Do not route around them.

From demo agent to production integration #

  • ✔ Use a dedicated FlaskTrack service identity and minimum required permissions
  • ✔ Keep API keys outside model-visible context
  • ✔ Discover tools from the target deployment at runtime
  • ✔ Use read tools to resolve exact records before mutation
  • ✔ Validate typed entity relationships rather than accepting arbitrary UUIDs
  • ✔ Add explicit human approval for high-impact or mutating operations
  • ✔ Use bounded retries and timeouts
  • ✔ Preserve idempotency keys where supported or required
  • ✔ Log tool names, correlation IDs, statuses, and returned record IDs without secrets
  • ✔ Treat electronic-signature and compliance controls as server-authoritative

Build the agent around your laboratory #

Start with one read workflow, add one reviewed mutation, and expand only after the integration behaves predictably against real FlaskTrack records.

Start read-only

Begin with discovery, workflow lookup, batch status, or reporting before enabling mutation tools.

Add approval

Put a human or policy gate in front of creation, updates, completion, and other operational actions.

Expand deliberately

Add tools as the agent proves reliable rather than exposing every available mutation on day one.

Your agent can now operate on the same laboratory model as your team #

Full Biolab Integrated MCP Agent Example On Github

FlaskTrack gives agents a structured, permission-aware interface to laboratory records and operations without browser automation, direct database access, or a separate shadow data model.

── more in #ai-agents 4 stories · sorted by recency
── more on @flasktrack 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/build-your-first-fla…] indexed:0 read:6min 2026-08-19 ·