#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import dotenv from "dotenv";
import { CorporateNumberClient } from "./clients/CorporateNumberClient.js";
import { LawApiClient } from "./clients/LawApiClient.js";
import { EStatClient } from "./clients/EStatClient.js";
dotenv.config();
const NTA_API_KEY = process.env.NTA_API_KEY || "";
const ESTAT_APP_ID = process.env.ESTAT_APP_ID || "";
const corporateClient = new CorporateNumberClient(NTA_API_KEY);
const lawClient = new LawApiClient();
const estatClient = new EStatClient(ESTAT_APP_ID);
// Define tools
const TOOLS = [
{
name: "list_corporation",
description: "Get corporate information by corporate number",
inputSchema: {
type: "object",
properties: {
corporate_number: {
type: "string",
description: "13-digit corporate number",
},
},
required: ["corporate_number"],
},
},
{
name: "get_law_article",
description: "Get law article text",
inputSchema: {
type: "object",
properties: {
law_name: {
type: "string",
description: "Name of the law (e.g., 法人税法)",
},
article: {
type: "string",
description: "Article number (e.g., 34)",
},
paragraph: {
type: "string",
description: "Paragraph number (e.g., 1)",
},
},
required: ["law_name", "article"],
},
},
{
name: "get_region_stats",
description: "Get regional statistics",
inputSchema: {
type: "object",
properties: {
prefecture: {
type: "string",
description: "Prefecture name (e.g., 石川県)",
},
sector_code: {
type: "string",
description: "Industrial sector code",
},
},
required: ["prefecture"],
},
},
];
const server = new Server(
{
name: "sme-copilot-mcp",
version: "0.1.0",
},
{
capabilities: {
tools: {},
},
}
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: TOOLS,
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === "list_corporation") {
const corporateNumber = String(args?.corporate_number);
if (!corporateNumber) throw new Error("corporate_number is required");
const info = await corporateClient.getCorporateInfo(corporateNumber);
return {
content: [{ type: "text", text: JSON.stringify(info, null, 2) }],
};
} else if (name === "get_law_article") {
const lawName = String(args?.law_name);
const article = String(args?.article);
const paragraph = args?.paragraph ? String(args.paragraph) : "1";
if (!lawName || !article) throw new Error("law_name and article are required");
const info = await lawClient.getLawArticle(lawName, article, paragraph);
return {
content: [{ type: "text", text: JSON.stringify(info, null, 2) }],
};
} else if (name === "get_region_stats") {
const prefecture = String(args?.prefecture);
const sectorCode = args?.sector_code ? String(args.sector_code) : "E"; // Default to E if not provided? Or make it required.
if (!prefecture) throw new Error("prefecture is required");
const info = await estatClient.getRegionStats(prefecture, sectorCode);
return {
content: [{ type: "text", text: JSON.stringify(info, null, 2) }],
};
} else {
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [{ type: "text", text: `Error: ${errorMessage}` }],
isError: true,
};
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("SME Copilot MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});