Skip to content

Commit 018f50a

Browse files
authored
Merge pull request #31 from perses/ibakshay/add-read-only-flag
[FEATURE]: Add read-only mode for Perses MCP Server
2 parents f8ec8dd + 3da9d4d commit 018f50a

File tree

2 files changed

+66
-29
lines changed

2 files changed

+66
-29
lines changed

README.md

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
> [!WARNING]
77
> This MCP Server is currently in **beta**. Features and tools may change, and stability is not guaranteed. Feedback and contributions are most welcome!
88
9-
109
## Overview
1110

1211
The Perses MCP Server is a local [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) Server that enables the LLM hosts(Claude Desktop, VS Code, Cursor) to interact with the Perses Application in a standardized way.
@@ -29,12 +28,13 @@ https://github.com/user-attachments/assets/87137515-1b45-442d-a4c9-68f460a1ba4c
2928
<summary>VS Code with GitHub Copilot</summary>
3029

3130
https://github.com/user-attachments/assets/b80c354a-8006-4e1f-b7f4-e123002f7dc3
32-
</details>
3331

32+
</details>
3433

3534
## Usage
3635

3736
### Pre-requisites
37+
3838
- [percli](https://perses.dev/perses/docs/cli/)
3939
- `PERSES_TOKEN`
4040

@@ -46,14 +46,16 @@ https://github.com/user-attachments/assets/b80c354a-8006-4e1f-b7f4-e123002f7dc3
4646
percli login <PERSES_SERVER_URL>
4747
```
4848

49-
For example, `percli login https://demo.perses.dev`.
49+
For example, `percli login https://demo.perses.dev`.
5050

51-
Or `percli login http://localhost:8080` if you are running [perses/perses](https://github.com/perses/perses) locally from the source code or from the perses image.
51+
Or `percli login http://localhost:8080` if you are running [perses/perses](https://github.com/perses/perses) locally from the source code or from the perses image.
5252

5353
2. After successful login, retrieve your token:
54+
5455
```bash
5556
percli whoami --show-token
5657
```
58+
5759
Copy the token to use in your MCP server configuration.
5860

5961
**WARNING: Your login will automatically expire in 15 minutes**. If you want to extend the token duration, you can change the `access_token_ttl` setting in the Perses app [configuration](https://perses.dev/perses/docs/configuration/configuration/?h=configu), then restart the app (if running locally) or rebuild the Docker image.
@@ -67,7 +69,7 @@ To add this MCP server to [Claude Desktop](https://claude.ai/download):
6769
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
6870
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
6971
- Linux: `~/.config/Claude/claude_desktop_config.json`
70-
72+
7173
You can easily access this file via the Claude Desktop app by navigating to `Claude > Settings > Developer > Edit Config`.
7274

7375
2. Get the binary
@@ -87,9 +89,10 @@ You have two options to obtain the MCP server binary:
8789

8890
**Option B: Build from Source**
8991

90-
```bash
91-
make build
92+
```bash
93+
make build
9294
```
95+
9396
This should create a `bin` directory which contains the binary named `mcp-server`. Copy the absolute path to the binary to use in your MCP server configuration.
9497

9598
3. Add the following JSON block to the configuration file:
@@ -102,6 +105,7 @@ This should create a `bin` directory which contains the binary named `mcp-server
102105
"args": [
103106
"--perses-server-url",
104107
"<PERSES_SERVER_URL>"
108+
// Add "--read-only" here for read-only mode
105109
],
106110
"env": {
107111
"PERSES_TOKEN": "<PERSES_TOKEN>"
@@ -118,6 +122,7 @@ This should create a `bin` directory which contains the binary named `mcp-server
118122
To integrate the MCP server with VS Code GitHub Copilot, follow these steps:
119123

120124
1. Open User Settings (JSON) in VS Code:
125+
121126
- Press `Cmd + Shift + P` (on macOS) or `Ctrl + Shift + P` (on other platforms).
122127
- Type `Preferences: Open User Settings (JSON)` and select it.
123128

@@ -139,6 +144,7 @@ To integrate the MCP server with VS Code GitHub Copilot, follow these steps:
139144
"args": [
140145
"--perses-server-url",
141146
"http://localhost:8080"
147+
// Add "--read-only" here for read-only mode
142148
],
143149
"env": {
144150
"PERSES_TOKEN": "${input:perses-token}"
@@ -152,32 +158,35 @@ To integrate the MCP server with VS Code GitHub Copilot, follow these steps:
152158

153159
## Tools
154160

161+
> [!NOTE]
162+
> When running in read-only mode (`--read-only` flag), only tools that retrieve information are available. Write operations like `create_project`, `create_dashboard`, `create_global_datasource`, `update_global_datasource`, and `create_project_variable` are disabled in read-only mode.
163+
155164
### Projects
156165

157166
| Tool | Description | Required Parameters |
158167
| ---------------------------- | --------------------- | ------------------- |
159168
| `perses_list_projects` | List all projects | - |
160-
| `perses_get_project_by_name` | Get a project by name | `project` |
161-
| `perses_create_project` | Create a new project | `project` |
169+
| `perses_get_project_by_name` | Get a project by name | `project` |
170+
| `perses_create_project` | Create a new project | `project` |
162171

163172
### Dashboards
164173

165174
| Tool | Description | Required Parameters |
166-
| ------------------------------ | ------------------------------------------------------------- | ---------------------- |
175+
| ------------------------------ | -------------------------------------------------------------- | ---------------------- |
167176
| `perses_list_dashboards` | List all dashboards for a specific project | `project` |
168177
| `perses_get_dashboard_by_name` | Get a dashboard by name for a project | `project`, `dashboard` |
169178
| `perses_create_dashboard` | Create a dashboard given a project and dashboard configuration | `project`, `dashboard` |
170179

171-
For dashboard configuration, see [Perses Dashboards](https://github.com/perses/perses/blob/main/docs/api/dashboard.md)
180+
For dashboard configuration, see [Perses Dashboards](https://github.com/perses/perses/blob/main/docs/api/dashboard.md)
172181

173182
### Datasources
174183

175-
| Tool | Description | Required Parameters | Optional Parameters |
176-
| --------------------------------------- | ------------------------------------------- | ----------------------- | ------------------- |
177-
| `perses_list_global_datasources` | List all global datasources | - | - |
178-
| `perses_list_datasources` | List all datasources for a specific project | `project` | - |
179-
| `perses_get_global_datasource_by_name` | Get a global datasource by name | `datasource` | - |
180-
| `perses_get_project_datasource_by_name` | Get a project datasource by name | `project`, `datasource` | - |
184+
| Tool | Description | Required Parameters | Optional Parameters |
185+
| --------------------------------------- | ------------------------------------------- | ----------------------- | ---------------------------- |
186+
| `perses_list_global_datasources` | List all global datasources | - | - |
187+
| `perses_list_datasources` | List all datasources for a specific project | `project` | - |
188+
| `perses_get_global_datasource_by_name` | Get a global datasource by name | `datasource` | - |
189+
| `perses_get_project_datasource_by_name` | Get a project datasource by name | `project`, `datasource` | - |
181190
| `perses_create_global_datasource` | Create a new global datasource | `name`, `type`, `url` | `display_name`, `proxy_type` |
182191
| `perses_update_global_datasource` | Update an existing global datasource | `name`, `type`, `url` | `display_name`, `proxy_type` |
183192

@@ -208,6 +217,7 @@ For dashboard configuration, see [Perses Dashboards](https://github.com/perses/p
208217
| `perses_get_global_variable_by_name` | Get a global variable by name | `variable` |
209218
| `perses_list_variables` | List all variables for a specific project | `project` |
210219
| `perses_get_project_variable_by_name` | Get a project variable by name | `project`, `variable` |
220+
| `perses_create_project_variable` | Create a project level variable | `name`, `project` |
211221

212222
## License
213223

main.go

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import (
1717
var (
1818
persesServerURL string
1919
logLevel string
20+
readOnly bool
2021
)
2122

2223
const PERSES_TOKEN = "PERSES_TOKEN"
2324

2425
func init() {
2526
flag.StringVar(&persesServerURL, "perses-server-url", "http://localhost:8080", "The Perses backend server URL")
2627
flag.StringVar(&logLevel, "log-level", "info", "Log level (debug, info, warn, error)")
28+
flag.BoolVar(&readOnly, "read-only", false, "Restrict the server to read-only operations")
2729
flag.Parse()
2830

2931
// configure logging
@@ -51,25 +53,37 @@ func main() {
5153
server.WithLogging(),
5254
)
5355

54-
slog.Info("Starting Perses MCP server using stdio transport")
56+
if readOnly {
57+
slog.Info("Starting Perses MCP server in READ-ONLY mode")
58+
} else {
59+
slog.Info("Starting Perses MCP server in FULL-ACCESS mode")
60+
}
61+
62+
addReadOnlyTools(mcpServer, persesClient)
63+
64+
if !readOnly {
65+
addWriteTools(mcpServer, persesClient)
66+
}
5567

56-
//Project
68+
if err := server.ServeStdio(mcpServer); err != nil {
69+
slog.Error("Error starting server", "error", err)
70+
}
71+
}
72+
73+
func addReadOnlyTools(mcpServer *server.MCPServer, persesClient apiClient.ClientInterface) {
74+
// Project
5775
mcpServer.AddTool(tools.ListProjects(persesClient))
5876
mcpServer.AddTool(tools.GetProjectByName(persesClient))
59-
mcpServer.AddTool(tools.CreateProject(persesClient))
6077

61-
//Dashboard
78+
// Dashboard
6279
mcpServer.AddTool(tools.ListDashboards(persesClient))
6380
mcpServer.AddTool(tools.GetDashboardByName(persesClient))
64-
mcpServer.AddTool(tools.CreateDashboard(persesClient))
6581

66-
//Datasource
82+
// Datasource
6783
mcpServer.AddTool(tools.ListGlobalDatasources(persesClient))
6884
mcpServer.AddTool(tools.ListProjectDatasources(persesClient))
6985
mcpServer.AddTool(tools.GetGlobalDatasourceByName(persesClient))
7086
mcpServer.AddTool(tools.GetProjectDatasourceByName(persesClient))
71-
mcpServer.AddTool(tools.CreateGlobalDatasource(persesClient))
72-
mcpServer.AddTool(tools.UpdateGlobalDatasource(persesClient))
7387

7488
// Roles and Role Bindings
7589
mcpServer.AddTool(tools.ListGlobalRoles(persesClient))
@@ -90,11 +104,24 @@ func main() {
90104
mcpServer.AddTool(tools.ListProjectVariables(persesClient))
91105
mcpServer.AddTool(tools.GetProjectVariableByName(persesClient))
92106

93-
// mcpServer.AddTool(tools.CreateProjectTextVariable(persesClient))
107+
slog.Debug("Added read-only tools")
108+
}
94109

95-
if err := server.ServeStdio(mcpServer); err != nil {
96-
slog.Error("Error starting server", "error", err)
97-
}
110+
func addWriteTools(mcpServer *server.MCPServer, persesClient apiClient.ClientInterface) {
111+
// Project
112+
mcpServer.AddTool(tools.CreateProject(persesClient))
113+
114+
// Dashboard
115+
mcpServer.AddTool(tools.CreateDashboard(persesClient))
116+
117+
// Datasource
118+
mcpServer.AddTool(tools.CreateGlobalDatasource(persesClient))
119+
mcpServer.AddTool(tools.UpdateGlobalDatasource(persesClient))
120+
121+
// Variable
122+
mcpServer.AddTool(tools.CreateProjectTextVariable(persesClient))
123+
124+
slog.Debug("Added write tools")
98125
}
99126

100127
func initializePersesClient(baseURL string) (apiClient.ClientInterface, error) {

0 commit comments

Comments
 (0)