Merge branch 'main' into fix-import-path-in-readme
This commit is contained in:
commit
1e56091c89
5 changed files with 86 additions and 4 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/sdk",
|
||||
"version": "1.11.0",
|
||||
"version": "1.11.1",
|
||||
"description": "Model Context Protocol implementation for TypeScript",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
|
|||
|
|
@ -177,6 +177,31 @@ describe("OAuth Authorization", () => {
|
|||
expect(codeVerifier).toBe("test_verifier");
|
||||
});
|
||||
|
||||
it("includes scope parameter when provided", async () => {
|
||||
const { authorizationUrl } = await startAuthorization(
|
||||
"https://auth.example.com",
|
||||
{
|
||||
clientInformation: validClientInfo,
|
||||
redirectUrl: "http://localhost:3000/callback",
|
||||
scope: "read write profile",
|
||||
}
|
||||
);
|
||||
|
||||
expect(authorizationUrl.searchParams.get("scope")).toBe("read write profile");
|
||||
});
|
||||
|
||||
it("excludes scope parameter when not provided", async () => {
|
||||
const { authorizationUrl } = await startAuthorization(
|
||||
"https://auth.example.com",
|
||||
{
|
||||
clientInformation: validClientInfo,
|
||||
redirectUrl: "http://localhost:3000/callback",
|
||||
}
|
||||
);
|
||||
|
||||
expect(authorizationUrl.searchParams.has("scope")).toBe(false);
|
||||
});
|
||||
|
||||
it("uses metadata authorization_endpoint when provided", async () => {
|
||||
const { authorizationUrl } = await startAuthorization(
|
||||
"https://auth.example.com",
|
||||
|
|
|
|||
|
|
@ -145,7 +145,8 @@ export async function auth(
|
|||
const { authorizationUrl, codeVerifier } = await startAuthorization(serverUrl, {
|
||||
metadata,
|
||||
clientInformation,
|
||||
redirectUrl: provider.redirectUrl
|
||||
redirectUrl: provider.redirectUrl,
|
||||
scope: provider.clientMetadata.scope
|
||||
});
|
||||
|
||||
await provider.saveCodeVerifier(codeVerifier);
|
||||
|
|
@ -202,10 +203,12 @@ export async function startAuthorization(
|
|||
metadata,
|
||||
clientInformation,
|
||||
redirectUrl,
|
||||
scope,
|
||||
}: {
|
||||
metadata?: OAuthMetadata;
|
||||
clientInformation: OAuthClientInformation;
|
||||
redirectUrl: string | URL;
|
||||
scope?: string;
|
||||
},
|
||||
): Promise<{ authorizationUrl: URL; codeVerifier: string }> {
|
||||
const responseType = "code";
|
||||
|
|
@ -246,6 +249,10 @@ export async function startAuthorization(
|
|||
codeChallengeMethod,
|
||||
);
|
||||
authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
|
||||
|
||||
if (scope) {
|
||||
authorizationUrl.searchParams.set("scope", scope);
|
||||
}
|
||||
|
||||
return { authorizationUrl, codeVerifier };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -622,6 +622,53 @@ describe("tool()", () => {
|
|||
});
|
||||
});
|
||||
|
||||
test("should register tool with description, empty params, and annotations", async () => {
|
||||
const mcpServer = new McpServer({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.tool(
|
||||
"test",
|
||||
"A tool with everything but empty params",
|
||||
{},
|
||||
{ title: "Complete Test Tool with empty params", readOnlyHint: true, openWorldHint: false },
|
||||
async () => ({
|
||||
content: [{ type: "text", text: "Test response" }]
|
||||
})
|
||||
);
|
||||
|
||||
const [clientTransport, serverTransport] =
|
||||
InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([
|
||||
client.connect(clientTransport),
|
||||
mcpServer.server.connect(serverTransport),
|
||||
]);
|
||||
|
||||
const result = await client.request(
|
||||
{ method: "tools/list" },
|
||||
ListToolsResultSchema,
|
||||
);
|
||||
|
||||
expect(result.tools).toHaveLength(1);
|
||||
expect(result.tools[0].name).toBe("test");
|
||||
expect(result.tools[0].description).toBe("A tool with everything but empty params");
|
||||
expect(result.tools[0].inputSchema).toMatchObject({
|
||||
type: "object",
|
||||
properties: {}
|
||||
});
|
||||
expect(result.tools[0].annotations).toEqual({
|
||||
title: "Complete Test Tool with empty params",
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
});
|
||||
});
|
||||
|
||||
test("should validate tool args", async () => {
|
||||
const mcpServer = new McpServer({
|
||||
name: "test server",
|
||||
|
|
|
|||
|
|
@ -663,8 +663,11 @@ export class McpServer {
|
|||
// Helper to check if an object is a Zod schema (ZodRawShape)
|
||||
const isZodRawShape = (obj: unknown): obj is ZodRawShape => {
|
||||
if (typeof obj !== "object" || obj === null) return false;
|
||||
// Check that at least one property is a ZodType instance
|
||||
return Object.values(obj as object).some(v => v instanceof ZodType);
|
||||
|
||||
const isEmptyObject = z.object({}).strict().safeParse(obj).success;
|
||||
|
||||
// Check if object is empty or at least one property is a ZodType instance
|
||||
return isEmptyObject || Object.values(obj as object).some(v => v instanceof ZodType);
|
||||
};
|
||||
|
||||
let description: string | undefined;
|
||||
|
|
|
|||
Loading…
Reference in a new issue