Skip to main content
Glama

Forgeline

Read-only Modbus TCP monitoring, exposed as safe MCP tools.

CI License: Apache 2.0

Forgeline is an MCP server that lets an AI agent monitor an industrial Modbus TCP device — reading holding/input registers, coils, and device identity — without being able to change anything.

It's read-only on purpose: there are no write or command tools, and no code that writes coils or registers, so a connected agent can't alter device state.

A simulated Modbus device is bundled, so you can run it with no hardware.

Status

Working MVP. Four read-only tools — get_device_info, read_holding_registers, read_input_registers, read_coils — tested against the bundled simulator.

Related MCP server: safe-postgres-mcp

Project layout

forgeline/
├── src/forgeline/
│   ├── server.py        # FastMCP server: registers MCP tools
│   └── tools.py         # Read-only Modbus implementations (transport-agnostic)
├── simulator/
│   └── device.py        # Bundled pymodbus TCP simulator (zero hardware)
├── docker-compose.yml   # Starts simulator + server together
├── Dockerfile
├── pyproject.toml
├── README.md
└── LICENSE              # Apache 2.0

Quick start

Option A — Docker (simulator + server, one command)

docker compose up --build

This starts:

  • simulator — a virtual Modbus device on localhost:5020.

  • forgeline — the MCP server over streamable-http at http://localhost:8000/mcp, already pointed at the simulator.

Option B — Local Python

Requires Python 3.10+.

pip install -e .

# Terminal 1: start the bundled simulator
forgeline-simulator

# Terminal 2: run the MCP server (stdio transport, for an MCP client)
forgeline

By default the server talks to the simulator on 127.0.0.1:5020.

Configuration

All configuration is via environment variables.

Variable

Default

Description

MODBUS_HOST

127.0.0.1

Host of the Modbus TCP device to monitor.

MODBUS_PORT

5020

Port of the Modbus TCP device.

MODBUS_UNIT_ID

1

Modbus unit / slave id.

MODBUS_TIMEOUT

3.0

Per-request timeout in seconds.

FORGELINE_TRANSPORT

stdio

MCP transport: stdio, sse, or streamable-http.

FORGELINE_HOST

127.0.0.1

Bind host for HTTP transports.

FORGELINE_PORT

8000

Bind port for HTTP transports.

SIMULATOR_HOST

0.0.0.0

Bind host for the bundled simulator.

SIMULATOR_PORT

5020

Bind port for the bundled simulator.

Connecting an MCP client

To launch Forgeline over stdio (e.g. from Claude Desktop or another MCP client), register a server that runs the forgeline command. Example client config:

{
  "mcpServers": {
    "forgeline": {
      "command": "forgeline",
      "env": { "MODBUS_HOST": "127.0.0.1", "MODBUS_PORT": "5020" }
    }
  }
}

(Start forgeline-simulator first, or point MODBUS_HOST/MODBUS_PORT at a real device.)

Tools

get_device_info

Returns identity and connection details for the monitored device.

{
  "host": "127.0.0.1",
  "port": 5020,
  "unit_id": 1,
  "connected": true,
  "device_identification_supported": true,
  "identity": {
    "vendor_name": "Forgeline",
    "product_code": "FL-SIM-1",
    "revision": "1.0.0",
    "vendor_url": "https://github.com/codenikhildr/Forgeline",
    "product_name": "Forgeline Modbus Simulator",
    "model_name": "Virtual PLC",
    "user_application_name": "Forgeline MVP Simulator"
  }
}

Devices that do not implement Modbus device identification still return connection details, with device_identification_supported: false.

read_holding_registers / read_input_registers

Read 16-bit registers — holding (FC 0x03, read/write on the device) or input (FC 0x04, read-only measurements). Parameters:

Param

Type

Default

Bounds

address

int

065535

count

int

1

1125 (Modbus FC03/04 limit)

// read_holding_registers(address=0, count=5)
{
  "start_address": 0,
  "count": 5,
  "unit_id": 1,
  "values": [
    { "address": 0, "value": 100 },
    { "address": 1, "value": 101 },
    { "address": 2, "value": 102 },
    { "address": 3, "value": 103 },
    { "address": 4, "value": 104 }
  ]
}

read_coils

Read single-bit on/off coils (FC 0x01). Parameters:

Param

Type

Default

Bounds

address

int

065535

count

int

1

12000 (Modbus FC01 limit)

// read_coils(address=0, count=4)
{
  "start_address": 0,
  "count": 4,
  "unit_id": 1,
  "values": [
    { "address": 0, "value": false },
    { "address": 1, "value": true },
    { "address": 2, "value": false },
    { "address": 3, "value": true }
  ]
}

Requests outside these bounds (count over the limit, or a range that exceeds the 16-bit address space) are rejected before any request reaches the device.

Simulator data map

The bundled simulator pre-populates each table (addresses are zero-based):

Table

FC

Addresses

Values

Holding registers

0x03

0–99

100 + addr

Input registers

0x04

0–99

200 + addr

Coils

0x01

0–99

addr % 2

Discrete inputs

0x02

0–99

(addr+1) % 2

Development

Run the test suite — it starts the bundled simulator on a test port and exercises all four tools plus the input-validation guards:

pip install -e ".[dev]"
pytest

CI runs the same suite on every push and pull request across Python 3.10–3.12.

License

Apache License 2.0. See LICENSE.

Available Tools

4 tools
get_device_infoA

Get identity and connection details for the monitored Modbus device.

