diff --git a/src/http-server.ts b/src/http-server.ts index d386742..c626d16 100644 --- a/src/http-server.ts +++ b/src/http-server.ts @@ -2,6 +2,7 @@ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; +import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js"; import express from "express"; import { randomUUID } from "node:crypto"; @@ -62,9 +63,7 @@ export async function main() { // Create and connect server first const server = createServer(); // The transport will have sessionId after initialization - await server.connect( - transport as StreamableHTTPServerTransport & { sessionId: string } - ); + await server.connect(transport as Transport); // Log after successful connection logger.info("New MCP session server connected", { diff --git a/src/mcp/tools/application/applicationCreate.ts b/src/mcp/tools/application/applicationCreate.ts index 02f262e..963816f 100644 --- a/src/mcp/tools/application/applicationCreate.ts +++ b/src/mcp/tools/application/applicationCreate.ts @@ -1,7 +1,6 @@ import { z } from "zod"; import apiClient from "../../../utils/apiClient.js"; import { createTool } from "../toolFactory.js"; -import { ResponseFormatter } from "../../../utils/responseFormatter.js"; export const applicationCreate = createTool({ name: "application-create", @@ -29,6 +28,14 @@ export const applicationCreate = createTool({ .optional() .describe("The ID of the server where the application will be deployed."), }), + outputSchema: z.object({ + success: z.boolean().describe("Whether the operation was successful"), + message: z.string().describe("A message describing the result"), + data: z + .record(z.any()) + .optional() + .describe("The application data returned from the API"), + }), annotations: { title: "Create Application", destructiveHint: false, @@ -38,9 +45,20 @@ export const applicationCreate = createTool({ handler: async (input) => { const response = await apiClient.post("/application.create", input); - return ResponseFormatter.success( - `Application "${input.name}" created successfully in environment "${input.environmentId}"`, - response.data - ); + const structuredData = { + success: true, + message: `Application "${input.name}" created successfully in environment "${input.environmentId}"`, + data: response.data, + }; + + return { + content: [ + { + type: "text", + text: JSON.stringify(structuredData, null, 2), + }, + ], + structuredContent: structuredData, + }; }, }); diff --git a/src/mcp/tools/toolFactory.ts b/src/mcp/tools/toolFactory.ts index ceec7f0..d63db53 100644 --- a/src/mcp/tools/toolFactory.ts +++ b/src/mcp/tools/toolFactory.ts @@ -11,10 +11,15 @@ export type ToolHandler = (input: T) => Promise<{ // Defines the structure for a tool. // TShape is the ZodRawShape (the object passed to z.object()). -export interface ToolDefinition { +// TOutputShape is the optional output schema ZodRawShape +export interface ToolDefinition< + TShape extends ZodRawShape, + TOutputShape extends ZodRawShape = ZodRawShape, +> { name: string; description: string; schema: ZodObject; // The schema must be a ZodObject + outputSchema?: ZodObject; // Optional output schema for validation handler: ToolHandler>>; // Handler input is inferred from the ZodObject annotations?: { title?: string; @@ -39,9 +44,12 @@ export function createToolContext(): ToolContext { }; } -export function createTool( - definition: ToolDefinition -): ToolDefinition { +export function createTool< + TShape extends import("zod").ZodRawShape, + TOutputShape extends import("zod").ZodRawShape = import("zod").ZodRawShape, +>( + definition: ToolDefinition +): ToolDefinition { return { ...definition, handler: async (input) => { diff --git a/src/server.ts b/src/server.ts index 1aa357b..cefa7a2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -8,7 +8,16 @@ export function createServer() { }); for (const tool of allTools) { - server.tool(tool.name, tool.description, tool.schema.shape, tool.handler); + server.registerTool( + tool.name, + { + description: tool.description, + inputSchema: tool.schema.shape, + ...(tool.outputSchema && { outputSchema: tool.outputSchema.shape }), + ...(tool.annotations && { annotations: tool.annotations }), + }, + tool.handler + ); } return server;