Skip to content

Commit 8b9f2e6

Browse files
committed
Cleanup README
Signed-off-by: Mihai Criveti <[email protected]>
1 parent 1a5bf83 commit 8b9f2e6

File tree

1 file changed

+119
-34
lines changed

1 file changed

+119
-34
lines changed

README.md

Lines changed: 119 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ BASIC_AUTH_PASSWORD=password JWT_SECRET_KEY=my-test-key mcpgateway --host 0.0.0.
123123
mcpgateway --help; mcpgateway --version
124124

125125
# 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
127128

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:
129130
pip install uvenv
130131
npx -y supergateway --stdio "uvenv run mcp-server-git" # requires node.js and npx
131132
# 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" \
149150
curl -s -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" http://localhost:4444/gateways | jq
150151

151152
# 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
153154

154155
# List the global tools
155156
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
159160
curl -X POST -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \
160161
-H "Content-Type: application/json" \
161162
-d '{"name":"devtools_mcp_server","description":"My developer tools","associatedTools": ["1","2","3"]}' \
162-
http://localhost:4444/servers
163+
http://localhost:4444/servers | jq
163164

164165
# 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
166167

167168
# 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
169170

170171
# You can now use http://localhost:4444/servers/1 as an SSE server with the configured JWT token in any MCP client
171172

172173
# To stop the running process, you can either:
173174
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
175176

176177
# Optionally, test the stdio wrapper to mirror tools from the gateway:
177178
# This lets you connect to the gateway with tools that don't support SSE:
178179
export MCP_AUTH_TOKEN=${MCPGATEWAY_BEARER_TOKEN}
179180
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
181183
# Alternatively with uv
182184
uv run --directory . -m mcpgateway.wrapper
183185
```
184186

185187
See [.env.example](.env.example) for full list of ENV variables you can use to override the configuration.
186188

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>
188199

189-
If you just want to run the gateway using the official OCI container image from GitHub Container Registry:
200+
#### 1 · Minimum viable run
190201

191202
```bash
192203
docker run -d --name mcpgateway \
@@ -199,31 +210,105 @@ docker run -d --name mcpgateway \
199210
-e DATABASE_URL=sqlite:///./mcp.db \
200211
ghcr.io/ibm/mcp-context-forge:0.1.1
201212

202-
docker logs mcpgateway
213+
# Tail logs (Ctrl+C to quit)
214+
docker logs -f mcpgateway
203215
```
204216

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+
```
206235

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`.
210237

211-
### Optional: Mount a local volume for persistent SQLite storage
238+
#### 3 · Local tool discovery (host network)
212239

213240
```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
215248
```
216249

217-
### Generate a token for API access
250+
</details>
251+
252+
---
253+
254+
<details>
255+
<summary><strong>🦭 Podman (rootless-friendly)</strong></summary>
218256

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
220258

221259
```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
224288
```
225289

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>
227312

228313
```bash
229314
curl -s -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \
@@ -234,9 +319,14 @@ curl -s -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \
234319
http://localhost:4444/version | jq
235320
```
236321

237-
### Running the MCP Gateway stdio wrapper
322+
</details>
323+
324+
---
238325

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.
240330

241331
```bash
242332
# Set environment variables
@@ -246,15 +336,6 @@ export MCP_SERVER_CATALOG_URLS='http://localhost:4444/servers/1'
246336
export MCP_TOOL_CALL_TIMEOUT=120
247337
export MCP_WRAPPER_LOG_LEVEL=DEBUG # or OFF to disable logging
248338

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
258339
docker run --rm -i \
259340
-e MCP_AUTH_TOKEN=$MCPGATEWAY_BEARER_TOKEN \
260341
-e MCP_SERVER_CATALOG_URLS=http://host.docker.internal:4444/servers/1 \
@@ -264,7 +345,11 @@ docker run --rm -i \
264345
python3 -m mcpgateway.wrapper
265346
```
266347

267-
**Testing `mcpgateway.wrapper` by hand:**
348+
</details>
349+
350+
---
351+
352+
## Testing `mcpgateway.wrapper` by hand:
268353

269354
Because the wrapper speaks JSON-RPC over stdin/stdout, you can interact with it using nothing more than a terminal or pipes.
270355

0 commit comments

Comments
 (0)