-
Notifications
You must be signed in to change notification settings - Fork 165
add Mcp tutorial #2953
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
add Mcp tutorial #2953
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
76975bc
add mcp server tutorial
christiangoerdes b8961c2
improvements
christiangoerdes 42e4024
clarify mcp server tutorial details
christiangoerdes 8016f82
simulate WordPress/PHP probe traffic in MCP tutorials and scripts
christiangoerdes 2b6779e
remove protected MCP server tutorial and update existing examples
christiangoerdes File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # yaml-language-server: $schema=https://www.membrane-api.io/v7.2.1.json | ||
| # | ||
| # Tutorial: MCP Server | ||
| # | ||
| # This configuration exposes the Membrane MCP server directly on | ||
| # http://localhost:2000 and starts two demo APIs that generate traffic | ||
| # the AI client can inspect through MCP. | ||
| # | ||
| # 1.) Start Membrane: | ||
| # | ||
| # Linux/Mac: | ||
| # ./membrane.sh -c 10-MCP-Server.yaml | ||
| # Windows: | ||
| # membrane.cmd -c 10-MCP-Server.yaml | ||
| # | ||
| # 2.) Generate some demo traffic in a second terminal: | ||
| # | ||
| # Linux/Mac: | ||
| # ./generate-traffic.sh 20 | ||
| # Windows: | ||
| # generate-traffic.cmd 20 | ||
| # | ||
| # The script also sends a few typical WordPress/PHP probe requests. | ||
| # | ||
| # 3.) Configure Claude Desktop as described in README.md. | ||
| # | ||
| # 4.) Ask the AI client to inspect recent exchanges or list the available APIs. | ||
| # Example prompts: | ||
| # - List the available APIs exposed by this Membrane MCP server. | ||
| # - Show me the most recent exchanges and summarize what happened. | ||
| # - Which endpoints received the most requests in the recent traffic? | ||
|
|
||
| api: | ||
| port: 2000 | ||
| name: MCP-Server | ||
| flow: | ||
| - membraneMCPServer: | ||
| maxExchanges: 10000 | ||
|
|
||
| --- | ||
| api: | ||
| port: 3000 | ||
| name: Fruitshop | ||
| path: | ||
| uri: /shop/v2/ | ||
| target: | ||
| url: https://api.predic8.de | ||
|
|
||
| --- | ||
| api: | ||
| port: 3001 | ||
| name: ApiBin | ||
| target: | ||
| url: https://apibin.io/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # Membrane API Gateway Tutorial - MCP | ||
|
|
||
| This tutorial shows how to expose Membrane API Gateway as an MCP server for AI clients. | ||
| It covers: | ||
|
|
||
| - running a local MCP server | ||
| - inspecting recent API traffic through MCP | ||
|
|
||
| To begin, open [10-MCP-Server.yaml](10-MCP-Server.yaml) and follow the instructions in the file. | ||
|
|
||
| If you want to protect the MCP endpoint, put the `membraneMCPServer` behind an `apiKey` interceptor and expose it only through the network path you actually want clients to use. If the client should keep talking to a simple local URL, you can also place a small local proxy in front of the protected MCP endpoint and let that proxy add the required authentication details. | ||
|
|
||
| ## Claude Desktop Setup | ||
|
|
||
| Open `Settings` -> `Developer`, edit `claude_desktop_config.json`, and add: | ||
|
|
||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "membrane": { | ||
| "command": "npx", | ||
| "args": [ | ||
| "mcp-remote", | ||
| "http://localhost:2000" | ||
| ] | ||
| } | ||
| }, | ||
| "preferences": { | ||
| "coworkScheduledTasksEnabled": true, | ||
| "ccdScheduledTasksEnabled": true, | ||
| "sidebarMode": "task", | ||
| "coworkWebSearchEnabled": true | ||
| } | ||
| } | ||
|
christiangoerdes marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| Start membrane and restart Claude Desktop. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| @echo off | ||
| setlocal EnableExtensions EnableDelayedExpansion | ||
|
|
||
| if "%FRUIT_BASE%"=="" set FRUIT_BASE=http://localhost:3000/shop/v2 | ||
| if "%APIBIN_BASE%"=="" set APIBIN_BASE=http://localhost:3001 | ||
| if "%ATTACK_BASE%"=="" set ATTACK_BASE=http://localhost:3000 | ||
|
|
||
| if "%~1"=="" ( | ||
| set ROUNDS=20 | ||
| ) else ( | ||
| set ROUNDS=%~1 | ||
|
christiangoerdes marked this conversation as resolved.
|
||
| ) | ||
|
|
||
| for /L %%i in (1,1,%ROUNDS%) do ( | ||
| call :request GET "%FRUIT_BASE%/products/" | ||
| call :request GET "%FRUIT_BASE%/products/4" | ||
| call :request GET "%FRUIT_BASE%/categories/" | ||
|
|
||
| call :request GET "%APIBIN_BASE%/analyze?round=%%i&delay=50" | ||
| call :request GET "%APIBIN_BASE%/faker?profile=order&count=2&locale=de-DE&seed=%%i" | ||
| call :request POST "%APIBIN_BASE%/echo" "hello apibin round %%i" | ||
| call :request GET "%ATTACK_BASE%/wp-login.php" | ||
| call :request GET "%ATTACK_BASE%/xmlrpc.php" | ||
| call :request GET "%ATTACK_BASE%/wp-admin/install.php" | ||
| call :request GET "%ATTACK_BASE%/.env" | ||
| call :request GET "%ATTACK_BASE%/phpinfo.php" | ||
| ) | ||
|
|
||
| exit /b 0 | ||
|
|
||
| :request | ||
| set METHOD=%~1 | ||
| set URL=%~2 | ||
| set BODY=%~3 | ||
|
|
||
| echo %METHOD% %URL% | ||
|
|
||
| if "%BODY%"=="" ( | ||
| curl -sS -o NUL -w " -^> %%{http_code}\n" -X %METHOD% "%URL%" | ||
| ) else ( | ||
| curl -sS -o NUL -w " -^> %%{http_code}\n" -X %METHOD% "%URL%" -H "Content-Type: text/plain" --data "%BODY%" | ||
| ) | ||
|
|
||
| exit /b 0 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| #!/usr/bin/env sh | ||
| set -eu | ||
|
|
||
| FRUIT_BASE="${FRUIT_BASE:-http://localhost:3000/shop/v2}" | ||
| APIBIN_BASE="${APIBIN_BASE:-http://localhost:3001}" | ||
| ATTACK_BASE="${ATTACK_BASE:-http://localhost:3000}" | ||
| ROUNDS="${1:-20}" | ||
|
|
||
| request() { | ||
| method="$1" | ||
| url="$2" | ||
| body="${3:-}" | ||
|
|
||
| printf "%s %s" "$method" "$url" | ||
|
|
||
| if [ -n "$body" ]; then | ||
| curl -sS -o /dev/null -w " -> %{http_code}\n" \ | ||
| -X "$method" "$url" \ | ||
| -H "Content-Type: text/plain" \ | ||
| --data "$body" || true | ||
| else | ||
| curl -sS -o /dev/null -w " -> %{http_code}\n" \ | ||
| -X "$method" "$url" || true | ||
| fi | ||
| } | ||
|
|
||
| i=1 | ||
| while [ "$i" -le "$ROUNDS" ]; do | ||
| request GET "$FRUIT_BASE/products/" | ||
| request GET "$FRUIT_BASE/products/4" | ||
| request GET "$FRUIT_BASE/categories/" | ||
|
|
||
| request GET "$APIBIN_BASE/analyze?round=$i&delay=50" | ||
| request GET "$APIBIN_BASE/faker?profile=order&count=2&locale=de-DE&seed=$i" | ||
| request POST "$APIBIN_BASE/echo" "hello apibin round $i" | ||
| request GET "$ATTACK_BASE/wp-login.php" | ||
| request GET "$ATTACK_BASE/xmlrpc.php" | ||
| request GET "$ATTACK_BASE/wp-admin/install.php" | ||
| request GET "$ATTACK_BASE/.env" | ||
| request GET "$ATTACK_BASE/phpinfo.php" | ||
|
|
||
| i=$((i + 1)) | ||
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| @echo off | ||
| setlocal EnableExtensions | ||
|
|
||
| set "SCRIPT_DIR=%~dp0" | ||
| if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%" | ||
|
|
||
| set "dir=%SCRIPT_DIR%" | ||
|
|
||
| :search_up | ||
| if exist "%dir%\LICENSE.txt" if exist "%dir%\scripts\run-membrane.cmd" goto found | ||
| for %%A in ("%dir%\..") do set "next=%%~fA" | ||
| if /I "%next%"=="%dir%" goto notfound | ||
| set "dir=%next%" | ||
| goto search_up | ||
|
|
||
| :found | ||
| set "MEMBRANE_HOME=%dir%" | ||
| set "MEMBRANE_CALLER_DIR=%SCRIPT_DIR%" | ||
| call "%MEMBRANE_HOME%\scripts\run-membrane.cmd" %* | ||
| exit /b %ERRORLEVEL% | ||
|
|
||
| :notfound | ||
| >&2 echo Could not locate Membrane root. Ensure directory structure is correct. | ||
| exit /b 1 | ||
|
christiangoerdes marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #!/bin/sh | ||
| # Default: ./proxies.xml (next to this script); fallback -> $MEMBRANE_HOME/conf/proxies.xml | ||
| # JAVA_OPTS: relative -D paths are auto-resolved against $MEMBRANE_HOME (absolute/URI unchanged). | ||
| # Examples: | ||
| # export JAVA_OPTS='-Dlog4j.configurationFile=examples/logging/access/log4j2_access.xml' | ||
| # export JAVA_OPTS='-Dlog4j.configurationFile=/abs/path/log4j2.xml' | ||
|
|
||
| SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) | ||
|
|
||
| dir="$SCRIPT_DIR" | ||
| while [ "$dir" != "/" ]; do | ||
| if [ -f "$dir/LICENSE.txt" ] && [ -f "$dir/scripts/run-membrane.sh" ]; then | ||
| export MEMBRANE_HOME="$dir" | ||
| export MEMBRANE_CALLER_DIR="$SCRIPT_DIR" | ||
| exec sh "$dir/scripts/run-membrane.sh" "$@" | ||
| fi | ||
| dir=$(dirname "$dir") | ||
| done | ||
|
|
||
| echo "Could not locate Membrane root. Ensure directory structure is correct." >&2 | ||
| exit 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| @echo off | ||
| setlocal enabledelayedexpansion | ||
|
|
||
| set "DIR=%~dp0" | ||
| set "IMAGE=predic8/membrane:7.2.1" | ||
|
|
||
| for /f "delims=" %%i in ('docker create -p 2000-2010:2000-2010 %IMAGE% %*') do set "CID=%%i" | ||
|
|
||
| set "CLEANUP_CMD=docker rm -f %CID% >nul 2>nul" | ||
|
|
||
| docker cp "%DIR%." "%CID%:/opt/membrane/" >nul | ||
| docker start -a "%CID%" | ||
|
|
||
| %CLEANUP_CMD% | ||
|
christiangoerdes marked this conversation as resolved.
|
||
| endlocal | ||
|
christiangoerdes marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" | ||
|
|
||
| cid="$(docker create -it -p 2000-2010:2000-2010 predic8/membrane:7.2.1 "$@")" | ||
|
|
||
| cleanup() { | ||
| docker rm -f "$cid" >/dev/null 2>&1 || true | ||
| } | ||
| trap cleanup EXIT INT TERM | ||
|
|
||
| docker cp "${DIR}/." "${cid}:/opt/membrane/" | ||
| docker start -a "$cid" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.