@smithery/sdk 1.5.4 → 1.5.6
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/dist/index.d.ts +7 -0
- package/dist/index.js +13 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +3 -0
- package/dist/server/stateful.js +3 -5
- package/dist/server/stateless.d.ts +35 -0
- package/dist/server/stateless.js +108 -0
- package/package.json +1 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./shared/config.js";
|
|
2
|
+
export * from "./shared/patch.js";
|
|
3
|
+
export * from "./client/transport.js";
|
|
4
|
+
export * from "./client/integrations/ai-sdk.js";
|
|
5
|
+
export * from "./client/integrations/wrap-error.js";
|
|
6
|
+
export { createStatefulServer, type StatefulServerOptions, } from "./server/stateful.js";
|
|
7
|
+
export * from "./server/session.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Smithery SDK – Barrel file
|
|
2
|
+
// Central re-exports so that `dist/index.js` & `index.d.ts` are generated.
|
|
3
|
+
// Update this list whenever a new top-level feature is added.
|
|
4
|
+
// Shared utilities
|
|
5
|
+
export * from "./shared/config.js";
|
|
6
|
+
export * from "./shared/patch.js";
|
|
7
|
+
// Client-side helpers
|
|
8
|
+
export * from "./client/transport.js";
|
|
9
|
+
export * from "./client/integrations/ai-sdk.js";
|
|
10
|
+
export * from "./client/integrations/wrap-error.js";
|
|
11
|
+
// Server-side helpers (selective to avoid duplicate type names)
|
|
12
|
+
export { createStatefulServer, } from "./server/stateful.js";
|
|
13
|
+
export * from "./server/session.js";
|
package/dist/server/stateful.js
CHANGED
|
@@ -108,8 +108,8 @@ export function createStatefulServer(createMcpServer, options) {
|
|
|
108
108
|
};
|
|
109
109
|
res.json(configSchema);
|
|
110
110
|
});
|
|
111
|
-
//
|
|
112
|
-
|
|
111
|
+
// Handle GET requests for server-to-client notifications via SSE
|
|
112
|
+
app.get("/mcp", async (req, res) => {
|
|
113
113
|
const sessionId = req.headers["mcp-session-id"];
|
|
114
114
|
if (!sessionId || !sessionStore.get(sessionId)) {
|
|
115
115
|
res.status(400).send("Invalid or expired session ID");
|
|
@@ -118,9 +118,7 @@ export function createStatefulServer(createMcpServer, options) {
|
|
|
118
118
|
// biome-ignore lint/style/noNonNullAssertion: Not possible
|
|
119
119
|
const transport = sessionStore.get(sessionId);
|
|
120
120
|
await transport.handleRequest(req, res);
|
|
121
|
-
};
|
|
122
|
-
// Handle GET requests for server-to-client notifications via SSE
|
|
123
|
-
app.get("/mcp", handleSessionRequest);
|
|
121
|
+
});
|
|
124
122
|
// Handle DELETE requests for session termination
|
|
125
123
|
// https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#session-management
|
|
126
124
|
app.delete("/mcp", async (req, res) => {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Arguments when we create a stateless server instance
|
|
6
|
+
*/
|
|
7
|
+
export interface CreateStatelessServerArg<T = Record<string, unknown>> {
|
|
8
|
+
config: T;
|
|
9
|
+
}
|
|
10
|
+
export type CreateStatelessServerFn<T = Record<string, unknown>> = (arg: CreateStatelessServerArg<T>) => Server;
|
|
11
|
+
/**
|
|
12
|
+
* Configuration options for the stateless server
|
|
13
|
+
*/
|
|
14
|
+
export interface StatelessServerOptions<T = Record<string, unknown>> {
|
|
15
|
+
/**
|
|
16
|
+
* Zod schema for config validation
|
|
17
|
+
*/
|
|
18
|
+
schema?: z.ZodSchema<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Express app instance to use (optional)
|
|
21
|
+
*/
|
|
22
|
+
app?: express.Application;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a stateless server for handling MCP requests.
|
|
26
|
+
* Each request creates a new server instance - no session state is maintained.
|
|
27
|
+
* This is ideal for stateless API integrations and serverless environments.
|
|
28
|
+
*
|
|
29
|
+
* @param createMcpServer Function to create an MCP server
|
|
30
|
+
* @param options Configuration options including optional schema validation and Express app
|
|
31
|
+
* @returns Express app
|
|
32
|
+
*/
|
|
33
|
+
export declare function createStatelessServer<T = Record<string, unknown>>(createMcpServer: CreateStatelessServerFn<T>, options?: StatelessServerOptions<T>): {
|
|
34
|
+
app: express.Application;
|
|
35
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { parseAndValidateConfig } from "../shared/config.js";
|
|
4
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
5
|
+
/**
|
|
6
|
+
* Creates a stateless server for handling MCP requests.
|
|
7
|
+
* Each request creates a new server instance - no session state is maintained.
|
|
8
|
+
* This is ideal for stateless API integrations and serverless environments.
|
|
9
|
+
*
|
|
10
|
+
* @param createMcpServer Function to create an MCP server
|
|
11
|
+
* @param options Configuration options including optional schema validation and Express app
|
|
12
|
+
* @returns Express app
|
|
13
|
+
*/
|
|
14
|
+
export function createStatelessServer(createMcpServer, options) {
|
|
15
|
+
const app = options?.app ?? express();
|
|
16
|
+
app.use("/mcp", express.json());
|
|
17
|
+
// Handle POST requests for client-to-server communication
|
|
18
|
+
app.post("/mcp", async (req, res) => {
|
|
19
|
+
// In stateless mode, create a new instance of transport and server for each request
|
|
20
|
+
// to ensure complete isolation. A single instance would cause request ID collisions
|
|
21
|
+
// when multiple clients connect concurrently.
|
|
22
|
+
try {
|
|
23
|
+
// Validate config for all requests in stateless mode
|
|
24
|
+
const configResult = parseAndValidateConfig(req, options?.schema);
|
|
25
|
+
if (!configResult.ok) {
|
|
26
|
+
const status = configResult.error.status || 400;
|
|
27
|
+
res.status(status).json(configResult.error);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const config = configResult.value;
|
|
31
|
+
// Create a fresh server instance for each request
|
|
32
|
+
const server = createMcpServer({
|
|
33
|
+
config,
|
|
34
|
+
});
|
|
35
|
+
// Create a new transport for this request (no session management)
|
|
36
|
+
const transport = new StreamableHTTPServerTransport({
|
|
37
|
+
sessionIdGenerator: undefined,
|
|
38
|
+
});
|
|
39
|
+
// Clean up resources when request closes
|
|
40
|
+
res.on("close", () => {
|
|
41
|
+
transport.close();
|
|
42
|
+
server.close();
|
|
43
|
+
});
|
|
44
|
+
// Connect to the MCP server
|
|
45
|
+
await server.connect(transport);
|
|
46
|
+
// Handle the request directly
|
|
47
|
+
await transport.handleRequest(req, res, req.body);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error("Error handling MCP request:", error);
|
|
51
|
+
if (!res.headersSent) {
|
|
52
|
+
res.status(500).json({
|
|
53
|
+
jsonrpc: "2.0",
|
|
54
|
+
error: {
|
|
55
|
+
code: -32603,
|
|
56
|
+
message: "Internal server error",
|
|
57
|
+
},
|
|
58
|
+
id: null,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// SSE notifications not supported in stateless mode
|
|
64
|
+
app.get("/mcp", async (_req, res) => {
|
|
65
|
+
res.status(405).json({
|
|
66
|
+
jsonrpc: "2.0",
|
|
67
|
+
error: {
|
|
68
|
+
code: -32000,
|
|
69
|
+
message: "Method not allowed.",
|
|
70
|
+
},
|
|
71
|
+
id: null,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
// Session termination not needed in stateless mode
|
|
75
|
+
app.delete("/mcp", async (_req, res) => {
|
|
76
|
+
res.status(405).json({
|
|
77
|
+
jsonrpc: "2.0",
|
|
78
|
+
error: {
|
|
79
|
+
code: -32000,
|
|
80
|
+
message: "Method not allowed.",
|
|
81
|
+
},
|
|
82
|
+
id: null,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
// Add .well-known/mcp-config endpoint for configuration discovery
|
|
86
|
+
app.get("/.well-known/mcp-config", (req, res) => {
|
|
87
|
+
// Set proper content type for JSON Schema
|
|
88
|
+
res.set("Content-Type", "application/schema+json; charset=utf-8");
|
|
89
|
+
const baseSchema = options?.schema
|
|
90
|
+
? zodToJsonSchema(options.schema)
|
|
91
|
+
: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {},
|
|
94
|
+
required: [],
|
|
95
|
+
};
|
|
96
|
+
const configSchema = {
|
|
97
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
98
|
+
$id: `${req.protocol}://${req.get("host")}/.well-known/mcp-config`,
|
|
99
|
+
title: "MCP Session Configuration",
|
|
100
|
+
description: "Schema for the /mcp endpoint configuration",
|
|
101
|
+
"x-mcp-version": "1.0",
|
|
102
|
+
"x-query-style": "dot+bracket",
|
|
103
|
+
...baseSchema,
|
|
104
|
+
};
|
|
105
|
+
res.json(configSchema);
|
|
106
|
+
});
|
|
107
|
+
return { app };
|
|
108
|
+
}
|