FFO MCP Server
Federal Frontier Ontology MCP server — 10 tools for querying, creating, and traversing the TypeDB knowledge graph.
Overview
The FFO MCP Server exposes the Federal Frontier Ontology (FFO) — a TypeDB 3.x knowledge graph containing the platform’s entity model — as 10 MCP tools. It answers “what is X?” questions: what entities exist, how they relate, what can be inferred. FFO is explicitly not an authorization system; authorization lives in PostgreSQL per ADR-001.
| Property | Value |
|---|---|
| Image | harbor.vitro.lan/ffp/ffo-mcp-server:v1.0.0 |
| Base | python:3.11-slim |
| Port | 50060 |
| Transport | SSE at /mcp/sse, messages at /mcp/messages/ |
| Namespace | f3iai |
| ArgoCD App | ffp-ffo-mcp |
| Source | ~/vscode/ffo-mcp-server/ |
Architecture
src/
main.py # FastAPI app, SSE transport, health/metrics endpoints
config.py # YAML + env var config (layered: defaults < YAML < env)
typedb_client.py # TypeDB 3.x driver wrapper — ALL queries go through here
models/ # Pydantic request/response models
tools/ # MCP tool handlers (one file per domain)
query.py # ffo.query
entity.py # ffo.entity.get, ffo.entity.create, ffo.entity.update
search.py # ffo.search
traverse.py # ffo.traverse
context.py # ffo.context.for_action
relationship.py # ffo.relationship.create
write.py # ffo.write
All tool handlers follow the same pattern: Pydantic request model -> handler function -> TypeDBClient method -> Pydantic response. Tool handlers never use the TypeDB driver directly; all database access goes through typedb_client.py.
Tools
Read Tools
ffo.query
Execute a raw TypeQL query against the ontology. Intended for advanced users who need full query flexibility.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | yes | TypeQL query string |
query_type |
string | no | read (default) or schema |
ffo.entity.get
Retrieve a single entity by type and name, including all its attributes.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type |
string | yes | TypeDB entity type (e.g., cluster, deployment) |
entity_name |
string | yes | Value of the entity’s name attribute |
ffo.search
Search entities by partial name match or attribute filters. Returns paginated results.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type |
string | yes | Entity type to search within |
query |
string | no | Partial name match |
limit |
integer | no | Max results (default 25) |
offset |
integer | no | Pagination offset |
ffo.traverse
Traverse relationships from a starting entity. Returns the entity’s neighbors — related entities connected via relations.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type |
string | yes | Starting entity type |
entity_name |
string | yes | Starting entity name |
relation_type |
string | no | Filter to a specific relation type |
depth |
integer | no | Traversal depth (default 1) |
ffo.infer
Query the ontology with TypeDB inference enabled (inference is always on in TypeDB 3.x). Returns inferred facts derived from rules defined in the schema.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | yes | TypeQL query that leverages inference rules |
Write Tools
ffo.entity.create
Create a new entity with attributes.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type |
string | yes | TypeDB entity type |
attributes |
object | yes | Key-value pairs of attributes to set |
ffo.entity.update
Update attributes on an existing entity.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type |
string | yes | Entity type |
entity_name |
string | yes | Entity to update |
attributes |
object | yes | Attributes to set or modify |
ffo.relationship.create
Create a relationship between two entities.
| Parameter | Type | Required | Description |
|---|---|---|---|
relation_type |
string | yes | Relation type (e.g., cluster_deployment) |
roles |
object | yes | Role-player mapping |
ffo.write
Execute a raw TypeQL write query. Use for bulk operations or complex inserts that don’t fit the structured create/update tools.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | yes | TypeQL write query |
Context Tools
ffo.context.for_action
Retrieve ontology context relevant to a planned action. Given an action description, returns the entities and relationships that an agent should consider before proceeding.
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | yes | Description of the planned action |
entity_type |
string | no | Scope to a specific entity type |
entity_name |
string | no | Scope to a specific entity |
Configuration
Configuration is layered: defaults < YAML file < environment variables. The YAML file path is set via FFO_CONFIG_PATH.
| Environment Variable | Alternatives | Default | Description |
|---|---|---|---|
TYPEDB_ADDRESS |
TYPEDB_HOST + TYPEDB_PORT |
localhost:1729 |
TypeDB server address |
FFO_DATABASE |
DATABASE_NAME |
ffo |
TypeDB database name |
TYPEDB_USERNAME |
TYPEDB_USER |
admin |
TypeDB username |
TYPEDB_PASSWORD |
— | — | TypeDB password |
FFO_SERVER_PORT |
— | 8080 (k8s uses 50060) |
Server listen port |
TypeDB 3.x Driver Notes
The FFO server uses the typedb-driver 3.8.0 Python package. Key differences from TypeDB 2.x:
- No sessions — transactions are opened directly:
driver.transaction(database, TransactionType) - Queries return Promises — you must call
.resolve()on query results - Fetch syntax uses curly braces:
fetch { $x.* }notfetch $x: *; - limit/offset before fetch:
match ...; limit N; fetch { ... }; - has clauses chain:
$e isa cluster, has name "foo"(no repeated$e) - Inference is always on — there is no toggle
Health and Readiness
| Endpoint | Purpose |
|---|---|
/health |
Liveness probe — returns 200 if the process is running |
/ready |
Readiness probe — returns 200 only if TypeDB is reachable |
/metrics |
Prometheus metrics (request counts, durations, TypeDB query counts) |
Testing
# Unit tests — mocked TypeDB, no tunnel needed (22 tests)
pytest tests/test_tools.py -v
# Integration tests — requires SSH tunnel to TypeDB pod (16 tests)
TYPEDB_ADDRESS=localhost:1729 TYPEDB_USERNAME=admin TYPEDB_PASSWORD=password \
FFO_INTEGRATION_TESTS=1 pytest tests/test_integration.py -v
Unit tests mock the TypeDBClient class and validate that tool handlers correctly translate Pydantic requests into TypeQL queries and parse responses. Integration tests require a live TypeDB instance (tunnel to the pod in f3iai).
Deployment
The FFO MCP server is deployed via ArgoCD application ffp-ffo-mcp into the f3iai namespace. The Dockerfile uses python:3.11-slim as the base image.
# Build and push (run on texas-dell-04)
docker build -t harbor.vitro.lan/ffp/ffo-mcp-server:v1.0.0 .
docker push harbor.vitro.lan/ffp/ffo-mcp-server:v1.0.0
TypeDB is a ClusterIP service in the same namespace — there is no NodePort. For local development, tunnel to the TypeDB pod IP:
ssh -fN -L 1729:<pod-ip>:1729 ubuntu@texas-dell-04