Files
hapi/cli/src/claude/utils/startHappyServer.ts
T
weishu 4f03f29ac3 docs: rebrand Happy to HAPI and add component documentation
This commit rebrands the project from "Happy" to "HAPI" throughout the codebase, including documentation, comments, logs, and tool references. It also adds comprehensive README files for the server and web components, clarifies the monorepo structure in AGENTS.md and root README.md, and removes the outdated roadmap.md file.

Changes include:
- Rebrand references from Happy to HAPI in CLI, server, and web components
- MCP tool names updated from mcp__happy__ to mcp__hapi__
- Process/service names updated consistently
- New server/README.md with deployment and configuration guide
- New web/README.md with stack and development instructions
- Updated root README.md with quickstart guide
- Updated AGENTS.md with cleaner structure documentation
- Removed cli/roadmap.md (now superseded by documentation)
2025-12-21 18:49:04 +08:00

114 lines
3.4 KiB
TypeScript

/**
* HAPI MCP server
* Provides HAPI CLI specific tools including chat session title management
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { createServer } from "node:http";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { AddressInfo } from "node:net";
import { z } from "zod";
import { logger } from "@/ui/logger";
import { ApiSessionClient } from "@/api/apiSession";
import { randomUUID } from "node:crypto";
export async function startHappyServer(client: ApiSessionClient) {
// Handler that sends title updates via the client
const handler = async (title: string) => {
logger.debug('[hapiMCP] Changing title to:', title);
try {
// Send title as a summary message, similar to title generator
client.sendClaudeSessionMessage({
type: 'summary',
summary: title,
leafUuid: randomUUID()
});
return { success: true };
} catch (error) {
return { success: false, error: String(error) };
}
};
//
// Create the MCP server
//
const mcp = new McpServer({
name: "HAPI MCP",
version: "1.0.0",
});
mcp.registerTool('change_title', {
description: 'Change the title of the current chat session',
title: 'Change Chat Title',
inputSchema: {
title: z.string().describe('The new title for the chat session'),
},
}, async (args) => {
const response = await handler(args.title);
logger.debug('[hapiMCP] Response:', response);
if (response.success) {
return {
content: [
{
type: 'text',
text: `Successfully changed chat title to: "${args.title}"`,
},
],
isError: false,
};
} else {
return {
content: [
{
type: 'text',
text: `Failed to change chat title: ${response.error || 'Unknown error'}`,
},
],
isError: true,
};
}
});
const transport = new StreamableHTTPServerTransport({
// NOTE: Returning session id here will result in claude
// sdk spawn to fail with `Invalid Request: Server already initialized`
sessionIdGenerator: undefined
});
await mcp.connect(transport);
//
// Create the HTTP server
//
const server = createServer(async (req, res) => {
try {
await transport.handleRequest(req, res);
} catch (error) {
logger.debug("Error handling request:", error);
if (!res.headersSent) {
res.writeHead(500).end();
}
}
});
const baseUrl = await new Promise<URL>((resolve) => {
server.listen(0, "127.0.0.1", () => {
const addr = server.address() as AddressInfo;
resolve(new URL(`http://127.0.0.1:${addr.port}`));
});
});
return {
url: baseUrl.toString(),
toolNames: ['change_title'],
stop: () => {
logger.debug('[hapiMCP] Stopping server');
mcp.close();
server.close();
}
}
}