@eznix/mcp-gateway 1.3.3
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/.dockerignore +8 -0
- package/.github/workflows/docker.yml +51 -0
- package/.github/workflows/npm.yml +53 -0
- package/AGENTS.md +111 -0
- package/Dockerfile +22 -0
- package/LICENSE +21 -0
- package/README.md +292 -0
- package/dist/index.js +26252 -0
- package/examples/README.md +34 -0
- package/examples/config.json +10 -0
- package/package.json +30 -0
- package/src/config.ts +63 -0
- package/src/connections.ts +116 -0
- package/src/docker.ts +64 -0
- package/src/gateway.ts +114 -0
- package/src/handlers.ts +113 -0
- package/src/index.ts +9 -0
- package/src/jobs.ts +74 -0
- package/src/search.ts +94 -0
- package/src/types.ts +51 -0
- package/templates/AGENTS.md +187 -0
- package/tsconfig.json +29 -0
package/.dockerignore
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Docker Build & Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
packages: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
docker:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout code
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up QEMU
|
|
20
|
+
uses: docker/setup-qemu-action@v3
|
|
21
|
+
|
|
22
|
+
- name: Set up Docker Buildx
|
|
23
|
+
uses: docker/setup-buildx-action@v3
|
|
24
|
+
|
|
25
|
+
- name: Login to GHCR
|
|
26
|
+
uses: docker/login-action@v3
|
|
27
|
+
with:
|
|
28
|
+
registry: ghcr.io
|
|
29
|
+
username: ${{ github.actor }}
|
|
30
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
31
|
+
|
|
32
|
+
- name: Extract metadata for Docker
|
|
33
|
+
id: meta
|
|
34
|
+
uses: docker/metadata-action@v5
|
|
35
|
+
with:
|
|
36
|
+
images: ghcr.io/${{ github.repository_owner }}/mcp-gateway
|
|
37
|
+
tags: |
|
|
38
|
+
type=semver,pattern={{version}}
|
|
39
|
+
type=semver,pattern={{major}}
|
|
40
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
41
|
+
|
|
42
|
+
- name: Build and push Docker image
|
|
43
|
+
uses: docker/build-push-action@v5
|
|
44
|
+
with:
|
|
45
|
+
context: .
|
|
46
|
+
platforms: linux/amd64,linux/arm64
|
|
47
|
+
push: true
|
|
48
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
49
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
50
|
+
cache-from: type=gha
|
|
51
|
+
cache-to: type=gha,mode=max
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Publish to npm (Bun)
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
contents: write
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout repository
|
|
16
|
+
uses: actions/checkout@v6
|
|
17
|
+
|
|
18
|
+
- name: Setup Bun
|
|
19
|
+
uses: oven-sh/setup-bun@v2
|
|
20
|
+
with:
|
|
21
|
+
bun-version: latest
|
|
22
|
+
|
|
23
|
+
- name: Cache dependencies
|
|
24
|
+
uses: actions/cache@v5
|
|
25
|
+
with:
|
|
26
|
+
path: |
|
|
27
|
+
~/.bun/install/cache
|
|
28
|
+
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: bun install --frozen-lockfile
|
|
32
|
+
|
|
33
|
+
- name: Build package
|
|
34
|
+
run: bun run build
|
|
35
|
+
|
|
36
|
+
- name: Publish to npm
|
|
37
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
38
|
+
env:
|
|
39
|
+
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
40
|
+
run: bun publish --verbose -p --access public
|
|
41
|
+
|
|
42
|
+
- name: Update CHANGELOG
|
|
43
|
+
id: changelog
|
|
44
|
+
uses: requarks/changelog-action@v1
|
|
45
|
+
with:
|
|
46
|
+
token: ${{ github.token }}
|
|
47
|
+
tag: ${{ github.ref_name }}
|
|
48
|
+
useGitmojis: false
|
|
49
|
+
|
|
50
|
+
- name: Create Release
|
|
51
|
+
uses: softprops/action-gh-release@v2
|
|
52
|
+
with:
|
|
53
|
+
body: ${{ steps.changelog.outputs.changes }}
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use Bun instead of Node.js, npm, pnpm, or vite.
|
|
3
|
+
globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Default to using Bun instead of Node.js.
|
|
8
|
+
|
|
9
|
+
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
10
|
+
- Use `bun test` instead of `jest` or `vitest`
|
|
11
|
+
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
|
12
|
+
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
|
13
|
+
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
|
14
|
+
- Use `bunx <package> <command>` instead of `npx <package> <command>`
|
|
15
|
+
- Bun automatically loads .env, so don't use dotenv.
|
|
16
|
+
|
|
17
|
+
## APIs
|
|
18
|
+
|
|
19
|
+
- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
|
|
20
|
+
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
|
21
|
+
- `Bun.redis` for Redis. Don't use `ioredis`.
|
|
22
|
+
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
|
23
|
+
- `WebSocket` is built-in. Don't use `ws`.
|
|
24
|
+
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
|
25
|
+
- Bun.$`ls` instead of execa.
|
|
26
|
+
|
|
27
|
+
## Testing
|
|
28
|
+
|
|
29
|
+
Use `bun test` to run tests.
|
|
30
|
+
|
|
31
|
+
```ts#index.test.ts
|
|
32
|
+
import { test, expect } from "bun:test";
|
|
33
|
+
|
|
34
|
+
test("hello world", () => {
|
|
35
|
+
expect(1).toBe(1);
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Frontend
|
|
40
|
+
|
|
41
|
+
Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
|
|
42
|
+
|
|
43
|
+
Server:
|
|
44
|
+
|
|
45
|
+
```ts#index.ts
|
|
46
|
+
import index from "./index.html"
|
|
47
|
+
|
|
48
|
+
Bun.serve({
|
|
49
|
+
routes: {
|
|
50
|
+
"/": index,
|
|
51
|
+
"/api/users/:id": {
|
|
52
|
+
GET: (req) => {
|
|
53
|
+
return new Response(JSON.stringify({ id: req.params.id }));
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
// optional websocket support
|
|
58
|
+
websocket: {
|
|
59
|
+
open: (ws) => {
|
|
60
|
+
ws.send("Hello, world!");
|
|
61
|
+
},
|
|
62
|
+
message: (ws, message) => {
|
|
63
|
+
ws.send(message);
|
|
64
|
+
},
|
|
65
|
+
close: (ws) => {
|
|
66
|
+
// handle close
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
development: {
|
|
70
|
+
hmr: true,
|
|
71
|
+
console: true,
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
|
|
77
|
+
|
|
78
|
+
```html#index.html
|
|
79
|
+
<html>
|
|
80
|
+
<body>
|
|
81
|
+
<h1>Hello, world!</h1>
|
|
82
|
+
<script type="module" src="./frontend.tsx"></script>
|
|
83
|
+
</body>
|
|
84
|
+
</html>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
With the following `frontend.tsx`:
|
|
88
|
+
|
|
89
|
+
```tsx#frontend.tsx
|
|
90
|
+
import React from "react";
|
|
91
|
+
import { createRoot } from "react-dom/client";
|
|
92
|
+
|
|
93
|
+
// import .css files directly and it works
|
|
94
|
+
import './index.css';
|
|
95
|
+
|
|
96
|
+
const root = createRoot(document.body);
|
|
97
|
+
|
|
98
|
+
export default function Frontend() {
|
|
99
|
+
return <h1>Hello, world!</h1>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
root.render(<Frontend />);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then, run index.ts
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
bun --hot ./index.ts
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
FROM oven/bun:1-alpine
|
|
2
|
+
|
|
3
|
+
RUN adduser -D -s /bin/sh gateway
|
|
4
|
+
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
COPY package.json bun.lock ./
|
|
8
|
+
RUN bun install
|
|
9
|
+
|
|
10
|
+
COPY . .
|
|
11
|
+
|
|
12
|
+
RUN bun build src/docker.ts --target=bun --outfile=/app/gateway
|
|
13
|
+
|
|
14
|
+
# Create config directory for non-root user
|
|
15
|
+
RUN mkdir -p /home/gateway/.config/mcp-gateway && chown -R gateway:gateway /home/gateway
|
|
16
|
+
|
|
17
|
+
# Use non-root user
|
|
18
|
+
USER gateway
|
|
19
|
+
|
|
20
|
+
EXPOSE 3000
|
|
21
|
+
|
|
22
|
+
CMD ["/app/gateway"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bruno Bernard
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# MCP Gateway
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@eznix/mcp-gateway)
|
|
4
|
+
[](https://www.npmjs.com/package/@eznix/mcp-gateway)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/eznix86/mcp-gateway/stargazers)
|
|
7
|
+
|
|
8
|
+
MCP Gateway is a server aggregation tool that connects multiple Model Context Protocol (MCP) servers into a single gateway, exposing all tools from connected servers through unified search, describe, and invoke interfaces and it exposes only 5 tools.
|
|
9
|
+
|
|
10
|
+
## The Context Limit Problem
|
|
11
|
+
|
|
12
|
+
When connecting an client (Claude Code, Opencode, etc.) to multiple MCP servers, each server lists all its tools. With 10+ MCPs each exposing 10-50 tools, you can easily exceed 500+ tool descriptions in the system prompt:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
10 servers × 20 tools each = 200+ tool descriptions
|
|
16
|
+
Each tool: 200-500 chars → 40KB-100KB of description just for tool schemas!
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This creates two problems:
|
|
20
|
+
1. **Context overflow**: Many LLMs hit their context limit before any conversation happens
|
|
21
|
+
2. **Cognitive overload**: LLMs struggle to choose the right tool from hundreds of options
|
|
22
|
+
|
|
23
|
+
## The Gateway Solution
|
|
24
|
+
|
|
25
|
+
MCP Gateway solves this by providing **tool search** instead of dumping all tool schemas:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
┌─────────────┐ gateway.search ┌─────────────────┐ kubernetes::pods_list ┌──────────────────┐
|
|
29
|
+
│ AI Client │ ───────────────────► │ MCP Gateway │ ─────────────────────────► │ Kubernetes MCP │
|
|
30
|
+
│ │ │ │ │ │
|
|
31
|
+
│ │ ◄────────────────────│ │ ◄───────────────────────── │ │
|
|
32
|
+
└─────────────┘ pods_list schema └─────────────────┘ pods output └──────────────────┘
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## How It Works
|
|
36
|
+
|
|
37
|
+
MCP Gateway operates as both an MCP client (connecting to upstream servers) and an MCP server (exposing tools to downstream clients):
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
┌──────────────┐ MCP ┌─────────────────┐ MCP ┌──────────────────┐
|
|
41
|
+
│ AI Client │ ◄──────────── │ MCP Gateway │ ◄──────────── │ Upstream Server │
|
|
42
|
+
│ (Claude, etc)│ │ (this gateway) │ │ (playwright, │
|
|
43
|
+
└──────────────┘ └─────────────────┘ │ kubernetes...) │
|
|
44
|
+
└──────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
1. Gateway starts and reads configuration
|
|
48
|
+
2. For each configured upstream server, Gateway connects via stdio (local) or HTTP/WebSocket (remote)
|
|
49
|
+
3. Gateway fetches the tool catalog from each server
|
|
50
|
+
4. All tools are indexed in a unified catalog with search capabilities
|
|
51
|
+
5. AI clients connect to Gateway and use `gateway.search` to find relevant tools
|
|
52
|
+
6. Only the tools the client actually needs are invoked
|
|
53
|
+
|
|
54
|
+
You will notice around ~40% reduction of initial token used.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
### Claude Code
|
|
59
|
+
|
|
60
|
+
Add to your Claude MCP configuration:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"gateway": {
|
|
66
|
+
"command": "bunx",
|
|
67
|
+
"args": ["@eznix/mcp-gateway@latest"]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### OpenCode
|
|
74
|
+
|
|
75
|
+
Add to your OpenCode MCP configuration:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"$schema": "https://opencode.ai/config.json",
|
|
80
|
+
"mcp": {
|
|
81
|
+
"mcp-gateway": {
|
|
82
|
+
"type": "local",
|
|
83
|
+
"command": ["bunx", "@eznix/mcp-gateway@latest"]
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You may append your global AGENTS.md (`~/.config/opencode/AGENTS.md`) with this [template](./templates/AGENTS.md).
|
|
90
|
+
|
|
91
|
+
You may now just simple enumerate the MCP available.
|
|
92
|
+
|
|
93
|
+
## Configuration
|
|
94
|
+
|
|
95
|
+
MCP Gateway reads configuration from a JSON file. By default, it looks for:
|
|
96
|
+
|
|
97
|
+
1. Path provided as first command-line argument
|
|
98
|
+
2. `MCP_GATEWAY_CONFIG` environment variable
|
|
99
|
+
3. `~/.config/mcp-gateway/config.json`
|
|
100
|
+
|
|
101
|
+
### Configuration Format
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"local-server": {
|
|
106
|
+
"type": "local",
|
|
107
|
+
"command": ["bun", "run", "/path/to/server.ts"],
|
|
108
|
+
},
|
|
109
|
+
"remote-server": {
|
|
110
|
+
"type": "remote",
|
|
111
|
+
"url": "https://mcp.example.com",
|
|
112
|
+
"enabled": true
|
|
113
|
+
},
|
|
114
|
+
"websocket-server": {
|
|
115
|
+
"type": "remote",
|
|
116
|
+
"url": "wss://mcp.example.com/ws",
|
|
117
|
+
"enabled": true
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Each entry specifies:
|
|
123
|
+
- `type`: `"local"` or `"remote"`
|
|
124
|
+
- `command` (local only): Array with command and arguments to spawn the upstream server
|
|
125
|
+
- `url` (remote only): Full URL of the remote MCP server
|
|
126
|
+
- `transport` (optional, remote only): Override transport detection (`"streamable_http"` or `"websocket"`). Usually auto-detected from URL protocol.
|
|
127
|
+
- `enabled`: Set to false to skip connecting to this server
|
|
128
|
+
|
|
129
|
+
### Docker
|
|
130
|
+
|
|
131
|
+
Run MCP Gateway in Docker with HTTP transport:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Build the image
|
|
135
|
+
docker build -t mcp-gateway .
|
|
136
|
+
|
|
137
|
+
# Run with config mounted
|
|
138
|
+
docker run -p 3000:3000 \
|
|
139
|
+
-v ./examples/config.json:/home/gateway/.config/mcp-gateway/config.json:ro \
|
|
140
|
+
mcp-gateway
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Endpoints:**
|
|
144
|
+
|
|
145
|
+
| Endpoint | Description |
|
|
146
|
+
|----------|-------------|
|
|
147
|
+
| `GET /` | Gateway info and endpoints |
|
|
148
|
+
| `GET /health` | Health check |
|
|
149
|
+
| `/mcp` | MCP protocol endpoint |
|
|
150
|
+
|
|
151
|
+
**Example:**
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
curl http://localhost:3000/
|
|
155
|
+
# {"name":"MCP Gateway",...,"endpoints":{"mcp":"/mcp","health":"/health"}}
|
|
156
|
+
|
|
157
|
+
curl http://localhost:3000/health
|
|
158
|
+
# {"status":"ok"}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Remote Server Configuration
|
|
162
|
+
|
|
163
|
+
Remote servers are auto-detected based on the URL protocol:
|
|
164
|
+
- `http://` or `https://` → Streamable HTTP (recommended)
|
|
165
|
+
- `ws://` or `wss://` → WebSocket
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"gh-grep": {
|
|
170
|
+
"type": "remote",
|
|
171
|
+
"url": "https://mcp.grep.app"
|
|
172
|
+
},
|
|
173
|
+
"custom-websocket": {
|
|
174
|
+
"type": "remote",
|
|
175
|
+
"url": "wss://my-server.com/mcp"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Available Tools
|
|
181
|
+
|
|
182
|
+
### `gateway.search`
|
|
183
|
+
|
|
184
|
+
Search for tools across all connected servers.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
{
|
|
188
|
+
query: "kubernetes pods",
|
|
189
|
+
limit: 10, // optional, max 50
|
|
190
|
+
filters: {
|
|
191
|
+
server: "kubernetes", // optional, filter by server name
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Returns matching tools with relevance scores. Tools matching in name are boosted.
|
|
197
|
+
|
|
198
|
+
### `gateway.describe`
|
|
199
|
+
|
|
200
|
+
Get detailed information about a specific tool.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
{
|
|
204
|
+
id: "kubernetes::pods_list" // format: serverKey::toolName
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Returns the full tool schema including inputSchema.
|
|
209
|
+
|
|
210
|
+
### `gateway.invoke`
|
|
211
|
+
|
|
212
|
+
Execute a tool synchronously and get immediate results.
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
{
|
|
216
|
+
id: "kubernetes::pods_list",
|
|
217
|
+
args: { namespace: "default" },
|
|
218
|
+
timeoutMs: 30000 // optional, default 30 seconds
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### `gateway.invoke_async`
|
|
223
|
+
|
|
224
|
+
Start an asynchronous tool execution. Returns a job ID for polling.
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
{
|
|
228
|
+
id: "some-server::long-running-tool",
|
|
229
|
+
args: { ... },
|
|
230
|
+
priority: 10, // optional, higher values run first
|
|
231
|
+
timeoutMs: 60000
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### `gateway.invoke_status`
|
|
236
|
+
|
|
237
|
+
Check the status of an async job.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
{
|
|
241
|
+
jobId: "job_123456789_abc123"
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Tool ID Format
|
|
246
|
+
|
|
247
|
+
All gateway tools use the format `serverKey::toolName` to identify tools:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
kubernetes::pods_list
|
|
251
|
+
playwright::browser_navigate
|
|
252
|
+
github::create_issue
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The `serverKey` is the key name in your configuration file.
|
|
256
|
+
|
|
257
|
+
## Architecture
|
|
258
|
+
|
|
259
|
+
### Components
|
|
260
|
+
|
|
261
|
+
- **MCPGateway class**: Main orchestrator
|
|
262
|
+
- **Upstream connection manager**: Manages connections to MCP servers (stdio for local, HTTP/WebSocket for remote)
|
|
263
|
+
- **Tool catalog**: In-memory index of all available tools with metadata
|
|
264
|
+
- **Job queue**: Handles async tool invocations with priority ordering and concurrency limits (max 3 concurrent by default)
|
|
265
|
+
- **Search engine**: MiniSearch with BM25 scoring and fuzzy matching
|
|
266
|
+
|
|
267
|
+
### Search Algorithm
|
|
268
|
+
|
|
269
|
+
The search uses [MiniSearch](https://github.com/lucaong/minisearch) with BM25 ranking:
|
|
270
|
+
|
|
271
|
+
- **BM25 scoring**: Relevance algorithm
|
|
272
|
+
- **Field boosting**: Name matches (3x), title matches (2x), description/server matches (1x)
|
|
273
|
+
- **Fuzzy matching**: Handles typos with 0.2 threshold (e.g., "kubenetes" → finds "kubernetes")
|
|
274
|
+
- **Prefix search**: Partial word matching (e.g., "pod" matches "pods_list")
|
|
275
|
+
|
|
276
|
+
### Contributing
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
git clone https://github.com/eznix86/mcp-gateway.git
|
|
280
|
+
cd mcp-gateway
|
|
281
|
+
bun install
|
|
282
|
+
|
|
283
|
+
# Run locally (stdio transport)
|
|
284
|
+
bun run index.ts
|
|
285
|
+
|
|
286
|
+
# Run with Docker (HTTP transport on port 3000)
|
|
287
|
+
bun run docker:build && bun run docker:run
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
MIT License. See the [LICENSE](LICENSE).
|