@frihet/mcp-server 1.5.3 → 1.5.5

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
@@ -17,7 +17,7 @@
17
17
  <a href="https://smithery.ai/server/frihet/frihet-mcp"><img src="https://smithery.ai/badge/frihet/frihet-mcp" alt="Smithery installs"></a>
18
18
  <a href="https://registry.modelcontextprotocol.io/?q=io.frihet"><img src="https://img.shields.io/badge/MCP_Registry-io.frihet%2Ferp-4A90D9?style=flat&logo=anthropic&logoColor=white" alt="MCP Registry"></a>
19
19
  <a href="https://github.com/Frihet-io/frihet-mcp/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-18181b?style=flat&labelColor=09090b" alt="license"></a>
20
- <img src="https://img.shields.io/badge/tools-52-18181b?style=flat&labelColor=09090b" alt="52 tools">
20
+ <img src="https://img.shields.io/badge/tools-55-18181b?style=flat&labelColor=09090b" alt="55 tools">
21
21
  <img src="https://img.shields.io/badge/node-%3E%3D18-18181b?style=flat&labelColor=09090b" alt="node >=18">
22
22
  <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-18181b?style=flat&labelColor=09090b" alt="TypeScript"></a>
23
23
  </p>
@@ -33,7 +33,7 @@ You: "Create an invoice for TechStart SL, 40 hours of consulting at 75 EUR/h
33
33
  Claude: Done. Invoice INV-2026-089 created. Total: 3,000.00 EUR + 21% IVA = 3,630.00 EUR.
