@ubuligan/server 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/dist/index.d.ts +45 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 jsznpm
|
|
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/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
export { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { Logger, LogLevel } from '@ubuligan/shared';
|
|
4
|
+
export { LogLevel, Logger } from '@ubuligan/shared';
|
|
5
|
+
|
|
6
|
+
interface CreateServerOptions {
|
|
7
|
+
name: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create an MCP server. Returns the SDK `McpServer` directly — register tools,
|
|
12
|
+
* resources and prompts on it with the standard `registerTool` / etc. methods,
|
|
13
|
+
* then boot it with {@link serve}.
|
|
14
|
+
*/
|
|
15
|
+
declare function createMCPServer(opts: CreateServerOptions): McpServer;
|
|
16
|
+
/** Start a server over stdio (Claude Desktop / local MCP clients). */
|
|
17
|
+
declare function startStdio(server: McpServer, logger?: Logger | LogLevel): Promise<void>;
|
|
18
|
+
interface HttpOptions {
|
|
19
|
+
/** Port to listen on. Default 3000. */
|
|
20
|
+
port?: number;
|
|
21
|
+
/** HTTP path the MCP endpoint is mounted at. Default "/mcp". */
|
|
22
|
+
path?: string;
|
|
23
|
+
logger?: Logger | LogLevel;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Start a server over Streamable HTTP (the production transport). Runs in
|
|
27
|
+
* stateless mode: a fresh transport per request. Resolves once listening.
|
|
28
|
+
*/
|
|
29
|
+
declare function startHttp(serverFactory: McpServer | (() => McpServer), opts?: HttpOptions): Promise<{
|
|
30
|
+
port: number;
|
|
31
|
+
close: () => Promise<void>;
|
|
32
|
+
}>;
|
|
33
|
+
interface ServeOptions {
|
|
34
|
+
transport: "stdio" | "http";
|
|
35
|
+
port?: number;
|
|
36
|
+
path?: string;
|
|
37
|
+
logger?: Logger | LogLevel;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Boot a server over the chosen transport. For stdio pass the server instance;
|
|
41
|
+
* for http you may pass a factory to get a fresh server per request.
|
|
42
|
+
*/
|
|
43
|
+
declare function serve(serverOrFactory: McpServer | (() => McpServer), opts: ServeOptions): Promise<void>;
|
|
44
|
+
|
|
45
|
+
export { type CreateServerOptions, type HttpOptions, type ServeOptions, createMCPServer, serve, startHttp, startStdio };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
|
+
import { createConsoleLogger, noopLogger } from "@ubuligan/shared";
|
|
7
|
+
function createMCPServer(opts) {
|
|
8
|
+
return new McpServer({ name: opts.name, version: opts.version ?? "0.1.0" });
|
|
9
|
+
}
|
|
10
|
+
function resolveLogger(logger) {
|
|
11
|
+
if (!logger) return noopLogger;
|
|
12
|
+
return typeof logger === "string" ? createConsoleLogger(logger) : logger;
|
|
13
|
+
}
|
|
14
|
+
async function startStdio(server, logger) {
|
|
15
|
+
const log = resolveLogger(logger);
|
|
16
|
+
await server.connect(new StdioServerTransport());
|
|
17
|
+
log.info("MCP server running on stdio");
|
|
18
|
+
}
|
|
19
|
+
function startHttp(serverFactory, opts = {}) {
|
|
20
|
+
const port = opts.port ?? 3e3;
|
|
21
|
+
const path = opts.path ?? "/mcp";
|
|
22
|
+
const log = resolveLogger(opts.logger);
|
|
23
|
+
const makeServer = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
|
|
24
|
+
const app = express();
|
|
25
|
+
app.use(express.json());
|
|
26
|
+
app.post(path, async (req, res) => {
|
|
27
|
+
const server = makeServer();
|
|
28
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
29
|
+
res.on("close", () => {
|
|
30
|
+
transport.close();
|
|
31
|
+
if (typeof serverFactory === "function") server.close();
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
await server.connect(transport);
|
|
35
|
+
await transport.handleRequest(req, res, req.body);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
log.error("request failed", error instanceof Error ? error.message : String(error));
|
|
38
|
+
if (!res.headersSent) res.status(500).json({ error: "internal error" });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const httpServer = app.listen(port, () => {
|
|
43
|
+
const addr = httpServer.address();
|
|
44
|
+
const actualPort = addr && typeof addr === "object" ? addr.port : port;
|
|
45
|
+
log.info(`MCP server on http://localhost:${actualPort}${path}`);
|
|
46
|
+
resolve({
|
|
47
|
+
port: actualPort,
|
|
48
|
+
close: () => new Promise((res, rej) => httpServer.close((err) => err ? rej(err) : res()))
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function serve(serverOrFactory, opts) {
|
|
54
|
+
if (opts.transport === "http") {
|
|
55
|
+
await startHttp(serverOrFactory, opts);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const server = typeof serverOrFactory === "function" ? serverOrFactory() : serverOrFactory;
|
|
59
|
+
await startStdio(server, opts.logger);
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
McpServer,
|
|
63
|
+
createMCPServer,
|
|
64
|
+
serve,
|
|
65
|
+
startHttp,
|
|
66
|
+
startStdio
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import express from \"express\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { createConsoleLogger, noopLogger, type Logger, type LogLevel } from \"@ubuligan/shared\";\n\nexport type { Logger, LogLevel } from \"@ubuligan/shared\";\n\nexport interface CreateServerOptions {\n name: string;\n version?: string;\n}\n\n/**\n * Create an MCP server. Returns the SDK `McpServer` directly — register tools,\n * resources and prompts on it with the standard `registerTool` / etc. methods,\n * then boot it with {@link serve}.\n */\nexport function createMCPServer(opts: CreateServerOptions): McpServer {\n return new McpServer({ name: opts.name, version: opts.version ?? \"0.1.0\" });\n}\n\nfunction resolveLogger(logger: Logger | LogLevel | undefined): Logger {\n if (!logger) return noopLogger;\n return typeof logger === \"string\" ? createConsoleLogger(logger) : logger;\n}\n\n/** Start a server over stdio (Claude Desktop / local MCP clients). */\nexport async function startStdio(server: McpServer, logger?: Logger | LogLevel): Promise<void> {\n const log = resolveLogger(logger);\n await server.connect(new StdioServerTransport());\n log.info(\"MCP server running on stdio\");\n}\n\nexport interface HttpOptions {\n /** Port to listen on. Default 3000. */\n port?: number;\n /** HTTP path the MCP endpoint is mounted at. Default \"/mcp\". */\n path?: string;\n logger?: Logger | LogLevel;\n}\n\n/**\n * Start a server over Streamable HTTP (the production transport). Runs in\n * stateless mode: a fresh transport per request. Resolves once listening.\n */\nexport function startHttp(\n serverFactory: McpServer | (() => McpServer),\n opts: HttpOptions = {},\n): Promise<{ port: number; close: () => Promise<void> }> {\n const port = opts.port ?? 3000;\n const path = opts.path ?? \"/mcp\";\n const log = resolveLogger(opts.logger);\n const makeServer = typeof serverFactory === \"function\" ? serverFactory : () => serverFactory;\n\n const app = express();\n app.use(express.json());\n\n app.post(path, async (req, res) => {\n const server = makeServer();\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n res.on(\"close\", () => {\n transport.close();\n if (typeof serverFactory === \"function\") server.close();\n });\n try {\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n } catch (error) {\n log.error(\"request failed\", error instanceof Error ? error.message : String(error));\n if (!res.headersSent) res.status(500).json({ error: \"internal error\" });\n }\n });\n\n return new Promise((resolve) => {\n const httpServer = app.listen(port, () => {\n const addr = httpServer.address();\n const actualPort = addr && typeof addr === \"object\" ? addr.port : port;\n log.info(`MCP server on http://localhost:${actualPort}${path}`);\n resolve({\n port: actualPort,\n close: () =>\n new Promise<void>((res, rej) => httpServer.close((err) => (err ? rej(err) : res()))),\n });\n });\n });\n}\n\nexport interface ServeOptions {\n transport: \"stdio\" | \"http\";\n port?: number;\n path?: string;\n logger?: Logger | LogLevel;\n}\n\n/**\n * Boot a server over the chosen transport. For stdio pass the server instance;\n * for http you may pass a factory to get a fresh server per request.\n */\nexport async function serve(\n serverOrFactory: McpServer | (() => McpServer),\n opts: ServeOptions,\n): Promise<void> {\n if (opts.transport === \"http\") {\n await startHttp(serverOrFactory, opts);\n return;\n }\n const server = typeof serverOrFactory === \"function\" ? serverOrFactory() : serverOrFactory;\n await startStdio(server, opts.logger);\n}\n\nexport { McpServer };\n"],"mappings":";AAAC,OAAO,aAAa;AACrB,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,SAAS,qCAAqC;AAC9C,SAAS,qBAAqB,kBAA8C;AAcrE,SAAS,gBAAgB,MAAsC;AACpE,SAAO,IAAI,UAAU,EAAE,MAAM,KAAK,MAAM,SAAS,KAAK,WAAW,QAAQ,CAAC;AAC5E;AAEA,SAAS,cAAc,QAA+C;AACpE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,WAAW,WAAW,oBAAoB,MAAM,IAAI;AACpE;AAGA,eAAsB,WAAW,QAAmB,QAA2C;AAC7F,QAAM,MAAM,cAAc,MAAM;AAChC,QAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AAC/C,MAAI,KAAK,6BAA6B;AACxC;AAcO,SAAS,UACd,eACA,OAAoB,CAAC,GACkC;AACvD,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,MAAM,cAAc,KAAK,MAAM;AACrC,QAAM,aAAa,OAAO,kBAAkB,aAAa,gBAAgB,MAAM;AAE/E,QAAM,MAAM,QAAQ;AACpB,MAAI,IAAI,QAAQ,KAAK,CAAC;AAEtB,MAAI,KAAK,MAAM,OAAO,KAAK,QAAQ;AACjC,UAAM,SAAS,WAAW;AAC1B,UAAM,YAAY,IAAI,8BAA8B,EAAE,oBAAoB,OAAU,CAAC;AACrF,QAAI,GAAG,SAAS,MAAM;AACpB,gBAAU,MAAM;AAChB,UAAI,OAAO,kBAAkB,WAAY,QAAO,MAAM;AAAA,IACxD,CAAC;AACD,QAAI;AACF,YAAM,OAAO,QAAQ,SAAS;AAC9B,YAAM,UAAU,cAAc,KAAK,KAAK,IAAI,IAAI;AAAA,IAClD,SAAS,OAAO;AACd,UAAI,MAAM,kBAAkB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAClF,UAAI,CAAC,IAAI,YAAa,KAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,CAAC;AAAA,IACxE;AAAA,EACF,CAAC;AAED,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,aAAa,IAAI,OAAO,MAAM,MAAM;AACxC,YAAM,OAAO,WAAW,QAAQ;AAChC,YAAM,aAAa,QAAQ,OAAO,SAAS,WAAW,KAAK,OAAO;AAClE,UAAI,KAAK,kCAAkC,UAAU,GAAG,IAAI,EAAE;AAC9D,cAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,MACL,IAAI,QAAc,CAAC,KAAK,QAAQ,WAAW,MAAM,CAAC,QAAS,MAAM,IAAI,GAAG,IAAI,IAAI,CAAE,CAAC;AAAA,MACvF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;AAaA,eAAsB,MACpB,iBACA,MACe;AACf,MAAI,KAAK,cAAc,QAAQ;AAC7B,UAAM,UAAU,iBAAiB,IAAI;AACrC;AAAA,EACF;AACA,QAAM,SAAS,OAAO,oBAAoB,aAAa,gBAAgB,IAAI;AAC3E,QAAM,WAAW,QAAQ,KAAK,MAAM;AACtC;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ubuligan/server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Thin DX layer over the MCP SDK server: create a server and boot it over stdio or Streamable HTTP in one call",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
21
|
+
"express": "^4.21.2",
|
|
22
|
+
"@ubuligan/shared": "^0.1.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/express": "^4.17.21",
|
|
26
|
+
"tsup": "^8.3.5",
|
|
27
|
+
"typescript": "^5.7.2",
|
|
28
|
+
"zod": "^3.23.8"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"author": "jsznpm",
|
|
34
|
+
"homepage": "https://github.com/jsznpm/create-mcp-toolkit#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/jsznpm/create-mcp-toolkit/issues"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/jsznpm/create-mcp-toolkit.git",
|
|
41
|
+
"directory": "packages/server"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"mcp",
|
|
45
|
+
"model-context-protocol",
|
|
46
|
+
"ai",
|
|
47
|
+
"llm",
|
|
48
|
+
"server",
|
|
49
|
+
"stdio",
|
|
50
|
+
"http"
|
|
51
|
+
],
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"typecheck": "tsc --noEmit"
|
|
55
|
+
}
|
|
56
|
+
}
|