tinyfish-mcp-lite 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +326 -2
- package/dist/config.d.ts +17 -0
- package/dist/config.js +79 -0
- package/dist/core/errors.d.ts +126 -0
- package/dist/core/errors.js +214 -0
- package/dist/core/proxy-core.d.ts +104 -0
- package/dist/core/proxy-core.js +249 -0
- package/dist/core/session.d.ts +60 -0
- package/dist/core/session.js +89 -0
- package/dist/core/sse.d.ts +20 -0
- package/dist/core/sse.js +123 -0
- package/dist/core/tool-filter.d.ts +48 -0
- package/dist/core/tool-filter.js +213 -0
- package/dist/core/upstream.d.ts +58 -0
- package/dist/core/upstream.js +178 -0
- package/dist/http/adapter.d.ts +3 -0
- package/dist/http/adapter.js +294 -0
- package/dist/http/index.d.ts +22 -0
- package/dist/http/index.js +85 -0
- package/dist/http/origin.d.ts +14 -0
- package/dist/http/origin.js +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -0
- package/dist/log.d.ts +10 -0
- package/dist/log.js +18 -0
- package/dist/shutdown.d.ts +2 -0
- package/dist/shutdown.js +2 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +6 -0
- package/package.json +75 -4
package/dist/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { ConfigError, parseConfig } from "./config.js";
|
|
3
|
+
import { createProxyCore } from "./core/proxy-core.js";
|
|
4
|
+
// FORK(lite): free-tool allowlist — see src/core/tool-filter.ts and FORK.md.
|
|
5
|
+
import { parseToolPolicy, withToolFilter } from "./core/tool-filter.js";
|
|
6
|
+
import { createMcpAdapter } from "./http/adapter.js";
|
|
7
|
+
import { createAppHandler, startHttpServer } from "./http/index.js";
|
|
8
|
+
import { log } from "./log.js";
|
|
9
|
+
import { shutdownHooks } from "./shutdown.js";
|
|
10
|
+
import { VERSION } from "./version.js";
|
|
11
|
+
function isErrnoException(err) {
|
|
12
|
+
return err instanceof Error && "code" in err;
|
|
13
|
+
}
|
|
14
|
+
async function main() {
|
|
15
|
+
let config;
|
|
16
|
+
let toolPolicy; // FORK(lite)
|
|
17
|
+
try {
|
|
18
|
+
config = parseConfig(process.env);
|
|
19
|
+
// FORK(lite): TINYFISH_TOOLS allowlist (default: the free search +
|
|
20
|
+
// fetch_content; "*" restores unfiltered upstream passthrough).
|
|
21
|
+
toolPolicy = parseToolPolicy(process.env.TINYFISH_TOOLS);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (err instanceof ConfigError) {
|
|
25
|
+
process.stderr.write(`${err.message}\n`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
// The real MCP handler: origin/routing shell → adapter → proxy core.
|
|
31
|
+
// createProxyCore registers session teardown into shutdownHooks itself.
|
|
32
|
+
// FORK(lite): the decorator hides non-allowed tools from tools/list and
|
|
33
|
+
// answers tools/call for them locally — paid tools are never advertised
|
|
34
|
+
// and never invoked upstream.
|
|
35
|
+
const core = withToolFilter(createProxyCore({ upstreamUrl: config.upstreamUrl, apiKey: config.apiKey }), toolPolicy);
|
|
36
|
+
const handler = createAppHandler(createMcpAdapter(core));
|
|
37
|
+
let server;
|
|
38
|
+
try {
|
|
39
|
+
server = await startHttpServer(config.port, handler);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (isErrnoException(err) && err.code === "EADDRINUSE") {
|
|
43
|
+
log.error(`Port ${config.port} is already in use — stop the other process or set PORT to a free port`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
// The one startup line. Never include config.apiKey here or in any other log call.
|
|
49
|
+
log.info(`listening on http://127.0.0.1:${config.port} — upstream ${config.upstreamUrl} — v${VERSION}`);
|
|
50
|
+
// FORK(lite): state the active tool policy so a "missing tool" is never a
|
|
51
|
+
// mystery. Tool names only — never the API key.
|
|
52
|
+
if (toolPolicy.mode === "allow") {
|
|
53
|
+
log.info(`tool filter: exposing [${[...toolPolicy.allowed].join(", ")}] — set TINYFISH_TOOLS=* to expose every upstream tool`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
log.info("tool filter: off (TINYFISH_TOOLS=*) — exposing every upstream tool");
|
|
57
|
+
}
|
|
58
|
+
let shuttingDown = false;
|
|
59
|
+
const shutdown = async () => {
|
|
60
|
+
if (shuttingDown)
|
|
61
|
+
return;
|
|
62
|
+
shuttingDown = true;
|
|
63
|
+
server.close();
|
|
64
|
+
for (const hook of shutdownHooks) {
|
|
65
|
+
try {
|
|
66
|
+
await hook();
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
log.error(`shutdown hook failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
process.exit(0);
|
|
73
|
+
};
|
|
74
|
+
process.on("SIGINT", () => void shutdown());
|
|
75
|
+
process.on("SIGTERM", () => void shutdown());
|
|
76
|
+
}
|
|
77
|
+
main().catch((err) => {
|
|
78
|
+
log.error(`startup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
package/dist/log.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal leveled logger. Writes to stderr only — stdout stays clean for a
|
|
3
|
+
* future stdio transport. Callers must never pass the API key into a message.
|
|
4
|
+
*/
|
|
5
|
+
export type LogLevel = "info" | "warn" | "error";
|
|
6
|
+
export declare const log: {
|
|
7
|
+
info(message: string): void;
|
|
8
|
+
warn(message: string): void;
|
|
9
|
+
error(message: string): void;
|
|
10
|
+
};
|
package/dist/log.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal leveled logger. Writes to stderr only — stdout stays clean for a
|
|
3
|
+
* future stdio transport. Callers must never pass the API key into a message.
|
|
4
|
+
*/
|
|
5
|
+
function write(level, message) {
|
|
6
|
+
process.stderr.write(`tinyfish-mcp [${level}] ${message}\n`);
|
|
7
|
+
}
|
|
8
|
+
export const log = {
|
|
9
|
+
info(message) {
|
|
10
|
+
write("info", message);
|
|
11
|
+
},
|
|
12
|
+
warn(message) {
|
|
13
|
+
write("warn", message);
|
|
14
|
+
},
|
|
15
|
+
error(message) {
|
|
16
|
+
write("error", message);
|
|
17
|
+
},
|
|
18
|
+
};
|
package/dist/shutdown.js
ADDED
package/dist/version.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
// Resolves to the package root's package.json from both src/ (dev) and dist/ (published).
|
|
4
|
+
const pkg = require("../package.json");
|
|
5
|
+
/** Package version, read once at startup. Feeds X-TF-Client-Version upstream. */
|
|
6
|
+
export const VERSION = pkg.version;
|
package/package.json
CHANGED
|
@@ -1,6 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinyfish-mcp-lite",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Fork of @tiny-fish/mcp exposing only the free TinyFish tools (search, fetch_content) \u2014 local reverse proxy to agent.tinyfish.ai/mcp",
|
|
5
|
+
"mcpName": "io.github.ByronFinn/tinyfish-mcp-lite",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/ByronFinn/tinyfish-mcp-lite.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/ByronFinn/tinyfish-mcp-lite#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/ByronFinn/tinyfish-mcp-lite/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mcp",
|
|
16
|
+
"model-context-protocol",
|
|
17
|
+
"tinyfish",
|
|
18
|
+
"web-automation",
|
|
19
|
+
"browser-automation",
|
|
20
|
+
"proxy"
|
|
21
|
+
],
|
|
22
|
+
"author": "ByronFinn (fork of TinyFish's tinyfish-mcp-server, MIT)",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"allowScripts": {
|
|
26
|
+
"tinyfish-mcp-lite": true,
|
|
27
|
+
"esbuild": true,
|
|
28
|
+
"fsevents": true
|
|
29
|
+
},
|
|
30
|
+
"bin": {
|
|
31
|
+
"tinyfish-mcp": "dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist/",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc && chmod +x dist/index.js",
|
|
40
|
+
"test": "vitest --run",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"test:integration": "vitest --run --config vitest.integration.config.ts",
|
|
43
|
+
"lint": "eslint src tests",
|
|
44
|
+
"format": "prettier --write src tests",
|
|
45
|
+
"type-check": "tsc --noEmit --project tsconfig.all.json",
|
|
46
|
+
"prepublishOnly": "npm run build",
|
|
47
|
+
"prepare": "npm run build"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
51
|
+
"zod": "^4.4.3"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^10.0.1",
|
|
55
|
+
"@types/node": "^22.0.0",
|
|
56
|
+
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
|
57
|
+
"@typescript-eslint/parser": "^8.57.2",
|
|
58
|
+
"eslint": "^10.1.0",
|
|
59
|
+
"globals": "^17.4.0",
|
|
60
|
+
"prettier": "^3.0.0",
|
|
61
|
+
"tsx": "^4.23.1",
|
|
62
|
+
"typescript": "^5.0.0",
|
|
63
|
+
"vitest": "^4.1.11"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=22.0.0"
|
|
67
|
+
},
|
|
68
|
+
"publishConfig": {
|
|
69
|
+
"registry": "https://registry.npmjs.org/"
|
|
70
|
+
},
|
|
71
|
+
"overrides": {
|
|
72
|
+
"@vitest/mocker": "^4.1.11",
|
|
73
|
+
"fast-uri": "^3.1.8",
|
|
74
|
+
"nanoid": "^3.3.19",
|
|
75
|
+
"qs": "^6.16.0"
|
|
76
|
+
}
|
|
77
|
+
}
|