34
34
  ```
35
35
 
36
- 52 tools. 11 resources. 10 prompts. Structured output on every tool. Zero boilerplate.
36
+ 55 tools. 8 resources. 7 prompts. Structured output on every tool. Zero boilerplate.
37
37
 
38
38
  ---
39
39
 
@@ -161,7 +161,7 @@ Talk to your ERP. These are real prompts, not marketing copy.
161
161
 
162
162
  ## What to expect
163
163
 
164
- This MCP is a **structured data interface** -- you describe what you want in natural language, and the AI creates, queries, or modifies business records in Frihet. All 52 tools are CRUD operations over the REST API.
164
+ This MCP is a **structured data interface** -- you describe what you want in natural language, and the AI creates, queries, or modifies business records in Frihet. All 55 tools are CRUD operations over the REST API.
165
165
 
166
166
  **Works great:**
167
167
 
@@ -188,7 +188,7 @@ If you need to digitize paper invoices or receipts, extract the data first (e.g.
188
188
 
189
189
  ---
190
190
 
191
- ## Tools (52)
191
+ ## Tools (55)
192
192
 
193
193
  ### Invoices (6)
194
194
 
@@ -283,7 +283,7 @@ If you need to digitize paper invoices or receipts, extract the data first (e.g.
283
283
  | `get_quarterly_taxes` | Quarterly tax prep: Modelo 303/130 fields, collected vs deductible, liability |
284
284
  | `duplicate_invoice` | Clone an invoice for recurring billing (copies items/client/tax, starts as draft) |
285
285
 
286
- All 52 tools return **structured output** via `outputSchema` -- typed JSON, not raw text. List tools return paginated results (`{ data, total, limit, offset }`).
286
+ All 55 tools return **structured output** via `outputSchema` -- typed JSON, not raw text. List tools return paginated results (`{ data, total, limit, offset }`).
287
287
 
288
288
  ---
289
289
 
@@ -462,10 +462,12 @@ npm run build # must pass before submitting
462
462
 
463
463
  | Package | What it is |
464
464
  |---------|-----------|
465
- | [`@frihet/mcp-server`](https://www.npmjs.com/package/@frihet/mcp-server) | This MCP server (52 tools, 11 resources, 10 prompts) |
465
+ | [`@frihet/mcp-server`](https://www.npmjs.com/package/@frihet/mcp-server) | This MCP server (55 tools, 8 resources, 7 prompts) |
466
466
  | [`@frihet/sdk`](https://github.com/Frihet-io/frihet-sdk) | TypeScript SDK (`frihet.invoices.create()`) |
467
467
  | [`frihet`](https://www.npmjs.com/package/frihet) | CLI (`frihet invoices list --status overdue`) |
468
+ | [`n8n-nodes-frihet`](https://www.npmjs.com/package/n8n-nodes-frihet) | n8n community node for workflow automation |
468
469
  | [REST API](https://docs.frihet.io/desarrolladores/api-rest) | OpenAPI 3.1 at `api.frihet.io/v1` |
470
+ | [Remote MCP](https://mcp.frihet.io) | Hosted endpoint on Cloudflare Workers (zero install) |
469
471
  | [Webhooks](https://docs.frihet.io/desarrolladores/webhooks) | Real-time events with HMAC-SHA256 |
470
472
 
471
473
  ## Links
package/dist/index.js CHANGED
@@ -14,15 +14,18 @@ import { FrihetClient } from "./client.js";
14
14
  import { registerAllTools } from "./tools/register-all.js";
15
15
  import { registerAllResources } from "./resources/register-all.js";
16
16
  import { registerAllPrompts } from "./prompts/register-all.js";
17
+ import { applyOpenAIProfile, OPENAI_EXCLUDED_COUNT, OPENAI_EXCLUDED_RESOURCE_COUNT } from "./openai-profile.js";
17
18
  import { log } from "./logger.js";
18
19
  import { registerShutdownHook } from "./metrics.js";
19
20
  function main() {
20
21
  const apiKey = process.env.FRIHET_API_KEY;
21
22
  if (!apiKey) {
22
- console.error("Error: FRIHET_API_KEY environment variable is required.\n" +
23
- "Set it in your MCP configuration or export it in your shell.\n\n" +
24
- "Example:\n" +
25
- ' export FRIHET_API_KEY="fri_your_api_key_here"\n');
23
+ console.error("Error: FRIHET_API_KEY environment variable is required.\n\n" +
24
+ "Get your API key:\n" +
25
+ " 1. Create a free account at https://app.frihet.io\n" +
26
+ " 2. Go to Settings > Developers > API Keys\n" +
27
+ " 3. Create a key and add it to your MCP configuration\n\n" +
28
+ "Documentation: https://docs.frihet.io/desarrolladores/mcp-server\n");
26
29
  process.exit(1);
27
30
  }
28
31
  const baseUrl = process.env.FRIHET_API_URL;
@@ -55,7 +58,17 @@ function main() {
55
58
  "11 resources (8 static + 3 live), and 10 workflow prompts for business management " +
56
59
  "with full Spanish tax compliance (IVA, IGIC, IPSI).",
57
60
  });
58
- // Register all 52 tools (36 CRUD + 8 CRM + 4 intelligence + 4 actions)
61
+ // Apply OpenAI-safe profile if enabled (strips sensitive fields, fixes annotations)
62
+ const openaiMode = process.env.FRIHET_OPENAI_MODE === "true";
63
+ if (openaiMode) {
64
+ applyOpenAIProfile(server);
65
+ log({
66
+ level: "info",
67
+ message: `OpenAI safety profile active — ${OPENAI_EXCLUDED_COUNT} tools + ${OPENAI_EXCLUDED_RESOURCE_COUNT} resources excluded, gov IDs + credentials redacted`,
68
+ operation: "startup",
69
+ });
70
+ }
71
+ // Register tools (55 full / 53 in OpenAI mode)
59
72
  registerAllTools(server, client);
60
73
  // Register 11 resources (8 static + 3 dynamic via API)
61
74
  registerAllResources(server, client);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * OpenAI-safe profile for the Frihet MCP server.
3
+ *
4
+ * Activated by FRIHET_OPENAI_MODE=true (env var or Worker binding).
5
+ *
6
+ * Applies transformations to every tool registration to comply with
7
+ * OpenAI's ChatGPT Apps submission requirements:
8
+ *
9
+ * 1. Excludes tools that return highly sensitive fiscal data
10
+ * 2. Corrects openWorldHint for tools that trigger external communication
11
+ * 3. Removes government IDs and credentials from input schemas
12
+ * 4. Redacts sensitive fields from all tool outputs
13
+ * 5. Updates descriptions to reflect modified behavior + openWorldHint justifications
14
+ *
15
+ * The full MCP server (55 tools) remains available for Claude, Cursor,
16
+ * Windsurf, Cline, Codex, and all other MCP clients.
17
+ *
18
+ * OpenAI-safe mode: 53 tools (2 excluded), 0 government IDs in I/O.
19
+ *
20
+ * @see https://developers.openai.com/apps-sdk/app-submission-guidelines
21
+ */
22
+ /**
23
+ * Content-Security-Policy for the OpenAI-safe MCP endpoint.
24
+ * OpenAI requires CSP specifying the exact domains the app fetches from.
25
+ */
26
+ export declare const OPENAI_CSP: string;
27
+ /**
28
+ * Applies the OpenAI-safe profile to an MCP server.
29
+ *
30
+ * Must be called BEFORE registerAllTools() and registerAllResources().
31
+ * Intercepts both registerTool() and registerResource() to apply
32
+ * the profile transformations.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const server = new McpServer({ name: "Frihet", version: "1.5.4" });
37
+ * if (process.env.FRIHET_OPENAI_MODE === "true") {
38
+ * applyOpenAIProfile(server);
39
+ * }
40
+ * registerAllTools(server, client);
41
+ * registerAllResources(server, client);
42
+ * ```
43
+ */
44
+ export declare function applyOpenAIProfile(server: any): void;
45
+ /** Number of tools excluded in OpenAI mode (for logging). */
46
+ export declare const OPENAI_EXCLUDED_COUNT: number;
47
+ /** Number of resources excluded in OpenAI mode (for logging). */
48
+ export declare const OPENAI_EXCLUDED_RESOURCE_COUNT: number;
49
+ //# sourceMappingURL=openai-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-profile.d.ts","sourceRoot":"","sources":["../src/openai-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA2LH;;;GAGG;AACH,eAAO,MAAM,UAAU,QAQkB,CAAC;AAM1C;;;;;;;;;;;;;;;;GAgBG;AAEH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAiGpD;AAED,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,QAA4B,CAAC;AAE/D,iEAAiE;AACjE,eAAO,MAAM,8BAA8B,QAAyB,CAAC"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * OpenAI-safe profile for the Frihet MCP server.
3
+ *
4
+ * Activated by FRIHET_OPENAI_MODE=true (env var or Worker binding).
5
+ *
6
+ * Applies transformations to every tool registration to comply with
7
+ * OpenAI's ChatGPT Apps submission requirements:
8
+ *
9
+ * 1. Excludes tools that return highly sensitive fiscal data
10
+ * 2. Corrects openWorldHint for tools that trigger external communication
11
+ * 3. Removes government IDs and credentials from input schemas
12
+ * 4. Redacts sensitive fields from all tool outputs
13
+ * 5. Updates descriptions to reflect modified behavior + openWorldHint justifications
14
+ *
15
+ * The full MCP server (55 tools) remains available for Claude, Cursor,
16
+ * Windsurf, Cline, Codex, and all other MCP clients.
17
+ *
18
+ * OpenAI-safe mode: 53 tools (2 excluded), 0 government IDs in I/O.
19
+ *
20
+ * @see https://developers.openai.com/apps-sdk/app-submission-guidelines
21
+ */
22
+ const PROFILE = {
23
+ // ── Tools excluded entirely ─────────────────────────────────────────
24
+ // Return restricted data categories that cannot be adequately redacted.
25
+ excludeTools: new Set([
26
+ "get_quarterly_taxes", // Modelo 303/130 tax filing data — sensitive fiscal PII
27
+ "get_invoice_einvoice", // EN16931 XML mandatorily contains seller+buyer NIF/CIF
28
+ ]),
29
+ // ── Annotation corrections ──────────────────────────────────────────
30
+ // openWorldHint MUST be true for tools that cause external side effects.
31
+ annotationOverrides: {
32
+ send_invoice: { openWorldHint: true },
33
+ send_quote: { openWorldHint: true },
34
+ create_webhook: { openWorldHint: true },
35
+ update_webhook: { openWorldHint: true },
36
+ },
37
+ // ── Description overrides ───────────────────────────────────────────
38
+ // Remove references to stripped fields (taxId, secret, to) and include
39
+ // openWorldHint justifications as required by OpenAI review guidelines.
40
+ descriptionOverrides: {
41
+ list_clients: "List all clients/customers with optional pagination. " +
42
+ "Returns contact info and addresses. " +
43
+ "/ Lista todos los clientes con paginacion opcional. " +
44
+ "Devuelve informacion de contacto y direcciones.",
45
+ create_client: "Create a new client/customer. Requires at minimum a name. " +
46
+ "Clients are used when creating invoices and quotes. " +
47
+ "Example: name='Acme Corp', email='billing@acme.com', " +
48
+ "address={street:'Main St 1', city:'Madrid', country:'ES'} " +
49
+ "/ Crea un nuevo cliente. Requiere como minimo un nombre.",
50
+ update_client: "Update an existing client using PATCH semantics. Only the provided fields will be changed. " +
51
+ "Example: id='abc123', email='new@acme.com', phone='+34600123456' " +
52
+ "/ Actualiza un cliente existente. Solo se modifican los campos proporcionados.",
53
+ list_vendors: "List all vendors/suppliers with optional pagination and search. " +
54
+ "Returns contact info and addresses. " +
55
+ "/ Lista todos los proveedores con paginacion y busqueda opcional. " +
56
+ "Devuelve informacion de contacto y direcciones.",
57
+ create_vendor: "Create a new vendor/supplier. Requires at minimum a name. " +
58
+ "Vendors are used when tracking expenses and purchase orders. " +
59
+ "Example: name='Office Supplies Ltd', email='billing@office.com', " +
60
+ "address={street:'Gran Via 1', city:'Madrid', country:'ES'} " +
61
+ "/ Crea un nuevo proveedor. Requiere como minimo un nombre.",
62
+ update_vendor: "Update an existing vendor using PATCH semantics. Only the provided fields will be changed. " +
63
+ "Example: id='abc123', email='new@supplier.com', phone='+34600123456' " +
64
+ "/ Actualiza un proveedor existente. Solo se modifican los campos proporcionados.",
65
+ send_invoice: "Send an invoice to the client via email using the client's stored email address. " +
66
+ "The invoice must exist and should not already be cancelled. " +
67
+ "[openWorldHint: true — triggers email delivery to the client's external email address " +
68
+ "via Frihet's transactional email service] " +
69
+ "/ Envia una factura al cliente por email usando el email almacenado del cliente.",
70
+ send_quote: "Send a quote to the client via email using the client's stored email address. " +
71
+ "The quote must exist and should not already be expired or rejected. " +
72
+ "[openWorldHint: true — triggers email delivery to the client's external email address " +
73
+ "via Frihet's transactional email service] " +
74
+ "/ Envia un presupuesto al cliente por email usando el email almacenado del cliente.",
75
+ create_webhook: "Register a new webhook endpoint. Specify the URL and events to subscribe to. " +
76
+ "Available events: invoice.created, invoice.updated, invoice.paid, invoice.deleted, " +
77
+ "expense.created, expense.updated, expense.deleted, client.created, client.updated, " +
78
+ "quote.created, quote.updated, quote.accepted. " +
79
+ "Example: url='https://example.com/webhook', events=['invoice.created','invoice.paid'] " +
80
+ "[openWorldHint: true — configures Frihet to POST event data to the specified external URL] " +
81
+ "/ Registra un nuevo endpoint de webhook.",
82
+ update_webhook: "Update an existing webhook configuration using PATCH semantics. " +
83
+ "Example: id='abc123', active=false to disable a webhook. " +
84
+ "[openWorldHint: true — can modify the external URL that receives webhook notifications] " +
85
+ "/ Actualiza la configuracion de un webhook.",
86
+ },
87
+ // ── Input fields stripped ──────────────────────────────────────────
88
+ // Government IDs (NIF/CIF/VAT), auth credentials, and unsolicited
89
+ // email address collection removed from input schemas.
90
+ stripInputFields: {
91
+ create_client: ["taxId"], // NIF/CIF/VAT — government-issued identifier
92
+ update_client: ["taxId"],
93
+ create_vendor: ["taxId"],
94
+ update_vendor: ["taxId"],
95
+ send_invoice: ["to"], // Don't solicit email — use client's stored email
96
+ send_quote: ["to"],
97
+ create_webhook: ["secret"], // Signing credential — manage via Frihet web app
98
+ update_webhook: ["secret"],
99
+ },
100
+ // ── Output fields redacted ─────────────────────────────────────────
101
+ // Stripped from structuredContent and text in ALL tool responses.
102
+ // Includes synonyms that the Frihet API may return via .passthrough() schemas.
103
+ redactOutputFields: [
104
+ "taxId", "tax_id", // Primary field name + snake_case variant
105
+ "nif", "cif", "vatNumber", // Spanish/EU synonyms for government tax ID
106
+ "vat_number", "vatId", "vat_id",
107
+ "secret", // Webhook signing credential
108
+ "iban", "bankAccount", // Banking identifiers (if exposed via passthrough)
109
+ "bank_account", "accountNumber",
110
+ ],
111
+ };
112
+ /* ------------------------------------------------------------------ */
113
+ /* Deep field redaction */
114
+ /* ------------------------------------------------------------------ */
115
+ /** Recursively removes named fields from an object/array tree. */
116
+ function deepRedact(obj, fields) {
117
+ if (obj === null || typeof obj !== "object")
118
+ return;
119
+ if (Array.isArray(obj)) {
120
+ for (const item of obj)
121
+ deepRedact(item, fields);
122
+ return;
123
+ }
124
+ const record = obj;
125
+ for (const field of fields) {
126
+ if (field in record)
127
+ delete record[field];
128
+ }
129
+ for (const value of Object.values(record)) {
130
+ deepRedact(value, fields);
131
+ }
132
+ }
133
+ /** Best-effort redaction of JSON field patterns from display text. */
134
+ function redactText(text, fields) {
135
+ let result = text;
136
+ for (const field of fields) {
137
+ // Remove "field": "value", or "field": value patterns
138
+ result = result.replace(new RegExp(`\\s*"${field}"\\s*:\\s*(?:"[^"]*"|null|true|false|\\d+(?:\\.\\d+)?)\\s*,?`, "g"), "");
139
+ }
140
+ // Clean up trailing commas before } or ] left by removals
141
+ return result.replace(/,(\s*[}\]])/g, "$1");
142
+ }
143
+ /* ------------------------------------------------------------------ */
144
+ /* Resources excluded / redacted in OpenAI mode */
145
+ /* ------------------------------------------------------------------ */
146
+ /** Dynamic resources excluded — return too much raw PII to safely redact. */
147
+ const EXCLUDE_RESOURCES = new Set([
148
+ "overdue-invoices", // Returns up to 100 raw invoice objects with client NIF/CIF
149
+ ]);
150
+ /* ------------------------------------------------------------------ */
151
+ /* CSP for the OpenAI Worker */
152
+ /* ------------------------------------------------------------------ */
153
+ /**
154
+ * Content-Security-Policy for the OpenAI-safe MCP endpoint.
155
+ * OpenAI requires CSP specifying the exact domains the app fetches from.
156
+ */
157
+ export const OPENAI_CSP = "default-src 'self'; " +
158
+ "script-src 'self' 'unsafe-inline' https://www.gstatic.com https://apis.google.com; " +
159
+ "style-src 'self' 'unsafe-inline'; " +
160
+ "connect-src 'self' https://api.frihet.io https://us-central1-gen-lang-client-0335716041.cloudfunctions.net " +
161
+ "https://identitytoolkit.googleapis.com https://securetoken.googleapis.com https://www.googleapis.com https://www.gstatic.com; " +
162
+ "frame-src https://accounts.google.com https://github.com https://login.microsoftonline.com; " +
163
+ "img-src 'self' data: https:; " +
164
+ "font-src 'self' https://www.frihet.io";
165
+ /* ------------------------------------------------------------------ */
166
+ /* Profile applicator */
167
+ /* ------------------------------------------------------------------ */
168
+ /**
169
+ * Applies the OpenAI-safe profile to an MCP server.
170
+ *
171
+ * Must be called BEFORE registerAllTools() and registerAllResources().
172
+ * Intercepts both registerTool() and registerResource() to apply
173
+ * the profile transformations.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * const server = new McpServer({ name: "Frihet", version: "1.5.4" });
178
+ * if (process.env.FRIHET_OPENAI_MODE === "true") {
179
+ * applyOpenAIProfile(server);
180
+ * }
181
+ * registerAllTools(server, client);
182
+ * registerAllResources(server, client);
183
+ * ```
184
+ */
185
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
186
+ export function applyOpenAIProfile(server) {
187
+ const fieldsToRedact = PROFILE.redactOutputFields;
188
+ /* ── Intercept registerTool ─────────────────────────────────────── */
189
+ const originalRegisterTool = server.registerTool.bind(server);
190
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
191
+ server.registerTool = (name, config, handler) => {
192
+ // 1. Skip excluded tools entirely
193
+ if (PROFILE.excludeTools.has(name))
194
+ return;
195
+ // 2. Merge annotation overrides
196
+ const annOverrides = PROFILE.annotationOverrides[name];
197
+ if (annOverrides) {
198
+ config.annotations = { ...config.annotations, ...annOverrides };
199
+ }
200
+ // 3. Replace descriptions
201
+ const descOverride = PROFILE.descriptionOverrides[name];
202
+ if (descOverride) {
203
+ config.description = descOverride;
204
+ }
205
+ // 4. Strip sensitive input fields
206
+ const inputStrip = PROFILE.stripInputFields[name];
207
+ if (inputStrip && config.inputSchema) {
208
+ for (const field of inputStrip) {
209
+ delete config.inputSchema[field];
210
+ }
211
+ }
212
+ // 5. Wrap handler to redact sensitive output fields
213
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
214
+ const wrappedHandler = async (input) => {
215
+ const result = await handler(input);
216
+ // Redact structuredContent (programmatic output)
217
+ if (result.structuredContent) {
218
+ deepRedact(result.structuredContent, fieldsToRedact);
219
+ }
220
+ // Best-effort redact text content (display output)
221
+ if (Array.isArray(result.content)) {
222
+ for (const block of result.content) {
223
+ if (block.type === "text" && typeof block.text === "string") {
224
+ block.text = redactText(block.text, fieldsToRedact);
225
+ }
226
+ }
227
+ }
228
+ return result;
229
+ };
230
+ return originalRegisterTool(name, config, wrappedHandler);
231
+ };
232
+ /* ── Intercept registerResource ─────────────────────────────────── */
233
+ const originalRegisterResource = server.registerResource.bind(server);
234
+ // registerResource(name, uri, config, handler) — 4 args
235
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
236
+ server.registerResource = (name, ...rest) => {
237
+ // Skip resources that expose too much raw PII
238
+ if (EXCLUDE_RESOURCES.has(name))
239
+ return;
240
+ // Find the handler (last argument) and wrap it
241
+ const handler = rest[rest.length - 1];
242
+ if (typeof handler === "function") {
243
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
244
+ rest[rest.length - 1] = async (...args) => {
245
+ const result = await handler(...args);
246
+ // Resources return { contents: [{ uri, text?, blob? }] }
247
+ if (result?.contents && Array.isArray(result.contents)) {
248
+ for (const content of result.contents) {
249
+ if (typeof content.text === "string") {
250
+ // Parse JSON, redact, re-serialize for clean removal
251
+ try {
252
+ const parsed = JSON.parse(content.text);
253
+ deepRedact(parsed, fieldsToRedact);
254
+ content.text = JSON.stringify(parsed, null, 2);
255
+ }
256
+ catch {
257
+ // Not JSON — fall back to regex redaction
258
+ content.text = redactText(content.text, fieldsToRedact);
259
+ }
260
+ }
261
+ }
262
+ }
263
+ return result;
264
+ };
265
+ }
266
+ return originalRegisterResource(name, ...rest);
267
+ };
268
+ }
269
+ /** Number of tools excluded in OpenAI mode (for logging). */
270
+ export const OPENAI_EXCLUDED_COUNT = PROFILE.excludeTools.size;
271
+ /** Number of resources excluded in OpenAI mode (for logging). */
272
+ export const OPENAI_EXCLUDED_RESOURCE_COUNT = EXCLUDE_RESOURCES.size;
273
+ //# sourceMappingURL=openai-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-profile.js","sourceRoot":"","sources":["../src/openai-profile.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@frihet/mcp-server",
3
- "version": "1.5.3",
4
- "description": "AI-native MCP server for business management — invoices, expenses, clients, products, quotes, webhooks, CRM. 55 tools with business intelligence. Works with Claude, Cursor, Windsurf, Cline.",
3
+ "version": "1.5.5",
4
+ "description": "AI-native MCP server for business management — invoices, expenses, clients, products, quotes, webhooks, CRM. 55 tools. Remote endpoint at mcp.frihet.io (zero install). Works with Claude, Cursor, Windsurf, Cline.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
@@ -39,6 +39,10 @@
39
39
  "quotes",
40
40
  "saas",
41
41
  "tax-compliance",
42
+ "gemini-cli",
43
+ "freelancer",
44
+ "small-business",
45
+ "business-automation",
42
46
  "verifactu",
43
47
  "webhooks",
44
48
  "windsurf"