Atlas / MCP servers / harrisoncn / mcp-gateway

mcp-gatewayBLOCK

mcp/harrisoncn/mcp-gateway

🔀 A lightweight, open-source gateway for managing, routing, and monitoring multiple MCP (Model Context Protocol) servers. Auth · Rate-limit · Metrics · Tool discovery.

Verdict
BLOCK
Grade
F
Trust score
39 /100
Exposed tools
39 32r · 6w · 1d
Transport
sse · streamable-http
License
MIT
Stars
1
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://www.npmjs.com/package/@winstonsayno/mcp-gateway) [](https://github.com/HarrisonCN/mcp-gateway/actions/workflows/ci.yml) [](https://github.com/HarrisonCN/mcp-gateway/actions/workflows/codeql.yml) [](https://securityscorecards.dev/viewer/?uri=github.com/HarrisonCN/mcp-gateway) [](https://nodejs.org) [](LICENSE)

English · 简体中文

One authenticated, observable endpoint in front of all your MCP servers.

mcp-gateway sits between AI clients (Claude Code, Cursor, your own agents, LLM apps, web and mobile front-ends) and the Model Context Protocol servers they use. Clients connect once — over MCP Streamable HTTP at /mcp or a REST API under /api/v1 — and the gateway authenticates the caller, checks what it may do, routes the call to the right upstream and records what happened. Keys, scopes, rate limits, policy, logs and metrics live in one place instead of in every client.

Current release: 13.6.0 (npm latest). Live dashboard demo with simulated traffic, no backend:

Contents

  • Architecture
  • Key features
  • Quick start
  • Minimal configuration
  • Connect clients and LLMs
  • Security model
  • Observability
  • Supported versions
  • Documentation
  • Contributing
  • [Licens
Read from source at commit ca6da521050aOBSERVED · 2026-10-10
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add mcp-gateway --env AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} --env AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} --env AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} --env CI_KEY=${CI_KEY} -- npx -y @winstonsayno/[email protected]
claude-desktop
{
  "mcpServers": {
    "mcp-gateway": {
      "command": "npx",
      "args": [
        "-y",
        "@winstonsayno/[email protected]"
      ],
      "env": {
        "AWS_ACCESS_KEY_ID": "${AWS_ACCESS_KEY_ID}",
        "AWS_SECRET_ACCESS_KEY": "${AWS_SECRET_ACCESS_KEY}",
        "AWS_SESSION_TOKEN": "${AWS_SESSION_TOKEN}",
        "CI_KEY": "${CI_KEY}"
      }
    }
  }
}
03

Exposed tools (39)

32 read · 6 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
Extrareadd
Fakereadtest
FetchreadFetch web pages and convert them to markdown
FilesystemwriteRead and write files under /srv/projects
GITHUB_TOKENreadGitHub personal access token
GitreadRead, search and manipulate a Git repository
GitHubreadRepositories, issues and pull requests
MemoryreadKnowledge-graph based persistent memory
PostgresreadRead-only SQL against the analytics replica
SlackwritePost and read team messages
TimereadCurrent time and time-zone conversion
a__echoread
a__nreadd
add-toolwrite
brave_local_searchreadSearch for local businesses and places
brave_web_searchreadSearch the web
cachedreadCacheable echo
create_issuewriteOpen a new issue
directoryreadAllowed directory
echoreadEcho the arguments
failreadAlways a JSON-RPC error
get_issuereadGet an issue by number
lateread
list_directoryreadList files and folders in a directory
list_pull_requestsreadList pull requests in a repository
list_tablesreadList tables in the public schema
pricedreadEcho with a usage block (budgets)
querywriteRun a read-only SQL query
readreadRead
read_filereadRead the complete contents of a file
repositoryreadPath of the repository
search_filesreadRecursively search for files matching a pattern
search_repositoriesreadSearch GitHub repositories
slack_get_channel_historyreadRecent messages in a channel
slack_post_messagewritePost a message to a channel
slowreadSleep
twicereadecho twice
write_filedestructiveCreate or overwrite a file
xread
04

Trust audit

