feat(transport): register all 9 tools and add HTTP transport

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-Claude)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-03-10 17:22:46 +00:00
parent 73e59412b4
commit 0af3af3ff2
5 changed files with 102 additions and 6 deletions

View File

@@ -10,7 +10,8 @@
"dev": "tsx src/index.ts",
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"start:http": "MCP_TRANSPORT=http node dist/index.js"
},
"keywords": [],
"author": "",

View File

@@ -1,13 +1,82 @@
import { createServer as createHttpServer } from 'node:http';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { loadConfig } from './config/index.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { loadConfig, getTransportConfig } from './config/index.js';
import { createServer } from './server.js';
async function readRequestBody(req: IncomingMessage): Promise<unknown> {
const chunks: Buffer[] = [];
for await (const chunk of req) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
const raw = Buffer.concat(chunks).toString('utf-8');
if (!raw) return undefined;
return JSON.parse(raw);
}
async function main(): Promise<void> {
const rawTransport = process.env['MCP_TRANSPORT'];
if (rawTransport && rawTransport !== 'stdio' && rawTransport !== 'http') {
console.error(
`FATAL: Invalid MCP_TRANSPORT '${rawTransport}': must be 'stdio' or 'http'`,
);
process.exit(1);
}
const config = loadConfig();
const server = createServer(config);
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Sage X3 MCP server started (stdio transport)');
const { transport: transportType, httpPort } = getTransportConfig();
if (transportType === 'stdio') {
const server = createServer(config);
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Sage X3 MCP server started (stdio transport)');
} else {
const httpServer = createHttpServer(
async (req: IncomingMessage, res: ServerResponse) => {
if (req.url !== '/mcp') {
res.writeHead(404);
res.end('Not found');
return;
}
try {
const body =
req.method === 'POST' ? await readRequestBody(req) : undefined;
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
const server = createServer(config);
await server.connect(transport);
await transport.handleRequest(req, res, body);
} catch (error) {
if (!res.headersSent) {
res.writeHead(500);
res.end('Internal server error');
}
console.error(
'Request error:',
error instanceof Error ? error.message : String(error),
);
}
},
);
httpServer.listen(httpPort, () => {
console.error(
`Sage X3 MCP server started (HTTP transport on port ${httpPort})`,
);
});
const shutdown = (): void => {
console.error('Shutting down...');
httpServer.close();
process.exit(0);
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
}
}
main().catch((error: unknown) => {

View File

@@ -3,6 +3,14 @@ import type { SageConfig } from './types/index.js';
import { RestClient } from './clients/rest-client.js';
import { SoapClient } from './clients/soap-client.js';
import { registerHealthTool } from './tools/sage-health.js';
import { registerQueryTool } from './tools/sage-query.js';
import { registerReadTool } from './tools/sage-read.js';
import { registerSearchTool } from './tools/sage-search.js';
import { registerListEntitiesTool } from './tools/sage-list-entities.js';
import { registerGetContextTool } from './tools/sage-get-context.js';
import { registerSoapReadTool } from './tools/sage-soap-read.js';
import { registerSoapQueryTool } from './tools/sage-soap-query.js';
import { registerDescribeEntityTool } from './tools/sage-describe-entity.js';
export function createServer(config: SageConfig): McpServer {
const server = new McpServer(
@@ -14,6 +22,14 @@ export function createServer(config: SageConfig): McpServer {
const soapClient = new SoapClient(config);
registerHealthTool(server, restClient, soapClient, config);
registerQueryTool(server, restClient);
registerReadTool(server, restClient);
registerSearchTool(server, restClient);
registerListEntitiesTool(server, restClient);
registerGetContextTool(server, restClient);
registerSoapReadTool(server, soapClient);
registerSoapQueryTool(server, soapClient);
registerDescribeEntityTool(server, soapClient);
return server;
}

9
src/tools/index.ts Normal file
View File

@@ -0,0 +1,9 @@
export { registerHealthTool } from './sage-health.js';
export { registerQueryTool } from './sage-query.js';
export { registerReadTool } from './sage-read.js';
export { registerSearchTool } from './sage-search.js';
export { registerListEntitiesTool } from './sage-list-entities.js';
export { registerGetContextTool } from './sage-get-context.js';
export { registerSoapReadTool } from './sage-soap-read.js';
export { registerSoapQueryTool } from './sage-soap-query.js';
export { registerDescribeEntityTool } from './sage-describe-entity.js';

View File

@@ -5,5 +5,6 @@ export default defineConfig({
globals: true,
environment: 'node',
passWithNoTests: true,
exclude: ['**/node_modules/**', '**/dist/**'],
},
});