Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/http-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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", {
Expand Down
28 changes: 23 additions & 5 deletions src/mcp/tools/application/applicationCreate.ts
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -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,
Expand All @@ -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,
};
},
});
16 changes: 12 additions & 4 deletions src/mcp/tools/toolFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ export type ToolHandler<T> = (input: T) => Promise<{

// Defines the structure for a tool.
// TShape is the ZodRawShape (the object passed to z.object()).
export interface ToolDefinition<TShape extends ZodRawShape> {
// TOutputShape is the optional output schema ZodRawShape
export interface ToolDefinition<
TShape extends ZodRawShape,
TOutputShape extends ZodRawShape = ZodRawShape,
> {
name: string;
description: string;
schema: ZodObject<TShape>; // The schema must be a ZodObject
outputSchema?: ZodObject<TOutputShape>; // Optional output schema for validation
handler: ToolHandler<z.infer<ZodObject<TShape>>>; // Handler input is inferred from the ZodObject
annotations?: {
title?: string;
Expand All @@ -39,9 +44,12 @@ export function createToolContext(): ToolContext {
};
}

export function createTool<TShape extends import("zod").ZodRawShape>(
definition: ToolDefinition<TShape>
): ToolDefinition<TShape> {
export function createTool<
TShape extends import("zod").ZodRawShape,
TOutputShape extends import("zod").ZodRawShape = import("zod").ZodRawShape,
>(
definition: ToolDefinition<TShape, TOutputShape>
): ToolDefinition<TShape, TOutputShape> {
return {
...definition,
handler: async (input) => {
Expand Down
11 changes: 10 additions & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down