opik-mcp 0.1.3 → 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 +128 -125
- package/build/cli.js +23 -10
- package/build/config.js +112 -32
- package/build/debug-log.js +5 -5
- package/build/index.js +89 -83
- package/build/prompts/core-prompts.js +52 -0
- package/build/resources/opik-resources.js +241 -0
- package/build/test-client.js +10 -9
- package/build/tools/capabilities.js +183 -0
- package/build/tools/dataset.js +219 -0
- package/build/tools/integration.js +3 -3
- package/build/tools/metrics.js +54 -48
- package/build/tools/project.js +77 -48
- package/build/tools/prompt.js +128 -53
- package/build/tools/registration.js +114 -0
- package/build/tools/schema.js +24 -0
- package/build/tools/trace.js +351 -359
- package/build/transports/streamable-http-transport.js +315 -0
- package/build/transports/types.js +0 -3
- package/build/utils/capabilities.js +44 -7
- package/build/utils/examples.js +2 -2
- package/build/utils/opik-sdk.js +124 -0
- package/build/utils/remote-auth.js +181 -0
- package/build/utils/request-context.js +32 -0
- package/build/utils/tracing-info.js +7 -1
- package/package.json +27 -21
- package/build/transports/sse-transport.js +0 -169
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,198 +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
|
-
|
|
35
|
-
</p>
|
|
36
|
-
|
|
37
|
-
<p align="center">
|
|
38
|
-
<a href="https://glama.ai/mcp/servers/@comet-ml/opik-mcp" rel="nofollow" target="_blank">
|
|
39
|
-
<img width="380" height="200" src="https://glama.ai/mcp/servers/@comet-ml/opik-mcp/badge" alt="Opik Server MCP server" />
|
|
40
|
-
</a>
|
|
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>
|
|
41
34
|
</p>
|
|
42
35
|
|
|
43
|
-
>
|
|
44
|
-
|
|
45
|
-
|
|
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.
|
|
46
39
|
|
|
47
|
-
|
|
40
|
+
## Why this server
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
Opik MCP Server gives MCP-compatible clients one interface for:
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
55
48
|
|
|
56
|
-
|
|
57
|
-
* Access all Opik features through a standardized protocol
|
|
58
|
-
* Leverage multiple transport options (stdio, SSE) for different integration scenarios
|
|
49
|
+
## Quickstart
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
* Manage prompts, projects, traces, and metrics through a consistent interface
|
|
62
|
-
* Organize and monitor your LLM applications efficiently
|
|
51
|
+
### 1. Run with npx
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
- **Traces**: Track and analyze trace data
|
|
69
|
-
- **Metrics**: Gather and query metrics data
|
|
70
|
-
|
|
71
|
-
## Quick Start
|
|
72
|
-
|
|
73
|
-
### Installation
|
|
74
|
-
|
|
75
|
-
#### Cursor Integration
|
|
53
|
+
```bash
|
|
54
|
+
# Opik Cloud
|
|
55
|
+
npx -y opik-mcp --apiKey YOUR_API_KEY
|
|
56
|
+
```
|
|
76
57
|
|
|
77
|
-
|
|
78
|
-
to the Features tab. If you scroll down to the MCP section you will see the
|
|
79
|
-
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.
|
|
80
59
|
|
|
81
|
-
|
|
82
|
-
enter the command: `npx -y opik-mcp --apiKey YOUR_API_KEY`.
|
|
60
|
+
### 2. Add to your MCP client
|
|
83
61
|
|
|
84
|
-
|
|
62
|
+
Cursor (`.cursor/mcp.json`):
|
|
85
63
|
|
|
86
64
|
```json
|
|
87
65
|
{
|
|
88
66
|
"mcpServers": {
|
|
89
67
|
"opik": {
|
|
90
68
|
"command": "npx",
|
|
91
|
-
"args": [
|
|
92
|
-
"-y",
|
|
93
|
-
"opik-mcp",
|
|
94
|
-
"--apiKey",
|
|
95
|
-
"YOUR_API_KEY"
|
|
96
|
-
]
|
|
69
|
+
"args": ["-y", "opik-mcp", "--apiKey", "YOUR_API_KEY"]
|
|
97
70
|
}
|
|
98
71
|
}
|
|
99
72
|
}
|
|
100
73
|
```
|
|
101
74
|
|
|
102
|
-
|
|
103
|
-
the `apiBaseUrl` parameter as `http://localhost:5173/api`.
|
|
75
|
+
VS Code / GitHub Copilot (`.vscode/mcp.json`):
|
|
104
76
|
|
|
105
|
-
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"inputs": [
|
|
80
|
+
{
|
|
81
|
+
"type": "promptString",
|
|
82
|
+
"id": "opik-api-key",
|
|
83
|
+
"description": "Opik API Key",
|
|
84
|
+
"password": true
|
|
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
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
106
96
|
|
|
107
|
-
|
|
108
|
-
and navigate to the MCP section. From there, click on `View raw config` and update
|
|
109
|
-
the configuration object to be:
|
|
97
|
+
Windsurf (raw config):
|
|
110
98
|
|
|
111
99
|
```json
|
|
112
100
|
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"-y",
|
|
118
|
-
"opik-mcp",
|
|
119
|
-
"--apiKey",
|
|
120
|
-
"YOUR_API_KEY"
|
|
121
|
-
]
|
|
122
|
-
}
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"opik": {
|
|
103
|
+
"command": "npx",
|
|
104
|
+
"args": ["-y", "opik-mcp", "--apiKey", "YOUR_API_KEY"]
|
|
123
105
|
}
|
|
124
106
|
}
|
|
107
|
+
}
|
|
125
108
|
```
|
|
126
109
|
|
|
127
|
-
|
|
128
|
-
|
|
110
|
+
More client-specific examples: [docs/ide-integration.md](docs/ide-integration.md)
|
|
111
|
+
|
|
112
|
+
## Run from source
|
|
129
113
|
|
|
130
|
-
#### Manual Installation
|
|
131
114
|
```bash
|
|
132
|
-
# Clone the repository
|
|
133
115
|
git clone https://github.com/comet-ml/opik-mcp.git
|
|
134
116
|
cd opik-mcp
|
|
135
|
-
|
|
136
|
-
# Install dependencies and build
|
|
137
117
|
npm install
|
|
138
118
|
npm run build
|
|
139
119
|
```
|
|
140
120
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
Create a `.env` file based on the example:
|
|
121
|
+
Optional local config:
|
|
144
122
|
|
|
145
123
|
```bash
|
|
146
124
|
cp .env.example .env
|
|
147
|
-
# Edit .env with your specific configuration
|
|
148
125
|
```
|
|
149
126
|
|
|
150
|
-
|
|
127
|
+
Start the server:
|
|
151
128
|
|
|
152
129
|
```bash
|
|
153
|
-
# Start with stdio transport (default)
|
|
154
130
|
npm run start:stdio
|
|
155
|
-
|
|
156
|
-
# Start with SSE transport for network access (experimental)
|
|
157
|
-
npm run start:sse
|
|
131
|
+
npm run start:http
|
|
158
132
|
```
|
|
159
133
|
|
|
160
|
-
## Transport
|
|
134
|
+
## Transport modes
|
|
161
135
|
|
|
162
|
-
|
|
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` |
|
|
163
140
|
|
|
164
|
-
|
|
141
|
+
### Remote auth defaults (`streamable-http`)
|
|
165
142
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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`.
|
|
169
147
|
|
|
170
|
-
|
|
148
|
+
Key environment flags:
|
|
171
149
|
|
|
172
|
-
|
|
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`)
|
|
173
154
|
|
|
174
|
-
|
|
175
|
-
make start-sse
|
|
176
|
-
```
|
|
155
|
+
Deep dive: [docs/streamable-http-transport.md](docs/streamable-http-transport.md)
|
|
177
156
|
|
|
178
|
-
|
|
157
|
+
## Toolsets
|
|
179
158
|
|
|
180
|
-
|
|
159
|
+
Toolsets let you narrow which capabilities are enabled:
|
|
181
160
|
|
|
182
|
-
|
|
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)
|
|
183
169
|
|
|
184
|
-
|
|
185
|
-
# Run all tests
|
|
186
|
-
npm test
|
|
170
|
+
Configure via:
|
|
187
171
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
172
|
+
- CLI: `--toolsets all`
|
|
173
|
+
- Env: `OPIK_TOOLSETS=core,expert-prompts,metrics`
|
|
174
|
+
|
|
175
|
+
Details: [docs/configuration.md](docs/configuration.md)
|
|
176
|
+
|
|
177
|
+
## MCP resources and prompts
|
|
191
178
|
|
|
192
|
-
|
|
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
|
|
193
183
|
|
|
194
|
-
|
|
184
|
+
## Development
|
|
195
185
|
|
|
196
186
|
```bash
|
|
197
|
-
#
|
|
187
|
+
# Lint
|
|
188
|
+
npm run lint
|
|
189
|
+
|
|
190
|
+
# Test
|
|
191
|
+
npm test
|
|
192
|
+
|
|
193
|
+
# Build
|
|
194
|
+
npm run build
|
|
195
|
+
|
|
196
|
+
# Run precommit checks
|
|
198
197
|
make precommit
|
|
199
198
|
```
|
|
200
199
|
|
|
201
200
|
## Documentation
|
|
202
201
|
|
|
203
|
-
- [
|
|
204
|
-
- [
|
|
205
|
-
- [
|
|
206
|
-
- [
|
|
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.
|
|
207
210
|
|
|
208
211
|
## Citation
|
|
209
212
|
|
|
210
|
-
If you use this project in
|
|
213
|
+
If you use this project in research, cite:
|
|
211
214
|
|
|
212
215
|
```
|
|
213
216
|
Comet ML, Inc, Koc, V., & Boiko, Y. (2025). Opik MCP Server. Github. https://doi.org/10.5281/zenodo.15411156
|
|
214
217
|
```
|
|
215
218
|
|
|
216
|
-
|
|
219
|
+
BibTeX:
|
|
217
220
|
|
|
218
221
|
```bibtex
|
|
219
222
|
@software{CometML_Opik_MCP_Server_2025,
|
|
@@ -226,7 +229,7 @@ Or use the following BibTeX entry:
|
|
|
226
229
|
}
|
|
227
230
|
```
|
|
228
231
|
|
|
229
|
-
|
|
232
|
+
Citation metadata is also available in [CITATION.cff](CITATION.cff).
|
|
230
233
|
|
|
231
234
|
## License
|
|
232
235
|
|
package/build/cli.js
CHANGED
|
@@ -2,31 +2,44 @@
|
|
|
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')
|
|
8
9
|
.usage('$0 [args]')
|
|
9
10
|
.option('transport', {
|
|
10
11
|
alias: 't',
|
|
11
|
-
description: 'Transport to use (stdio or
|
|
12
|
+
description: 'Transport to use (stdio or streamable-http)',
|
|
12
13
|
type: 'string',
|
|
13
|
-
|
|
14
|
-
choices: ['stdio', 'sse'],
|
|
14
|
+
choices: ['stdio', 'streamable-http'],
|
|
15
15
|
})
|
|
16
16
|
.option('port', {
|
|
17
17
|
alias: 'p',
|
|
18
|
-
description: 'Port to listen on (for
|
|
18
|
+
description: 'Port to listen on (for streamable-http transport)',
|
|
19
19
|
type: 'number',
|
|
20
|
-
default: 3001,
|
|
21
20
|
})
|
|
22
21
|
.help()
|
|
23
22
|
.alias('help', 'h')
|
|
24
23
|
.strict(false) // Allow unknown options
|
|
25
24
|
.parseSync();
|
|
26
25
|
// Update config based on CLI arguments
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
if (argv.transport) {
|
|
27
|
+
configImport.transport = argv.transport;
|
|
28
|
+
process.env.TRANSPORT = argv.transport;
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
if (argv.transport === 'streamable-http' && typeof argv.port === 'number') {
|
|
31
|
+
configImport.streamableHttpPort = argv.port;
|
|
32
|
+
process.env.STREAMABLE_HTTP_PORT = String(argv.port);
|
|
33
|
+
}
|
|
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
|
@@ -31,7 +31,76 @@ function writeToLogFile(message, forceWrite = false) {
|
|
|
31
31
|
// Silently fail if we can't write to the log file
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
export const DEFAULT_TOOLSETS = ['
|
|
34
|
+
export const DEFAULT_TOOLSETS = ['core'];
|
|
35
|
+
export const ALL_TOOLSETS = [
|
|
36
|
+
'core',
|
|
37
|
+
'expert-prompts',
|
|
38
|
+
'expert-datasets',
|
|
39
|
+
'expert-trace-actions',
|
|
40
|
+
'expert-project-actions',
|
|
41
|
+
'integration',
|
|
42
|
+
'metrics',
|
|
43
|
+
];
|
|
44
|
+
const ALL_TOOLSET_CHOICES = [
|
|
45
|
+
'all',
|
|
46
|
+
'core',
|
|
47
|
+
'expert-prompts',
|
|
48
|
+
'expert-datasets',
|
|
49
|
+
'expert-trace-actions',
|
|
50
|
+
'expert-project-actions',
|
|
51
|
+
'integration',
|
|
52
|
+
'metrics',
|
|
53
|
+
'capabilities',
|
|
54
|
+
'prompts',
|
|
55
|
+
'datasets',
|
|
56
|
+
'projects',
|
|
57
|
+
'traces',
|
|
58
|
+
];
|
|
59
|
+
export function normalizeToolsets(values) {
|
|
60
|
+
const normalized = new Set();
|
|
61
|
+
for (const value of values
|
|
62
|
+
.flatMap((v) => v.split(','))
|
|
63
|
+
.map((v) => v.trim())) {
|
|
64
|
+
const toolset = value;
|
|
65
|
+
switch (toolset) {
|
|
66
|
+
case 'all':
|
|
67
|
+
for (const item of ALL_TOOLSETS) {
|
|
68
|
+
normalized.add(item);
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
case 'core':
|
|
72
|
+
case 'expert-prompts':
|
|
73
|
+
case 'expert-datasets':
|
|
74
|
+
case 'expert-trace-actions':
|
|
75
|
+
case 'expert-project-actions':
|
|
76
|
+
case 'integration':
|
|
77
|
+
case 'metrics':
|
|
78
|
+
normalized.add(toolset);
|
|
79
|
+
break;
|
|
80
|
+
// Legacy aliases
|
|
81
|
+
case 'capabilities':
|
|
82
|
+
normalized.add('core');
|
|
83
|
+
break;
|
|
84
|
+
case 'prompts':
|
|
85
|
+
normalized.add('expert-prompts');
|
|
86
|
+
break;
|
|
87
|
+
case 'datasets':
|
|
88
|
+
normalized.add('expert-datasets');
|
|
89
|
+
break;
|
|
90
|
+
case 'projects':
|
|
91
|
+
normalized.add('core');
|
|
92
|
+
normalized.add('expert-project-actions');
|
|
93
|
+
break;
|
|
94
|
+
case 'traces':
|
|
95
|
+
normalized.add('core');
|
|
96
|
+
normalized.add('expert-trace-actions');
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return Array.from(normalized);
|
|
103
|
+
}
|
|
35
104
|
/**
|
|
36
105
|
* Load configuration from ~/.opik.config file
|
|
37
106
|
*/
|
|
@@ -49,7 +118,9 @@ function loadOpikConfigFile() {
|
|
|
49
118
|
for (const line of lines) {
|
|
50
119
|
const trimmedLine = line.trim();
|
|
51
120
|
// Skip empty lines and comments
|
|
52
|
-
if (!trimmedLine ||
|
|
121
|
+
if (!trimmedLine ||
|
|
122
|
+
trimmedLine.startsWith('#') ||
|
|
123
|
+
trimmedLine.startsWith(';')) {
|
|
53
124
|
continue;
|
|
54
125
|
}
|
|
55
126
|
// Check for section headers
|
|
@@ -78,7 +149,7 @@ function loadOpikConfigFile() {
|
|
|
78
149
|
}
|
|
79
150
|
}
|
|
80
151
|
}
|
|
81
|
-
writeToLogFile(`Loaded config from ~/.opik.config: ${
|
|
152
|
+
writeToLogFile(`Loaded config from ~/.opik.config with keys: ${Object.keys(config).join(', ') || '(none)'}`);
|
|
82
153
|
return config;
|
|
83
154
|
}
|
|
84
155
|
catch (error) {
|
|
@@ -118,24 +189,20 @@ function parseCommandLineArgs() {
|
|
|
118
189
|
// Transport Configuration
|
|
119
190
|
.option('transport', {
|
|
120
191
|
type: 'string',
|
|
121
|
-
description: 'Transport type (stdio or
|
|
122
|
-
choices: ['stdio', '
|
|
123
|
-
default: 'stdio',
|
|
192
|
+
description: 'Transport type (stdio or streamable-http)',
|
|
193
|
+
choices: ['stdio', 'streamable-http'],
|
|
124
194
|
})
|
|
125
|
-
.option('
|
|
195
|
+
.option('streamableHttpPort', {
|
|
126
196
|
type: 'number',
|
|
127
|
-
description: 'Port for
|
|
128
|
-
default: 3001,
|
|
197
|
+
description: 'Port for streamable-http transport',
|
|
129
198
|
})
|
|
130
|
-
.option('
|
|
199
|
+
.option('streamableHttpHost', {
|
|
131
200
|
type: 'string',
|
|
132
|
-
description: 'Host for
|
|
133
|
-
default: 'localhost',
|
|
201
|
+
description: 'Host for streamable-http transport',
|
|
134
202
|
})
|
|
135
|
-
.option('
|
|
203
|
+
.option('streamableHttpLogPath', {
|
|
136
204
|
type: 'string',
|
|
137
|
-
description: 'Log file path for
|
|
138
|
-
default: '/tmp/opik-mcp-sse.log',
|
|
205
|
+
description: 'Log file path for streamable-http transport',
|
|
139
206
|
})
|
|
140
207
|
// MCP Configuration
|
|
141
208
|
.option('mcpName', {
|
|
@@ -162,7 +229,7 @@ function parseCommandLineArgs() {
|
|
|
162
229
|
.option('toolsets', {
|
|
163
230
|
type: 'array',
|
|
164
231
|
description: 'Comma-separated list of toolsets to enable',
|
|
165
|
-
choices:
|
|
232
|
+
choices: ALL_TOOLSET_CHOICES,
|
|
166
233
|
})
|
|
167
234
|
.help()
|
|
168
235
|
.parse();
|
|
@@ -190,28 +257,41 @@ export function loadConfig() {
|
|
|
190
257
|
isSelfHosted: args.selfHosted !== undefined
|
|
191
258
|
? args.selfHosted
|
|
192
259
|
: process.env.OPIK_SELF_HOSTED === 'true' || false,
|
|
193
|
-
debugMode: args.debug !== undefined
|
|
260
|
+
debugMode: args.debug !== undefined
|
|
261
|
+
? args.debug
|
|
262
|
+
: process.env.DEBUG_MODE === 'true' || false,
|
|
194
263
|
// Transport configuration
|
|
195
|
-
transport: (args.transport
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
264
|
+
transport: (args.transport ?? process.env.TRANSPORT ?? 'stdio'),
|
|
265
|
+
streamableHttpPort: args.streamableHttpPort ??
|
|
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',
|
|
272
|
+
streamableHttpLogPath: args.streamableHttpLogPath ??
|
|
273
|
+
(process.env.STREAMABLE_HTTP_LOG_PATH ||
|
|
274
|
+
'/tmp/opik-mcp-streamable-http.log'),
|
|
199
275
|
// MCP configuration with fallbacks
|
|
200
276
|
mcpName: args.mcpName || process.env.MCP_NAME || 'opik-manager',
|
|
201
|
-
mcpVersion: args.mcpVersion || process.env.MCP_VERSION || '
|
|
202
|
-
mcpPort: args.mcpPort ||
|
|
203
|
-
|
|
204
|
-
|
|
277
|
+
mcpVersion: args.mcpVersion || process.env.MCP_VERSION || '2.0.0',
|
|
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',
|
|
205
286
|
// Toolset configuration with fallbacks
|
|
206
287
|
enabledToolsets: (() => {
|
|
207
288
|
// Command line takes precedence
|
|
208
289
|
if (args.toolsets && args.toolsets.length > 0) {
|
|
209
|
-
return args.toolsets
|
|
290
|
+
return normalizeToolsets(args.toolsets);
|
|
210
291
|
}
|
|
211
292
|
// Environment variable fallback
|
|
212
293
|
if (process.env.OPIK_TOOLSETS) {
|
|
213
|
-
|
|
214
|
-
return envToolsets.filter((t) => ['integration', 'prompts', 'projects', 'traces', 'metrics'].includes(t));
|
|
294
|
+
return normalizeToolsets(process.env.OPIK_TOOLSETS.split(','));
|
|
215
295
|
}
|
|
216
296
|
// Default toolsets
|
|
217
297
|
return DEFAULT_TOOLSETS;
|
|
@@ -244,10 +324,10 @@ export function loadConfig() {
|
|
|
244
324
|
// Log transport configuration
|
|
245
325
|
writeToLogFile('\nTransport Configuration:');
|
|
246
326
|
writeToLogFile(`- Transport: ${config.transport}`);
|
|
247
|
-
if (config.transport === '
|
|
248
|
-
writeToLogFile(`-
|
|
249
|
-
writeToLogFile(`-
|
|
250
|
-
writeToLogFile(`-
|
|
327
|
+
if (config.transport === 'streamable-http') {
|
|
328
|
+
writeToLogFile(`- Streamable HTTP Port: ${config.streamableHttpPort}`);
|
|
329
|
+
writeToLogFile(`- Streamable HTTP Host: ${config.streamableHttpHost}`);
|
|
330
|
+
writeToLogFile(`- Streamable HTTP Log Path: ${config.streamableHttpLogPath}`);
|
|
251
331
|
}
|
|
252
332
|
// Log MCP configuration
|
|
253
333
|
writeToLogFile('\nMCP Configuration:');
|
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
|
}
|