Build your first FlaskTrack MCP agent
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.
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.
/mcp/tools./mcp/call.Before you start
Create a FlaskTrack API credential for the integration and keep it outside your prompt, source code, browser JavaScript, and model context.
requests, and any model client you prefer.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"),
)
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,
},
})
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
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 GithubFlaskTrack gives agents a structured, permission-aware interface to laboratory records and operations without browser automation, direct database access, or a separate shadow data model.