ワンクリックで
add-freee-tool
Automates the standard workflow for adding a new freee MCP tool
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Automates the standard workflow for adding a new freee MCP tool
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | add-freee-tool |
| description | Automates the standard workflow for adding a new freee MCP tool |
| user-invocable | true |
| allowed-tools | ["Bash","Read","Edit","Write","Grep","Glob"] |
| argument-hint | <tool_name> [endpoint_path] |
Automates the 7-step workflow for adding a new MCP tool to the freee-mcp project.
/add-freee-tool freee_get_xxx
/add-freee-tool freee_create_xxx /api/1/xxx
The argument should be the tool name (e.g., freee_get_deals) and optionally the freee API endpoint path.
Check if the endpoint exists in the OpenAPI spec:
SPEC="$(git rev-parse --show-toplevel)/openapi/minimal/accounting.json"
If the file exists, search for the endpoint path:
cat "$SPEC" | jq '.paths["<endpoint_path>"]'
Extract: HTTP method, path parameters, query parameters, response schema.
If the spec file does not exist: warn the user that openapi/minimal/accounting.json is not available, then ask the user to provide the endpoint details (path, method, parameters, response fields) or reference the freee API documentation. Do NOT abort — proceed with user-provided or documentation-based information.
If the endpoint is not found in the spec: warn the user and confirm whether to proceed.
File: src/types/freee.ts
Add a FreeeXxx interface matching the API response structure. Follow snake_case matching the freee API JSON keys.
Pattern reference — read existing interfaces in the file for conventions:
export interface FreeeXxx {
id: number;
company_id: number;
name: string;
// Match freee API response field names (snake_case)
// Use ? for optional fields
created_at?: string;
updated_at?: string;
}
Key conventions:
FreeeXxx (PascalCase with Freee prefix)snake_case matching API response?number, string, boolean, and nested interfaces as appropriateFile: src/api/freeeClient.ts
Add a method to the FreeeClient class. Read the file first to understand existing patterns.
Pattern reference:
async getXxx(companyId: number, params?: { offset?: number; limit?: number }): Promise<{ xxx: FreeeXxx[] }> {
const response = await this.api.get<{ xxx: FreeeXxx[] }>(`/api/1/xxx`, {
params: {
company_id: companyId,
...params,
},
});
return response.data;
}
Key conventions:
getXxx / createXxx / updateXxx / deleteXxxcompanyId: numberthis.api.get/post/put/delete (Axios instance with auth interceptors)response.dataApiCache, CACHE_TTL_*)../types/freee.js if not already importedFile: src/schemas.ts
Add a schema as a plain object (NOT z.object()). Read the file first to see companyIdField, optionalDateField, and other shared helpers.
Pattern reference:
export const GetXxxSchema = {
companyId: companyIdField,
offset: z.number().min(0).optional().describe("Pagination offset"),
limit: z
.number()
.min(1)
.max(100)
.optional()
.describe("Number of results (1-100)"),
};
Key conventions:
GetXxxSchema / CreateXxxSchema (PascalCase)Record<string, z.ZodTypeAny> (plain object, NOT z.object()).describe() with human-readable descriptioncompanyIdField for optional company IDoptionalDateField(description) and dateField(description) for dates.optional() before .describe()File: src/index.ts
Use the registerTool wrapper (NOT server.registerTool()). Read the file first to find the registration section.
Pattern reference:
registerTool(
"freee_get_xxx",
{
description: "Get xxx resources for a company",
inputSchema: schemas.GetXxxSchema,
},
async ({ companyId, offset, limit }) => {
try {
const data = await freeeClient.getXxx(getCompanyId(companyId), {
offset,
limit,
});
return {
content: [
{
type: "text" as const,
text: JSON.stringify(data, null, 2),
},
],
};
} catch (error) {
handleToolError("freee_get_xxx", error);
}
},
);
Key conventions:
freee_ prefix with snake_casetry/catch with handleToolErrorgetCompanyId(companyId) to resolve optional company ID{ content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] }ResponseFormatter methods if applicableAdd tests in the following locations:
File: src/__tests__/handlers.test.ts
Find the expectedSchemas array in the 'Tool Schema Validation' describe block and add the new schema export name (NOT the tool name):
const expectedSchemas = [
// ... existing schemas
"GetXxxSchema", // Add the schema export name (PascalCase), NOT the tool name
];
Also add the new client method to the mockClient object in beforeEach.
File: src/__tests__/api/freeeClient.test.ts
Add a describe block for the new method:
describe("getXxx", () => {
it("should fetch xxx with correct parameters", async () => {
const mockResponse = { xxx: [{ id: 1, name: "Test" }] };
mockAxiosInstance.get.mockResolvedValue({ data: mockResponse });
const result = await client.getXxx(123, { offset: 0, limit: 10 });
expect(mockAxiosInstance.get).toHaveBeenCalledWith("/api/1/xxx", {
params: { company_id: 123, offset: 0, limit: 10 },
});
expect(result).toEqual(mockResponse);
});
});
File: src/__tests__/schemas.test.ts
Add validation tests using safeParse to verify schema constraints. Read the existing test file first to follow its patterns:
describe("GetXxxSchema validation", () => {
const schema = z.object(schemas.GetXxxSchema);
it("should accept valid input", () => {
const result = schema.safeParse({ companyId: 123 });
expect(result.success).toBe(true);
});
it("should accept optional fields", () => {
const result = schema.safeParse({
companyId: 123,
offset: 0,
limit: 10,
});
expect(result.success).toBe(true);
});
});
Run all checks to ensure nothing is broken:
npm run typecheck && npm run lint && npm test
If any step fails, fix the issues before proceeding. Common issues:
src/api/freeeClient.ts or src/index.ts.describe()| Step | File | Purpose |
|---|---|---|
| 1 | openapi/minimal/accounting.json | API endpoint spec (may not exist) |
| 2 | src/types/freee.ts | Type definitions |
| 3 | src/api/freeeClient.ts | API client methods |
| 4 | src/schemas.ts | Zod input schemas |
| 5 | src/index.ts | Tool registration |
| 6a | src/__tests__/handlers.test.ts | Schema existence tests |
| 6b | src/__tests__/api/freeeClient.test.ts | Client method tests |
| 6c | src/__tests__/schemas.test.ts | Schema validation tests |
| 7 | package.json | Verification commands |
These rules are auto-loaded by path matching but are useful references:
.claude/rules/adding-tools.md — Full registerTool pattern and schema conventions.claude/rules/testing.md — Mock patterns for FreeeClient and TokenManager.claude/rules/mcp-tools.md — Tool registration rules.claude/rules/freee-api.md — API constraints (single-use refresh tokens, rate limits)