Use explicit capabilities lists for now
This commit is contained in:
parent
90e91cdd62
commit
7ab5880569
5 changed files with 179 additions and 83 deletions
29
src/cli.ts
29
src/cli.ts
|
|
@ -17,10 +17,15 @@ import { StdioServerTransport } from "./server/stdio.js";
|
|||
import { ListResourcesResultSchema } from "./types.js";
|
||||
|
||||
async function runClient(url_or_command: string, args: string[]) {
|
||||
const client = new Client({
|
||||
name: "mcp-typescript test client",
|
||||
version: "0.1.0",
|
||||
});
|
||||
const client = new Client(
|
||||
{
|
||||
name: "mcp-typescript test client",
|
||||
version: "0.1.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
let clientTransport;
|
||||
|
||||
|
|
@ -97,10 +102,18 @@ async function runServer(port: number | null) {
|
|||
console.log(`Server running on http://localhost:${port}/sse`);
|
||||
});
|
||||
} else {
|
||||
const server = new Server({
|
||||
name: "mcp-typescript test server",
|
||||
version: "0.1.0",
|
||||
});
|
||||
const server = new Server(
|
||||
{
|
||||
name: "mcp-typescript test server",
|
||||
version: "0.1.0",
|
||||
},
|
||||
{
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
);
|
||||
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
|
|
|
|||
|
|
@ -40,10 +40,15 @@ test("should initialize with matching protocol version", async () => {
|
|||
}),
|
||||
};
|
||||
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
await client.connect(clientTransport);
|
||||
|
||||
|
|
@ -82,10 +87,15 @@ test("should initialize with supported older protocol version", async () => {
|
|||
}),
|
||||
};
|
||||
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
await client.connect(clientTransport);
|
||||
|
||||
|
|
@ -119,10 +129,15 @@ test("should reject unsupported protocol version", async () => {
|
|||
}),
|
||||
};
|
||||
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
await expect(client.connect(clientTransport)).rejects.toThrow(
|
||||
"Server's protocol version is not supported: invalid-version",
|
||||
|
|
@ -132,12 +147,18 @@ test("should reject unsupported protocol version", async () => {
|
|||
});
|
||||
|
||||
test("should respect server capabilities", async () => {
|
||||
const server = new Server({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const server = new Server(
|
||||
{
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
resources: {},
|
||||
tools: {},
|
||||
},
|
||||
);
|
||||
|
||||
server.setRequestHandler(InitializeRequestSchema, (request) => ({
|
||||
server.setRequestHandler(InitializeRequestSchema, (_request) => ({
|
||||
protocolVersion: LATEST_PROTOCOL_VERSION,
|
||||
capabilities: {
|
||||
resources: {},
|
||||
|
|
@ -160,10 +181,15 @@ test("should respect server capabilities", async () => {
|
|||
const [clientTransport, serverTransport] =
|
||||
InMemoryTransport.createLinkedPair();
|
||||
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
client.connect(clientTransport),
|
||||
|
|
@ -231,10 +257,15 @@ test("should typecheck", () => {
|
|||
WeatherRequest,
|
||||
WeatherNotification,
|
||||
WeatherResult
|
||||
>({
|
||||
name: "WeatherClient",
|
||||
version: "1.0.0",
|
||||
});
|
||||
>(
|
||||
{
|
||||
name: "WeatherClient",
|
||||
version: "1.0.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
// Typecheck that only valid weather requests/notifications/results are allowed
|
||||
false &&
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Transport } from "../shared/transport.js";
|
|||
import {
|
||||
CallToolRequest,
|
||||
CallToolResultSchema,
|
||||
ClientCapabilities,
|
||||
ClientNotification,
|
||||
ClientRequest,
|
||||
ClientResult,
|
||||
|
|
@ -75,7 +76,10 @@ export class Client<
|
|||
/**
|
||||
* Initializes this client with the given name and version information.
|
||||
*/
|
||||
constructor(private _clientInfo: Implementation) {
|
||||
constructor(
|
||||
private _clientInfo: Implementation,
|
||||
private _capabilities: ClientCapabilities,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +92,7 @@ export class Client<
|
|||
method: "initialize",
|
||||
params: {
|
||||
protocolVersion: LATEST_PROTOCOL_VERSION,
|
||||
capabilities: {},
|
||||
capabilities: this._capabilities,
|
||||
clientInfo: this._clientInfo,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
ResultSchema,
|
||||
LATEST_PROTOCOL_VERSION,
|
||||
SUPPORTED_PROTOCOL_VERSIONS,
|
||||
CreateMessageRequestSchema,
|
||||
} from "../types.js";
|
||||
import { Transport } from "../shared/transport.js";
|
||||
import { InMemoryTransport } from "../inMemory.js";
|
||||
|
|
@ -39,10 +40,18 @@ test("should accept latest protocol version", async () => {
|
|||
}),
|
||||
};
|
||||
|
||||
const server = new Server({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const server = new Server(
|
||||
{
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
);
|
||||
|
||||
await server.connect(serverTransport);
|
||||
|
||||
|
|
@ -90,10 +99,18 @@ test("should accept supported older protocol version", async () => {
|
|||
}),
|
||||
};
|
||||
|
||||
const server = new Server({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const server = new Server(
|
||||
{
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
);
|
||||
|
||||
await server.connect(serverTransport);
|
||||
|
||||
|
|
@ -140,10 +157,18 @@ test("should handle unsupported protocol version", async () => {
|
|||
}),
|
||||
};
|
||||
|
||||
const server = new Server({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const server = new Server(
|
||||
{
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
);
|
||||
|
||||
await server.connect(serverTransport);
|
||||
|
||||
|
|
@ -166,14 +191,39 @@ test("should handle unsupported protocol version", async () => {
|
|||
});
|
||||
|
||||
test("should respect client capabilities", async () => {
|
||||
const server = new Server({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const server = new Server(
|
||||
{
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
);
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
sampling: {},
|
||||
},
|
||||
);
|
||||
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
// Implement request handler for sampling/createMessage
|
||||
client.setRequestHandler(CreateMessageRequestSchema, async (request) => {
|
||||
// Mock implementation of createMessage
|
||||
return {
|
||||
model: "test-model",
|
||||
role: "assistant",
|
||||
content: {
|
||||
type: "text",
|
||||
text: "This is a test response",
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const [clientTransport, serverTransport] =
|
||||
|
|
@ -184,9 +234,17 @@ test("should respect client capabilities", async () => {
|
|||
server.connect(serverTransport),
|
||||
]);
|
||||
|
||||
expect(server.getClientCapabilities()).toEqual({});
|
||||
expect(server.getClientCapabilities()).toEqual({ sampling: {} });
|
||||
|
||||
// This should throw because roots are not supported by the client
|
||||
// This should work because sampling is supported by the client
|
||||
await expect(
|
||||
server.createMessage({
|
||||
messages: [],
|
||||
maxTokens: 10,
|
||||
}),
|
||||
).resolves.not.toThrow();
|
||||
|
||||
// This should still throw because roots are not supported by the client
|
||||
await expect(server.listRoots()).rejects.toThrow(
|
||||
"Client does not support roots",
|
||||
);
|
||||
|
|
@ -237,10 +295,18 @@ test("should typecheck", () => {
|
|||
WeatherRequest,
|
||||
WeatherNotification,
|
||||
WeatherResult
|
||||
>({
|
||||
name: "WeatherServer",
|
||||
version: "1.0.0",
|
||||
});
|
||||
>(
|
||||
{
|
||||
name: "WeatherServer",
|
||||
version: "1.0.0",
|
||||
},
|
||||
{
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
);
|
||||
|
||||
// Typecheck that only valid weather requests/notifications/results are allowed
|
||||
weatherServer.setRequestHandler(GetWeatherRequestSchema, (request) => {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,10 @@ export class Server<
|
|||
/**
|
||||
* Initializes this server with the given name and version information.
|
||||
*/
|
||||
constructor(private _serverInfo: Implementation) {
|
||||
constructor(
|
||||
private _serverInfo: Implementation,
|
||||
private _capabilities: ServerCapabilities,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.setRequestHandler(InitializeRequestSchema, (request) =>
|
||||
|
|
@ -116,28 +119,7 @@ export class Server<
|
|||
}
|
||||
|
||||
private getCapabilities(): ServerCapabilities {
|
||||
return {
|
||||
prompts: this._requestHandlers.has(
|
||||
ListPromptsRequestSchema.shape.method.value as string,
|
||||
)
|
||||
? {}
|
||||
: undefined,
|
||||
resources: this._requestHandlers.has(
|
||||
ListResourcesRequestSchema.shape.method.value as string,
|
||||
)
|
||||
? {}
|
||||
: undefined,
|
||||
tools: this._requestHandlers.has(
|
||||
ListToolsRequestSchema.shape.method.value as string,
|
||||
)
|
||||
? {}
|
||||
: undefined,
|
||||
logging: this._requestHandlers.has(
|
||||
SetLevelRequestSchema.shape.method.value as string,
|
||||
)
|
||||
? {}
|
||||
: undefined,
|
||||
};
|
||||
return this._capabilities;
|
||||
}
|
||||
|
||||
private assertCapability(
|
||||
|
|
|
|||
Loading…
Reference in a new issue