使用说明
Waveform MCP Server
An MCP (Model Context Protocol) server for reading and analyzing waveform files (VCD/FST format) using the wellen library.
Usage
Installation
Install via cargo:
cargo install waveform-mcp
The built binary will be at ~/.cargo/bin/waveform-mcp.
Install manually:
# Clone the repository
git clone https://github.com/jiegec/waveform-mcp
cd waveform-mcp
# Build the server
cargo build --release
The built binary will be at target/release/waveform-mcp.
Running
# Run the server with stdio transport (default)
target/release/waveform-mcp
# Run the server in HTTP mode
target/release/waveform-mcp --http
# Run the server in HTTP mode with custom bind address
target/release/waveform-mcp --http --bind-address 0.0.0.0:8000
The server supports two transport modes:
- Stdio mode (default): Uses standard input/output for MCP communication
- HTTP mode: Uses streamable HTTP server for remote access at
/mcpendpoint
When running in HTTP mode, the server listens on the specified bind address (default: 127.0.0.1:8000). HTTP mode allows the waveform store to be shared across multiple HTTP sessions, enabling remote analysis of waveform files.
Features
- Open VCD (Value Change Dump) and FST (Fast Signal Trace) waveform files
- List all signals in a waveform with hierarchical paths
- Read the waveform module hierarchy as an indented tree
- Read signal values at specific time indices (single or multiple)
- Get signal metadata (type, width, index range)
- Find signal events (changes) within a time range
- Format time values with timescale information (e.g., "10ns", "5000ps")
- Streamable HTTP server support for remote access
Tools
The server provides 8 MCP tools:
-
open_waveform - Open a waveform file
file_path: Path to .vcd or .fst filealias: Optional alias for the waveform (defaults to filename)overwrite: Optional flag to reopen a waveform whose id is already open (default: false); otherwise opening an id twice is an error
When the file does not exist, files with a similar name in the same directory are suggested. Failures are reported as tool errors, like every other tool.
Example response:
Waveform opened successfully with alias: waveform.vcd -
close_waveform - Close a waveform and free its memory
waveform_id: ID or alias of the waveform to close
Example response:
Waveform 'waveform.vcd' closed successfully -
list_signals - List all signals in an open waveform
waveform_id: ID or alias of the waveformpattern: Optional pattern (a string or an array of strings) matched against the full signal path, e.g.tb.dut.abc_bank. Multiple patterns are OR-edmatch_mode: Howpatternis interpreted (default:substring)substring- case-insensitive substring match (the pattern is a literal fragment)glob- case-insensitive glob over the whole path:*(any characters, including dots),?(one character),[0-9],{a,b}— e.g.*bank*,tb.*.clkregex- regular expression, case-insensitive by default (use(?-i)to opt out)
hierarchy_prefix: Optional prefix to filter signals by hierarchy path (AND-ed withpattern)recursive: Optional flag to include signals from sub-hierarchies (default: true)limit: Optional maximum number of signals to return (default: 100)
Invalid glob or regex patterns are reported as errors rather than silently matching nothing, and when nothing matches the response suggests the closest signal paths.
Example response:
Found 3 signals: top.clock top.reset top.data -
read_hierarchy - Read the waveform module hierarchy as an indented tree
waveform_id: ID or alias of the waveformscope_path: Optional scope path to start fromrecursive: Optional flag to include descendants (default: false)limit: Optional maximum number of modules to return (default: 200)
Example response:
Hierarchy rooted at 'top': top submodule -
read_signal - Read signal values at specific time indices
waveform_id: ID or alias of the waveformsignal_path: Hierarchical path to signal (e.g., "top.module.signal")time_index: Optional single time index to read (provide exactly one oftime_indexortime_indices)time_indices: Optional array of time indices to read multiple values
Example response:
Time index 0 (0ns): 0 Time index 10 (10ns): 1 Time index 20 (20ns): 1 -
get_signal_info - Get metadata about a signal
waveform_id: ID or alias of the waveformsignal_path: Hierarchical path to signal
Example response:
Signal: top.data Type: Wire Width: 8 bits Index: [7:0] -
find_signal_events - Find all signal changes within a time range
waveform_id: ID or alias of the waveformsignal_path: Hierarchical path to signalstart_time_index: Optional start of time range (default: 0)end_time_index: Optional end of time range (default: last time index)limit: Optional maximum number of events to return (default: unlimited)
Example response:
Found 3 events for signal 'top.clock' (time range: 0 to 20): Time index 0 (0ns): 0 Time index 10 (10ns): 1 Time index 20 (20ns): 0 -
find_conditional_events - Find events where a condition is satisfied
waveform_id: ID or alias of waveformcondition: Conditional expression to evaluatestart_time_index: Optional start of time range (default: 0)end_time_index: Optional end of time range (default: last time index)limit: Optional maximum number of events to return (default: 100)
Example response:
Found 2 events for condition '!$past(TOP.signal) && TOP.signal' (time range: 0 to 50): Time index 5 (50ns): top.signal = 8'h0A Time index 15 (150ns): top.signal = 8'hFFSupported condition syntax:
- Signal paths (e.g.,
TOP.signal) - Bitwise operators:
~(NOT),&(AND),|(OR),^(XOR) - Boolean operators:
&&(AND),||(OR),!(NOT) - Comparison operators:
==,!= - Parentheses for grouping:
(condition) $past(signal)- read signal value from previous time index- Verilog-style literals:
4'b0101(binary),3'd2(decimal),5'h1A(hex) - Bit extraction:
signal[bit]for single bit,signal[msb:lsb]for range
Operator precedence (highest to lowest):
~,!(bitwise NOT, logical NOT)==,!=(equality/inequality)&(bitwise AND)^(bitwise XOR)|(bitwise OR)&&(logical AND)||(logical OR)
Examples:
- Find when signal1 AND signal2 are true:
TOP.signal1 && TOP.signal2 - Find when counter equals a specific value:
TOP.counter == 4'd10 - Find rising edge:
!$past(TOP.signal) && TOP.signal - Find falling edge:
$past(TOP.signal) && !TOP.signal - Find handshake cycles (when both valid and ready are asserted):
TOP.valid && TOP.ready - Complex condition:
(TOP.valid && TOP.data != 8'hFF) || TOP.error - Bitwise operations:
TOP.flags & 4'b0001(check if bit 0 is set) - Bitwise NOT:
~TOP.mask(invert all bits)
Standalone CLI
In addition to the MCP server, a standalone CLI tool waveform-cli is available for direct command-line access without an MCP client.
CLI Usage
# Help
waveform-cli --help # general usage
waveform-cli help list_signals # detailed help for one command
waveform-cli list_signals --help # same as above
# Basic command
waveform-cli open_waveform /path/to/waveform.vcd
# Chain multiple commands with --
waveform-cli open_waveform test.vcd -- list_signals test.vcd --contains clk
# Full workflow example
waveform-cli open_waveform test.vcd --alias mywave -- \\
list_signals mywave -- \\
read_signal mywave top.clk --time-indices 0,1,2,3 -- \\
close_waveform mywave
CLI Commands
- open_waveform
<file_path>[--alias<name>] [--overwrite] - Open waveform file (--overwritereopens a waveform that is already open) - close_waveform
<id>- Close waveform - list_signals
<id>[--contains<p>] [--glob<p>] [--regex<p>] [--hierarchy<h>] [--recursive<bool>] [--limit<n>]--contains/-p/--pattern: case-insensitive substring match (default)--glob/-g: case-insensitive glob over the whole path, e.g.--glob '*bank*'--regex/-x: regular expression, case-insensitive by default- The three flags are mutually exclusive: the flag you use selects the match mode, and it
applies to the whole command. Repeat the same flag to OR several patterns together, e.g.
--glob '*bank*' --glob '*ram*' --patternis an alias of--contains
- read_hierarchy
<id>[--scope<scope>] [--recursive<bool>] [--limit<n>] - read_signal
<id><signal>[--time-index<idx>| --time-indices<list>] - get_signal_info
<id><signal>- Get signal metadata - find_signal_events
<id><signal>[--start<idx>] [--end<idx>] [--limit<n>] - find_conditional_events
<id><condition>[--start<idx>] [--end<idx>] [--limit<n>]
Every command also accepts --help/-h, and waveform-cli --version prints the version.
Options accept both --flag value and --flag=value; use the = form when the value itself
starts with - (for example --contains=-h).
Development
Building
cargo build
cargo build --release
Testing
cargo test