@@ -123,9 +123,10 @@ BASIC_AUTH_PASSWORD=password JWT_SECRET_KEY=my-test-key mcpgateway --host 0.0.0.
123
123
mcpgateway --help; mcpgateway --version
124
124
125
125
# Generate your JWT token from the key and list it
126
- export MCPGATEWAY_BEARER_TOKEN=$( python3 -m mcpgateway.utils.create_jwt_token --username admin --exp 10080 --secret my-test-key) ; echo $MCPGATEWAY_BEARER_TOKEN
126
+ export MCPGATEWAY_BEARER_TOKEN=$( python3 -m mcpgateway.utils.create_jwt_token --username admin --exp 10080 --secret my-test-key)
127
+ echo $MCPGATEWAY_BEARER_TOKEN
127
128
128
- # Run a local MCP Server (github) listening on SSE http://localhost:8000/sse
129
+ # Run a local MCP Server (github) listening on SSE http://localhost:8000/sse in another terminal:
129
130
pip install uvenv
130
131
npx -y supergateway --stdio " uvenv run mcp-server-git" # requires node.js and npx
131
132
# or time: npx -y supergateway --stdio "uvenv run mcp_server_time -- --local-timezone=Europe/Dublin" --port 8002
@@ -149,7 +150,7 @@ curl -s -X POST -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \
149
150
curl -s -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/gateways | jq
150
151
151
152
# Get gateway by ID
152
- curl -s -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/gateways/1
153
+ curl -s -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/gateways/1 | jq
153
154
154
155
# List the global tools
155
156
curl -s -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/tools | jq
@@ -159,34 +160,44 @@ curl -s -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" http://localhost:444
159
160
curl -X POST -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " \
160
161
-H " Content-Type: application/json" \
161
162
-d ' {"name":"devtools_mcp_server","description":"My developer tools","associatedTools": ["1","2","3"]}' \
162
- http://localhost:4444/servers
163
+ http://localhost:4444/servers | jq
163
164
164
165
# List servers
165
- curl -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/servers
166
+ curl -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/servers | jq
166
167
167
168
# Get an individual server
168
- curl -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/servers/1
169
+ curl -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " http://localhost:4444/servers/1 | jq
169
170
170
171
# You can now use http://localhost:4444/servers/1 as an SSE server with the configured JWT token in any MCP client
171
172
172
173
# To stop the running process, you can either:
173
174
fg # Return the process to foreground, you can not Ctrl + C, or:
174
- pkill mcpgateway; # ps -ef | grep mcpgateway | awk '{print $2}' | xargs
175
+ pkill mcpgateway
175
176
176
177
# Optionally, test the stdio wrapper to mirror tools from the gateway:
177
178
# This lets you connect to the gateway with tools that don't support SSE:
178
179
export MCP_AUTH_TOKEN=${MCPGATEWAY_BEARER_TOKEN}
179
180
export MCP_SERVER_CATALOG_URLS=http://localhost:4444/servers/1
180
- python3 -m mcpgateway.wrapper
181
+ python3 -m mcpgateway.wrapper # ^C to exit
182
+ # Expected: INFO mcpgateway.wrapper: Starting MCP wrapper 0.1.1: base_url=http://localhost:4444, timeout=90
181
183
# Alternatively with uv
182
184
uv run --directory . -m mcpgateway.wrapper
183
185
```
184
186
185
187
See [ .env.example] ( .env.example ) for full list of ENV variables you can use to override the configuration.
186
188
187
- ## Quick Start (Pre-built Container Image)
189
+ ---
190
+
191
+ ## Quick Start — Containers
192
+
193
+ Use the official OCI image from GHCR with ** Docker** * or* ** Podman** .
194
+
195
+ ---
196
+
197
+ <details >
198
+ <summary ><strong >🐳 Docker</strong ></summary >
188
199
189
- If you just want to run the gateway using the official OCI container image from GitHub Container Registry:
200
+ #### 1 · Minimum viable run
190
201
191
202
``` bash
192
203
docker run -d --name mcpgateway \
@@ -199,31 +210,105 @@ docker run -d --name mcpgateway \
199
210
-e DATABASE_URL=sqlite:///./mcp.db \
200
211
ghcr.io/ibm/mcp-context-forge:0.1.1
201
212
202
- docker logs mcpgateway
213
+ # Tail logs (Ctrl+C to quit)
214
+ docker logs -f mcpgateway
203
215
```
204
216
205
- You can now access the UI at [ http://localhost:4444/admin ] ( http://localhost:4444/admin )
217
+ Browse to ** [ http://localhost:4444/admin ] ( http://localhost:4444/admin ) ** (user ` admin ` / pass ` changeme ` ).
218
+
219
+ #### 2 · Persist the SQLite database
220
+
221
+ ``` bash
222
+ mkdir -p $( pwd) /data
223
+
224
+ docker run -d --name mcpgateway \
225
+ --restart unless-stopped \
226
+ -p 4444:4444 \
227
+ -v $( pwd) /data:/data \
228
+ -e DATABASE_URL=sqlite:////data/mcp.db \
229
+ -e HOST=0.0.0.0 \
230
+ -e JWT_SECRET_KEY=my-test-key \
231
+ -e BASIC_AUTH_USER=admin \
232
+ -e BASIC_AUTH_PASSWORD=changeme \
233
+ ghcr.io/ibm/mcp-context-forge:0.1.1
234
+ ```
206
235
207
- > 💡 You can also use ` --env-file .env ` if you have a config file already. See the provided [ .env.example] ( .env.example )
208
- > 💡 To access local tools, consider using ` --network=host `
209
- > 💡 Consider using a stable / release version of the image, ex: ` ghcr.io/ibm/mcp-context-forge:v0.1.1 ` rather than ` latest `
236
+ SQLite now lives on the host at ` ./data/mcp.db ` .
210
237
211
- ### Optional: Mount a local volume for persistent SQLite storage
238
+ #### 3 · Local tool discovery (host network)
212
239
213
240
``` bash
214
- -v $( pwd) /data:/app
241
+ docker run -d --name mcpgateway \
242
+ --network=host \
243
+ -e HOST=0.0.0.0 \
244
+ -e PORT=4444 \
245
+ -e DATABASE_URL=sqlite:////data/mcp.db \
246
+ -v $( pwd) /data:/data \
247
+ ghcr.io/ibm/mcp-context-forge:0.1.1
215
248
```
216
249
217
- ### Generate a token for API access
250
+ </details >
251
+
252
+ ---
253
+
254
+ <details >
255
+ <summary ><strong >🦭 Podman (rootless-friendly)</strong ></summary >
218
256
219
- A JWT token is required to access all API endpoints. This can be generated with the provided CLI, specifying a username, secret (that matches the one defined in ` .env ` for the gateway) and expiration time (in seconds).
257
+ #### 1 · Basic run
220
258
221
259
``` bash
222
- export MCPGATEWAY_BEARER_TOKEN=$( docker exec mcpgateway python3 -m mcpgateway.utils.create_jwt_token --username admin --exp 100800 --secret my-test-key)
223
- echo ${MCPGATEWAY_BEARER_TOKEN}
260
+ podman run -d --name mcpgateway \
261
+ -p 4444:4444 \
262
+ -e HOST=0.0.0.0 \
263
+ -e DATABASE_URL=sqlite:///./mcp.db \
264
+ ghcr.io/ibm/mcp-context-forge:0.1.1
265
+ ```
266
+
267
+ #### 2 · Persist SQLite
268
+
269
+ ``` bash
270
+ mkdir -p $( pwd) /data
271
+
272
+ podman run -d --name mcpgateway \
273
+ --restart=on-failure \
274
+ -p 4444:4444 \
275
+ -v $( pwd) /data:/data \
276
+ -e DATABASE_URL=sqlite:////data/mcp.db \
277
+ ghcr.io/ibm/mcp-context-forge:0.1.1
278
+ ```
279
+
280
+ #### 3 · Host networking (rootless)
281
+
282
+ ``` bash
283
+ podman run -d --name mcpgateway \
284
+ --network=host \
285
+ -v $( pwd) /data:/data \
286
+ -e DATABASE_URL=sqlite:////data/mcp.db \
287
+ ghcr.io/ibm/mcp-context-forge:0.1.1
224
288
```
225
289
226
- ### Smoke-test the running container
290
+ </details >
291
+
292
+ ---
293
+
294
+ <details >
295
+ <summary ><strong >✏️ Docker/Podman tips</strong ></summary >
296
+
297
+ * ** .env files** — Put all the ` -e FOO= ` lines into a file and replace them with ` --env-file .env ` . See the provided [ .env.example] ( .env.example ) for reference.
298
+ * ** Pinned tags** — Use an explicit version (e.g. ` v0.1.1 ` ) instead of ` latest ` for reproducible builds.
299
+ * ** JWT tokens** — Generate one in the running container:
300
+
301
+ ``` bash
302
+ docker exec mcpgateway python3 -m mcpgateway.utils.create_jwt_token -u admin -e 10080 --secret my-test-key
303
+ ```
304
+ * ** Upgrades** — Stop, remove, and rerun with the same ` -v $(pwd)/data:/data ` mount; your DB and config stay intact.
305
+
306
+ </details >
307
+
308
+ ---
309
+
310
+ <details >
311
+ <summary ><strong >🚑 Smoke-test the running container</strong ></summary >
227
312
228
313
``` bash
229
314
curl -s -H " Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN " \
@@ -234,9 +319,14 @@ curl -s -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \
234
319
http://localhost:4444/version | jq
235
320
```
236
321
237
- ### Running the MCP Gateway stdio wrapper
322
+ </details >
323
+
324
+ ---
238
325
239
- The ` mcpgateway.wrapper ` lets you connect to the gateway over ** stdio** , while retaining authentication using the JWT token when the wrapper connect to a remote gateway. You should run this from a MCP client (ex: defined in the ` json ` configuration of Claude/Copilot, etc). You can test this from a shell with:
326
+ <details >
327
+ <summary ><strong >🖧 Running the MCP Gateway stdio wrapper</strong ></summary >
328
+
329
+ The ` mcpgateway.wrapper ` lets you connect to the gateway over ** stdio** while keeping JWT authentication. You should run this from the MCP Client. The example below is just for testing.
240
330
241
331
``` bash
242
332
# Set environment variables
@@ -246,15 +336,6 @@ export MCP_SERVER_CATALOG_URLS='http://localhost:4444/servers/1'
246
336
export MCP_TOOL_CALL_TIMEOUT=120
247
337
export MCP_WRAPPER_LOG_LEVEL=DEBUG # or OFF to disable logging
248
338
249
- # Run the wrapper from the installed module
250
- python3 -m mcpgateway.wrapper
251
- # Alternatively with uv
252
- uv run --directory . -m mcpgateway.wrapper
253
- ```
254
-
255
- ** Or using the container image:**
256
-
257
- ``` bash
258
339
docker run --rm -i \
259
340
-e MCP_AUTH_TOKEN=$MCPGATEWAY_BEARER_TOKEN \
260
341
-e MCP_SERVER_CATALOG_URLS=http://host.docker.internal:4444/servers/1 \
@@ -264,7 +345,11 @@ docker run --rm -i \
264
345
python3 -m mcpgateway.wrapper
265
346
```
266
347
267
- ** Testing ` mcpgateway.wrapper ` by hand:**
348
+ </details >
349
+
350
+ ---
351
+
352
+ ## Testing ` mcpgateway.wrapper ` by hand:
268
353
269
354
Because the wrapper speaks JSON-RPC over stdin/stdout, you can interact with it using nothing more than a terminal or pipes.
270
355
0 commit comments