Returns the device's vendor, product code, revision and related fields (when the device supports Modbus device identification), plus the host, port and unit id Forgeline is connected to. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description declares the tool is 'Read-only', which is a key behavioral trait. It also notes that certain fields are conditional ('when the device supports...'), providing transparency beyond the empty schema. No annotations are present, so the description fully handles transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the main action, and every sentence adds value. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description thoroughly explains what is returned (vendor, product code, revision, host, port, unit id). It is sufficient for an AI to understand the tool's output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so schema_description_coverage is 100%. Per guidelines, baseline is 4. No additional parameter information is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves identity and connection details for a Modbus device. It uses a specific verb 'Get' and specifies the resource (device info). The sibling tools read coils/registers, which are distinct, so this tool is well differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives. It implies usage for device identity and connection details, but no when-not or alternative references are provided. However, the context is clear enough from the sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_coilsA

Read coils (FC 0x01) from the monitored Modbus device.

Coils are single-bit on/off values. Returns the start address, count, unit id, and a list of address -> boolean value pairs. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesZero-based start address (0..65535).
countNoNumber of coils to read (1..2000).

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It clearly states 'Read-only' and describes the return structure (start address, count, unit id, list of address->boolean pairs). This sufficiently discloses that the operation is safe and has no side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise—three sentences with no fluff: purpose, explanation of coils, and return value structure. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool is simple and no output schema exists, the description adequately covers the return components. Missing are error conditions and prerequisites (e.g., device connection), but for a basic read operation the description is largely complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already describes both parameters well. The description adds context about coils being 'single-bit on/off values' but does not expand on parameter meaning beyond the schema. Baseline 3 is appropriate; the description adds marginal value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific verb 'read' and resource 'coils' and includes the function code (FC 0x01). It distinguishes from siblings like 'read_holding_registers' by specifying it reads single-bit values, making the tool's purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool vs. alternatives. It does not mention when not to use it or compare to sibling tools. The sibling names are listed externally but not referenced in the description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_holding_registersB

Read holding registers (FC 0x03) from the monitored Modbus device.

Holding registers are 16-bit read/write values (Forgeline reads them only). Returns the start address, count, unit id, and a list of address -> value pairs. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesZero-based start address (0..65535).
countNoNumber of registers to read (1..125).

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the burden. It correctly states the tool is read-only and describes the return format (start address, count, unit id, list of address->value pairs). However, it does not disclose potential error conditions, timeouts, or concurrency behavior, leaving gaps in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (2 sentences) and front-loads the key purpose with the function code. It efficiently covers the operation, data type, and return structure without unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately describes the return structure. It covers the essential aspects of the operation for a simple read tool. However, it omits details like the unit id source or defaults, which could be inferred but are not explicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage for both parameters (address and count) with clear ranges and defaults. The description adds no new information about parameter semantics beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads holding registers using Modbus function code 0x03, specifying the data type (16-bit read/write values). It implicitly distinguishes from siblings like read_coils and read_input_registers by name and context, but could be more explicit about differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives or any prerequisites. It mentions 'Read-only' but does not specify when not to use it or any preconditions for the Modbus device.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_input_registersA

Read input registers (FC 0x04) from the monitored Modbus device.

Input registers are 16-bit read-only measurements. Returns the start address, count, unit id, and a list of address -> value pairs.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesZero-based start address (0..65535).
countNoNumber of registers to read (1..125).

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It states the tool reads read-only input registers, implying no side effects, but does not elaborate on error behavior, potential delays, or other operational traits. Adequate but not comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with action and context. Every word is purposeful with no redundancy. Efficient and clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with two well-documented parameters, the description covers the purpose, register type, and return format. Lacks only finer behavioral details, but overall complete given the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline 3. The description only mentions address and count as part of the return but adds no additional meaning or syntax details beyond what the schema provides. No new parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads input registers via Modbus function code 0x04, specifying they are 16-bit read-only measurements. This distinguishes it from sibling tools like read_coils and read_holding_registers by naming the specific register type and function code.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading input registers but provides no explicit guidance on when to use this tool versus alternatives like read_holding_registers. No exclusion criteria or context for selection are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 4 tool updatesv0.1.0
    • First observedget_device_info
    • First observedread_coils
    • First observedread_holding_registers
    • First observedread_input_registers

TDQS

A4/5.0
Disambiguation5/5

Each tool has a distinct purpose: get_device_info for identity/connection, read_coils for single-bit values, read_holding_registers for 16-bit read/write registers, and read_input_registers for 16-bit read-only registers. No overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern using lowercase and underscores (e.g., get_device_info, read_coils). The naming convention is uniform and predictable.

Tool Count5/5

With 4 tools, the server is well-scoped for its purpose of monitoring a Modbus device. The count is within the ideal range of 3-15 tools and covers essential read operations without unnecessary bloat.

Completeness4/5

The tool set covers device identity and the three primary read function codes (coils, holding registers, input registers) for Modbus monitoring. A minor gap is the absence of reading discrete inputs (FC 0x02), but this is a reasonable omission for a basic monitoring server.

Maintenance

ActivityInactive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    This MCP server enables AI agents to read MQTT and Sparkplug B data via tools like list_topics, get_latest, and read_all, providing read-only access to latest sensor values.
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A zero-config, read-only PostgreSQL MCP server that enforces read-only access at the database level using READ ONLY transactions, allowing AI agents to safely explore schemas and run SELECT queries without risk of mutation.
    49
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Read-only MCP server for diagnosing H7-TOOL hardware via Modbus, USB HID, and Lua diagnostics, exposing only safe read operations.
    10
    -
  • F
    license
    A
    quality
    C
    maintenance
    A secure, read-only MCP server for AI-powered system monitoring. It provides real-time OS metrics, config discovery, and safe log tailing to enable autonomous infrastructure audits without shell access risks.
    4
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/codenikhildr/Forgeline'

If you have feedback or need assistance with the MCP directory API, please join our Discord server