Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,44 @@ go run .\example\readme.go
"2. Bus Fault on: 28 ARIZONA 132. kV 1LG Type=A" Ia:2890.36∠-81.2° Ib:0.00∠-42.4° Ic:0.00∠-143.8°
```

## MCP Server (Beta/Untested)

An MCP (Model Context Protocol) server is included at `cmd/mcp-server/`, allowing LLMs like Claude to interact directly with loaded Oneliner cases over stdio.

### Build

```bash
GOOS=windows GOARCH=386 go build -o mcp-server.exe ./cmd/mcp-server/
```

### Available Tools

| Tool | Description |
|------|-------------|
| `load_case` | Load an .olr file (read-only) or check current file |
| `get_system_info` | System summary: equipment counts, base MVA |
| `find_bus` | Look up a bus by name+kV or bus number |
| `list_equipment` | List equipment, optionally filtered by bus |
| `get_equipment` | Detailed data for specific equipment |
| `run_fault` | Run fault simulation and return currents/voltages |
| `run_stepped_event` | Run stepped event analysis with relay timeline |

### Claude Desktop Configuration

Add to your Claude Desktop `claude_desktop_config.json`:

```json
{
"mcpServers": {
"goolx": {
"command": "C:\\path\\to\\mcp-server.exe"
}
}
}
```

> **Note**: This feature is beta and has not been tested against a live OlxAPI DLL. The MCP server requires the same ASPEN Oneliner license and DLL as the main library.

## Disclaimer
This project is not endorsed or affiliated with ASPEN Inc.

Expand Down
44 changes: 44 additions & 0 deletions cmd/mcp-server/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"strings"

"github.com/readpe/goolx"
)

// formatBus formats a Bus for LLM-readable output.
func formatBus(b *goolx.Bus) string {
var sb strings.Builder
fmt.Fprintf(&sb, "Bus: %s\n", b.Name)
fmt.Fprintf(&sb, " Handle: %d\n", b.Hnd)
fmt.Fprintf(&sb, " kV: %0.2f\n", b.KVNominal)
fmt.Fprintf(&sb, " Area: %d\n", b.Area)
fmt.Fprintf(&sb, " Zone: %d\n", b.Zone)
fmt.Fprintf(&sb, " Location: %s\n", b.Location)
return sb.String()
}

// formatLine formats a Line for LLM-readable output.
func formatLine(l *goolx.Line) string {
var sb strings.Builder
fmt.Fprintf(&sb, "Line: %s\n", l)
fmt.Fprintf(&sb, " Handle: %d\n", l.Hnd)
fmt.Fprintf(&sb, " Name: %s\n", l.Name)
fmt.Fprintf(&sb, " In Service: %d\n", l.InService)
fmt.Fprintf(&sb, " Length: %0.2f %s\n", l.Length, l.LengthUnit)
fmt.Fprintf(&sb, " R/X: %0.5f / %0.5f pu\n", l.R, l.X)
fmt.Fprintf(&sb, " R0/X0: %0.5f / %0.5f pu\n", l.R0, l.X0)
if l.Bus1 != nil {
fmt.Fprintf(&sb, " Bus1: %s (handle %d)\n", l.Bus1, l.Bus1.Hnd)
}
if l.Bus2 != nil {
fmt.Fprintf(&sb, " Bus2: %s (handle %d)\n", l.Bus2, l.Bus2.Hnd)
}
return sb.String()
}

// formatPhasors formats three phase phasors as a single line.
func formatPhasors(label string, a, b, c goolx.Phasor) string {
return fmt.Sprintf(" %s: A=%s B=%s C=%s", label, a, b, c)
}
39 changes: 39 additions & 0 deletions cmd/mcp-server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// cmd/mcp-server provides an MCP (Model Context Protocol) server for interacting
// with ASPEN Oneliner power system cases via goolx. It exposes read-only tools
// for querying equipment, running fault analysis, and inspecting results.
//
// Usage:
//
// mcp-server
//
// The server communicates over stdio using the MCP protocol.
package main

import (
"context"
"log"
"os"
"os/signal"

"github.com/modelcontextprotocol/go-sdk/mcp"
"github.com/readpe/goolx"
)

func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

client := goolx.NewClient()
defer client.Release()

server := mcp.NewServer(&mcp.Implementation{
Name: "goolx-mcp-server",
Version: "0.1.0",
}, nil)

registerTools(server, client)

if err := server.Run(ctx, &mcp.StdioTransport{}); err != nil {
log.Fatal(err)
}
}
Loading