Add Jortt API MCP server
Model Context Protocol server that exposes the full Jortt accounting API as MCP tools, generated from Jortt's OpenAPI specification. - OAuth 2.0 client-credentials auth with token caching and 401 refresh - 82 tools covering customers, invoices, estimates, expenses, projects, bank accounts, reports, labels, ledger accounts and payroll - Spec fetched at build time (with a runtime fetch fallback), so new API operations become new tools automatically with no code changes - Path/query/body parameters handled automatically; request bodies passed under a single `body` argument with a resolved JSON Schema - Readable, stable snake_case tool names derived from method, path and operation summary Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QhaFvGz9gfRg5qDV3ragu
This commit is contained in:
commit
240a53fade
12 changed files with 2057 additions and 0 deletions
31
scripts/fetch-spec.mjs
Normal file
31
scripts/fetch-spec.mjs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env node
|
||||
// Downloads the Jortt OpenAPI specification into src/openapi.json so it can be
|
||||
// bundled with the build. Run automatically by `npm run build`.
|
||||
import { writeFile, mkdir } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const SPEC_URL = process.env.JORTT_OPENAPI_URL || "https://api.jortt.nl/swagger_doc";
|
||||
const target = join(__dirname, "..", "src", "openapi.json");
|
||||
|
||||
async function main() {
|
||||
process.stderr.write(`Fetching Jortt OpenAPI spec from ${SPEC_URL} ...\n`);
|
||||
const res = await fetch(SPEC_URL, { headers: { Accept: "application/json" } });
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
||||
}
|
||||
const spec = await res.json();
|
||||
if (!spec.paths || typeof spec.paths !== "object") {
|
||||
throw new Error("Downloaded file does not look like an OpenAPI spec (no paths).");
|
||||
}
|
||||
await mkdir(dirname(target), { recursive: true });
|
||||
await writeFile(target, JSON.stringify(spec));
|
||||
const count = Object.keys(spec.paths).length;
|
||||
process.stderr.write(`Wrote ${target} (${count} paths).\n`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
process.stderr.write(`Failed to fetch spec: ${err.message}\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue