diff --git a/.github/assets/images/repo-header-a4.png b/.github/assets/images/repo-header-a4.png
new file mode 100644
index 0000000..3672ea5
Binary files /dev/null and b/.github/assets/images/repo-header-a4.png differ
diff --git a/.github/assets/images/repo-header-a4.txt b/.github/assets/images/repo-header-a4.txt
new file mode 100644
index 0000000..a1f671f
--- /dev/null
+++ b/.github/assets/images/repo-header-a4.txt
@@ -0,0 +1,15 @@
+Image Description Sheet
+-----------------------
+
+File Name: repo-header-a4.png
+Format: PNG
+Dimensions: 830 x 173 pixels
+
+Short Description:
+A banner image featuring the word "Openapi" on the left, Various tech figures in the background,
+and the Openapi logo on the right.
+
+Purpose:
+This image is intended to be used as a header/banner for documentation or repository README.
+It visually associates linux tools with the Openapi MCP,
+giving a professional and modern look to the project materials.
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 6d1ab7b..12d4e12 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -1,6 +1,6 @@
## Quick context for AI coding agents
-This repository implements the OpenAPI.com MCP gateway (FastAPI + FastMCP). The server acts as a proxy that forwards a client's Bearer token to downstream OpenAPI services and exposes MCP tools implemented under `src/openapi_mcp_sdk/apis/`.
+This repository implements the Openapi.com MCP gateway (FastAPI + FastMCP). The server acts as a proxy that forwards a client's Bearer token to downstream Openapi services and exposes MCP tools implemented under `src/openapi_mcp_sdk/apis/`.
Key files
- `src/openapi_mcp_sdk/main.py` โ application entry point. Mounts the MCP app and contains HTTP endpoints `/callbacks` and `/status/{request_id}`. Shows how token query params are converted into an Authorization header.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..70a2002
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,38 @@
+
+name: build
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ["3.9", "3.10", "3.11"]
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install flake8 pytest
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+ - name: Lint with flake8
+ run: |
+ # stop the build if there are Python syntax errors or undefined names
+ flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+ # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+ flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+ - name: Test with pytest
+ run: |
+ pytest
diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
new file mode 100644
index 0000000..0782831
--- /dev/null
+++ b/.github/workflows/pylint.yml
@@ -0,0 +1,23 @@
+name: Pylint
+
+on: [push]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: ["3.8", "3.9", "3.10"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install pylint
+ - name: Analysing the code with pylint
+ run: |
+ pylint $(git ls-files '*.py')
diff --git a/.gitignore b/.gitignore
index 621398b..34568e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@ re-deploy.sh
# Local build artifacts
.install.stamp
+.python-version
# Generated by integration tests (contains token)
.mcp.json
diff --git a/README.md b/README.md
index 2e51372..38ec4e2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,22 @@
-# openapi-mcp-sdk
+
+
+
+
-**`openapi-mcp-sdk`** is the official [openapi.com](https://openapi.com/) MCP SDK.
+
๐ Openapiยฎ MCP
+
The official Python MCP SDK and ready-to-run MCP server for Openapiยฎ
+
+[](https://pypi.org/project/openapi-mcp-sdk/)
+[](https://www.python.org/)
+[](LICENSE)
+[](https://modelcontextprotocol.io/)
+
+[](https://www.linuxfoundation.org/about/members)
+
+
+# Overview
+
+Welcome to **`openapi-mcp-sdk`**, this is the official [openapi.com](https://openapi.com/) MCP SDK.
It ships as a Python package on [PyPI](https://pypi.org/project/openapi-mcp-sdk/) and
can be used in two ways:
@@ -10,8 +26,6 @@ can be used in two ways:
custom MCP server that wraps openapi.com APIs with your own logic, tools, or auth
layer on top.
----
-
## Environment variables
All configuration is done through environment variables. None are required to
@@ -19,13 +33,13 @@ start the server โ defaults are suitable for local use.
### Core
-| Variable | Default | Description |
-|---|---|---|
-| `MCP_PORT` | `8080` | HTTP port the server listens on |
-| `MCP_ENV` | `production` | Runtime environment: `dev` \| `staging` \| `production` |
-| `MCP_BASE_URL` | `https://mcp.openapi.com` | Public URL of this server (used to build callback and file download URLs) |
-| `MCP_CALLBACK_URL` | `$MCP_BASE_URL/callbacks` | Explicit callback URL sent to async APIs |
-| `MCP_OPENAPI_ENV` | _(empty)_ | OpenAPI environment: `dev`, `test`, `sandbox` (alias of `test`), or empty for production |
+| Variable | Default | Description |
+|---|---|------------------------------------------------------------------------------------------|
+| `MCP_PORT` | `8080` | HTTP port the server listens on |
+| `MCP_ENV` | `production` | Runtime environment: `dev` \| `staging` \| `production` |
+| `MCP_BASE_URL` | `http://localhost:8080` | Public URL of this server (used to build callback and file download URLs) |
+| `MCP_CALLBACK_URL` | `$MCP_BASE_URL/callbacks` | Explicit callback URL sent to async APIs |
+| `MCP_OPENAPI_ENV` | _(empty)_ | Openapi environment: `dev`, `test`, `sandbox` (alias of `test`), or empty for production |
### Storage
@@ -53,8 +67,6 @@ Used to share async callback results across multiple server instances.
See [`docs/env/`](docs/env/) for per-environment configuration guides (local,
Docker, AWS, GCP, Kubernetes).
----
-
## Features
- **Secure proxy**: Pass-through of the Bearer Token provided by the client, without direct handling of sensitive credentials.
@@ -62,8 +74,6 @@ Docker, AWS, GCP, Kubernetes).
- **MCP-compatible**: Designed according to MCP protocol best practices.
- **Modular**: All API call logic and tool registration is centralized in [`mcp_core.py`](src/openapi_mcp_sdk/mcp_core.py).
----
-
## Quick Start โ run from PyPI (recommended)
No cloning, no virtual environment. Start the server in one command:
@@ -98,34 +108,7 @@ Commands:
token Generate or inspect an openapi.com Bearer token [coming soon]
```
----
-## Local launcher script
-
-Copy the block below, paste it into your terminal, and press Enter. It will
-create a `mcp-server.sh` file in the current directory and launch the server:
-
-```bash
-cat > mcp-server.sh << 'EOF'
-#!/bin/bash
-# ============================================================
-# Openapi.com MCP Server โ local launcher
-# Edit the variables below, then run: bash mcp-server.sh
-# ============================================================
-
-export MCP_PORT="${MCP_PORT:-8080}"
-uvx openapi-mcp-sdk server
-EOF
-bash mcp-server.sh
-```
-
-Next time, just run:
-
-```bash
-bash mcp-server.sh
-```
-
----
## Running with Docker
@@ -144,7 +127,7 @@ docker compose logs -f mcp
The server will be accessible at `http://localhost:8080`.
----
+
## Debug and Development
@@ -162,13 +145,13 @@ server listens on `http://0.0.0.0:8080`.
To test endpoints manually:
```bash
-curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/mcp/
+curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080
```
The server prints request headers and parameters to stdout โ no extra
configuration needed.
----
+
### Remote debugging with VS Code and Docker (one click)
@@ -218,7 +201,7 @@ required. Just send a new request and the updated code runs.
| MCP server | `localhost:8080` | `0.0.0.0:8080` |
| debugpy listener | `localhost:5678` | `0.0.0.0:5678` |
----
+
## Authentication
@@ -248,7 +231,7 @@ before the request reaches the MCP layer, so the behaviour is identical.
> MCP playgrounds, and any client whose configuration only accepts a plain URL
> without a headers field.
----
+
## MCP Client Configuration (VS Code)
@@ -289,7 +272,7 @@ before the request reaches the MCP layer, so the behaviour is identical.
- Open the Copilot chat and type `@workspace`.
- Use the tools exposed by the MCP server.
----
+
## File storage
@@ -319,7 +302,7 @@ uvx openapi-mcp-sdk server
> The directory is created automatically on first use. For the download links to
> work correctly, `MCP_BASE_URL` must point to the public address of the server
-> (default: `https://mcp.openapi.com`).
+> (default: `http://localhost:8080`).
### Cloud storage backends
@@ -331,7 +314,7 @@ uvx openapi-mcp-sdk server
See [`docs/env/`](docs/env/) for full per-environment configuration guides.
----
+
## Deployment environments
@@ -343,7 +326,7 @@ See [`docs/env/`](docs/env/) for full per-environment configuration guides.
| Amazon Web Services | [`docs/env/aws.md`](docs/env/aws.md) |
| Kubernetes | [`docs/env/kubernetes.md`](docs/env/kubernetes.md) |
----
+
## Project Structure
@@ -357,7 +340,7 @@ See [`docs/env/`](docs/env/) for full per-environment configuration guides.
- [`.vscode/launch.json`](.vscode/launch.json): VS Code debug configuration (attach to debugpy).
- [`docs/`](docs/): Documentation and example configurations.
----
+
## Adding New Tools/APIs
@@ -374,7 +357,7 @@ See [`docs/env/`](docs/env/) for full per-environment configuration guides.
```
2. Restart the server to apply the changes.
----
+
## Security Notes
@@ -382,7 +365,7 @@ See [`docs/env/`](docs/env/) for full per-environment configuration guides.
- The server expects the Bearer Token to be provided by the client via HTTP headers.
- All API calls are proxied using the token provided by the client.
----
+
## Useful Resources
@@ -390,7 +373,6 @@ See [`docs/env/`](docs/env/) for full per-environment configuration guides.
- [fastmcp](https://pypi.org/project/fastmcp/)
- [openapi.com](https://openapi.com/)
----
## Contributing
diff --git a/docs/env/README.md b/docs/env/README.md
index 4754d4f..1f9ec79 100644
--- a/docs/env/README.md
+++ b/docs/env/README.md
@@ -10,21 +10,21 @@ cache backend, and any platform-specific notes.
## Quick reference โ all environment variables
-| Variable | Default | Description |
-|---|---|---|
-| `MCP_PORT` | `8080` | HTTP port the server listens on |
-| `MCP_ENV` | `production` | Runtime environment: `dev` \| `staging` \| `production` |
-| `MCP_BASE_URL` | `https://mcp.openapi.com` | Public URL of this server (used in callback URLs) |
-| `MCP_CALLBACK_URL` | `$MCP_BASE_URL/callbacks` | Full callback URL sent to async APIs |
-| `MCP_OPENAPI_ENV` | _(empty)_ | OpenAPI environment: `dev`, `test`, `sandbox` (alias of `test`), or empty for production |
-| `MCP_STORAGE_BACKEND` | `local` | Storage backend: `local` \| `gcs` \| `s3` |
-| `MCP_STORAGE_PATH` | `./openapi_storage` | Local filesystem path for `local` backend |
-| `MCP_STORAGE_BUCKET` | _(required for cloud)_ | Bucket/container name for `gcs` or `s3` backend |
-| `MCP_STORAGE_REGION` | _(required for s3)_ | AWS region for the S3 bucket |
-| `MCP_CACHE_BACKEND` | `none` | Cache for async callbacks: `none` \| `memcached` \| `redis` |
-| `MCP_CACHE_HOST` | _(none)_ | Memcached host (used when `MCP_CACHE_BACKEND=memcached`) |
-| `MCP_CACHE_PORT` | `11211` | Memcached port |
-| `MCP_CACHE_URL` | _(none)_ | Redis connection URL (used when `MCP_CACHE_BACKEND=redis`) |
+| Variable | Default | Description |
+|---|---|------------------------------------------------------------------------------------------|
+| `MCP_PORT` | `8080` | HTTP port the server listens on |
+| `MCP_ENV` | `production` | Runtime environment: `dev` \| `staging` \| `production` |
+| `MCP_BASE_URL` | `http://localhost:8080` | Public URL of this server (used in callback URLs) |
+| `MCP_CALLBACK_URL` | `$MCP_BASE_URL/callbacks` | Full callback URL sent to async APIs |
+| `MCP_OPENAPI_ENV` | _(empty)_ | Openapi environment: `dev`, `test`, `sandbox` (alias of `test`), or empty for production |
+| `MCP_STORAGE_BACKEND` | `local` | Storage backend: `local` \| `gcs` \| `s3` |
+| `MCP_STORAGE_PATH` | `./openapi_storage` | Local filesystem path for `local` backend |
+| `MCP_STORAGE_BUCKET` | _(required for cloud)_ | Bucket/container name for `gcs` or `s3` backend |
+| `MCP_STORAGE_REGION` | _(required for s3)_ | AWS region for the S3 bucket |
+| `MCP_CACHE_BACKEND` | `none` | Cache for async callbacks: `none` \| `memcached` \| `redis` |
+| `MCP_CACHE_HOST` | _(none)_ | Memcached host (used when `MCP_CACHE_BACKEND=memcached`) |
+| `MCP_CACHE_PORT` | `11211` | Memcached port |
+| `MCP_CACHE_URL` | _(none)_ | Redis connection URL (used when `MCP_CACHE_BACKEND=redis`) |
### Legacy variables (GCP Cloud Run โ deprecated)
diff --git a/docs/env/gcp.md b/docs/env/gcp.md
index 2ddae0a..7445126 100644
--- a/docs/env/gcp.md
+++ b/docs/env/gcp.md
@@ -26,8 +26,8 @@ Internet โ Cloud Run (openapi-mcp-sdk server)
# Core
MCP_PORT=8080
MCP_ENV=production
-MCP_BASE_URL=https://mcp.openapi.com
-MCP_CALLBACK_URL=https://mcp.openapi.com/callbacks
+MCP_BASE_URL=https://mcp.example.com
+MCP_CALLBACK_URL=https://mcp.example.com/callbacks
MCP_OPENAPI_ENV= # dev, test, sandbox (alias of test), or empty for production
# Storage
@@ -81,7 +81,7 @@ spec:
- name: MCP_PORT
value: "8080"
- name: MCP_BASE_URL
- value: "https://mcp.openapi.com"
+ value: "https://mcp.example.com"
- name: MCP_STORAGE_BACKEND
value: "gcs"
- name: MCP_STORAGE_BUCKET
diff --git a/docs/env/local.md b/docs/env/local.md
index c224895..3fff676 100644
--- a/docs/env/local.md
+++ b/docs/env/local.md
@@ -75,7 +75,7 @@ Options:
export MCP_BASE_URL=https://abc123.ngrok.io
```
-If `MCP_BASE_URL` is not set the server defaults to `https://mcp.openapi.com`, which
+If `MCP_BASE_URL` is not set the server defaults to `http://localhost:8080`, which
will not work for local callbacks.
---
@@ -103,7 +103,7 @@ source local.env && openapi-mcp-sdk server
cat > mcp-server.sh << 'EOF'
#!/bin/bash
export MCP_PORT="${MCP_PORT:-8080}"
-export MCP_BASE_URL="${MCP_BASE_URL:-https://mcp.openapi.com}"
+export MCP_BASE_URL="${MCP_BASE_URL:-http://localhost:8080}"
export MCP_STORAGE_BACKEND="${MCP_STORAGE_BACKEND:-local}"
export MCP_STORAGE_PATH="${MCP_STORAGE_PATH:-./openapi_storage}"
diff --git a/docs/project.md b/docs/project.md
index 575c5d8..04fe348 100644
--- a/docs/project.md
+++ b/docs/project.md
@@ -116,7 +116,7 @@ def make_api_call(ctx: Context, method: str, url: str, **kwargs) -> Any:
# --- Inizializzazione del Server MCP ---
mcp = FastMCP(
- name="OpenAPI.com Gateway",
+ name="Openapi.com Gateway",
instructions="Questo server fornisce un gateway unificato per diversi servizi di openapi.com."
)
@@ -215,7 +215,7 @@ if __name__ == "__main__":
"servers": {
"openapi.com": {
"type": "http",
- "url": "http://INDIRIZZO_IP_DEL_TUO_SERVER:8000/mcp/",
+ "url": "http://INDIRIZZO_IP_DEL_TUO_SERVER:8000",
"headers": {
"Authorization": "Bearer IL_TUO_BEARER_TOKEN_DI_PRODUZIONE"
}
diff --git a/docs/claude_desktop_config.json b/docs/settings/claude_desktop_config.json
similarity index 84%
rename from docs/claude_desktop_config.json
rename to docs/settings/claude_desktop_config.json
index 39a636c..2766748 100644
--- a/docs/claude_desktop_config.json
+++ b/docs/settings/claude_desktop_config.json
@@ -4,7 +4,7 @@
"command": "npx",
"args": [
"mcp-remote",
- "http://127.0.0.1:8000/mcp/",
+ "http://127.0.0.1:8000",
"--header",
"Authorization: Bearer 68614e09843b57c48308abc5"
]
diff --git a/docs/mcp.json b/docs/settings/mcp.json
similarity index 87%
rename from docs/mcp.json
rename to docs/settings/mcp.json
index bb955c8..065b49f 100644
--- a/docs/mcp.json
+++ b/docs/settings/mcp.json
@@ -8,7 +8,7 @@
"servers": {
"openapi.com": {
"type": "http",
- "url": "http://127.0.0.1:8000/mcp/",
+ "url": "http://127.0.0.1:8000",
"headers": {
"Authorization": "Bearer ${input:OpenapiToken}"
}
diff --git a/docs/settings.json b/docs/settings/settings.json
similarity index 100%
rename from docs/settings.json
rename to docs/settings/settings.json
diff --git a/docs/testing.md b/docs/testing.md
index d70503b..fe4a79d 100644
--- a/docs/testing.md
+++ b/docs/testing.md
@@ -112,7 +112,7 @@ ngrok http 8080
# Terminal 3 โ run tests
export OPENAI_API_KEY=sk-...
export OPENAPI_SANDBOX_TOKEN=your_sandbox_token
-MCP_URL=https://abcd1234.ngrok-free.app/mcp/ SANDBOX=1 make test-openai-sandbox
+MCP_URL=https://abcd1234.ngrok-free.app SANDBOX=1 make test-openai-sandbox
```
---
diff --git a/scripts/try-claude.sh b/scripts/try-claude.sh
index b7908ec..203b7f5 100755
--- a/scripts/try-claude.sh
+++ b/scripts/try-claude.sh
@@ -10,7 +10,7 @@ WORK_DIR="$(mktemp -d /tmp/openapi-try-XXXXXX)"
SERVER_PID=""
-# Sandbox mode: SANDBOX=1 uses OPENAPI_SANDBOX_TOKEN and the test OpenAPI environment
+# Sandbox mode: SANDBOX=1 uses OPENAPI_SANDBOX_TOKEN and the test Openapi environment
SANDBOX="${SANDBOX:-0}"
if [ "$SANDBOX" = "1" ]; then
TOKEN="${OPENAPI_SANDBOX_TOKEN:-}"
diff --git a/src/openapi_mcp_sdk/apis/info.py b/src/openapi_mcp_sdk/apis/info.py
index c03d96b..af56436 100644
--- a/src/openapi_mcp_sdk/apis/info.py
+++ b/src/openapi_mcp_sdk/apis/info.py
@@ -27,7 +27,7 @@
_FASTMCP_VERSION = "unknown"
_SERVER_VERSION = "0.2.0"
-_SERVER_NAME = "OpenAPI.com MCP Gateway"
+_SERVER_NAME = "Openapi.com MCP Gateway"
def _mask_token(token: str) -> str:
diff --git a/src/openapi_mcp_sdk/memory_store.py b/src/openapi_mcp_sdk/memory_store.py
index dcd9bea..ea5334e 100644
--- a/src/openapi_mcp_sdk/memory_store.py
+++ b/src/openapi_mcp_sdk/memory_store.py
@@ -39,8 +39,6 @@
OPENAPI_HOST_PREFIX = f"{MCP_OPENAPI_ENV}." if MCP_OPENAPI_ENV else ""
MCP_BASE_URL = os.getenv("MCP_BASE_URL", "http://localhost:8080")
-if MCP_STORAGE_BUCKET and "MCP_BASE_URL" not in os.environ:
- MCP_BASE_URL = "https://" + MCP_STORAGE_BUCKET.replace("-", ".")
callbackUrl = os.getenv("MCP_CALLBACK_URL")
if not callbackUrl:
diff --git a/tests/docker/test-compose-up.sh b/tests/docker/test-compose-up.sh
index 2a3e86e..50dcb33 100755
--- a/tests/docker/test-compose-up.sh
+++ b/tests/docker/test-compose-up.sh
@@ -142,7 +142,7 @@ assert_contains "initialize โ jsonrpc result" "$INIT_BODY" '"result"'
assert_contains "initialize โ protocolVersion" "$INIT_BODY" '"protocolVersion"'
assert_contains "initialize โ serverInfo" "$INIT_BODY" '"serverInfo"'
assert_contains "initialize โ capabilities" "$INIT_BODY" '"capabilities"'
-assert_contains "initialize โ server name" "$INIT_BODY" 'OpenAPI'
+assert_contains "initialize โ server name" "$INIT_BODY" 'Openapi'
SESSION_ID=$(extract_session_id)
if [ -n "$SESSION_ID" ]; then
@@ -190,7 +190,7 @@ CALL_BODY=$(parse_mcp_response "$CALL_RAW")
assert_contains "tools/call โ jsonrpc result" "$CALL_BODY" '"result"'
assert_contains "tools/call โ content array" "$CALL_BODY" '"content"'
assert_contains "tools/call โ isError false" "$CALL_BODY" 'false'
-assert_contains "tools/call โ server name in payload" "$CALL_BODY" 'OpenAPI'
+assert_contains "tools/call โ server name in payload" "$CALL_BODY" 'Openapi'
assert_contains "tools/call โ status ok in payload" "$CALL_BODY" 'status'
# =============================================================================
diff --git a/tests/integration/run-vs-codex.sh b/tests/integration/run-vs-codex.sh
index e82f5af..8e196a6 100755
--- a/tests/integration/run-vs-codex.sh
+++ b/tests/integration/run-vs-codex.sh
@@ -59,7 +59,7 @@ fi
codex mcp remove "$MCP_SERVER_NAME" 2>/dev/null || true
codex mcp add "$MCP_SERVER_NAME" \
- --url "http://localhost:8080/mcp/" \
+ --url "http://localhost:8080" \
--bearer-token-env-var "OPENAPI_MCP_TOKEN"
# --- start MCP server in background ---
diff --git a/tests/integration/run-vs-openai.sh b/tests/integration/run-vs-openai.sh
index a63cedc..bece8f1 100755
--- a/tests/integration/run-vs-openai.sh
+++ b/tests/integration/run-vs-openai.sh
@@ -22,8 +22,8 @@ fi
# MCP_URL: the URL OpenAI will use to reach the MCP server.
# OpenAI cloud CANNOT reach localhost โ expose the server first:
# ngrok http 8080
-# MCP_URL=https://xxxx.ngrok-free.app/mcp/ make test-openai
-MCP_URL="${MCP_URL:-http://localhost:8080/mcp/}"
+# MCP_URL=https://xxxx.ngrok-free.app make test-openai
+MCP_URL="${MCP_URL:-http://localhost:8080}"
cleanup() {
[ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null || true
@@ -53,7 +53,7 @@ if echo "$MCP_URL" | grep -qE "localhost|127\.0\.0\.1"; then
echo "WARNING: MCP_URL='$MCP_URL' โ OpenAI cloud cannot reach localhost."
echo " Expose the server with ngrok and set MCP_URL to the public URL:"
echo " ngrok http 8080"
- echo " MCP_URL=https://xxxx.ngrok-free.app/mcp/ make test-openai"
+ echo " MCP_URL=https://xxxx.ngrok-free.app make test-openai"
echo ""
fi