MCP server#

GLOW’s Solution API server can optionally expose a Model Context Protocol (MCP) server, allowing AI agents and MCP-compatible clients to interact with your solution programmatically.

When enabled, the MCP server is automatically mounted on the GLOW API server process. The MCP URL will be http://$SOLUTION_API_URL/$GLOW_MCP_PATH (default path: /sse). It’s independent of how you launch the API Server, either through SAF Desktop Orchestrator, with a Docker compose file, using the GLOW CLI or manually launching the server.

The MCP server provides resources listing the available tools and expected solution workflow, and tools for managing projects, setting and retrieving step fields, uploading and downloading entity handle files (including entity handles nested in lists, dictionaries, or custom objects), and running transaction methods, both sync and long running.

Important

This is an experimental feature and it’s disabled by default. The following limitations apply:

  • Not supporting uploading/downloading directories.

  • Not recommended to upload/download large files. At the moment, they are injected into the LLM context/output.

  • Not supporting websockets

  • Not supporting authentication. The MCP will be automatically disabled if GLOW_AUTH_DISABLED is set to false.

Enable the MCP server#

The following steps assume you are using SAF CLI to manage your solution. For different environments, adjust accordingly.

  1. Add the core-mcp extra to the ansys-saf-sdk dependency in your solution’s pyproject.toml. Afterwards, update your lock file and install the new dependencies:

    ansys-saf-sdk = {version = "^0.2.0", extras = ["core-mcp"]}
    
    saf execute my_solution "poetry lock"
    saf install my_solution
    
  2. In your solution’s .env file, enable MCP by setting:

    GLOW_MCP_DISABLED=False
    
  3. Run your solution. No need to launch the UI:

    saf run --no-ui
    
  4. Check the GLOW API logs and confirm that MCP is mounted. Look for an INFO line similar to:

    MCP mounted at path /sse
    

Configuration#

The MCP server is configured through the following environment variables:

MCP server environment variables#

Environment variable

Default

Description

GLOW_MCP_DISABLED

True

Set to False to enable the MCP server. When True, the MCP server is not started and none of the other MCP settings have any effect.

GLOW_MCP_PATH

/sse

The subpath at which the MCP server is mounted on the GLOW API server. For example, with the default value and the API running on http://localhost:8000, the MCP endpoint is reachable at http://localhost:8000/sse.

GLOW_MCP_TRANSPORT_MODE

http

The transport protocol used by the MCP server. Accepted values: http, streamable-http, sse.

The SOLUTION.md file#

The MCP server reads an optional Markdown file named SOLUTION.md located in the same directory as definition.py of your solution. This file provides custom human-readable context to the AI agent using the MCP server.

File format#

The file uses standard Markdown with two recognised level-2 headings:

 # My Solution

 <this will be ignored>

 ## Instructions

 <Content describing the purpose of the solution and any important constraints for the AI agent.
 This text is passed to the MCP server as its system-level instructions.>

 ## Workflow

 <A step-by-step description of how to use the solution.
This text is returned by the ``solution_workflow`` tool.>

 ## Other section

 <this will be ignored>

Both sections are optional and any other section will be ignored. If a section is missing, a default is generated.

Tip

Generic SAF concepts (what a project, step, field, or entity handle is, that transactions download and upload step fields, or that long-running transactions must be awaited with wait_for_longrunning_transaction) are already explained to the agent by the saf_concepts tool. Keep SOLUTION.md focused on what is specific to your solution: the meaning of its steps and fields, the order transactions must run in, and any domain constraints, rather than restating how SAF or its generic tools work.

Example#

# My Solution

## Instructions

This solution runs structural analyses using Ansys Mechanical.
Do not run `solve` until `setup_geometry` has completed successfully.

## Workflow

1. In a fresh project, upload the geometry file on the `pre_processing` step, field `geometry_file`.
2. Run `setup_geometry` to prepare the model.
3. Set mesh parameters on the `meshing` step.
4. Run `generate_mesh`.
5. Run `solve`.
6. Download the results on the `post_processing` step, field `result_file`.

Available tools#

Workflow guidance#

Workflow guidance tools#

Tool

Description

solution_workflow

Returns the step-by-step workflow guide for the solution, sourced from the ## Workflow section of SOLUTION.md. If the section is missing, a default generated from the available solution’s information is returned.

saf_concepts

Explains the generic SAF solution concepts (projects, steps, fields, entity handles, transactions, long-running transactions) that apply to every solution, regardless of its specific steps or fields.

Project management#

Project management tools#

Tool

Description

create_project

Creates a new project in the solution and returns its name. Accepts an optional display_name; if omitted, a name is generated automatically.

