tinyfish-mcp-lite 0.0.0-stage → 0.2.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 +354 -2
- package/dist/config.d.ts +17 -0
- package/dist/config.js +77 -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 +105 -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/stdio/adapter.d.ts +13 -0
- package/dist/stdio/adapter.js +177 -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,105 @@
|
|
|
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
|
+
// FORK(lite): stdio transport — spawn-and-forget mode for clients that
|
|
37
|
+
// launch their MCP servers as commands (`tinyfish-mcp --stdio`, or
|
|
38
|
+
// `npx -y tinyfish-mcp-lite --stdio`). Same core, same filter; the client
|
|
39
|
+
// owns the lifecycle (stdin closed ⇒ exit), so no PORT and no long-running
|
|
40
|
+
// server. See src/stdio/adapter.ts and FORK.md.
|
|
41
|
+
if (process.argv.includes("--stdio")) {
|
|
42
|
+
const { runStdioTransport } = await import("./stdio/adapter.js");
|
|
43
|
+
log.info(`stdio transport — upstream ${config.upstreamUrl} — v${VERSION}`);
|
|
44
|
+
if (toolPolicy.mode === "allow") {
|
|
45
|
+
log.info(`tool filter: exposing [${[...toolPolicy.allowed].join(", ")}] — set TINYFISH_TOOLS=* to expose every upstream tool`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
log.info("tool filter: off (TINYFISH_TOOLS=*) — exposing every upstream tool");
|
|
49
|
+
}
|
|
50
|
+
await runStdioTransport(core);
|
|
51
|
+
for (const hook of shutdownHooks) {
|
|
52
|
+
try {
|
|
53
|
+
await hook();
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
log.error(`shutdown hook failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
const handler = createAppHandler(createMcpAdapter(core));
|
|
62
|
+
let server;
|
|
63
|
+
try {
|
|
64
|
+
server = await startHttpServer(config.port, handler);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
if (isErrnoException(err) && err.code === "EADDRINUSE") {
|
|
68
|
+
log.error(`Port ${config.port} is already in use — stop the other process or set PORT to a free port`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
// The one startup line. Never include config.apiKey here or in any other log call.
|
|
74
|
+
log.info(`listening on http://127.0.0.1:${config.port} — upstream ${config.upstreamUrl} — v${VERSION}`);
|
|
75
|
+
// FORK(lite): state the active tool policy so a "missing tool" is never a
|
|
76
|
+
// mystery. Tool names only — never the API key.
|
|
77
|
+
if (toolPolicy.mode === "allow") {
|
|
78
|
+
log.info(`tool filter: exposing [${[...toolPolicy.allowed].join(", ")}] — set TINYFISH_TOOLS=* to expose every upstream tool`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
log.info("tool filter: off (TINYFISH_TOOLS=*) — exposing every upstream tool");
|
|
82
|
+
}
|
|
83
|
+
let shuttingDown = false;
|
|
84
|
+
const shutdown = async () => {
|
|
85
|
+
if (shuttingDown)
|
|
86
|
+
return;
|
|
87
|
+
shuttingDown = true;
|
|
88
|
+
server.close();
|
|
89
|
+
for (const hook of shutdownHooks) {
|
|
90
|
+
try {
|
|
91
|
+
await hook();
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
log.error(`shutdown hook failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
process.exit(0);
|
|
98
|
+
};
|
|
99
|
+
process.on("SIGINT", () => void shutdown());
|
|
100
|
+
process.on("SIGTERM", () => void shutdown());
|
|
101
|
+
}
|
|
102
|
+
main().catch((err) => {
|
|
103
|
+
log.error(`startup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
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
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
import { type ProxyCore } from "../core/proxy-core.js";
|
|
3
|
+
export interface StdioStreams {
|
|
4
|
+
input: Readable;
|
|
5
|
+
output: Writable;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Run the transport until `streams.input` ends (the client closed its pipe —
|
|
9
|
+
* MCP stdio shutdown) or `streams.output` errors (EPIPE: the client died
|
|
10
|
+
* without closing stdin). Resolves void; the caller runs shutdown hooks and
|
|
11
|
+
* exits.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runStdioTransport(core: ProxyCore, streams?: StdioStreams): Promise<void>;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FORK ADDITION (tinyfish-mcp-lite) — this module does not exist upstream.
|
|
3
|
+
*
|
|
4
|
+
* stdio transport: spawn-and-forget mode for MCP clients that launch their
|
|
5
|
+
* servers as commands. The client owns the process lifecycle (stdin closed ⇒
|
|
6
|
+
* shutdown), no port to manage, no server to start by hand. Newline-delimited
|
|
7
|
+
* JSON-RPC on stdin/stdout per the MCP stdio spec; every log goes to stderr
|
|
8
|
+
* (log.ts) so stdout stays protocol-pure — log.ts documents exactly this
|
|
9
|
+
* contract ("stdout stays clean for a future stdio transport").
|
|
10
|
+
*
|
|
11
|
+
* Routing mirrors the HTTP adapter's route() one-to-one (notifications →
|
|
12
|
+
* notify BEFORE any tools/call check; initialize → initialize; tools/call →
|
|
13
|
+
* forwardStream; everything else, including forbidden batch arrays and
|
|
14
|
+
* shapeless bodies, → forward), so the withToolFilter decorator covers both
|
|
15
|
+
* transports identically: tools/list filtered, hidden tools/call answered
|
|
16
|
+
* locally, notification-shaped calls dropped, batches rejected — see
|
|
17
|
+
* tests/stdio.test.ts and tests/tool-filter.test.ts.
|
|
18
|
+
*
|
|
19
|
+
* Differences from the HTTP hop that are intrinsic to stdio:
|
|
20
|
+
* - No status codes, no headers: upstream's JSON-RPC body is the message;
|
|
21
|
+
* a JSON-RPC error body relays verbatim, and failures upstream never
|
|
22
|
+
* answered as JSON-RPC are shaped through toJsonRpcError (same as HTTP).
|
|
23
|
+
* - One client, one session: the localKey is the constant "stdio" — the
|
|
24
|
+
* core stores the upstream session id on that entry at initialize and
|
|
25
|
+
* replays it on every later call. No Mcp-Session-Id plumbing exists here.
|
|
26
|
+
* - A parse error answers with id null (JSON-RPC rule for unparseable
|
|
27
|
+
* input) rather than the HTTP hop's -1: there is no upstream shape to
|
|
28
|
+
* stay byte-compatible with on this transport.
|
|
29
|
+
* - Progress notifications from a streamed tools/call relay to stdout as
|
|
30
|
+
* ordinary JSON-RPC notification lines (MCP stdio allows server → client
|
|
31
|
+
* notifications any time), serialized through the same write queue as
|
|
32
|
+
* responses.
|
|
33
|
+
*
|
|
34
|
+
* Writes are queued (requests dispatch concurrently — a slow search must not
|
|
35
|
+
* stall pings — so responses may become ready out of order, which JSON-RPC
|
|
36
|
+
* ids disambiguate), and each write respects pipe backpressure: a full
|
|
37
|
+
* tools/list line is far larger than PIPE_BUF, so writes must never overlap
|
|
38
|
+
* mid-line. stdin end drains the queue before the run promise resolves, so
|
|
39
|
+
* the caller's exit never truncates a half-written response.
|
|
40
|
+
*/
|
|
41
|
+
import { createInterface } from "node:readline";
|
|
42
|
+
import { ProxyCoreError, toJsonRpcError } from "../core/errors.js";
|
|
43
|
+
import { requestIdOf } from "../core/proxy-core.js";
|
|
44
|
+
import { log } from "../log.js";
|
|
45
|
+
/** stdio serves exactly one client, so the local session key is a constant. */
|
|
46
|
+
const SESSION_KEY = "stdio";
|
|
47
|
+
/**
|
|
48
|
+
* Run the transport until `streams.input` ends (the client closed its pipe —
|
|
49
|
+
* MCP stdio shutdown) or `streams.output` errors (EPIPE: the client died
|
|
50
|
+
* without closing stdin). Resolves void; the caller runs shutdown hooks and
|
|
51
|
+
* exits.
|
|
52
|
+
*/
|
|
53
|
+
export function runStdioTransport(core, streams = { input: process.stdin, output: process.stdout }) {
|
|
54
|
+
let resolveRun;
|
|
55
|
+
const run = new Promise((resolve) => {
|
|
56
|
+
resolveRun = resolve;
|
|
57
|
+
});
|
|
58
|
+
let writeChain = Promise.resolve();
|
|
59
|
+
let finished = false;
|
|
60
|
+
const finish = () => {
|
|
61
|
+
if (finished)
|
|
62
|
+
return;
|
|
63
|
+
finished = true;
|
|
64
|
+
input.close();
|
|
65
|
+
// Drain pending writes before resolving: the caller exits right after,
|
|
66
|
+
// and process.exit would truncate an in-flight line.
|
|
67
|
+
void writeChain.finally(() => resolveRun());
|
|
68
|
+
};
|
|
69
|
+
const enqueue = (message) => {
|
|
70
|
+
writeChain = writeChain
|
|
71
|
+
.then(() => writeLine(streams.output, message))
|
|
72
|
+
.catch((err) => {
|
|
73
|
+
// A failed stdout write means the local client is dying (EPIPE);
|
|
74
|
+
// the output 'error' handler finishes the transport.
|
|
75
|
+
log.warn(`writing to stdout failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
// Relayed SSE progress frames (free tools never stream today, but the
|
|
79
|
+
// relay must exist so the stdio path can never orphan upstream progress).
|
|
80
|
+
const onEvent = (event) => {
|
|
81
|
+
enqueue(event);
|
|
82
|
+
};
|
|
83
|
+
async function handleLine(line) {
|
|
84
|
+
const trimmed = line.trim();
|
|
85
|
+
if (trimmed === "")
|
|
86
|
+
return;
|
|
87
|
+
let message;
|
|
88
|
+
try {
|
|
89
|
+
message = JSON.parse(trimmed);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Unparseable input: the one message answered without forwarding.
|
|
93
|
+
enqueue({
|
|
94
|
+
jsonrpc: "2.0",
|
|
95
|
+
error: { code: -32700, message: "Parse error: Invalid JSON" },
|
|
96
|
+
id: null,
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
if (isNotification(message)) {
|
|
102
|
+
await core.notify(SESSION_KEY, message);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const method = methodOf(message);
|
|
106
|
+
if (method === "initialize") {
|
|
107
|
+
const response = await core.initialize(SESSION_KEY, message, protocolVersionOf(message));
|
|
108
|
+
enqueue(response.body);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (method === "tools/call") {
|
|
112
|
+
const response = await core.forwardStream(SESSION_KEY, message, onEvent);
|
|
113
|
+
enqueue(response.body);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Everything else — ping, tools/list, resources/*, client responses to
|
|
117
|
+
// (never-initiated) server requests, unknown methods, and batch arrays —
|
|
118
|
+
// forwards generically, byte-for-byte the HTTP adapter's fallthrough.
|
|
119
|
+
const response = await core.forward(SESSION_KEY, message);
|
|
120
|
+
enqueue(response.body);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
// Same classification as the HTTP adapter: classified core errors log
|
|
124
|
+
// their message; anything else is a proxy bug (full stack, generic
|
|
125
|
+
// InternalError to the client).
|
|
126
|
+
if (err instanceof ProxyCoreError) {
|
|
127
|
+
log.warn(err.message);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
log.error(`proxy bug (client got a generic InternalError): ${err instanceof Error ? (err.stack ?? err.message) : String(err)}`);
|
|
131
|
+
}
|
|
132
|
+
enqueue(toJsonRpcError(err, requestIdOf(message)).body);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const input = createInterface({ input: streams.input });
|
|
136
|
+
input.on("line", (line) => {
|
|
137
|
+
void handleLine(line);
|
|
138
|
+
});
|
|
139
|
+
input.on("close", finish);
|
|
140
|
+
streams.output.on("error", (err) => {
|
|
141
|
+
log.warn(`stdout error (client went away?): ${err instanceof Error ? err.message : String(err)}`);
|
|
142
|
+
finish();
|
|
143
|
+
});
|
|
144
|
+
return run;
|
|
145
|
+
}
|
|
146
|
+
/** One JSON-RPC message per line; resolves on kernel-buffer flush or drain. */
|
|
147
|
+
function writeLine(output, message) {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
const ok = output.write(`${JSON.stringify(message)}\n`, (err) => err ? reject(err) : resolve());
|
|
150
|
+
if (!ok)
|
|
151
|
+
output.once("drain", () => resolve());
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/** JSON-RPC notification: an object with a method and no id key (upstream's rule). */
|
|
155
|
+
function isNotification(message) {
|
|
156
|
+
return (typeof message === "object" &&
|
|
157
|
+
message !== null &&
|
|
158
|
+
!Array.isArray(message) &&
|
|
159
|
+
typeof message.method === "string" &&
|
|
160
|
+
!("id" in message));
|
|
161
|
+
}
|
|
162
|
+
function methodOf(message) {
|
|
163
|
+
if (typeof message !== "object" || message === null)
|
|
164
|
+
return undefined;
|
|
165
|
+
const method = message.method;
|
|
166
|
+
return typeof method === "string" ? method : undefined;
|
|
167
|
+
}
|
|
168
|
+
/** `initialize.params.protocolVersion`, when the client sent one. */
|
|
169
|
+
function protocolVersionOf(message) {
|
|
170
|
+
if (typeof message !== "object" || message === null)
|
|
171
|
+
return undefined;
|
|
172
|
+
const params = message.params;
|
|
173
|
+
if (typeof params !== "object" || params === null)
|
|
174
|
+
return undefined;
|
|
175
|
+
const version = params.protocolVersion;
|
|
176
|
+
return typeof version === "string" ? version : undefined;
|
|
177
|
+
}
|
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.2.0",
|
|
4
|
+
"description": "Fork of @tiny-fish/mcp exposing only the free TinyFish tools (search, fetch_content) — 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
|
+
}
|