opik-mcp 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -196
- package/build/cli.js +13 -2
- package/build/config.js +25 -9
- package/build/debug-log.js +5 -5
- package/build/index.js +45 -19
- package/build/prompts/core-prompts.js +1 -1
- package/build/resources/opik-resources.js +55 -10
- package/build/test-client.js +8 -5
- package/build/tools/capabilities.js +2 -2
- package/build/tools/dataset.js +60 -13
- package/build/tools/metrics.js +4 -2
- package/build/tools/project.js +10 -2
- package/build/tools/prompt.js +49 -13
- package/build/tools/registration.js +9 -5
- package/build/tools/schema.js +13 -2
- package/build/tools/trace.js +69 -18
- package/build/transports/streamable-http-transport.js +26 -9
- package/build/utils/capabilities.js +10 -3
- package/build/utils/examples.js +2 -2
- package/build/utils/opik-sdk.js +7 -2
- package/build/utils/remote-auth.js +8 -2
- package/build/utils/tracing-info.js +7 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
<h1 align="center" style="border-bottom: none">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
(Model Context Protocol)<br>
|
|
2
|
+
<div>
|
|
3
|
+
<a href="https://www.comet.com/site/products/opik/?from=llm&utm_source=opik&utm_medium=github&utm_content=header_img&utm_campaign=opik-mcp">
|
|
4
|
+
<picture>
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/comet-ml/opik-mcp/refs/heads/main/docs/assets/logo-dark-mode.svg">
|
|
6
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/comet-ml/opik-mcp/refs/heads/main/docs/assets/logo-light-mode.svg">
|
|
7
|
+
<img alt="Comet Opik logo" src="docs/assets/logo-light-mode.svg" width="200" />
|
|
8
|
+
</picture>
|
|
9
|
+
</a>
|
|
10
|
+
<br />
|
|
11
|
+
Opik MCP Server
|
|
12
|
+
</div>
|
|
14
13
|
</h1>
|
|
15
14
|
|
|
16
15
|
<p align="center">
|
|
17
|
-
|
|
16
|
+
Model Context Protocol (MCP) server for <a href="https://github.com/comet-ml/opik/">Opik</a>, with both local stdio and remote streamable-http transports.
|
|
18
17
|
</p>
|
|
19
18
|
|
|
20
19
|
<div align="center">
|
|
@@ -22,278 +21,202 @@ A Model Context Protocol (MCP) implementation for the <a href="https://github.co
|
|
|
22
21
|
[](https://github.com/comet-ml/opik-mcp/blob/main/LICENSE)
|
|
23
22
|
[](https://nodejs.org/)
|
|
24
23
|
[](https://www.typescriptlang.org/)
|
|
25
|
-
<img src="https://badge.mcpx.dev?status=on" title="MCP Enabled"
|
|
26
|
-
|
|
24
|
+
<a href="https://www.comet.com/docs/opik/prompt_engineering/mcp_server"><img src="https://badge.mcpx.dev?status=on" title="MCP Enabled" alt="MCP Enabled" /></a>
|
|
25
|
+
<a href="https://doi.org/10.5281/zenodo.15411156"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.15411156.svg" alt="DOI" /></a>
|
|
27
26
|
|
|
28
27
|
</div>
|
|
29
28
|
|
|
30
29
|
<p align="center">
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
<a href="https://www.comet.com/site/products/opik/?from=llm&utm_source=opik&utm_medium=github&utm_content=website_button&utm_campaign=opik"><b>Website</b></a> •
|
|
31
|
+
<a href="https://chat.comet.com"><b>Slack community</b></a> •
|
|
32
|
+
<a href="https://x.com/Cometml"><b>Twitter</b></a> •
|
|
33
|
+
<a href="https://www.comet.com/docs/opik/?from=llm&utm_source=opik&utm_medium=github&utm_content=docs_button&utm_campaign=opik"><b>Documentation</b></a>
|
|
35
34
|
</p>
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
</a>
|
|
41
|
-
</p>
|
|
42
|
-
|
|
43
|
-
> **Note:** This repository provides the MCP server implementation. We do not currently provide a hosted remote MCP service for Opik.
|
|
44
|
-
> If you run streamable-http remotely, authentication is fail-closed by default.
|
|
45
|
-
|
|
46
|
-
## 🚀 What is Opik MCP Server?
|
|
47
|
-
|
|
48
|
-
Opik MCP Server is an open-source implementation of the Model Context Protocol for the Opik platform. It provides a unified interface for interacting with Opik's capabilities, supporting multiple transport mechanisms for flexible integration into various environments.
|
|
36
|
+
> [!IMPORTANT]
|
|
37
|
+
> This repository ships the MCP server implementation only. We do not currently provide a hosted remote MCP service for Opik.
|
|
38
|
+
> If you run `streamable-http` remotely, authentication is fail-closed by default.
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
## Why this server
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
* **IDE Integration:**
|
|
54
|
-
* Seamlessly integrate with Cursor, VS Code, Windsurf and other compatible IDEs
|
|
55
|
-
* Provide direct access to Opik's capabilities from your development environment
|
|
42
|
+
Opik MCP Server gives MCP-compatible clients one interface for:
|
|
56
43
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
- Prompt lifecycle management
|
|
45
|
+
- Workspace, project, and trace exploration
|
|
46
|
+
- Metrics and dataset operations
|
|
47
|
+
- MCP resources and resource templates for metadata-aware flows
|
|
60
48
|
|
|
61
|
-
|
|
62
|
-
* Manage prompts, projects, traces, and metrics through a consistent interface
|
|
63
|
-
* Organize and monitor your LLM applications efficiently
|
|
49
|
+
## Quickstart
|
|
64
50
|
|
|
65
|
-
|
|
51
|
+
### 1. Run with npx
|
|
66
52
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
-
|
|
70
|
-
|
|
71
|
-
- **MCP Resources**: Read-only resources for workspace/project metadata plus resource templates for prompts, datasets, and traces
|
|
72
|
-
|
|
73
|
-
## Quick Start
|
|
74
|
-
|
|
75
|
-
### Installation
|
|
76
|
-
|
|
77
|
-
#### Cursor Integration
|
|
53
|
+
```bash
|
|
54
|
+
# Opik Cloud
|
|
55
|
+
npx -y opik-mcp --apiKey YOUR_API_KEY
|
|
56
|
+
```
|
|
78
57
|
|
|
79
|
-
|
|
80
|
-
to the Features tab. If you scroll down to the MCP section you will see the
|
|
81
|
-
button `+ Add new MCP server` that will allow you to add the Opik MCP server.
|
|
58
|
+
For self-hosted Opik, pass `--apiUrl` (for example `http://localhost:5173/api`) and use your local auth strategy.
|
|
82
59
|
|
|
83
|
-
|
|
84
|
-
enter the command: `npx -y opik-mcp --apiKey YOUR_API_KEY`.
|
|
60
|
+
### 2. Add to your MCP client
|
|
85
61
|
|
|
86
|
-
|
|
62
|
+
Cursor (`.cursor/mcp.json`):
|
|
87
63
|
|
|
88
64
|
```json
|
|
89
65
|
{
|
|
90
66
|
"mcpServers": {
|
|
91
67
|
"opik": {
|
|
92
68
|
"command": "npx",
|
|
93
|
-
"args": [
|
|
94
|
-
"-y",
|
|
95
|
-
"opik-mcp",
|
|
96
|
-
"--apiKey",
|
|
97
|
-
"YOUR_API_KEY"
|
|
98
|
-
]
|
|
69
|
+
"args": ["-y", "opik-mcp", "--apiKey", "YOUR_API_KEY"]
|
|
99
70
|
}
|
|
100
71
|
}
|
|
101
72
|
}
|
|
102
73
|
```
|
|
103
74
|
|
|
104
|
-
|
|
105
|
-
the `apiBaseUrl` parameter as `http://localhost:5173/api`.
|
|
106
|
-
|
|
107
|
-
#### VS Code Integration (GitHub Copilot)
|
|
108
|
-
|
|
109
|
-
To integrate Opik with VS Code (GitHub Copilot), you need to add the MCP server
|
|
110
|
-
configuration to your workspace or user settings.
|
|
111
|
-
|
|
112
|
-
1. Create or open the `.vscode/mcp.json` file in your workspace (or run the
|
|
113
|
-
**MCP: Open User Configuration** command to add it globally).
|
|
114
|
-
|
|
115
|
-
2. Add the Opik MCP server configuration:
|
|
75
|
+
VS Code / GitHub Copilot (`.vscode/mcp.json`):
|
|
116
76
|
|
|
117
77
|
```json
|
|
118
78
|
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
],
|
|
127
|
-
"servers": {
|
|
128
|
-
"opik-mcp": {
|
|
129
|
-
"type": "stdio",
|
|
130
|
-
"command": "npx",
|
|
131
|
-
"args": [
|
|
132
|
-
"-y",
|
|
133
|
-
"opik-mcp",
|
|
134
|
-
"--apiKey",
|
|
135
|
-
"${input:opik-api-key}"
|
|
136
|
-
]
|
|
137
|
-
}
|
|
79
|
+
"inputs": [
|
|
80
|
+
{
|
|
81
|
+
"type": "promptString",
|
|
82
|
+
"id": "opik-api-key",
|
|
83
|
+
"description": "Opik API Key",
|
|
84
|
+
"password": true
|
|
138
85
|
}
|
|
86
|
+
],
|
|
87
|
+
"servers": {
|
|
88
|
+
"opik-mcp": {
|
|
89
|
+
"type": "stdio",
|
|
90
|
+
"command": "npx",
|
|
91
|
+
"args": ["-y", "opik-mcp", "--apiKey", "${input:opik-api-key}"]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
139
94
|
}
|
|
140
95
|
```
|
|
141
96
|
|
|
142
|
-
|
|
143
|
-
to enter your Opik API key. The value is securely stored for subsequent use.
|
|
144
|
-
|
|
145
|
-
Note: If you are using the Open-Source version of Opik, add the `--apiBaseUrl`
|
|
146
|
-
argument and remove the `--apiKey` argument:
|
|
147
|
-
|
|
148
|
-
```json
|
|
149
|
-
{
|
|
150
|
-
"servers": {
|
|
151
|
-
"opik-mcp": {
|
|
152
|
-
"type": "stdio",
|
|
153
|
-
"command": "npx",
|
|
154
|
-
"args": [
|
|
155
|
-
"-y",
|
|
156
|
-
"opik-mcp",
|
|
157
|
-
"--apiBaseUrl",
|
|
158
|
-
"http://localhost:5173/api"
|
|
159
|
-
]
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
"inputs": []
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### Windsurf Installation
|
|
167
|
-
|
|
168
|
-
To install the MCP server in Windsurf, you will need to open the Windsurf settings
|
|
169
|
-
and navigate to the MCP section. From there, click on `View raw config` and update
|
|
170
|
-
the configuration object to be:
|
|
97
|
+
Windsurf (raw config):
|
|
171
98
|
|
|
172
99
|
```json
|
|
173
100
|
{
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
"-y",
|
|
179
|
-
"opik-mcp",
|
|
180
|
-
"--apiKey",
|
|
181
|
-
"YOUR_API_KEY"
|
|
182
|
-
]
|
|
183
|
-
}
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"opik": {
|
|
103
|
+
"command": "npx",
|
|
104
|
+
"args": ["-y", "opik-mcp", "--apiKey", "YOUR_API_KEY"]
|
|
184
105
|
}
|
|
185
106
|
}
|
|
107
|
+
}
|
|
186
108
|
```
|
|
187
109
|
|
|
188
|
-
|
|
189
|
-
|
|
110
|
+
More client-specific examples: [docs/ide-integration.md](docs/ide-integration.md)
|
|
111
|
+
|
|
112
|
+
## Run from source
|
|
190
113
|
|
|
191
|
-
#### Manual Installation
|
|
192
114
|
```bash
|
|
193
|
-
# Clone the repository
|
|
194
115
|
git clone https://github.com/comet-ml/opik-mcp.git
|
|
195
116
|
cd opik-mcp
|
|
196
|
-
|
|
197
|
-
# Install dependencies and build
|
|
198
117
|
npm install
|
|
199
118
|
npm run build
|
|
200
119
|
```
|
|
201
120
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
Create a `.env` file based on the example:
|
|
121
|
+
Optional local config:
|
|
205
122
|
|
|
206
123
|
```bash
|
|
207
124
|
cp .env.example .env
|
|
208
|
-
# Edit .env with your specific configuration
|
|
209
125
|
```
|
|
210
126
|
|
|
211
|
-
|
|
127
|
+
Start the server:
|
|
212
128
|
|
|
213
129
|
```bash
|
|
214
|
-
# Start with stdio transport (default)
|
|
215
130
|
npm run start:stdio
|
|
216
|
-
|
|
217
|
-
# Start with streamable-http transport for remote/self-hosted access
|
|
218
131
|
npm run start:http
|
|
219
132
|
```
|
|
220
133
|
|
|
221
|
-
## Transport
|
|
134
|
+
## Transport modes
|
|
222
135
|
|
|
223
|
-
|
|
136
|
+
| Transport | Use case | Command |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `stdio` | Local MCP integration (same machine as client) | `npm run start:stdio` |
|
|
139
|
+
| `streamable-http` | Remote/self-hosted MCP endpoint (`/mcp`) | `npm run start:http` |
|
|
224
140
|
|
|
225
|
-
|
|
141
|
+
### Remote auth defaults (`streamable-http`)
|
|
226
142
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
143
|
+
- `Authorization: Bearer <OPIK_API_KEY>` or `x-api-key` is required by default.
|
|
144
|
+
- Workspace is resolved server-side (token map recommended); workspace headers are not trusted by default.
|
|
145
|
+
- In remote mode, request-context workspace takes precedence over tool `workspaceName`.
|
|
146
|
+
- Missing or invalid auth returns HTTP `401`.
|
|
230
147
|
|
|
231
|
-
|
|
148
|
+
Key environment flags:
|
|
232
149
|
|
|
233
|
-
|
|
150
|
+
- `STREAMABLE_HTTP_REQUIRE_AUTH` (default `true`)
|
|
151
|
+
- `STREAMABLE_HTTP_VALIDATE_REMOTE_AUTH` (default `true`, except test env)
|
|
152
|
+
- `REMOTE_TOKEN_WORKSPACE_MAP` (JSON token-to-workspace map)
|
|
153
|
+
- `STREAMABLE_HTTP_TRUST_WORKSPACE_HEADERS` (default `false`)
|
|
234
154
|
|
|
235
|
-
|
|
236
|
-
- `Authorization: Bearer <OPIK_API_KEY>` or `x-api-key` is required by default.
|
|
237
|
-
- Workspace is resolved server-side (recommended via token mapping). Header workspaces are not trusted by default.
|
|
238
|
-
- In remote mode, request-context workspace takes precedence over tool `workspaceName` args.
|
|
239
|
-
- Missing/invalid auth returns HTTP `401`.
|
|
155
|
+
Deep dive: [docs/streamable-http-transport.md](docs/streamable-http-transport.md)
|
|
240
156
|
|
|
241
|
-
|
|
242
|
-
- `STREAMABLE_HTTP_REQUIRE_AUTH` (default `true`): require auth headers on `/mcp`.
|
|
243
|
-
- `STREAMABLE_HTTP_VALIDATE_REMOTE_AUTH` (default `true`, except test env): validate bearer/API key against Opik before accepting requests.
|
|
244
|
-
- `REMOTE_TOKEN_WORKSPACE_MAP`: JSON map of token -> workspace for server-side tenant routing.
|
|
245
|
-
- `STREAMABLE_HTTP_TRUST_WORKSPACE_HEADERS` (default `false`): allow workspace headers when token map is not configured.
|
|
157
|
+
## Toolsets
|
|
246
158
|
|
|
247
|
-
|
|
248
|
-
npm run start:http
|
|
249
|
-
```
|
|
159
|
+
Toolsets let you narrow which capabilities are enabled:
|
|
250
160
|
|
|
251
|
-
|
|
161
|
+
- `core`
|
|
162
|
+
- `integration`
|
|
163
|
+
- `expert-prompts`
|
|
164
|
+
- `expert-datasets`
|
|
165
|
+
- `expert-trace-actions`
|
|
166
|
+
- `expert-project-actions`
|
|
167
|
+
- `metrics`
|
|
168
|
+
- `all` (enables all modern toolsets)
|
|
252
169
|
|
|
253
|
-
|
|
170
|
+
Configure via:
|
|
254
171
|
|
|
255
|
-
-
|
|
256
|
-
- `
|
|
257
|
-
- `resources/read` supports both static URIs and filled template URIs.
|
|
258
|
-
- `prompts/list` and `prompts/get` expose workflow prompts (for example, `opik-triage-workflow`).
|
|
172
|
+
- CLI: `--toolsets all`
|
|
173
|
+
- Env: `OPIK_TOOLSETS=core,expert-prompts,metrics`
|
|
259
174
|
|
|
260
|
-
|
|
175
|
+
Details: [docs/configuration.md](docs/configuration.md)
|
|
261
176
|
|
|
262
|
-
|
|
177
|
+
## MCP resources and prompts
|
|
263
178
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
179
|
+
- `resources/list` exposes static URIs (for example `opik://workspace-info`)
|
|
180
|
+
- `resources/templates/list` exposes dynamic URI templates (for example `opik://projects/{page}/{size}`)
|
|
181
|
+
- `resources/read` supports static and templated URIs
|
|
182
|
+
- `prompts/list` and `prompts/get` expose workflow prompts
|
|
267
183
|
|
|
268
|
-
|
|
269
|
-
npm test -- tests/transports/streamable-http-transport.test.ts
|
|
270
|
-
```
|
|
184
|
+
## Development
|
|
271
185
|
|
|
272
|
-
|
|
186
|
+
```bash
|
|
187
|
+
# Lint
|
|
188
|
+
npm run lint
|
|
273
189
|
|
|
274
|
-
|
|
190
|
+
# Test
|
|
191
|
+
npm test
|
|
275
192
|
|
|
276
|
-
|
|
277
|
-
|
|
193
|
+
# Build
|
|
194
|
+
npm run build
|
|
195
|
+
|
|
196
|
+
# Run precommit checks
|
|
278
197
|
make precommit
|
|
279
198
|
```
|
|
280
199
|
|
|
281
200
|
## Documentation
|
|
282
201
|
|
|
283
|
-
- [
|
|
284
|
-
- [
|
|
285
|
-
- [
|
|
286
|
-
- [
|
|
202
|
+
- [API Reference](docs/api-reference.md)
|
|
203
|
+
- [Configuration](docs/configuration.md)
|
|
204
|
+
- [IDE Integration](docs/ide-integration.md)
|
|
205
|
+
- [Streamable HTTP Transport](docs/streamable-http-transport.md)
|
|
206
|
+
|
|
207
|
+
## Contributing
|
|
208
|
+
|
|
209
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR.
|
|
287
210
|
|
|
288
211
|
## Citation
|
|
289
212
|
|
|
290
|
-
If you use this project in
|
|
213
|
+
If you use this project in research, cite:
|
|
291
214
|
|
|
292
215
|
```
|
|
293
216
|
Comet ML, Inc, Koc, V., & Boiko, Y. (2025). Opik MCP Server. Github. https://doi.org/10.5281/zenodo.15411156
|
|
294
217
|
```
|
|
295
218
|
|
|
296
|
-
|
|
219
|
+
BibTeX:
|
|
297
220
|
|
|
298
221
|
```bibtex
|
|
299
222
|
@software{CometML_Opik_MCP_Server_2025,
|
|
@@ -306,7 +229,7 @@ Or use the following BibTeX entry:
|
|
|
306
229
|
}
|
|
307
230
|
```
|
|
308
231
|
|
|
309
|
-
|
|
232
|
+
Citation metadata is also available in [CITATION.cff](CITATION.cff).
|
|
310
233
|
|
|
311
234
|
## License
|
|
312
235
|
|
package/build/cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import yargs from 'yargs';
|
|
3
3
|
import { hideBin } from 'yargs/helpers';
|
|
4
4
|
import configImport from './config.js';
|
|
5
|
+
import { main } from './index.js';
|
|
5
6
|
// Parse command line arguments
|
|
6
7
|
const argv = yargs(hideBin(process.argv))
|
|
7
8
|
.scriptName('opik-mcp')
|
|
@@ -30,5 +31,15 @@ if (argv.transport === 'streamable-http' && typeof argv.port === 'number') {
|
|
|
30
31
|
configImport.streamableHttpPort = argv.port;
|
|
31
32
|
process.env.STREAMABLE_HTTP_PORT = String(argv.port);
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
function toErrorMessage(error) {
|
|
35
|
+
if (error instanceof Error) {
|
|
36
|
+
return error.message;
|
|
37
|
+
}
|
|
38
|
+
return String(error);
|
|
39
|
+
}
|
|
40
|
+
// Start the server after applying CLI overrides.
|
|
41
|
+
main().catch((error) => {
|
|
42
|
+
const message = toErrorMessage(error);
|
|
43
|
+
console.error(`Failed to start Opik MCP server: ${message}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
});
|
package/build/config.js
CHANGED
|
@@ -58,7 +58,9 @@ const ALL_TOOLSET_CHOICES = [
|
|
|
58
58
|
];
|
|
59
59
|
export function normalizeToolsets(values) {
|
|
60
60
|
const normalized = new Set();
|
|
61
|
-
for (const value of values
|
|
61
|
+
for (const value of values
|
|
62
|
+
.flatMap((v) => v.split(','))
|
|
63
|
+
.map((v) => v.trim())) {
|
|
62
64
|
const toolset = value;
|
|
63
65
|
switch (toolset) {
|
|
64
66
|
case 'all':
|
|
@@ -116,7 +118,9 @@ function loadOpikConfigFile() {
|
|
|
116
118
|
for (const line of lines) {
|
|
117
119
|
const trimmedLine = line.trim();
|
|
118
120
|
// Skip empty lines and comments
|
|
119
|
-
if (!trimmedLine ||
|
|
121
|
+
if (!trimmedLine ||
|
|
122
|
+
trimmedLine.startsWith('#') ||
|
|
123
|
+
trimmedLine.startsWith(';')) {
|
|
120
124
|
continue;
|
|
121
125
|
}
|
|
122
126
|
// Check for section headers
|
|
@@ -253,20 +257,32 @@ export function loadConfig() {
|
|
|
253
257
|
isSelfHosted: args.selfHosted !== undefined
|
|
254
258
|
? args.selfHosted
|
|
255
259
|
: process.env.OPIK_SELF_HOSTED === 'true' || false,
|
|
256
|
-
debugMode: args.debug !== undefined
|
|
260
|
+
debugMode: args.debug !== undefined
|
|
261
|
+
? args.debug
|
|
262
|
+
: process.env.DEBUG_MODE === 'true' || false,
|
|
257
263
|
// Transport configuration
|
|
258
264
|
transport: (args.transport ?? process.env.TRANSPORT ?? 'stdio'),
|
|
259
265
|
streamableHttpPort: args.streamableHttpPort ??
|
|
260
|
-
(process.env.STREAMABLE_HTTP_PORT
|
|
261
|
-
|
|
266
|
+
(process.env.STREAMABLE_HTTP_PORT
|
|
267
|
+
? parseInt(process.env.STREAMABLE_HTTP_PORT, 10)
|
|
268
|
+
: 3001),
|
|
269
|
+
streamableHttpHost: args.streamableHttpHost ??
|
|
270
|
+
process.env.STREAMABLE_HTTP_HOST ??
|
|
271
|
+
'127.0.0.1',
|
|
262
272
|
streamableHttpLogPath: args.streamableHttpLogPath ??
|
|
263
|
-
(process.env.STREAMABLE_HTTP_LOG_PATH ||
|
|
273
|
+
(process.env.STREAMABLE_HTTP_LOG_PATH ||
|
|
274
|
+
'/tmp/opik-mcp-streamable-http.log'),
|
|
264
275
|
// MCP configuration with fallbacks
|
|
265
276
|
mcpName: args.mcpName || process.env.MCP_NAME || 'opik-manager',
|
|
266
277
|
mcpVersion: args.mcpVersion || process.env.MCP_VERSION || '2.0.0',
|
|
267
|
-
mcpPort: args.mcpPort ||
|
|
268
|
-
|
|
269
|
-
|
|
278
|
+
mcpPort: args.mcpPort ||
|
|
279
|
+
(process.env.MCP_PORT ? parseInt(process.env.MCP_PORT, 10) : undefined),
|
|
280
|
+
mcpLogging: args.mcpLogging !== undefined
|
|
281
|
+
? args.mcpLogging
|
|
282
|
+
: process.env.MCP_LOGGING === 'true' || false,
|
|
283
|
+
mcpDefaultWorkspace: args.mcpDefaultWorkspace ||
|
|
284
|
+
process.env.MCP_DEFAULT_WORKSPACE ||
|
|
285
|
+
'default',
|
|
270
286
|
// Toolset configuration with fallbacks
|
|
271
287
|
enabledToolsets: (() => {
|
|
272
288
|
// Command line takes precedence
|
package/build/debug-log.js
CHANGED
|
@@ -21,8 +21,8 @@ export function initDebugLog() {
|
|
|
21
21
|
// Log environment variables
|
|
22
22
|
logDebug('Environment Variables:');
|
|
23
23
|
Object.keys(process.env)
|
|
24
|
-
.filter(key => key.startsWith('OPIK_'))
|
|
25
|
-
.forEach(key => {
|
|
24
|
+
.filter((key) => key.startsWith('OPIK_'))
|
|
25
|
+
.forEach((key) => {
|
|
26
26
|
let value = process.env[key];
|
|
27
27
|
// Mask sensitive information
|
|
28
28
|
if (key === 'OPIK_API_KEY')
|
|
@@ -35,7 +35,7 @@ export function initDebugLog() {
|
|
|
35
35
|
logDebug(` ${index}: ${arg}`);
|
|
36
36
|
});
|
|
37
37
|
// Set up uncaught exception handler
|
|
38
|
-
process.on('uncaughtException', error => {
|
|
38
|
+
process.on('uncaughtException', (error) => {
|
|
39
39
|
logDebug(`UNCAUGHT EXCEPTION: ${error.message}`);
|
|
40
40
|
logDebug(error.stack || 'No stack trace available');
|
|
41
41
|
});
|
|
@@ -44,7 +44,7 @@ export function initDebugLog() {
|
|
|
44
44
|
logDebug(`UNHANDLED REJECTION: ${reason}`);
|
|
45
45
|
});
|
|
46
46
|
// Set up exit handler
|
|
47
|
-
process.on('exit', code => {
|
|
47
|
+
process.on('exit', (code) => {
|
|
48
48
|
logDebug(`Process exiting with code: ${code}`);
|
|
49
49
|
});
|
|
50
50
|
}
|
|
@@ -52,7 +52,7 @@ export function logDebug(message) {
|
|
|
52
52
|
const logPath = '/tmp/opik-mcp-debug.log';
|
|
53
53
|
const timestamp = new Date().toISOString();
|
|
54
54
|
const logMessage = `[${timestamp}] ${message}\n`;
|
|
55
|
-
return new Promise(resolve => {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
56
|
try {
|
|
57
57
|
fs.appendFileSync(logPath, logMessage);
|
|
58
58
|
}
|
package/build/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
2
3
|
// Import other modules
|
|
3
4
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
5
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -35,14 +36,14 @@ if (config.debugMode) {
|
|
|
35
36
|
logToFile(`Arguments: ${process.argv.join(' ')}`);
|
|
36
37
|
logToFile(`Loaded configuration: API=${config.apiBaseUrl}, Workspace=${config.workspaceName || 'None'}`);
|
|
37
38
|
// Register error handlers
|
|
38
|
-
process.on('uncaughtException', err => {
|
|
39
|
+
process.on('uncaughtException', (err) => {
|
|
39
40
|
logToFile(`UNCAUGHT EXCEPTION: ${err.message}`);
|
|
40
41
|
logToFile(err.stack || 'No stack trace');
|
|
41
42
|
});
|
|
42
|
-
process.on('unhandledRejection', reason => {
|
|
43
|
+
process.on('unhandledRejection', (reason) => {
|
|
43
44
|
logToFile(`UNHANDLED REJECTION: ${reason}`);
|
|
44
45
|
});
|
|
45
|
-
process.on('exit', code => {
|
|
46
|
+
process.on('exit', (code) => {
|
|
46
47
|
logToFile(`Process exiting with code ${code}`);
|
|
47
48
|
});
|
|
48
49
|
}
|
|
@@ -72,9 +73,15 @@ if (enabledToolsets.has('core')) {
|
|
|
72
73
|
logToFile('Loaded core capabilities tools');
|
|
73
74
|
server = loadCorePrompts(server);
|
|
74
75
|
logToFile('Loaded core prompts');
|
|
75
|
-
server = loadProjectTools(server, {
|
|
76
|
+
server = loadProjectTools(server, {
|
|
77
|
+
includeReadOps: true,
|
|
78
|
+
includeMutations: false,
|
|
79
|
+
});
|
|
76
80
|
logToFile('Loaded core project read tools');
|
|
77
|
-
server = loadTraceTools(server, {
|
|
81
|
+
server = loadTraceTools(server, {
|
|
82
|
+
includeCoreTools: true,
|
|
83
|
+
includeExpertActions: false,
|
|
84
|
+
});
|
|
78
85
|
logToFile('Loaded core trace tools');
|
|
79
86
|
}
|
|
80
87
|
if (enabledToolsets.has('expert-prompts')) {
|
|
@@ -86,11 +93,17 @@ if (enabledToolsets.has('expert-datasets')) {
|
|
|
86
93
|
logToFile('Loaded expert datasets toolset');
|
|
87
94
|
}
|
|
88
95
|
if (enabledToolsets.has('expert-project-actions')) {
|
|
89
|
-
server = loadProjectTools(server, {
|
|
96
|
+
server = loadProjectTools(server, {
|
|
97
|
+
includeReadOps: false,
|
|
98
|
+
includeMutations: true,
|
|
99
|
+
});
|
|
90
100
|
logToFile('Loaded expert project actions toolset');
|
|
91
101
|
}
|
|
92
102
|
if (enabledToolsets.has('expert-trace-actions')) {
|
|
93
|
-
server = loadTraceTools(server, {
|
|
103
|
+
server = loadTraceTools(server, {
|
|
104
|
+
includeCoreTools: false,
|
|
105
|
+
includeExpertActions: true,
|
|
106
|
+
});
|
|
94
107
|
logToFile('Loaded expert trace actions toolset');
|
|
95
108
|
}
|
|
96
109
|
if (enabledToolsets.has('metrics')) {
|
|
@@ -132,16 +145,29 @@ export async function main() {
|
|
|
132
145
|
}
|
|
133
146
|
logToFile('Main function completed successfully');
|
|
134
147
|
}
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
console.error(error.stack);
|
|
144
|
-
}
|
|
148
|
+
// Used by Smithery capability scanning when importing the module.
|
|
149
|
+
export function createSandboxServer() {
|
|
150
|
+
return server;
|
|
151
|
+
}
|
|
152
|
+
export default createSandboxServer;
|
|
153
|
+
function shouldAutoStart() {
|
|
154
|
+
if (!process.argv[1]) {
|
|
155
|
+
return false;
|
|
145
156
|
}
|
|
146
|
-
process.
|
|
147
|
-
}
|
|
157
|
+
return import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
158
|
+
}
|
|
159
|
+
// Start the server only when this file is the process entrypoint.
|
|
160
|
+
if (shouldAutoStart()) {
|
|
161
|
+
main().catch((error) => {
|
|
162
|
+
const message = toErrorMessage(error);
|
|
163
|
+
logToFile(`Error starting server: ${message}`);
|
|
164
|
+
console.error(`Failed to start Opik MCP server: ${message}`);
|
|
165
|
+
if (error instanceof Error && error.stack) {
|
|
166
|
+
logToFile(error.stack);
|
|
167
|
+
if (config.debugMode) {
|
|
168
|
+
console.error(error.stack);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
|
173
|
+
}
|