github TypeScript re-analysis due

ni-c/mcp-hub

github

Serve multiple stdio MCP servers from one container: path routing, hub meta-tools, OAuth 2.1 + API tokens for ChatGPT, Claude, Cursor and other MCP clients

maintainer
ni-c
licence
MIT
first seen
2026-08-13
last seen
2026-09-12
releases · 30d
19
short id

Drift inferred · capture-to-capture

No drift recorded — single capability capture; advisories appear once its surface changes.

capabilities 15 tools
transport stdio · streamable-http · http verified reported listed in the official MCP registry counts 15 tools · 0 res · 0 prompts permission surface via code analysis

tools

  • call_tool
  • create_ticket
  • get_forecast
  • get_ticket
  • get_tool_schema
  • list_docs
  • list_servers
  • list_stations
  • list_statuses
  • list_tickets
  • list_tools
  • read_doc
  • search_docs
  • sleep_server
  • wake_server
skills & danger signals github-tarball
prompt-surface shipped agent-instruction files + hidden-content / dangerous-code findings — quoted from the analyzed source

analyzed commit 3fdbdb7 · analyzer v33 · 1w ago

danger signals2

code evidence vv0.10.0 · github-tarball
evidence-backed findings quoted directly from the published source artifact — not inferred

code files: 144

filesystem 46

  • fs (weak) ni-c-mcp-hub-3fdbdb7/docs/.vitepress/config.ts :1 import { readFileSync } from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/compose.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/docker.ts :2 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/gateway.ts :2 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/replay.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/workspace.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/suites/bins.e2e.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/suites/transcripts.e2e.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/tools/curate.ts :2 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/e2e/tools/record.ts :2 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/auth/store.ts :2 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/config.ts :2 import fs from 'node:fs';
show 28 more
  • fs ni-c-mcp-hub-3fdbdb7/src/docker-proxy/index.ts :2 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/docker-proxy/secrets-watcher.ts :2 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/docker-proxy/secrets.ts :1 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/logfile.ts :1 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/main-module.ts :1 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/mount-check.ts :1 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/stdio.ts :2 import fs from 'node:fs';
  • fs ni-c-mcp-hub-3fdbdb7/src/tool-cache.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/api-tokens.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/cimd.test.ts :3 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/client-compat.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/docker-client.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/docker-e2e.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/docker-policy.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/docker-proxy.test.ts :2 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/docker-secrets-watcher.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/dual-era.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/e2e.test.ts :2 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/elicitation-e2e.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/hardening.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/logfile.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/mount-check.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/oidc-mount.test.ts :2 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/oidc-parity.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/on-demand-e2e.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/on-demand.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/registration.test.ts :1 import fs from 'node:fs';
  • fs (weak) ni-c-mcp-hub-3fdbdb7/test/schema-portability.test.ts :1 import fs from 'node:fs';

6 more not shown — this panel samples each group; the count above is the real total.

