mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-25 23:35:19 +02:00
Merge branch 'main' into claude/issue-2361-20250817-1626
This commit is contained in:
9
package-lock.json
generated
9
package-lock.json
generated
@@ -5818,7 +5818,7 @@
|
|||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.12.0",
|
"@modelcontextprotocol/sdk": "^1.17.4",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"zod": "^3.23.8",
|
"zod": "^3.23.8",
|
||||||
"zod-to-json-schema": "^3.23.5"
|
"zod-to-json-schema": "^3.23.5"
|
||||||
@@ -5833,9 +5833,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/everything/node_modules/@modelcontextprotocol/sdk": {
|
"src/everything/node_modules/@modelcontextprotocol/sdk": {
|
||||||
"version": "1.12.3",
|
"version": "1.17.4",
|
||||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.3.tgz",
|
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.4.tgz",
|
||||||
"integrity": "sha512-DyVYSOafBvk3/j1Oka4z5BWT8o4AFmoNyZY9pALOm7Lh3GZglR71Co4r4dEUoqDWdDazIZQHBe7J2Nwkg6gHgQ==",
|
"integrity": "sha512-zq24hfuAmmlNZvik0FLI58uE5sriN0WWsQzIlYnzSuKDAHFqJtBFrl/LfB1NLgJT5Y7dEBzaX4yAKqOPrcetaw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.6",
|
"ajv": "^6.12.6",
|
||||||
@@ -5843,6 +5843,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cross-spawn": "^7.0.5",
|
"cross-spawn": "^7.0.5",
|
||||||
"eventsource": "^3.0.2",
|
"eventsource": "^3.0.2",
|
||||||
|
"eventsource-parser": "^3.0.0",
|
||||||
"express": "^5.0.1",
|
"express": "^5.0.1",
|
||||||
"express-rate-limit": "^7.5.0",
|
"express-rate-limit": "^7.5.0",
|
||||||
"pkce-challenge": "^5.0.0",
|
"pkce-challenge": "^5.0.0",
|
||||||
|
|||||||
@@ -89,6 +89,13 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is
|
|||||||
- `structuredContent` field conformant to the output schema
|
- `structuredContent` field conformant to the output schema
|
||||||
- A backward compatible Text Content field, a SHOULD advisory in the specification
|
- A backward compatible Text Content field, a SHOULD advisory in the specification
|
||||||
|
|
||||||
|
11. `listRoots`
|
||||||
|
- Lists the current MCP roots provided by the client
|
||||||
|
- Demonstrates the roots protocol capability even though this server doesn't access files
|
||||||
|
- No inputs required
|
||||||
|
- Returns: List of current roots with their URIs and names, or a message if no roots are set
|
||||||
|
- Shows how servers can interact with the MCP roots protocol
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
The server provides 100 test resources in two formats:
|
The server provides 100 test resources in two formats:
|
||||||
@@ -129,6 +136,18 @@ Resource features:
|
|||||||
- Returns: Multi-turn conversation with an embedded resource reference
|
- Returns: Multi-turn conversation with an embedded resource reference
|
||||||
- Shows how to include resources directly in prompt messages
|
- Shows how to include resources directly in prompt messages
|
||||||
|
|
||||||
|
### Roots
|
||||||
|
|
||||||
|
The server demonstrates the MCP roots protocol capability:
|
||||||
|
|
||||||
|
- Declares `roots: { listChanged: true }` capability to indicate support for roots
|
||||||
|
- Handles `roots/list_changed` notifications from clients
|
||||||
|
- Requests initial roots during server initialization
|
||||||
|
- Provides a `listRoots` tool to display current roots
|
||||||
|
- Logs roots-related events for demonstration purposes
|
||||||
|
|
||||||
|
Note: This server doesn't actually access files, but demonstrates how servers can interact with the roots protocol for clients that need to understand which directories are available for file operations.
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|
||||||
The server sends random-leveled log messages every 15 seconds, e.g.:
|
The server sends random-leveled log messages every 15 seconds, e.g.:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||||
import {
|
import {
|
||||||
CallToolRequestSchema,
|
CallToolRequestSchema,
|
||||||
|
ClientCapabilities,
|
||||||
CompleteRequestSchema,
|
CompleteRequestSchema,
|
||||||
CreateMessageRequest,
|
CreateMessageRequest,
|
||||||
CreateMessageResultSchema,
|
CreateMessageResultSchema,
|
||||||
@@ -12,11 +13,13 @@ import {
|
|||||||
LoggingLevel,
|
LoggingLevel,
|
||||||
ReadResourceRequestSchema,
|
ReadResourceRequestSchema,
|
||||||
Resource,
|
Resource,
|
||||||
|
RootsListChangedNotificationSchema,
|
||||||
SetLevelRequestSchema,
|
SetLevelRequestSchema,
|
||||||
SubscribeRequestSchema,
|
SubscribeRequestSchema,
|
||||||
Tool,
|
Tool,
|
||||||
ToolSchema,
|
ToolSchema,
|
||||||
UnsubscribeRequestSchema,
|
UnsubscribeRequestSchema,
|
||||||
|
type Root,
|
||||||
} from "@modelcontextprotocol/sdk/types.js";
|
} from "@modelcontextprotocol/sdk/types.js";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zodToJsonSchema } from "zod-to-json-schema";
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
||||||
@@ -96,6 +99,8 @@ const GetResourceLinksSchema = z.object({
|
|||||||
.describe("Number of resource links to return (1-10)"),
|
.describe("Number of resource links to return (1-10)"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ListRootsSchema = z.object({});
|
||||||
|
|
||||||
const StructuredContentSchema = {
|
const StructuredContentSchema = {
|
||||||
input: z.object({
|
input: z.object({
|
||||||
location: z
|
location: z
|
||||||
@@ -129,7 +134,8 @@ enum ToolName {
|
|||||||
GET_RESOURCE_REFERENCE = "getResourceReference",
|
GET_RESOURCE_REFERENCE = "getResourceReference",
|
||||||
ELICITATION = "startElicitation",
|
ELICITATION = "startElicitation",
|
||||||
GET_RESOURCE_LINKS = "getResourceLinks",
|
GET_RESOURCE_LINKS = "getResourceLinks",
|
||||||
STRUCTURED_CONTENT = "structuredContent"
|
STRUCTURED_CONTENT = "structuredContent",
|
||||||
|
LIST_ROOTS = "listRoots"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PromptName {
|
enum PromptName {
|
||||||
@@ -158,8 +164,7 @@ export const createServer = () => {
|
|||||||
resources: { subscribe: true },
|
resources: { subscribe: true },
|
||||||
tools: {},
|
tools: {},
|
||||||
logging: {},
|
logging: {},
|
||||||
completions: {},
|
completions: {}
|
||||||
elicitation: {},
|
|
||||||
},
|
},
|
||||||
instructions
|
instructions
|
||||||
}
|
}
|
||||||
@@ -171,6 +176,12 @@ export const createServer = () => {
|
|||||||
|
|
||||||
let logLevel: LoggingLevel = "debug";
|
let logLevel: LoggingLevel = "debug";
|
||||||
let logsUpdateInterval: NodeJS.Timeout | undefined;
|
let logsUpdateInterval: NodeJS.Timeout | undefined;
|
||||||
|
// Store client capabilities
|
||||||
|
let clientCapabilities: ClientCapabilities | undefined;
|
||||||
|
|
||||||
|
// Roots state management
|
||||||
|
let currentRoots: Root[] = [];
|
||||||
|
let clientSupportsRoots = false;
|
||||||
const messages = [
|
const messages = [
|
||||||
{ level: "debug", data: "Debug-level message" },
|
{ level: "debug", data: "Debug-level message" },
|
||||||
{ level: "info", data: "Info-level message" },
|
{ level: "info", data: "Info-level message" },
|
||||||
@@ -511,11 +522,6 @@ export const createServer = () => {
|
|||||||
"Returns a resource reference that can be used by MCP clients",
|
"Returns a resource reference that can be used by MCP clients",
|
||||||
inputSchema: zodToJsonSchema(GetResourceReferenceSchema) as ToolInput,
|
inputSchema: zodToJsonSchema(GetResourceReferenceSchema) as ToolInput,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: ToolName.ELICITATION,
|
|
||||||
description: "Demonstrates the Elicitation feature by asking the user to provide information about their favorite color, number, and pets.",
|
|
||||||
inputSchema: zodToJsonSchema(ElicitationSchema) as ToolInput,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: ToolName.GET_RESOURCE_LINKS,
|
name: ToolName.GET_RESOURCE_LINKS,
|
||||||
description:
|
description:
|
||||||
@@ -530,6 +536,17 @@ export const createServer = () => {
|
|||||||
outputSchema: zodToJsonSchema(StructuredContentSchema.output) as ToolOutput,
|
outputSchema: zodToJsonSchema(StructuredContentSchema.output) as ToolOutput,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
if (clientCapabilities!.roots) tools.push ({
|
||||||
|
name: ToolName.LIST_ROOTS,
|
||||||
|
description:
|
||||||
|
"Lists the current MCP roots provided by the client. Demonstrates the roots protocol capability even though this server doesn't access files.",
|
||||||
|
inputSchema: zodToJsonSchema(ListRootsSchema) as ToolInput,
|
||||||
|
});
|
||||||
|
if (clientCapabilities!.elicitation) tools.push ({
|
||||||
|
name: ToolName.ELICITATION,
|
||||||
|
description: "Demonstrates the Elicitation feature by asking the user to provide information about their favorite color, number, and pets.",
|
||||||
|
inputSchema: zodToJsonSchema(ElicitationSchema) as ToolInput,
|
||||||
|
});
|
||||||
|
|
||||||
return { tools };
|
return { tools };
|
||||||
});
|
});
|
||||||
@@ -791,8 +808,7 @@ export const createServer = () => {
|
|||||||
type: "resource_link",
|
type: "resource_link",
|
||||||
uri: resource.uri,
|
uri: resource.uri,
|
||||||
name: resource.name,
|
name: resource.name,
|
||||||
description: `Resource ${i + 1}: ${
|
description: `Resource ${i + 1}: ${resource.mimeType === "text/plain"
|
||||||
resource.mimeType === "text/plain"
|
|
||||||
? "plaintext resource"
|
? "plaintext resource"
|
||||||
: "binary blob resource"
|
: "binary blob resource"
|
||||||
}`,
|
}`,
|
||||||
@@ -824,6 +840,52 @@ export const createServer = () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === ToolName.LIST_ROOTS) {
|
||||||
|
ListRootsSchema.parse(args);
|
||||||
|
|
||||||
|
if (!clientSupportsRoots) {
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: "The MCP client does not support the roots protocol.\n\n" +
|
||||||
|
"This means the server cannot access information about the client's workspace directories or file system roots."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRoots.length === 0) {
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: "The client supports roots but no roots are currently configured.\n\n" +
|
||||||
|
"This could mean:\n" +
|
||||||
|
"1. The client hasn't provided any roots yet\n" +
|
||||||
|
"2. The client provided an empty roots list\n" +
|
||||||
|
"3. The roots configuration is still being loaded"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootsList = currentRoots.map((root, index) => {
|
||||||
|
return `${index + 1}. ${root.name || 'Unnamed Root'}\n URI: ${root.uri}`;
|
||||||
|
}).join('\n\n');
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: `Current MCP Roots (${currentRoots.length} total):\n\n${rootsList}\n\n` +
|
||||||
|
"Note: This server demonstrates the roots protocol capability but doesn't actually access files. " +
|
||||||
|
"The roots are provided by the MCP client and can be used by servers that need file system access."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`Unknown tool: ${name}`);
|
throw new Error(`Unknown tool: ${name}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -873,6 +935,87 @@ export const createServer = () => {
|
|||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Roots protocol handlers
|
||||||
|
server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {
|
||||||
|
try {
|
||||||
|
// Request the updated roots list from the client
|
||||||
|
const response = await server.listRoots();
|
||||||
|
if (response && 'roots' in response) {
|
||||||
|
currentRoots = response.roots;
|
||||||
|
|
||||||
|
// Log the roots update for demonstration
|
||||||
|
await server.notification({
|
||||||
|
method: "notifications/message",
|
||||||
|
params: {
|
||||||
|
level: "info",
|
||||||
|
logger: "everything-server",
|
||||||
|
data: `Roots updated: ${currentRoots.length} root(s) received from client`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
await server.notification({
|
||||||
|
method: "notifications/message",
|
||||||
|
params: {
|
||||||
|
level: "error",
|
||||||
|
logger: "everything-server",
|
||||||
|
data: `Failed to request roots from client: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle post-initialization setup for roots
|
||||||
|
server.oninitialized = async () => {
|
||||||
|
clientCapabilities = server.getClientCapabilities();
|
||||||
|
|
||||||
|
if (clientCapabilities?.roots) {
|
||||||
|
clientSupportsRoots = true;
|
||||||
|
try {
|
||||||
|
const response = await server.listRoots();
|
||||||
|
if (response && 'roots' in response) {
|
||||||
|
currentRoots = response.roots;
|
||||||
|
|
||||||
|
await server.notification({
|
||||||
|
method: "notifications/message",
|
||||||
|
params: {
|
||||||
|
level: "info",
|
||||||
|
logger: "everything-server",
|
||||||
|
data: `Initial roots received: ${currentRoots.length} root(s) from client`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await server.notification({
|
||||||
|
method: "notifications/message",
|
||||||
|
params: {
|
||||||
|
level: "warning",
|
||||||
|
logger: "everything-server",
|
||||||
|
data: "Client returned no roots set",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
await server.notification({
|
||||||
|
method: "notifications/message",
|
||||||
|
params: {
|
||||||
|
level: "error",
|
||||||
|
logger: "everything-server",
|
||||||
|
data: `Failed to request initial roots from client: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await server.notification({
|
||||||
|
method: "notifications/message",
|
||||||
|
params: {
|
||||||
|
level: "info",
|
||||||
|
logger: "everything-server",
|
||||||
|
data: "Client does not support MCP roots protocol",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const cleanup = async () => {
|
const cleanup = async () => {
|
||||||
if (subsUpdateInterval) clearInterval(subsUpdateInterval);
|
if (subsUpdateInterval) clearInterval(subsUpdateInterval);
|
||||||
if (logsUpdateInterval) clearInterval(logsUpdateInterval);
|
if (logsUpdateInterval) clearInterval(logsUpdateInterval);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"start:streamableHttp": "node dist/streamableHttp.js"
|
"start:streamableHttp": "node dist/streamableHttp.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.12.0",
|
"@modelcontextprotocol/sdk": "^1.17.4",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"zod": "^3.23.8",
|
"zod": "^3.23.8",
|
||||||
"zod-to-json-schema": "^3.23.5"
|
"zod-to-json-schema": "^3.23.5"
|
||||||
|
|||||||
Reference in New Issue
Block a user