list_projects

Lists existing projects and their names, with optional pagination, ordering, and filtering. Use it to discover projects before using, exporting, or deleting them.

delete_projects

Deletes one or more projects and their data. This is destructive and irreversible. Deletion is attempted for every name, so a failure on one project does not prevent the others from being deleted. Returns the outcome per project name.

import_project

Imports a .safx project archive as a new project and returns its name. Because the archive is a binary zip, its content must be base64-encoded.

export_project

Exports a project as a .safx project archive. Because the archive is a binary zip, it is returned base64-encoded and must be decoded before being written to a file.

Data management#

Data management tools#

Tool

Description

set_fields

Sets one or more step field values on an existing project.

get_fields

Gets the current values of one or more step fields from an existing project.

upload_data

Uploads binary content to an EntityHandle step field on an existing project, including entity handles nested within a list, dictionary, or custom object field.

download_data

Downloads binary content from an EntityHandle step field on an existing project, including entity handles nested within a list, dictionary, or custom object field.

Addressing nested entity handles#

upload_data and download_data locate the target EntityHandle through their field_path argument, a slash-separated list of segments:

  • The first segment is always the step field name.

  • Each following segment navigates one level into the value stored in that field: a list index (0, 1, …), a dictionary key, or an attribute name of a custom (Pydantic model) object.

There is no depth limit, so arbitrary combinations of lists, dictionaries, and custom objects can be traversed:

field_path examples#

field_path

Field value it addresses

my_file

The step field my_file is itself an EntityHandle.

my_files/0

First item of the list stored in the my_files field.

my_files_map/geometry

Value under the geometry key of the dictionary stored in the my_files_map field.

my_object/file

The file attribute of the custom object stored in the my_object field.

my_object/files/0

First item of the files list of the custom object stored in the my_object field.

my_nested_map/inputs/mesh

Value under inputs → mesh of the nested dictionary stored in the my_nested_map field.

download_data returns the bytes referenced by the addressed entity handle. upload_data stores the given content as a new entity in the project storage, replaces the addressed entity handle with the new one, and writes the whole step field back, so the surrounding list, dictionary, or custom object is preserved.

Note

Both tools only read and replace entity handles that already exist at the given path. They do not create missing list items, dictionary keys, or object attributes.

Expected errors#

Both tools fail with an error (surfaced to the MCP client as a tool error) in the following cases:

upload_data and download_data errors#

Situation

Error message

The first segment is not a field of the step.

'<StepClass>' has no field(s) '<name>'.

A list index is not an integer.

'<segment>' is not a valid list index.

A list index is out of range.

List index '<segment>' does not exist.

A dictionary key is missing.

Dictionary key '<segment>' does not exist.

A custom object has no such attribute.

Field '<segment>' does not exist on '<ObjectClass>'.

A segment tries to navigate into a value that is not a list, dictionary, or custom object (for example, a string or a number).

Cannot navigate into a value of type '<type>' using segment '<segment>'.

The value addressed by the full path is not an EntityHandle.

Field path '<field_path>' does not refer to an entity handle field.

When upload_data fails, no entity handle is replaced and the step field is left unchanged.

Important

Directories are not supported: an entity handle referencing a directory cannot be uploaded or downloaded through these tools. Large files should also be avoided, since their content goes through the agent’s context.

Transaction execution#

Transaction execution tools#

Tool

Description

<step_name>__<transaction_name>

Runs a transaction method. One tool is registered per transaction method defined in the solution. If a regular synchronous transaction is called, it’s a blocking call and the result (if there is) is returned at the end. If a long-running transaction is called, the call ends immediately and returns nothing. Use the tool wait_for_longrunning_transaction to wait for the transaction to complete and retrieve its result (if any). The tool’s description starts with the transaction method’s docstring, if it has one (otherwise a default sentence naming the transaction and step is used), followed by the step fields it downloads and uploads, its arguments, and its return type.

wait_for_longrunning_transaction

Waits for a previously started long-running transaction to complete and returns its result.

Connect an MCP client#

Once the MCP server is running, connect any MCP-compatible client (for example, a GitHub Copilot agent, Claude Code, or a FastMCP client) to $SOLUTION_API_URL$GLOW_MCP_PATH.

Example using the FastMCP Python client, assuming the Solution API is running at http://localhost:8000 and the MCP server is mounted at the default value of /sse:

import asyncio
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport


async def main():
    transport = StreamableHttpTransport(url="http://localhost:8000/sse")
    async with Client(transport=transport) as client:
        resources = await client.list_resources()
        print([r.name for r in resources])
        tools = await client.list_tools()
        print([t.name for t in tools])


asyncio.run(main())