freeagent-mcp-server 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,6 +7,7 @@ MCP server for the [FreeAgent](https://www.freeagent.com/) accounting API. Provi
7
7
 
8
8
  ## Features
9
9
 
10
+ - **OAuth2 Authentication** - Built-in browser-based auth flow with automatic token refresh
10
11
  - **Company** - Company info, business categories, tax timeline
11
12
  - **Users** - List, get, create, update, and delete users
12
13
  - **Contacts** - Full CRUD for clients and suppliers
@@ -24,15 +25,36 @@ MCP server for the [FreeAgent](https://www.freeagent.com/) accounting API. Provi
24
25
 
25
26
  ## Prerequisites
26
27
 
27
- You need a FreeAgent account and OAuth2 access token. To get one:
28
-
29
28
  1. Sign up for a [FreeAgent Developer](https://dev.freeagent.com/) account
30
29
  2. Create a sandbox account for testing
31
- 3. Register an application to get OAuth credentials
32
- 4. Complete the OAuth2 authorization flow to obtain an access token
30
+ 3. Register an application in the Developer Dashboard
31
+ 4. Set the **OAuth redirect URI** to `http://localhost:3456/callback`
32
+ 5. Note your **Client ID** and **Client Secret**
33
33
 
34
34
  See the [FreeAgent API Quick Start](https://dev.freeagent.com/docs/quick_start) for detailed instructions.
35
35
 
36
+ ## Getting Started
37
+
38
+ ### 1. Set environment variables
39
+
40
+ ```bash
41
+ export FREEAGENT_CLIENT_ID="your_client_id"
42
+ export FREEAGENT_CLIENT_SECRET="your_client_secret"
43
+ # export FREEAGENT_SANDBOX=false # uncomment for production accounts
44
+ ```
45
+
46
+ ### 2. Authenticate (one-time)
47
+
48
+ ```bash
49
+ npx freeagent-mcp-server auth
50
+ ```
51
+
52
+ This opens your browser to authorize the app. After approval, tokens are saved to `~/.freeagent-mcp/tokens.json` and automatically refreshed when they expire.
53
+
54
+ ### 3. Configure your MCP client
55
+
56
+ See the [Configuration](#configuration) section below.
57
+
36
58
  ## Installation
37
59
 
38
60
  ### Using npx (recommended)
@@ -64,13 +86,13 @@ npm start
64
86
 
65
87
  | Variable | Required | Description |
66
88
  |----------|----------|-------------|
67
- | `FREEAGENT_ACCESS_TOKEN` | Yes | Your FreeAgent OAuth2 access token |
68
- | `FREEAGENT_BASE_URL` | No | API base URL (defaults to `https://api.sandbox.freeagent.com/v2`) |
89
+ | `FREEAGENT_CLIENT_ID` | Yes* | OAuth2 client ID from Developer Dashboard |
90
+ | `FREEAGENT_CLIENT_SECRET` | Yes* | OAuth2 client secret from Developer Dashboard |
91
+ | `FREEAGENT_SANDBOX` | No | Set to `false` for production (defaults to `true`) |
92
+ | `FREEAGENT_ACCESS_TOKEN` | No | Legacy: direct access token (skips stored token flow) |
93
+ | `FREEAGENT_BASE_URL` | No | Override API base URL |
69
94
 
70
- For production, set:
71
- ```
72
- FREEAGENT_BASE_URL=https://api.freeagent.com/v2
73
- ```
95
+ *Not required if using `FREEAGENT_ACCESS_TOKEN` directly.
74
96
 
75
97
  ### Claude Desktop
76
98
 
@@ -83,7 +105,8 @@ Add to your `claude_desktop_config.json`:
83
105
  "command": "npx",
84
106
  "args": ["-y", "freeagent-mcp-server"],
85
107
  "env": {
86
- "FREEAGENT_ACCESS_TOKEN": "your_access_token_here"
108
+ "FREEAGENT_CLIENT_ID": "your_client_id",
109
+ "FREEAGENT_CLIENT_SECRET": "your_client_secret"
87
110
  }
88
111
  }
89
112
  }
@@ -101,7 +124,8 @@ Add to your `.mcp.json`:
101
124
  "command": "npx",
102
125
  "args": ["-y", "freeagent-mcp-server"],
103
126
  "env": {
104
- "FREEAGENT_ACCESS_TOKEN": "your_access_token_here"
127
+ "FREEAGENT_CLIENT_ID": "your_client_id",
128
+ "FREEAGENT_CLIENT_SECRET": "your_client_secret"
105
129
  }
106
130
  }
107
131
  }
@@ -114,8 +138,10 @@ Add to your `.mcp.json`:
114
138
  freeagent-mcp/
115
139
  ├── src/
116
140
  │ ├── index.ts # Entry point, server setup
141
+ │ ├── auth.ts # OAuth2 flow, token storage & refresh
117
142
  │ ├── client.ts # FreeAgent API HTTP client
118
143
  │ ├── utils.ts # Shared utilities (responses, logging)
144
+ │ ├── auth.test.ts # Auth module tests
119
145
  │ ├── client.test.ts # Client tests
120
146
  │ ├── utils.test.ts # Utils tests
121
147
  │ └── tools/
@@ -336,17 +362,23 @@ npm run format
336
362
 
337
363
  ## Troubleshooting
338
364
 
339
- **"Missing required environment variable: FREEAGENT_ACCESS_TOKEN"**
340
- Set the `FREEAGENT_ACCESS_TOKEN` environment variable with a valid OAuth2 access token.
365
+ **"Missing credentials" error on startup**
366
+ Set `FREEAGENT_CLIENT_ID` and `FREEAGENT_CLIENT_SECRET` environment variables, then run `npx freeagent-mcp-server auth` to authenticate.
367
+
368
+ **"No stored tokens found"**
369
+ You need to complete the one-time auth flow first: `npx freeagent-mcp-server auth`
370
+
371
+ **Authentication times out**
372
+ Ensure port 3456 is available and your browser can reach `http://localhost:3456/callback`. Check that your FreeAgent app's redirect URI is set to `http://localhost:3456/callback`.
341
373
 
342
374
  **401 Unauthorized errors**
343
- Your access token may have expired. FreeAgent OAuth tokens expire - you'll need to refresh your token using the OAuth2 refresh flow.
375
+ Your tokens may have been revoked. Re-run `npx freeagent-mcp-server auth` to re-authenticate.
344
376
 
345
377
  **"FreeAgent API error (403)"**
346
378
  Your token may not have the required permission level. Check that your FreeAgent app has the appropriate access scopes.
347
379
 
348
380
  **Sandbox vs Production**
349
- By default the server connects to the FreeAgent sandbox. Set `FREEAGENT_BASE_URL=https://api.freeagent.com/v2` for production.
381
+ By default the server connects to the FreeAgent sandbox. Set `FREEAGENT_SANDBOX=false` for production.
350
382
 
351
383
  **Tool not found**
352
384
  Ensure you're using the correct tool name with the `freeagent_` prefix (e.g., `freeagent_list_invoices`, not `list_invoices`).
@@ -0,0 +1,17 @@
1
+ export interface OAuthConfig {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ sandbox: boolean;
5
+ }
6
+ export interface StoredTokens {
7
+ access_token: string;
8
+ refresh_token: string;
9
+ expires_at: number;
10
+ }
11
+ export declare function getApiBase(sandbox: boolean): string;
12
+ export declare function loadTokens(): StoredTokens | null;
13
+ export declare function saveTokens(tokens: StoredTokens): void;
14
+ export declare function isTokenExpired(tokens: StoredTokens): boolean;
15
+ export declare function refreshAccessToken(config: OAuthConfig, refreshToken: string): Promise<StoredTokens>;
16
+ export declare function getValidAccessToken(config: OAuthConfig): Promise<string>;
17
+ export declare function runAuthFlow(config: OAuthConfig): Promise<void>;
package/build/auth.js ADDED
@@ -0,0 +1,195 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, chmodSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { createServer } from "node:http";
5
+ import { exec } from "node:child_process";
6
+ import { randomBytes } from "node:crypto";
7
+ import { TOKEN_BUFFER_MS } from "./utils.js";
8
+ const TOKEN_DIR = join(homedir(), ".freeagent-mcp");
9
+ const TOKEN_FILE = join(TOKEN_DIR, "tokens.json");
10
+ const CALLBACK_PORT = 3456;
11
+ const AUTH_TIMEOUT_MS = 120_000;
12
+ export function getApiBase(sandbox) {
13
+ return sandbox
14
+ ? "https://api.sandbox.freeagent.com/v2"
15
+ : "https://api.freeagent.com/v2";
16
+ }
17
+ export function loadTokens() {
18
+ try {
19
+ const data = readFileSync(TOKEN_FILE, "utf-8");
20
+ return JSON.parse(data);
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ export function saveTokens(tokens) {
27
+ mkdirSync(TOKEN_DIR, { recursive: true });
28
+ writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2), { mode: 0o600 });
29
+ try {
30
+ chmodSync(TOKEN_FILE, 0o600);
31
+ }
32
+ catch {
33
+ // chmod may fail on some platforms, file was already created with mode
34
+ }
35
+ }
36
+ export function isTokenExpired(tokens) {
37
+ return Date.now() >= tokens.expires_at - TOKEN_BUFFER_MS;
38
+ }
39
+ export async function refreshAccessToken(config, refreshToken) {
40
+ const base = getApiBase(config.sandbox);
41
+ const credentials = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString("base64");
42
+ const response = await fetch(`${base}/token_endpoint`, {
43
+ method: "POST",
44
+ headers: {
45
+ Authorization: `Basic ${credentials}`,
46
+ "Content-Type": "application/x-www-form-urlencoded",
47
+ },
48
+ body: new URLSearchParams({
49
+ grant_type: "refresh_token",
50
+ refresh_token: refreshToken,
51
+ }).toString(),
52
+ });
53
+ if (!response.ok) {
54
+ const text = await response.text();
55
+ throw new Error(`Token refresh failed (${response.status}): ${text}`);
56
+ }
57
+ const data = (await response.json());
58
+ return {
59
+ access_token: data.access_token,
60
+ refresh_token: data.refresh_token,
61
+ expires_at: Date.now() + data.expires_in * 1000,
62
+ };
63
+ }
64
+ let refreshPromise = null;
65
+ export async function getValidAccessToken(config) {
66
+ const tokens = loadTokens();
67
+ if (!tokens) {
68
+ throw new Error("No stored tokens found. Run `npx freeagent-mcp-server auth` to authenticate.");
69
+ }
70
+ if (!isTokenExpired(tokens)) {
71
+ return tokens.access_token;
72
+ }
73
+ // Mutex: if a refresh is already in flight, wait for it
74
+ if (refreshPromise) {
75
+ const refreshed = await refreshPromise;
76
+ return refreshed.access_token;
77
+ }
78
+ try {
79
+ refreshPromise = refreshAccessToken(config, tokens.refresh_token);
80
+ const newTokens = await refreshPromise;
81
+ saveTokens(newTokens);
82
+ return newTokens.access_token;
83
+ }
84
+ finally {
85
+ refreshPromise = null;
86
+ }
87
+ }
88
+ function openBrowser(url) {
89
+ const platform = process.platform;
90
+ const cmd = platform === "darwin"
91
+ ? "open"
92
+ : platform === "win32"
93
+ ? "start"
94
+ : "xdg-open";
95
+ exec(`${cmd} "${url}"`);
96
+ }
97
+ async function exchangeCodeForTokens(config, code) {
98
+ const base = getApiBase(config.sandbox);
99
+ const credentials = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString("base64");
100
+ const response = await fetch(`${base}/token_endpoint`, {
101
+ method: "POST",
102
+ headers: {
103
+ Authorization: `Basic ${credentials}`,
104
+ "Content-Type": "application/x-www-form-urlencoded",
105
+ },
106
+ body: new URLSearchParams({
107
+ grant_type: "authorization_code",
108
+ code,
109
+ redirect_uri: `http://localhost:${CALLBACK_PORT}/callback`,
110
+ }).toString(),
111
+ });
112
+ if (!response.ok) {
113
+ const text = await response.text();
114
+ throw new Error(`Token exchange failed (${response.status}): ${text}`);
115
+ }
116
+ const data = (await response.json());
117
+ return {
118
+ access_token: data.access_token,
119
+ refresh_token: data.refresh_token,
120
+ expires_at: Date.now() + data.expires_in * 1000,
121
+ };
122
+ }
123
+ export async function runAuthFlow(config) {
124
+ const state = randomBytes(16).toString("hex");
125
+ const base = getApiBase(config.sandbox);
126
+ const authUrl = `${base}/approve_app?response_type=code` +
127
+ `&client_id=${encodeURIComponent(config.clientId)}` +
128
+ `&redirect_uri=${encodeURIComponent(`http://localhost:${CALLBACK_PORT}/callback`)}` +
129
+ `&state=${encodeURIComponent(state)}`;
130
+ return new Promise((resolve, reject) => {
131
+ const timeout = setTimeout(() => {
132
+ server.close();
133
+ reject(new Error("Authentication timed out after 120 seconds"));
134
+ }, AUTH_TIMEOUT_MS);
135
+ const server = createServer(async (req, res) => {
136
+ const url = new URL(req.url || "/", `http://localhost:${CALLBACK_PORT}`);
137
+ if (url.pathname !== "/callback") {
138
+ res.writeHead(404);
139
+ res.end("Not found");
140
+ return;
141
+ }
142
+ const returnedState = url.searchParams.get("state");
143
+ const code = url.searchParams.get("code");
144
+ const error = url.searchParams.get("error");
145
+ if (error) {
146
+ res.writeHead(400);
147
+ res.end(`Authentication failed: ${error}`);
148
+ clearTimeout(timeout);
149
+ server.close();
150
+ reject(new Error(`OAuth error: ${error}`));
151
+ return;
152
+ }
153
+ if (returnedState !== state) {
154
+ res.writeHead(400);
155
+ res.end("State mismatch - possible CSRF attack");
156
+ clearTimeout(timeout);
157
+ server.close();
158
+ reject(new Error("OAuth state mismatch"));
159
+ return;
160
+ }
161
+ if (!code) {
162
+ res.writeHead(400);
163
+ res.end("No authorization code received");
164
+ clearTimeout(timeout);
165
+ server.close();
166
+ reject(new Error("No authorization code in callback"));
167
+ return;
168
+ }
169
+ try {
170
+ const tokens = await exchangeCodeForTokens(config, code);
171
+ saveTokens(tokens);
172
+ res.writeHead(200, { "Content-Type": "text/html" });
173
+ res.end("<html><body><h1>Authentication successful!</h1>" +
174
+ "<p>You can close this window and return to your terminal.</p>" +
175
+ "</body></html>");
176
+ clearTimeout(timeout);
177
+ server.close();
178
+ resolve();
179
+ }
180
+ catch (err) {
181
+ res.writeHead(500);
182
+ res.end("Token exchange failed");
183
+ clearTimeout(timeout);
184
+ server.close();
185
+ reject(err);
186
+ }
187
+ });
188
+ server.listen(CALLBACK_PORT, () => {
189
+ console.log(`\nOpening browser for FreeAgent authorization...`);
190
+ console.log(`If the browser doesn't open, visit:\n${authUrl}\n`);
191
+ openBrowser(authUrl);
192
+ });
193
+ });
194
+ }
195
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/build/client.d.ts CHANGED
@@ -4,9 +4,9 @@ export declare class FreeAgentApiError extends Error {
4
4
  constructor(status: number, errorCode: string, message: string);
5
5
  }
6
6
  export declare class FreeAgentClient {
7
- private accessToken;
7
+ private getAccessToken;
8
8
  private baseUrl;
9
- constructor(accessToken: string, baseUrl?: string);
9
+ constructor(tokenOrProvider: string | (() => Promise<string>), baseUrl?: string);
10
10
  get<T = unknown>(path: string, params?: Record<string, string>): Promise<T>;
11
11
  postForm<T = unknown>(path: string, body?: Record<string, string>): Promise<T>;
12
12
  postJson<T = unknown>(path: string, body: unknown): Promise<T>;
package/build/client.js CHANGED
@@ -27,10 +27,13 @@ function encodeFormBody(data) {
27
27
  return new URLSearchParams(data).toString();
28
28
  }
29
29
  export class FreeAgentClient {
30
- accessToken;
30
+ getAccessToken;
31
31
  baseUrl;
32
- constructor(accessToken, baseUrl) {
33
- this.accessToken = accessToken;
32
+ constructor(tokenOrProvider, baseUrl) {
33
+ this.getAccessToken =
34
+ typeof tokenOrProvider === "function"
35
+ ? tokenOrProvider
36
+ : async () => tokenOrProvider;
34
37
  this.baseUrl = baseUrl || DEFAULT_BASE_URL;
35
38
  }
36
39
  async get(path, params) {
@@ -63,8 +66,9 @@ export class FreeAgentClient {
63
66
  url.searchParams.set(k, v);
64
67
  }
65
68
  }
69
+ const accessToken = await this.getAccessToken();
66
70
  const headers = {
67
- Authorization: `Bearer ${this.accessToken}`,
71
+ Authorization: `Bearer ${accessToken}`,
68
72
  Accept: "application/json",
69
73
  "User-Agent": "freeagent-mcp/1.0.0",
70
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/build/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { FreeAgentClient } from "./client.js";
5
+ import { runAuthFlow, getValidAccessToken, getApiBase } from "./auth.js";
5
6
  import { registerCompanyTools } from "./tools/company.js";
6
7
  import { registerUserTools } from "./tools/users.js";
7
8
  import { registerContactTools } from "./tools/contacts.js";
@@ -17,37 +18,84 @@ import { registerBankingTools } from "./tools/banking.js";
17
18
  import { registerCategoryTools } from "./tools/categories.js";
18
19
  import { registerAccountingTools } from "./tools/accounting.js";
19
20
  const FREEAGENT_ACCESS_TOKEN = process.env.FREEAGENT_ACCESS_TOKEN;
21
+ const FREEAGENT_CLIENT_ID = process.env.FREEAGENT_CLIENT_ID;
22
+ const FREEAGENT_CLIENT_SECRET = process.env.FREEAGENT_CLIENT_SECRET;
23
+ const FREEAGENT_SANDBOX = process.env.FREEAGENT_SANDBOX !== "false";
20
24
  const FREEAGENT_BASE_URL = process.env.FREEAGENT_BASE_URL;
21
- if (!FREEAGENT_ACCESS_TOKEN) {
22
- console.error("Missing required environment variable: FREEAGENT_ACCESS_TOKEN");
23
- process.exit(1);
25
+ function buildOAuthConfig() {
26
+ if (FREEAGENT_CLIENT_ID && FREEAGENT_CLIENT_SECRET) {
27
+ return {
28
+ clientId: FREEAGENT_CLIENT_ID,
29
+ clientSecret: FREEAGENT_CLIENT_SECRET,
30
+ sandbox: FREEAGENT_SANDBOX,
31
+ };
32
+ }
33
+ return null;
24
34
  }
25
- const client = new FreeAgentClient(FREEAGENT_ACCESS_TOKEN, FREEAGENT_BASE_URL);
26
- const server = new McpServer({
27
- name: "freeagent-mcp",
28
- version: "1.0.0",
29
- });
30
- registerCompanyTools(server, client);
31
- registerUserTools(server, client);
32
- registerContactTools(server, client);
33
- registerProjectTools(server, client);
34
- registerTaskTools(server, client);
35
- registerTimeslipTools(server, client);
36
- registerInvoiceTools(server, client);
37
- registerEstimateTools(server, client);
38
- registerBillTools(server, client);
39
- registerCreditNoteTools(server, client);
40
- registerExpenseTools(server, client);
41
- registerBankingTools(server, client);
42
- registerCategoryTools(server, client);
43
- registerAccountingTools(server, client);
44
- async function main() {
45
- const transport = new StdioServerTransport();
46
- await server.connect(transport);
47
- console.error("FreeAgent MCP Server running on stdio");
35
+ // Handle `npx freeagent-mcp-server auth` subcommand
36
+ if (process.argv[2] === "auth") {
37
+ const config = buildOAuthConfig();
38
+ if (!config) {
39
+ console.error("Missing FREEAGENT_CLIENT_ID and FREEAGENT_CLIENT_SECRET environment variables.\n" +
40
+ "Set these from your FreeAgent Developer Dashboard app credentials.");
41
+ process.exit(1);
42
+ }
43
+ runAuthFlow(config)
44
+ .then(() => {
45
+ console.log("Authentication complete! Tokens saved.");
46
+ console.log("You can now start the MCP server.");
47
+ process.exit(0);
48
+ })
49
+ .catch((err) => {
50
+ console.error("Authentication failed:", err.message);
51
+ process.exit(1);
52
+ });
53
+ }
54
+ else {
55
+ // Normal server mode
56
+ let client;
57
+ if (FREEAGENT_ACCESS_TOKEN) {
58
+ // Legacy: direct access token
59
+ client = new FreeAgentClient(FREEAGENT_ACCESS_TOKEN, FREEAGENT_BASE_URL);
60
+ }
61
+ else {
62
+ const config = buildOAuthConfig();
63
+ if (!config) {
64
+ console.error("Missing credentials. Provide one of:\n" +
65
+ " 1. FREEAGENT_CLIENT_ID + FREEAGENT_CLIENT_SECRET (recommended)\n" +
66
+ " 2. FREEAGENT_ACCESS_TOKEN (legacy)\n\n" +
67
+ "For option 1, run `npx freeagent-mcp-server auth` first to authenticate.");
68
+ process.exit(1);
69
+ }
70
+ const baseUrl = FREEAGENT_BASE_URL || getApiBase(config.sandbox);
71
+ client = new FreeAgentClient(() => getValidAccessToken(config), baseUrl);
72
+ }
73
+ const server = new McpServer({
74
+ name: "freeagent-mcp",
75
+ version: "1.0.0",
76
+ });
77
+ registerCompanyTools(server, client);
78
+ registerUserTools(server, client);
79
+ registerContactTools(server, client);
80
+ registerProjectTools(server, client);
81
+ registerTaskTools(server, client);
82
+ registerTimeslipTools(server, client);
83
+ registerInvoiceTools(server, client);
84
+ registerEstimateTools(server, client);
85
+ registerBillTools(server, client);
86
+ registerCreditNoteTools(server, client);
87
+ registerExpenseTools(server, client);
88
+ registerBankingTools(server, client);
89
+ registerCategoryTools(server, client);
90
+ registerAccountingTools(server, client);
91
+ async function main() {
92
+ const transport = new StdioServerTransport();
93
+ await server.connect(transport);
94
+ console.error("FreeAgent MCP Server running on stdio");
95
+ }
96
+ main().catch((error) => {
97
+ console.error("Fatal error:", error);
98
+ process.exit(1);
99
+ });
48
100
  }
49
- main().catch((error) => {
50
- console.error("Fatal error:", error);
51
- process.exit(1);
52
- });
53
101
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,sBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;AAClE,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAE1D,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,CAAC;AAE/E,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACzD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "freeagent-mcp-server",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "MCP server for the FreeAgent API",
5
5
  "type": "module",
6
6
  "license": "MIT",