shell / exec 8

  • shell (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/compose.ts :39 exec(argv: string[]): Promise<{ code: number; stdout: string; stderr: string }>;
  • shell (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/docker.ts :1 import { execFile } from 'node:child_process';
  • shell (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/gateway.ts :1 import { execFile, spawn } from 'node:child_process';
  • shell (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/run.ts :1 import { spawn } from 'node:child_process';
  • shell (weak) ni-c-mcp-hub-3fdbdb7/test/docker-proxy.test.ts :1 import { spawn, type ChildProcess } from 'node:child_process';
  • shell (weak) ni-c-mcp-hub-3fdbdb7/test/hardening.test.ts :5 import { spawn } from 'node:child_process';
  • shell (weak) ni-c-mcp-hub-3fdbdb7/test/stdio.test.ts :4 import { spawn } from 'node:child_process';
  • shell (weak) ni-c-mcp-hub-3fdbdb7/test/transports.test.ts :1 import { spawn } from 'node:child_process';

network 27

  • net (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/gateway.ts :5 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/loopback.ts :1 import net from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/ports.ts :1 import net from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/wait.ts :81 const response = await fetch(url, { signal: AbortSignal.timeout(5_000), redirect: 'manual' });
  • net (weak) ni-c-mcp-hub-3fdbdb7/e2e/harness/wire.ts :62 const response = await fetch(`${this.gateway.baseUrl}${pathname}`, {
  • net (weak) ni-c-mcp-hub-3fdbdb7/e2e/tools/record.ts :3 import http from 'node:http';
  • net ni-c-mcp-hub-3fdbdb7/src/auth/address.ts :2 import net from 'node:net';
  • net ni-c-mcp-hub-3fdbdb7/src/auth/pinned-fetch.ts :1 import http from 'node:http';
  • net ni-c-mcp-hub-3fdbdb7/src/auth/rate-limit.ts :1 import net from 'node:net';
  • net ni-c-mcp-hub-3fdbdb7/src/docker-proxy/server.ts :1 import http from 'node:http';
  • net (weak) ni-c-mcp-hub-3fdbdb7/src/sandbox/docker-client.ts :1 import http from 'node:http';
  • net ni-c-mcp-hub-3fdbdb7/src/supervisor.ts :86 return fetch(input, { ...init, headers: merged });
show 15 more
  • net ni-c-mcp-hub-3fdbdb7/src/transports/socket.ts :1 import net from 'node:net';
  • net ni-c-mcp-hub-3fdbdb7/src/upstream/auth.ts :120 return fetch(url, { ...init, redirect: 'error', signal: AbortSignal.timeout(AS_TIMEOUT_MS) });
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/api-tokens.test.ts :4 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/cimd.test.ts :2 import http from 'node:http';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/docker-client.test.ts :2 import http from 'node:http';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/docker-e2e.test.ts :2 import http from 'node:http';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/docker-proxy.test.ts :3 import http from 'node:http';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/docker-secrets-watcher.test.ts :2 import http from 'node:http';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/dual-era.test.ts :4 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/e2e.test.ts :5 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/elicitation-e2e.test.ts :4 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/on-demand-e2e.test.ts :4 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/subscriptions-e2e.test.ts :4 import type { AddressInfo } from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/transports.test.ts :3 import net from 'node:net';
  • net (weak) ni-c-mcp-hub-3fdbdb7/test/upstream-oauth.test.ts :5 import type { AddressInfo } from 'node:net';

secrets 3

  • secrets (weak) ni-c-mcp-hub-3fdbdb7/e2e/suites/no-password.e2e.ts :36 // spreads `env` last, and the hub's own `process.env.PASSWORD` is falsy
  • secrets ni-c-mcp-hub-3fdbdb7/src/index.ts :456 password: process.env.PASSWORD,
  • secrets (weak) ni-c-mcp-hub-3fdbdb7/test/e2e.test.ts :118 process.env.REMOTE_SECRET = 'remote-secret';

tool registrations 15

  • search_docs ni-c-mcp-hub-3fdbdb7/demo/servers/docs.mjs :119
  • read_doc ni-c-mcp-hub-3fdbdb7/demo/servers/docs.mjs :148
  • list_docs ni-c-mcp-hub-3fdbdb7/demo/servers/docs.mjs :162
  • list_tickets ni-c-mcp-hub-3fdbdb7/demo/servers/tickets.mjs :78
  • get_ticket ni-c-mcp-hub-3fdbdb7/demo/servers/tickets.mjs :93
  • create_ticket ni-c-mcp-hub-3fdbdb7/demo/servers/tickets.mjs :107
  • list_statuses ni-c-mcp-hub-3fdbdb7/demo/servers/tickets.mjs :135
  • list_stations ni-c-mcp-hub-3fdbdb7/demo/servers/weather.mjs :74
  • get_forecast ni-c-mcp-hub-3fdbdb7/demo/servers/weather.mjs :84
  • list_servers ni-c-mcp-hub-3fdbdb7/src/hub.ts :215
  • list_tools ni-c-mcp-hub-3fdbdb7/src/hub.ts :238
  • get_tool_schema ni-c-mcp-hub-3fdbdb7/src/hub.ts :274
show 3 more
  • call_tool ni-c-mcp-hub-3fdbdb7/src/hub.ts :315
  • wake_server ni-c-mcp-hub-3fdbdb7/src/hub.ts :391
  • sleep_server ni-c-mcp-hub-3fdbdb7/src/hub.ts :414

install hooks 1

  • prepublishOnly ni-c-mcp-hub-3fdbdb7/package.json :56 npm test && npm run build

declared dependencies 22

  • @modelcontextprotocol/client@^2.0.0
  • @modelcontextprotocol/core@^2.0.0
  • @modelcontextprotocol/express@^2.0.0
  • @modelcontextprotocol/node@^2.0.0
  • @modelcontextprotocol/server@^2.0.0
  • @modelcontextprotocol/server-everything@^2026.7.4
  • bcryptjs@^3.0.2
  • express@^5.1.0
  • jose@^6.2.8
  • oidc-provider@^9.12.0
  • zod@^4.4.3
  • @types/express@^5.0.0
show 10 more
  • @types/node@^26.2.0
  • @types/oidc-provider@^9.11.1
  • @types/supertest@^7.2.1
  • @vitest/coverage-v8@4.1.11
  • oxlint@^1.80.0
  • supertest@^7.0.0
  • svg-asset-set@https://github.com/ni-c/svg-asset-set/releases/download/v0.1.0/svg-asset-set-0.1.0.tgz
  • tsx@^4.19.0
  • typescript@^7.0.2
  • vitest@^4.1.10

perm:untrusted 1

  • untrusted (weak) ni-c-mcp-hub-3fdbdb7/test/upstream-oauth.test.ts :403 const { code } = (await (await fetch(authorizationUrl)).json()) as { code: string };