BLOCKgrade F · trust 39/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (8 observation(s))
Network
declared (13 observation(s))
Shell
declared (6 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
bench/lib/upstreams.mjs:299
} else socket.write(exec(v));
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/features/task-graphs.ts:373
st.done = executeRun(run, exec(run), { checkpoint: (r) => taskRuns.save(r, dirOf(c)), cancelled: () => st.cancel }).finally(() => active.delete(run.id));
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/monitor/audit.ts:74
exec(sql: string): void;
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/policy/cedar.ts:534
eval(e: Expr): CedarValue {
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
deploy/helm/mcp-gateway/values.yaml:40
# Opt out of the auth requirement: start the gateway with --insecure (NO authentication on the pod address).
Why it matters. certificate verification is disabled
Fix. leave verification on
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
src/cli.ts:50
.option('--insecure', 'Allow starting without auth on a non-loopback address (trusted networks only)')
Why it matters. certificate verification is disabled
Fix. leave verification on
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
src/features/pq-tls.ts:85
const s = connect({ host, port, servername: /^[\d.]+$|:/.test(servername) ? undefined : servername, ecdhCurve, rejectUnauthorized: false, minVersion: 'TLSv1.3' }, () => {
Why it matters. certificate verification is disabled
Fix. leave verification on
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
src/gateway/index.ts:664
if (this.config.security?.insecure && (this.config.auth?.strategy ?? 'none') === 'none') logger.warn('Started with --insecure: authentication is off on a non-loopback address.');
Why it matters. certificate verification is disabled
Fix. leave verification on
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
src/security/posture.ts:43
'127.0.0.1, or — only on a trusted network — start with --insecure (security.insecure: true).'
Why it matters. certificate verification is disabled
Fix. leave verification on
MEDIUMInventory / provenance · inv.binary · CWE-1104
clients/kotlin/gradle/wrapper/gradle-wrapper.jar
gradle-wrapper.jar
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInsecure crypto · crypto.weak_random · CWE-327, CWE-338
dashboard/demo/mock.js:836
const nr = { id: uuid(), timestamp: Date.now(), serverId: s.id, toolName: r.toolName, durationMs: Math.round(s.base * (0.5 + Math.random())), success: up, clientId: 'key:demo', via: 'rest', kind: 'too
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/auth/oauth.ts:238
logger.warn(`OAuth token introspection failed: ${err instanceof Error ? err.message : String(err)}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/auth/oauth.ts:362
logger.warn(`OAuth token rejected from ${req.ip}: ${te.message}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/cli.ts:507
console.log(`Wrote ${options.out}.key (keep secret) and ${options.out}.pub (add to pluginTrust.keys)`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/cli.ts:559
console.log(`Wrote ${options.out}.hybrid.json (secret) and ${options.out}.pub.json (Ed25519 + ${options.alg}). Backend: ${pqBackend().note}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/gateway/api.ts:1518
logger.info(`Secret rotation requested via API: ${rotated.length} server(s) reconnected`);
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
dashboard/demo/mock.js:60
{ id: "sanitize", since: "7.3.0", summary: "Prompt-injection defence: tool-output sanitisation (hidden Unicode, ANSI, HTML, exfil images), spotlighting, inbound / outbound blocking" },
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
dashboard/demo/mock.js:622
{ timestamp: iso(Date.now() - 64e3), client: 'key:aura', kind: 'prompt-injection', detail: 'results: ignore-instructions, exfil-url', serverId: 'web', tool: 'fetch', score: 1 },
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
dashboard/demo/mock.js:625
if (p === '/admin/anomaly/score' && method === 'POST') return json({ score: 1, signals: ['ignore-instructions', 'prompt-exfiltration'], threshold: 0.6 });
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
src/features/anomaly.ts:47
'prompt-exfiltration': 0.5,
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
src/features/anomaly.ts:49
'exfil-url': 0.7,
MEDIUMHard-coded secrets · secret.anthropic · CWE-798, CWE-321
test/security.test.ts:42
'key sk-ant-REDACTEDREDACTEDREDACTED00',
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
test/security.test.ts:44
'aws AKIAABCDEFGHIJKLMNOP',
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
test/federation.test.ts:12
const SECRET = 'federation-secret-0123456789abcdef';
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
test/policy.test.ts:76
const input = { serverId: 's', tool: 't', args: { token: 'sk-abcdefghijklmnopqrstuvwxyz123456' }, via: 'rest' as const, clientId: 'key:app' };

Gates applied: no_behavioural_pass.

Audited 2026-10-10 · audit v0.4.1 · source sha ca6da521050afull audit observations/trust-audit/mcp-server/harrisoncn__mcp-gateway.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-10ca6da521050aBLOCKF39first audit
06

Questions

What is the @winstonsayno/mcp-gateway MCP server?

🔀 A lightweight, open-source gateway for managing, routing, and monitoring multiple MCP (Model Context Protocol) servers. Auth · Rate-limit · Metrics · Tool discovery.

What tools does @winstonsayno/mcp-gateway expose?

39 in total: 32 read-only, 6 that write, and 1 that can delete or overwrite (write_file). Every one is listed on this page with its risk.

Is @winstonsayno/mcp-gateway safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (39/100) and found 9 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does @winstonsayno/mcp-gateway need?

It reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, CI_KEY, GATEWAY_KEY, GH_TOKEN, GITHUB_TOKEN, GOOGLE_OAUTH_ACCESS_TOKEN, LLM_API_KEY, MCP_GATEWAY_ADMIN_KEY, MCP_GATEWAY_API_KEYS and MCP_GATEWAY_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does @winstonsayno/mcp-gateway run?

It speaks sse and streamable-http, so it runs as a service you connect to over the network. It is published on npm as @winstonsayno/mcp-gateway at 13.6.0.

How current is this page?

The grade is for one exact copy of the source (ca6da521050a), read on 2026-10-10. The repository is watched and re-audited when it changes.

Advertisement