@biggora/claude-plugins 1.1.0 → 1.2.0
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/.claude/settings.local.json +3 -1
- package/README.md +7 -22
- package/codex-cli-workspace/iteration-1/benchmark.json +122 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/eval_metadata.json +13 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/grading.json +52 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/outputs/response.md +163 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/timing.json +5 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/grading.json +58 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/outputs/response.md +151 -0
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/timing.json +5 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/eval_metadata.json +13 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/grading.json +52 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md +86 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/timing.json +5 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/grading.json +58 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md +164 -0
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/timing.json +5 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/eval_metadata.json +13 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/grading.json +52 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/outputs/response.md +130 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/timing.json +5 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/grading.json +64 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/outputs/response.md +209 -0
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/timing.json +5 -0
- package/codex-cli-workspace/iteration-1/review.html +1325 -0
- package/gemini-cli-workspace/iteration-1/benchmark.json +86 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/eval_metadata.json +37 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/outputs/response.md +401 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/outputs/response.md +405 -0
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/eval_metadata.json +37 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md +212 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md +427 -0
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/eval_metadata.json +32 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/grading.json +32 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/outputs/response.md +171 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/grading.json +32 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/outputs/response.md +199 -0
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-1/review.html +1325 -0
- package/gemini-cli-workspace/iteration-2/benchmark.json +173 -0
- package/gemini-cli-workspace/iteration-2/benchmark.md +28 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/eval_metadata.json +37 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/outputs/response.md +195 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/outputs/response.md +377 -0
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/eval_metadata.json +37 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/outputs/response.md +127 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/grading.json +37 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/outputs/response.md +164 -0
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/eval_metadata.json +32 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/grading.json +32 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/outputs/response.md +91 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/grading.json +32 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/outputs/response.md +112 -0
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/timing.json +5 -0
- package/gemini-cli-workspace/iteration-2/eval-viewer.html +1325 -0
- package/package.json +1 -1
- package/registry/registry.json +31 -1
- package/screen-recording-workspace/evals.json +41 -0
- package/screen-recording-workspace/iteration-1/benchmark.json +102 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/eval_metadata.json +31 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/grading.json +11 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/outputs/demo.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/timing.json +5 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/grading.json +11 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/outputs/demo.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/timing.json +5 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/eval_metadata.json +31 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/grading.json +11 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/outputs/region_capture.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/timing.json +5 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/grading.json +11 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/outputs/region_capture.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/timing.json +5 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/eval_metadata.json +31 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/grading.json +11 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/outputs/fallback_recording.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/timing.json +5 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/grading.json +11 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/outputs/fallback_recording.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/outputs/record_screen.py +67 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/timing.json +5 -0
- package/screen-recording-workspace/iteration-1/review.html +1325 -0
- package/src/skills/codex-cli/SKILL.md +21 -11
- package/src/skills/codex-cli/evals/evals.json +47 -0
- package/src/skills/gemini-cli/SKILL.md +27 -13
- package/src/skills/gemini-cli/evals/evals.json +46 -0
- package/src/skills/gemini-cli/references/commands.md +21 -14
- package/src/skills/gemini-cli/references/configuration.md +23 -18
- package/src/skills/gemini-cli/references/headless-and-scripting.md +7 -17
- package/src/skills/gemini-cli/references/mcp-and-extensions.md +12 -6
- package/src/skills/notebook-lm/SKILL.md +1 -1
- package/src/skills/screen-recording/SKILL.md +243 -213
- package/src/skills/screen-recording/references/design-patterns.md +4 -2
- package/src/skills/screen-recording/references/ffmpeg-recording.md +473 -0
- package/src/skills/screen-recording/references/{approach1-programmatic.md → programmatic-generation.md} +45 -22
- package/src/skills/screen-recording/references/python-fallback.md +222 -0
- package/src/skills/tm-search/SKILL.md +242 -106
- package/src/skills/tm-search/evals/evals.json +23 -0
- package/src/skills/tm-search/references/scraping-fallback.md +60 -95
- package/src/skills/tm-search/scripts/tm_search.py +453 -375
- package/src/skills/youtube-thumbnail/SKILL.md +11 -1
- package/src/skills/screen-recording/references/approach2-xvfb.md +0 -232
package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Connecting a Custom Python MCP Server to Gemini CLI
|
|
2
|
+
|
|
3
|
+
You need to configure your server in `settings.json`, pass the API key via the `env` field, and use `includeTools` to restrict which tools are exposed. Here is the full walkthrough.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Configure the MCP Server in settings.json
|
|
8
|
+
|
|
9
|
+
Edit (or create) `~/.gemini/settings.json` for a global configuration, or `<your-project>/.gemini/settings.json` for project-scoped configuration. Add your server under the `mcpServers` key:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"myPythonServer": {
|
|
15
|
+
"command": "python",
|
|
16
|
+
"args": ["-m", "my_mcp_server"],
|
|
17
|
+
"cwd": "./mcp_tools",
|
|
18
|
+
"env": {
|
|
19
|
+
"MY_API_KEY": "$MY_API_KEY"
|
|
20
|
+
},
|
|
21
|
+
"timeout": 15000,
|
|
22
|
+
"trust": false,
|
|
23
|
+
"includeTools": ["search_records", "get_status"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### What each field does
|
|
30
|
+
|
|
31
|
+
| Field | Type | Description |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `command` | string | The executable to run. Use `"python"` (or `"python3"` depending on your system). |
|
|
34
|
+
| `args` | string[] | Arguments passed to the command. `["-m", "my_mcp_server"]` runs your package as a module. You can also use a script path like `["./server.py"]`. |
|
|
35
|
+
| `cwd` | string | Working directory for the server process. Optional -- set this if your server needs to run from a specific directory. |
|
|
36
|
+
| `env` | object | Environment variables passed to the server process. Use the `"$VAR_NAME"` syntax to reference variables from your shell environment. |
|
|
37
|
+
| `timeout` | number | Connection timeout in milliseconds. Default is 10000 (10 seconds). Increase if your server takes longer to start. |
|
|
38
|
+
| `trust` | boolean | When `true`, skips all tool confirmation dialogs. Keep this `false` unless you fully control and trust the server. |
|
|
39
|
+
| `includeTools` | string[] | **Whitelist** -- only these tools will be exposed to Gemini. If set, all other tools from the server are hidden. |
|
|
40
|
+
| `excludeTools` | string[] | **Blacklist** -- these specific tools will be hidden. All others remain available. |
|
|
41
|
+
|
|
42
|
+
**Important:** `includeTools` and `excludeTools` are mutually exclusive approaches. Use one or the other:
|
|
43
|
+
- Use `includeTools` when your server exposes many tools but you only want a few available.
|
|
44
|
+
- Use `excludeTools` when you want most tools but need to block specific dangerous ones.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 2. Pass the API Key Securely
|
|
49
|
+
|
|
50
|
+
Never hardcode secrets directly in `settings.json`. Instead, use the `"$VAR_NAME"` pattern to reference environment variables from your shell:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
"env": {
|
|
54
|
+
"MY_API_KEY": "$MY_API_KEY"
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then set the variable in your shell before running Gemini:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
export MY_API_KEY="sk-your-actual-api-key-here"
|
|
62
|
+
gemini
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Alternatively, you can store the variable in a `.env` file that Gemini loads automatically:
|
|
66
|
+
|
|
67
|
+
- `~/.gemini/.env` -- global env file
|
|
68
|
+
- `./.gemini/.env` -- project-level env file
|
|
69
|
+
|
|
70
|
+
Example `.gemini/.env`:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
MY_API_KEY=sk-your-actual-api-key-here
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Security note:** Gemini CLI automatically redacts sensitive env vars (names containing `TOKEN`, `SECRET`, `KEY`, etc.) from MCP processes unless you explicitly list them in the `env` field. So you must include the variable in `env` for it to reach your server.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. Full Working Example
|
|
81
|
+
|
|
82
|
+
Suppose you have a Python MCP server at `~/mcp-servers/analytics_server.py` that exposes five tools (`query_data`, `generate_report`, `delete_records`, `export_csv`, `run_migration`), and you only want `query_data` and `generate_report` available. The server needs a `ANALYTICS_API_KEY`.
|
|
83
|
+
|
|
84
|
+
### settings.json
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"analytics": {
|
|
90
|
+
"command": "python3",
|
|
91
|
+
"args": ["analytics_server.py"],
|
|
92
|
+
"cwd": "/home/user/mcp-servers",
|
|
93
|
+
"env": {
|
|
94
|
+
"ANALYTICS_API_KEY": "$ANALYTICS_API_KEY"
|
|
95
|
+
},
|
|
96
|
+
"timeout": 15000,
|
|
97
|
+
"trust": false,
|
|
98
|
+
"includeTools": ["query_data", "generate_report"]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Shell setup
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
export ANALYTICS_API_KEY="your-key-here"
|
|
108
|
+
gemini
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Using the server in a Gemini session
|
|
112
|
+
|
|
113
|
+
Once inside the interactive session, you can verify the server connected:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
/mcp list
|
|
117
|
+
/mcp status
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then invoke the tools by addressing the server:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
> @analytics Query monthly active users for Q4 2025
|
|
124
|
+
> @analytics Generate a report on user retention trends
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 4. Alternative: Use excludeTools Instead
|
|
130
|
+
|
|
131
|
+
If you want all tools available except specific dangerous ones:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"mcpServers": {
|
|
136
|
+
"analytics": {
|
|
137
|
+
"command": "python3",
|
|
138
|
+
"args": ["analytics_server.py"],
|
|
139
|
+
"cwd": "/home/user/mcp-servers",
|
|
140
|
+
"env": {
|
|
141
|
+
"ANALYTICS_API_KEY": "$ANALYTICS_API_KEY"
|
|
142
|
+
},
|
|
143
|
+
"timeout": 15000,
|
|
144
|
+
"trust": false,
|
|
145
|
+
"excludeTools": ["delete_records", "run_migration"]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This exposes everything except `delete_records` and `run_migration`.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 5. Adding the Server via CLI (Alternative to Manual Editing)
|
|
156
|
+
|
|
157
|
+
You can also add MCP servers from the command line:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
gemini mcp add analytics --command "python3 analytics_server.py"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
However, the CLI `add` command provides less control over fields like `env`, `includeTools`, and `cwd`. For full configuration, editing `settings.json` directly is recommended.
|
|
164
|
+
|
|
165
|
+
To manage servers later:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
gemini mcp list # list all configured servers
|
|
169
|
+
gemini mcp remove analytics # remove a server
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Or from within an interactive session:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
/mcp list
|
|
176
|
+
/mcp enable analytics
|
|
177
|
+
/mcp disable analytics
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 6. Minimal Python MCP Server Skeleton
|
|
183
|
+
|
|
184
|
+
For reference, here is the basic structure of a Python MCP server that your configuration would launch:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
# analytics_server.py
|
|
188
|
+
import os
|
|
189
|
+
import json
|
|
190
|
+
import sys
|
|
191
|
+
|
|
192
|
+
# Read the API key passed through the env config
|
|
193
|
+
api_key = os.environ.get("ANALYTICS_API_KEY")
|
|
194
|
+
if not api_key:
|
|
195
|
+
print("Error: ANALYTICS_API_KEY not set", file=sys.stderr)
|
|
196
|
+
sys.exit(1)
|
|
197
|
+
|
|
198
|
+
# Your MCP server implementation here
|
|
199
|
+
# The server communicates over stdio using the MCP protocol
|
|
200
|
+
# Tools like query_data, generate_report, etc. are registered
|
|
201
|
+
# and handled according to the MCP specification.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Summary
|
|
207
|
+
|
|
208
|
+
1. Add your server to `mcpServers` in `~/.gemini/settings.json` (or project-level).
|
|
209
|
+
2. Pass the API key using `"env": { "MY_API_KEY": "$MY_API_KEY" }` -- never hardcode it.
|
|
210
|
+
3. Restrict tools with `"includeTools": ["tool1", "tool2"]` (whitelist) or `"excludeTools": ["bad_tool"]` (blacklist).
|
|
211
|
+
4. Set the actual environment variable in your shell or in a `.gemini/.env` file.
|
|
212
|
+
5. Verify the connection with `/mcp list` and `/mcp status` inside an interactive session.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"eval_id": 2,
|
|
3
|
+
"eval_name": "mcp-server-config",
|
|
4
|
+
"configuration": "without_skill",
|
|
5
|
+
"expectations": [
|
|
6
|
+
{
|
|
7
|
+
"text": "Points to ~/.gemini/settings.json or project-level settings.json",
|
|
8
|
+
"passed": true,
|
|
9
|
+
"evidence": "Mentions both `~/.gemini/settings.json` and `.gemini/settings.json` in project root"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"text": "Shows mcpServers config with command, args fields",
|
|
13
|
+
"passed": true,
|
|
14
|
+
"evidence": "Shows mcpServers config with command, args, cwd, env fields"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"text": "Shows $VAR pattern for environment variable references in env field",
|
|
18
|
+
"passed": false,
|
|
19
|
+
"evidence": "Hardcodes API key directly in env (`\"MY_API_KEY\": \"sk-abc123your-actual-key\"`). Uses `${MY_API_KEY}` syntax but adds caveat that it might not be supported. Does not show the correct `$VAR` pattern."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"text": "Explains includeTools and/or excludeTools for restricting exposed tools",
|
|
23
|
+
"passed": false,
|
|
24
|
+
"evidence": "Does not mention includeTools or excludeTools. Instead suggests server-side tool filtering and uses non-existent `toolFilter` field with `allow` sub-field."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"text": "Mentions security considerations (trust field, not hardcoding keys, etc.)",
|
|
28
|
+
"passed": false,
|
|
29
|
+
"evidence": "Does not mention the trust field. Actually recommends hardcoding as Option A. Does not mention env var redaction behavior."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"text": "Uses correct Python command (python/python3) in the command field",
|
|
33
|
+
"passed": true,
|
|
34
|
+
"evidence": "Uses `python` in the command field correctly"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
# Connecting a Custom Python MCP Server to Gemini CLI
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Gemini CLI supports MCP (Model Context Protocol) servers through its settings configuration. You can connect a custom Python MCP server, pass environment variables (like API keys), and restrict which tools are exposed.
|
|
6
|
+
|
|
7
|
+
## 1. Build Your Python MCP Server
|
|
8
|
+
|
|
9
|
+
First, make sure your Python MCP server uses the official MCP SDK. Here is a minimal example:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
# my_mcp_server.py
|
|
13
|
+
import os
|
|
14
|
+
from mcp.server.fastmcp import FastMCP
|
|
15
|
+
|
|
16
|
+
# Read the API key from environment
|
|
17
|
+
API_KEY = os.environ.get("MY_API_KEY")
|
|
18
|
+
if not API_KEY:
|
|
19
|
+
raise ValueError("MY_API_KEY environment variable is required")
|
|
20
|
+
|
|
21
|
+
mcp = FastMCP("my-custom-server")
|
|
22
|
+
|
|
23
|
+
@mcp.tool()
|
|
24
|
+
def fetch_data(query: str) -> str:
|
|
25
|
+
"""Fetch data from the external API using the configured API key."""
|
|
26
|
+
# Use API_KEY here for your requests
|
|
27
|
+
return f"Results for '{query}' using key ending in ...{API_KEY[-4:]}"
|
|
28
|
+
|
|
29
|
+
@mcp.tool()
|
|
30
|
+
def analyze_data(data: str) -> str:
|
|
31
|
+
"""Analyze the provided data."""
|
|
32
|
+
return f"Analysis of: {data}"
|
|
33
|
+
|
|
34
|
+
@mcp.tool()
|
|
35
|
+
def internal_debug(info: str) -> str:
|
|
36
|
+
"""Internal debug tool - you may want to hide this from Gemini."""
|
|
37
|
+
return f"Debug: {info}"
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
mcp.run()
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Install the dependency:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install mcp
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 2. Configure Gemini CLI to Use Your MCP Server
|
|
50
|
+
|
|
51
|
+
Gemini CLI reads MCP server configuration from a `settings.json` file. There are two levels:
|
|
52
|
+
|
|
53
|
+
- **Global (user-level):** `~/.gemini/settings.json`
|
|
54
|
+
- **Project-level:** `.gemini/settings.json` in your project root
|
|
55
|
+
|
|
56
|
+
### Basic Configuration
|
|
57
|
+
|
|
58
|
+
Create or edit `~/.gemini/settings.json` (or `.gemini/settings.json` in your project):
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"my-custom-server": {
|
|
64
|
+
"command": "python",
|
|
65
|
+
"args": ["my_mcp_server.py"],
|
|
66
|
+
"cwd": "/absolute/path/to/your/server/directory",
|
|
67
|
+
"env": {
|
|
68
|
+
"MY_API_KEY": "your-api-key-value-here"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Configuration Fields Explained
|
|
76
|
+
|
|
77
|
+
| Field | Description |
|
|
78
|
+
|-------|-------------|
|
|
79
|
+
| `command` | The executable to run (e.g., `python`, `python3`, `node`, `npx`) |
|
|
80
|
+
| `args` | Array of arguments passed to the command |
|
|
81
|
+
| `cwd` | Working directory for the server process (optional but recommended) |
|
|
82
|
+
| `env` | Environment variables passed to the server process |
|
|
83
|
+
|
|
84
|
+
### Using a Virtual Environment
|
|
85
|
+
|
|
86
|
+
If your MCP server has its own virtual environment:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"my-custom-server": {
|
|
92
|
+
"command": "/path/to/venv/bin/python",
|
|
93
|
+
"args": ["/absolute/path/to/my_mcp_server.py"],
|
|
94
|
+
"env": {
|
|
95
|
+
"MY_API_KEY": "your-api-key-value-here"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
On Windows, use the Windows path to the venv Python:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"mcpServers": {
|
|
107
|
+
"my-custom-server": {
|
|
108
|
+
"command": "C:\\path\\to\\venv\\Scripts\\python.exe",
|
|
109
|
+
"args": ["C:\\path\\to\\my_mcp_server.py"],
|
|
110
|
+
"env": {
|
|
111
|
+
"MY_API_KEY": "your-api-key-value-here"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 3. Passing the API Key Securely
|
|
119
|
+
|
|
120
|
+
There are several approaches to handle the API key:
|
|
121
|
+
|
|
122
|
+
### Option A: Inline in settings.json (simplest, but key is in plaintext)
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"mcpServers": {
|
|
127
|
+
"my-custom-server": {
|
|
128
|
+
"command": "python",
|
|
129
|
+
"args": ["my_mcp_server.py"],
|
|
130
|
+
"env": {
|
|
131
|
+
"MY_API_KEY": "sk-abc123your-actual-key"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Option B: Reference a shell variable at launch time
|
|
139
|
+
|
|
140
|
+
Set the environment variable in your shell profile (`.bashrc`, `.zshrc`, etc.):
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
export MY_API_KEY="sk-abc123your-actual-key"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Then in `settings.json`, you can omit the `env` block entirely if the variable is already in your shell environment. The child process inherits the parent environment. However, to be explicit:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"mcpServers": {
|
|
151
|
+
"my-custom-server": {
|
|
152
|
+
"command": "python",
|
|
153
|
+
"args": ["my_mcp_server.py"],
|
|
154
|
+
"env": {
|
|
155
|
+
"MY_API_KEY": "${MY_API_KEY}"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
> **Note:** Whether `${MY_API_KEY}` variable interpolation is supported depends on the Gemini CLI version. If it is not supported, you may need to use a wrapper script approach (see Option C).
|
|
163
|
+
|
|
164
|
+
### Option C: Wrapper script (most flexible)
|
|
165
|
+
|
|
166
|
+
Create a wrapper script `run_server.sh`:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
#!/bin/bash
|
|
170
|
+
# run_server.sh
|
|
171
|
+
# Load API key from a secure location
|
|
172
|
+
source ~/.secrets/my_api_keys.env
|
|
173
|
+
export MY_API_KEY
|
|
174
|
+
exec python /path/to/my_mcp_server.py "$@"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Then configure:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"mcpServers": {
|
|
182
|
+
"my-custom-server": {
|
|
183
|
+
"command": "bash",
|
|
184
|
+
"args": ["/path/to/run_server.sh"]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## 4. Restricting Which Tools Are Exposed
|
|
191
|
+
|
|
192
|
+
There are two approaches to restricting tools: server-side and client-side.
|
|
193
|
+
|
|
194
|
+
### Approach A: Server-Side Restriction (Recommended)
|
|
195
|
+
|
|
196
|
+
Only define the tools you want exposed in your MCP server. Simply remove or comment out any tools you do not want Gemini to access:
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
# my_mcp_server.py - only expose the tools you want
|
|
200
|
+
from mcp.server.fastmcp import FastMCP
|
|
201
|
+
import os
|
|
202
|
+
|
|
203
|
+
API_KEY = os.environ.get("MY_API_KEY")
|
|
204
|
+
mcp = FastMCP("my-custom-server")
|
|
205
|
+
|
|
206
|
+
@mcp.tool()
|
|
207
|
+
def fetch_data(query: str) -> str:
|
|
208
|
+
"""Fetch data from the external API."""
|
|
209
|
+
return f"Results for '{query}'"
|
|
210
|
+
|
|
211
|
+
@mcp.tool()
|
|
212
|
+
def analyze_data(data: str) -> str:
|
|
213
|
+
"""Analyze the provided data."""
|
|
214
|
+
return f"Analysis of: {data}"
|
|
215
|
+
|
|
216
|
+
# internal_debug is NOT registered - Gemini will never see it
|
|
217
|
+
|
|
218
|
+
if __name__ == "__main__":
|
|
219
|
+
mcp.run()
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Approach B: Conditional Tool Registration
|
|
223
|
+
|
|
224
|
+
Use an environment variable or config file to control which tools are registered:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
# my_mcp_server.py - conditionally register tools
|
|
228
|
+
from mcp.server.fastmcp import FastMCP
|
|
229
|
+
import os
|
|
230
|
+
import json
|
|
231
|
+
|
|
232
|
+
API_KEY = os.environ.get("MY_API_KEY")
|
|
233
|
+
ALLOWED_TOOLS = os.environ.get("ALLOWED_TOOLS", "").split(",")
|
|
234
|
+
|
|
235
|
+
mcp = FastMCP("my-custom-server")
|
|
236
|
+
|
|
237
|
+
def register_if_allowed(tool_name):
|
|
238
|
+
"""Decorator factory that only registers a tool if it's in the allowed list."""
|
|
239
|
+
def decorator(func):
|
|
240
|
+
if not ALLOWED_TOOLS or not ALLOWED_TOOLS[0]:
|
|
241
|
+
# No restriction set, register all tools
|
|
242
|
+
return mcp.tool()(func)
|
|
243
|
+
elif tool_name in ALLOWED_TOOLS:
|
|
244
|
+
return mcp.tool()(func)
|
|
245
|
+
return func
|
|
246
|
+
return decorator
|
|
247
|
+
|
|
248
|
+
@register_if_allowed("fetch_data")
|
|
249
|
+
def fetch_data(query: str) -> str:
|
|
250
|
+
"""Fetch data from the external API."""
|
|
251
|
+
return f"Results for '{query}'"
|
|
252
|
+
|
|
253
|
+
@register_if_allowed("analyze_data")
|
|
254
|
+
def analyze_data(data: str) -> str:
|
|
255
|
+
"""Analyze the provided data."""
|
|
256
|
+
return f"Analysis of: {data}"
|
|
257
|
+
|
|
258
|
+
@register_if_allowed("internal_debug")
|
|
259
|
+
def internal_debug(info: str) -> str:
|
|
260
|
+
"""Internal debug tool."""
|
|
261
|
+
return f"Debug: {info}"
|
|
262
|
+
|
|
263
|
+
if __name__ == "__main__":
|
|
264
|
+
mcp.run()
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Then in your `settings.json`, pass the allowed tools list:
|
|
268
|
+
|
|
269
|
+
```json
|
|
270
|
+
{
|
|
271
|
+
"mcpServers": {
|
|
272
|
+
"my-custom-server": {
|
|
273
|
+
"command": "python",
|
|
274
|
+
"args": ["my_mcp_server.py"],
|
|
275
|
+
"env": {
|
|
276
|
+
"MY_API_KEY": "your-api-key-here",
|
|
277
|
+
"ALLOWED_TOOLS": "fetch_data,analyze_data"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
This way, `internal_debug` is never registered and Gemini cannot call it.
|
|
285
|
+
|
|
286
|
+
### Approach C: Gemini CLI Tool Filtering (if supported)
|
|
287
|
+
|
|
288
|
+
Some MCP clients support an `allowedTools` or `toolFilter` field in the server configuration. If Gemini CLI supports this, the configuration would look like:
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"mcpServers": {
|
|
293
|
+
"my-custom-server": {
|
|
294
|
+
"command": "python",
|
|
295
|
+
"args": ["my_mcp_server.py"],
|
|
296
|
+
"env": {
|
|
297
|
+
"MY_API_KEY": "your-api-key-here"
|
|
298
|
+
},
|
|
299
|
+
"toolFilter": {
|
|
300
|
+
"allow": ["fetch_data", "analyze_data"]
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
> **Note:** The exact field name and syntax for client-side tool filtering varies by MCP client implementation. Check the Gemini CLI documentation for the exact syntax. If Gemini CLI does not support this field, use the server-side approaches (A or B) described above.
|
|
308
|
+
|
|
309
|
+
## 5. Complete Working Example
|
|
310
|
+
|
|
311
|
+
### Directory Structure
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
my-mcp-project/
|
|
315
|
+
my_mcp_server.py
|
|
316
|
+
requirements.txt
|
|
317
|
+
.gemini/
|
|
318
|
+
settings.json
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### requirements.txt
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
mcp>=1.0.0
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### my_mcp_server.py
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
import os
|
|
331
|
+
from mcp.server.fastmcp import FastMCP
|
|
332
|
+
|
|
333
|
+
API_KEY = os.environ.get("MY_API_KEY")
|
|
334
|
+
if not API_KEY:
|
|
335
|
+
raise ValueError("MY_API_KEY environment variable must be set")
|
|
336
|
+
|
|
337
|
+
ALLOWED_TOOLS = [t.strip() for t in os.environ.get("ALLOWED_TOOLS", "").split(",") if t.strip()]
|
|
338
|
+
|
|
339
|
+
mcp = FastMCP("my-custom-server")
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def expose(tool_name):
|
|
343
|
+
"""Only register the tool if it passes the allowlist filter."""
|
|
344
|
+
def decorator(func):
|
|
345
|
+
if not ALLOWED_TOOLS or tool_name in ALLOWED_TOOLS:
|
|
346
|
+
return mcp.tool()(func)
|
|
347
|
+
return func
|
|
348
|
+
return decorator
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@expose("fetch_data")
|
|
352
|
+
def fetch_data(query: str) -> str:
|
|
353
|
+
"""Fetch data from the external API using the configured API key."""
|
|
354
|
+
# Your real implementation here
|
|
355
|
+
return f"Fetched results for '{query}'"
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@expose("analyze_data")
|
|
359
|
+
def analyze_data(data: str) -> str:
|
|
360
|
+
"""Analyze the provided data and return insights."""
|
|
361
|
+
return f"Analysis complete for: {data}"
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
@expose("dangerous_reset")
|
|
365
|
+
def dangerous_reset() -> str:
|
|
366
|
+
"""Reset all data - restricted tool."""
|
|
367
|
+
return "Data reset complete"
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
if __name__ == "__main__":
|
|
371
|
+
mcp.run()
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### .gemini/settings.json
|
|
375
|
+
|
|
376
|
+
```json
|
|
377
|
+
{
|
|
378
|
+
"mcpServers": {
|
|
379
|
+
"my-custom-server": {
|
|
380
|
+
"command": "python",
|
|
381
|
+
"args": ["my_mcp_server.py"],
|
|
382
|
+
"cwd": "/absolute/path/to/my-mcp-project",
|
|
383
|
+
"env": {
|
|
384
|
+
"MY_API_KEY": "sk-your-api-key-here",
|
|
385
|
+
"ALLOWED_TOOLS": "fetch_data,analyze_data"
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
With this configuration:
|
|
393
|
+
- Gemini CLI launches your Python MCP server as a subprocess
|
|
394
|
+
- The `MY_API_KEY` environment variable is passed securely to the server process
|
|
395
|
+
- Only `fetch_data` and `analyze_data` are registered as tools; `dangerous_reset` is excluded
|
|
396
|
+
- Gemini can discover and invoke the allowed tools during conversation
|
|
397
|
+
|
|
398
|
+
## 6. Testing Your Server
|
|
399
|
+
|
|
400
|
+
Before connecting to Gemini CLI, test your server standalone:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
# Test that the server starts correctly
|
|
404
|
+
MY_API_KEY="test-key" python my_mcp_server.py
|
|
405
|
+
|
|
406
|
+
# Or with tool restrictions
|
|
407
|
+
MY_API_KEY="test-key" ALLOWED_TOOLS="fetch_data" python my_mcp_server.py
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
You can also use the MCP Inspector tool to verify your server works:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
npx @modelcontextprotocol/inspector python my_mcp_server.py
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
Then launch Gemini CLI in your project directory. It will automatically pick up the `.gemini/settings.json` and start your MCP server.
|
|
417
|
+
|
|
418
|
+
## 7. Troubleshooting
|
|
419
|
+
|
|
420
|
+
| Issue | Solution |
|
|
421
|
+
|-------|----------|
|
|
422
|
+
| Server not found | Use absolute paths in `command` and `args` |
|
|
423
|
+
| API key not available | Verify the `env` block in settings.json; check with a print/log statement |
|
|
424
|
+
| Tools not showing up | Confirm the tool functions are decorated with `@mcp.tool()` and not filtered out |
|
|
425
|
+
| Permission errors | Ensure the Python executable and script have correct permissions |
|
|
426
|
+
| Server crashes on start | Run the server manually from the terminal first to see error output |
|
|
427
|
+
| Wrong Python version | Use the full path to the correct Python interpreter in `command` |
|