@netlinksinc/odoo-mcp 0.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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +37 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/config.d.ts +7 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +59 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/context.d.ts +16 -0
  11. package/dist/context.d.ts.map +1 -0
  12. package/dist/context.js +37 -0
  13. package/dist/context.js.map +1 -0
  14. package/dist/errors.d.ts +10 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +15 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/logger.d.ts +26 -0
  23. package/dist/logger.d.ts.map +1 -0
  24. package/dist/logger.js +57 -0
  25. package/dist/logger.js.map +1 -0
  26. package/dist/probe.d.ts +19 -0
  27. package/dist/probe.d.ts.map +1 -0
  28. package/dist/probe.js +181 -0
  29. package/dist/probe.js.map +1 -0
  30. package/dist/resources.d.ts +11 -0
  31. package/dist/resources.d.ts.map +1 -0
  32. package/dist/resources.js +37 -0
  33. package/dist/resources.js.map +1 -0
  34. package/dist/server.d.ts +20 -0
  35. package/dist/server.d.ts.map +1 -0
  36. package/dist/server.js +32 -0
  37. package/dist/server.js.map +1 -0
  38. package/dist/tools/action.d.ts +6 -0
  39. package/dist/tools/action.d.ts.map +1 -0
  40. package/dist/tools/action.js +158 -0
  41. package/dist/tools/action.js.map +1 -0
  42. package/dist/tools/execute.d.ts +6 -0
  43. package/dist/tools/execute.d.ts.map +1 -0
  44. package/dist/tools/execute.js +156 -0
  45. package/dist/tools/execute.js.map +1 -0
  46. package/dist/tools/index.d.ts +5 -0
  47. package/dist/tools/index.d.ts.map +1 -0
  48. package/dist/tools/index.js +13 -0
  49. package/dist/tools/index.js.map +1 -0
  50. package/dist/tools/introspect.d.ts +6 -0
  51. package/dist/tools/introspect.d.ts.map +1 -0
  52. package/dist/tools/introspect.js +155 -0
  53. package/dist/tools/introspect.js.map +1 -0
  54. package/dist/tools/orm.d.ts +16 -0
  55. package/dist/tools/orm.d.ts.map +1 -0
  56. package/dist/tools/orm.js +139 -0
  57. package/dist/tools/orm.js.map +1 -0
  58. package/dist/tools/report.d.ts +6 -0
  59. package/dist/tools/report.d.ts.map +1 -0
  60. package/dist/tools/report.js +99 -0
  61. package/dist/tools/report.js.map +1 -0
  62. package/dist/tools/schemas.d.ts +202 -0
  63. package/dist/tools/schemas.d.ts.map +1 -0
  64. package/dist/tools/schemas.js +77 -0
  65. package/dist/tools/schemas.js.map +1 -0
  66. package/package.json +56 -0
@@ -0,0 +1,139 @@
1
+ import { OdooError, sanitizeArgs } from '@netlinksinc/odoo-client';
2
+ import { buildContext, validateCompanySubset } from '../context.js';
3
+ import { formatMcpError } from '../errors.js';
4
+ import { createSchema, readSchema, searchCountSchema, searchReadSchema, unlinkSchema, writeSchema, } from './schemas.js';
5
+ /**
6
+ * Central handler for all ORM tool invocations.
7
+ *
8
+ * Sequence:
9
+ * 1. Parse/validate args with the schema (returns isError on failure).
10
+ * 2. Validate allowed_company_ids against session (returns isError on failure).
11
+ * 3. Build Odoo RPC context.
12
+ * 4. Execute the client method.
13
+ * 5. Return serialised result or formatted OdooError.
14
+ *
15
+ * The callback is registered with the 2-arg overload `server.tool(name, cb)` so
16
+ * that tests can drive it via a simple mock that stores and directly calls `cb`.
17
+ * Inside the callback we perform our own safeParse so validation failures produce
18
+ * `isError: true` (not a thrown McpError as the SDK's schema-overload would do).
19
+ */
20
+ async function executeHandler(tool, args, schema, exec, logger, session) {
21
+ const t0 = Date.now();
22
+ try {
23
+ const parsed = schema.safeParse(args);
24
+ if (!parsed.success) {
25
+ const text = JSON.stringify({
26
+ error_type: 'InputValidationError',
27
+ message: parsed.error.message,
28
+ });
29
+ logger.toolCall({
30
+ tool,
31
+ args_sanitized: sanitizeArgs(tool, args),
32
+ latency_ms: Date.now() - t0,
33
+ status: 'error',
34
+ error: 'InputValidationError',
35
+ });
36
+ return { content: [{ type: 'text', text }], isError: true };
37
+ }
38
+ // Company-subset enforcement (US-7 AC-7).
39
+ const data = parsed.data;
40
+ if (data.allowed_company_ids) {
41
+ validateCompanySubset(data.allowed_company_ids, session.allowedCompanyIds);
42
+ }
43
+ const context = buildContext(session, {
44
+ allowed_company_ids: data.allowed_company_ids,
45
+ active_company_id: data.active_company_id,
46
+ });
47
+ const result = await exec(parsed.data, context);
48
+ logger.toolCall({
49
+ tool,
50
+ args_sanitized: sanitizeArgs(tool, args),
51
+ latency_ms: Date.now() - t0,
52
+ status: 'ok',
53
+ });
54
+ return { content: [{ type: 'text', text: JSON.stringify(result) }], isError: false };
55
+ }
56
+ catch (e) {
57
+ if (e instanceof OdooError) {
58
+ const formatted = formatMcpError(e);
59
+ logger.toolCall({
60
+ tool,
61
+ args_sanitized: sanitizeArgs(tool, args),
62
+ latency_ms: Date.now() - t0,
63
+ status: 'error',
64
+ error: formatted.error_type,
65
+ });
66
+ return { content: [{ type: 'text', text: JSON.stringify(formatted) }], isError: true };
67
+ }
68
+ // Non-OdooError — unexpected exception. Log + return as InternalError-shaped.
69
+ const message = e instanceof Error ? e.message : String(e);
70
+ logger.toolCall({
71
+ tool,
72
+ args_sanitized: sanitizeArgs(tool, args),
73
+ latency_ms: Date.now() - t0,
74
+ status: 'error',
75
+ error: 'InternalError',
76
+ });
77
+ return {
78
+ content: [
79
+ {
80
+ type: 'text',
81
+ text: JSON.stringify({
82
+ error_type: 'InternalError',
83
+ message: 'unexpected error',
84
+ detail: message,
85
+ }),
86
+ },
87
+ ],
88
+ isError: true,
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Register all 6 ORM tools on the MCP server.
94
+ *
95
+ * Tools registered: odoo_search_read, odoo_read, odoo_create, odoo_write,
96
+ * odoo_unlink, odoo_search_count.
97
+ *
98
+ * The server.tool(name, cb) 2-arg overload is used deliberately so that
99
+ * validation failures return `isError: true` rather than a thrown McpError.
100
+ * Tests drive the handlers via a lightweight mock that stores the callback.
101
+ */
102
+ export function registerOrmTools(server, client, session, logger) {
103
+ // -------------------------------------------------------------------------
104
+ // odoo_search_read
105
+ // -------------------------------------------------------------------------
106
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK no-schema tool() overload signature mismatch
107
+ server.tool('odoo_search_read', async (args) => executeHandler('odoo_search_read', args, searchReadSchema, (parsed, context) => client.searchRead(parsed.model, parsed.domain, parsed.fields, {
108
+ limit: parsed.limit,
109
+ offset: parsed.offset,
110
+ order: parsed.order,
111
+ context,
112
+ }), logger, session));
113
+ // -------------------------------------------------------------------------
114
+ // odoo_read
115
+ // -------------------------------------------------------------------------
116
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK no-schema tool() overload signature mismatch
117
+ server.tool('odoo_read', async (args) => executeHandler('odoo_read', args, readSchema, (parsed, context) => client.read(parsed.model, parsed.ids, parsed.fields, context), logger, session));
118
+ // -------------------------------------------------------------------------
119
+ // odoo_create
120
+ // -------------------------------------------------------------------------
121
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK no-schema tool() overload signature mismatch
122
+ server.tool('odoo_create', async (args) => executeHandler('odoo_create', args, createSchema, (parsed, context) => client.create(parsed.model, parsed.values, context), logger, session));
123
+ // -------------------------------------------------------------------------
124
+ // odoo_write
125
+ // -------------------------------------------------------------------------
126
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK no-schema tool() overload signature mismatch
127
+ server.tool('odoo_write', async (args) => executeHandler('odoo_write', args, writeSchema, (parsed, context) => client.write(parsed.model, parsed.ids, parsed.values, context), logger, session));
128
+ // -------------------------------------------------------------------------
129
+ // odoo_unlink
130
+ // -------------------------------------------------------------------------
131
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK no-schema tool() overload signature mismatch
132
+ server.tool('odoo_unlink', async (args) => executeHandler('odoo_unlink', args, unlinkSchema, (parsed, context) => client.unlink(parsed.model, parsed.ids, context), logger, session));
133
+ // -------------------------------------------------------------------------
134
+ // odoo_search_count
135
+ // -------------------------------------------------------------------------
136
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK no-schema tool() overload signature mismatch
137
+ server.tool('odoo_search_count', async (args) => executeHandler('odoo_search_count', args, searchCountSchema, (parsed, context) => client.searchCount(parsed.model, parsed.domain, context), logger, session));
138
+ }
139
+ //# sourceMappingURL=orm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orm.js","sourceRoot":"","sources":["../../src/tools/orm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type OdooSession } from '@netlinksinc/odoo-client';
3
+ import type { OdooClient } from '@netlinksinc/odoo-client';
4
+ import type { Logger } from '../logger.js';
5
+ export declare function registerReportTool(server: McpServer, client: OdooClient, session: OdooSession, logger: Logger): void;
6
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/tools/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAA2B,KAAK,WAAW,EAAgB,MAAM,0BAA0B,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CA0GN"}
@@ -0,0 +1,99 @@
1
+ import { OdooError, sanitizeArgs } from '@netlinksinc/odoo-client';
2
+ import { buildContext, validateCompanySubset } from '../context.js';
3
+ import { formatMcpError } from '../errors.js';
4
+ import { runReportSchema } from './schemas.js';
5
+ export function registerReportTool(server, client, session, logger) {
6
+ server.tool('odoo_run_report', async (args) => {
7
+ const t0 = Date.now();
8
+ const toolName = 'odoo_run_report';
9
+ const parsed = runReportSchema.safeParse(args);
10
+ if (!parsed.success) {
11
+ const errorPayload = {
12
+ error_type: 'InputValidationError',
13
+ message: parsed.error.message,
14
+ };
15
+ logger.toolCall({
16
+ tool: toolName,
17
+ args_sanitized: sanitizeArgs(toolName, args),
18
+ latency_ms: Date.now() - t0,
19
+ status: 'error',
20
+ error: 'InputValidationError',
21
+ });
22
+ return {
23
+ isError: true,
24
+ content: [{ type: 'text', text: JSON.stringify(errorPayload) }],
25
+ };
26
+ }
27
+ const data = parsed.data;
28
+ try {
29
+ if (data.allowed_company_ids !== undefined) {
30
+ validateCompanySubset(data.allowed_company_ids, session.allowedCompanyIds);
31
+ }
32
+ const context = buildContext(session, {
33
+ allowed_company_ids: data.allowed_company_ids,
34
+ active_company_id: data.active_company_id,
35
+ });
36
+ const { content, contentType } = await client.runReport(data.report_id, data.doc_ids, context);
37
+ const latency_ms = Date.now() - t0;
38
+ logger.toolCall({
39
+ tool: toolName,
40
+ args_sanitized: sanitizeArgs(toolName, args),
41
+ latency_ms,
42
+ status: 'ok',
43
+ });
44
+ return {
45
+ isError: false,
46
+ content: [
47
+ {
48
+ type: 'text',
49
+ text: JSON.stringify({ content, contentType }),
50
+ },
51
+ ],
52
+ };
53
+ }
54
+ catch (e) {
55
+ const latency_ms = Date.now() - t0;
56
+ if (e instanceof OdooError) {
57
+ logger.toolCall({
58
+ tool: toolName,
59
+ args_sanitized: sanitizeArgs(toolName, args),
60
+ latency_ms,
61
+ status: 'error',
62
+ error: e.message,
63
+ });
64
+ return {
65
+ isError: true,
66
+ content: [
67
+ {
68
+ type: 'text',
69
+ text: JSON.stringify(formatMcpError(e)),
70
+ },
71
+ ],
72
+ };
73
+ }
74
+ // Non-OdooError — unexpected exception. Log + return as InternalError-shaped.
75
+ const message = e instanceof Error ? e.message : String(e);
76
+ logger.toolCall({
77
+ tool: toolName,
78
+ args_sanitized: sanitizeArgs(toolName, args),
79
+ latency_ms,
80
+ status: 'error',
81
+ error: 'InternalError',
82
+ });
83
+ return {
84
+ isError: true,
85
+ content: [
86
+ {
87
+ type: 'text',
88
+ text: JSON.stringify({
89
+ error_type: 'InternalError',
90
+ message: 'unexpected error',
91
+ detail: message,
92
+ }),
93
+ },
94
+ ],
95
+ };
96
+ }
97
+ });
98
+ }
99
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/tools/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,202 @@
1
+ import { z } from 'zod';
2
+ export declare const searchReadSchema: z.ZodObject<{
3
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
4
+ active_company_id: z.ZodOptional<z.ZodNumber>;
5
+ model: z.ZodString;
6
+ domain: z.ZodDefault<z.ZodArray<z.ZodUnknown, "many">>;
7
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
8
+ limit: z.ZodDefault<z.ZodNumber>;
9
+ offset: z.ZodDefault<z.ZodNumber>;
10
+ order: z.ZodOptional<z.ZodString>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ limit: number;
13
+ model: string;
14
+ domain: unknown[];
15
+ fields: string[];
16
+ offset: number;
17
+ allowed_company_ids?: number[] | undefined;
18
+ order?: string | undefined;
19
+ active_company_id?: number | undefined;
20
+ }, {
21
+ model: string;
22
+ limit?: number | undefined;
23
+ allowed_company_ids?: number[] | undefined;
24
+ domain?: unknown[] | undefined;
25
+ fields?: string[] | undefined;
26
+ offset?: number | undefined;
27
+ order?: string | undefined;
28
+ active_company_id?: number | undefined;
29
+ }>;
30
+ export type SearchReadInput = z.infer<typeof searchReadSchema>;
31
+ export declare const readSchema: z.ZodObject<{
32
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
33
+ active_company_id: z.ZodOptional<z.ZodNumber>;
34
+ model: z.ZodString;
35
+ ids: z.ZodArray<z.ZodNumber, "many">;
36
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
37
+ }, "strip", z.ZodTypeAny, {
38
+ model: string;
39
+ fields: string[];
40
+ ids: number[];
41
+ allowed_company_ids?: number[] | undefined;
42
+ active_company_id?: number | undefined;
43
+ }, {
44
+ model: string;
45
+ ids: number[];
46
+ allowed_company_ids?: number[] | undefined;
47
+ fields?: string[] | undefined;
48
+ active_company_id?: number | undefined;
49
+ }>;
50
+ export type ReadInput = z.infer<typeof readSchema>;
51
+ export declare const createSchema: z.ZodObject<{
52
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
53
+ active_company_id: z.ZodOptional<z.ZodNumber>;
54
+ model: z.ZodString;
55
+ values: z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">]>;
56
+ }, "strip", z.ZodTypeAny, {
57
+ values: Record<string, unknown> | Record<string, unknown>[];
58
+ model: string;
59
+ allowed_company_ids?: number[] | undefined;
60
+ active_company_id?: number | undefined;
61
+ }, {
62
+ values: Record<string, unknown> | Record<string, unknown>[];
63
+ model: string;
64
+ allowed_company_ids?: number[] | undefined;
65
+ active_company_id?: number | undefined;
66
+ }>;
67
+ export type CreateInput = z.infer<typeof createSchema>;
68
+ export declare const writeSchema: z.ZodObject<{
69
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
70
+ active_company_id: z.ZodOptional<z.ZodNumber>;
71
+ model: z.ZodString;
72
+ ids: z.ZodArray<z.ZodNumber, "many">;
73
+ values: z.ZodRecord<z.ZodString, z.ZodUnknown>;
74
+ }, "strip", z.ZodTypeAny, {
75
+ values: Record<string, unknown>;
76
+ model: string;
77
+ ids: number[];
78
+ allowed_company_ids?: number[] | undefined;
79
+ active_company_id?: number | undefined;
80
+ }, {
81
+ values: Record<string, unknown>;
82
+ model: string;
83
+ ids: number[];
84
+ allowed_company_ids?: number[] | undefined;
85
+ active_company_id?: number | undefined;
86
+ }>;
87
+ export type WriteInput = z.infer<typeof writeSchema>;
88
+ export declare const unlinkSchema: z.ZodObject<{
89
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
90
+ active_company_id: z.ZodOptional<z.ZodNumber>;
91
+ model: z.ZodString;
92
+ ids: z.ZodArray<z.ZodNumber, "many">;
93
+ }, "strip", z.ZodTypeAny, {
94
+ model: string;
95
+ ids: number[];
96
+ allowed_company_ids?: number[] | undefined;
97
+ active_company_id?: number | undefined;
98
+ }, {
99
+ model: string;
100
+ ids: number[];
101
+ allowed_company_ids?: number[] | undefined;
102
+ active_company_id?: number | undefined;
103
+ }>;
104
+ export type UnlinkInput = z.infer<typeof unlinkSchema>;
105
+ export declare const searchCountSchema: z.ZodObject<{
106
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
107
+ active_company_id: z.ZodOptional<z.ZodNumber>;
108
+ model: z.ZodString;
109
+ domain: z.ZodDefault<z.ZodArray<z.ZodUnknown, "many">>;
110
+ }, "strip", z.ZodTypeAny, {
111
+ model: string;
112
+ domain: unknown[];
113
+ allowed_company_ids?: number[] | undefined;
114
+ active_company_id?: number | undefined;
115
+ }, {
116
+ model: string;
117
+ allowed_company_ids?: number[] | undefined;
118
+ domain?: unknown[] | undefined;
119
+ active_company_id?: number | undefined;
120
+ }>;
121
+ export type SearchCountInput = z.infer<typeof searchCountSchema>;
122
+ export declare const executeSchema: z.ZodObject<{
123
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
124
+ active_company_id: z.ZodOptional<z.ZodNumber>;
125
+ model: z.ZodString;
126
+ method: z.ZodString;
127
+ args: z.ZodDefault<z.ZodArray<z.ZodUnknown, "many">>;
128
+ kwargs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
+ }, "strip", z.ZodTypeAny, {
130
+ model: string;
131
+ method: string;
132
+ args: unknown[];
133
+ kwargs: Record<string, unknown>;
134
+ allowed_company_ids?: number[] | undefined;
135
+ active_company_id?: number | undefined;
136
+ }, {
137
+ model: string;
138
+ method: string;
139
+ allowed_company_ids?: number[] | undefined;
140
+ active_company_id?: number | undefined;
141
+ args?: unknown[] | undefined;
142
+ kwargs?: Record<string, unknown> | undefined;
143
+ }>;
144
+ export type ExecuteInput = z.infer<typeof executeSchema>;
145
+ export declare const runReportSchema: z.ZodObject<{
146
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
147
+ active_company_id: z.ZodOptional<z.ZodNumber>;
148
+ report_id: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
149
+ doc_ids: z.ZodArray<z.ZodNumber, "many">;
150
+ }, "strip", z.ZodTypeAny, {
151
+ report_id: string | number;
152
+ doc_ids: number[];
153
+ allowed_company_ids?: number[] | undefined;
154
+ active_company_id?: number | undefined;
155
+ }, {
156
+ report_id: string | number;
157
+ doc_ids: number[];
158
+ allowed_company_ids?: number[] | undefined;
159
+ active_company_id?: number | undefined;
160
+ }>;
161
+ export type RunReportInput = z.infer<typeof runReportSchema>;
162
+ export declare const callActionSchema: z.ZodObject<{
163
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
164
+ active_company_id: z.ZodOptional<z.ZodNumber>;
165
+ model: z.ZodString;
166
+ ids: z.ZodArray<z.ZodNumber, "many">;
167
+ action_name: z.ZodString;
168
+ context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
169
+ }, "strip", z.ZodTypeAny, {
170
+ model: string;
171
+ ids: number[];
172
+ action_name: string;
173
+ allowed_company_ids?: number[] | undefined;
174
+ active_company_id?: number | undefined;
175
+ context?: Record<string, unknown> | undefined;
176
+ }, {
177
+ model: string;
178
+ ids: number[];
179
+ action_name: string;
180
+ allowed_company_ids?: number[] | undefined;
181
+ active_company_id?: number | undefined;
182
+ context?: Record<string, unknown> | undefined;
183
+ }>;
184
+ export type CallActionInput = z.infer<typeof callActionSchema>;
185
+ export declare const fieldsGetSchema: z.ZodObject<{
186
+ allowed_company_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
187
+ active_company_id: z.ZodOptional<z.ZodNumber>;
188
+ model: z.ZodString;
189
+ attributes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
190
+ }, "strip", z.ZodTypeAny, {
191
+ model: string;
192
+ allowed_company_ids?: number[] | undefined;
193
+ active_company_id?: number | undefined;
194
+ attributes?: string[] | undefined;
195
+ }, {
196
+ model: string;
197
+ allowed_company_ids?: number[] | undefined;
198
+ active_company_id?: number | undefined;
199
+ attributes?: string[] | undefined;
200
+ }>;
201
+ export type FieldsGetInput = z.infer<typeof fieldsGetSchema>;
202
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/tools/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoBxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;EAKrB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEnD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;EAIvB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAEvD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;EAKtB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAErD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;EAIvB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAEvD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAI5B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;EAMxB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEzD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;EAI1B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE7D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAM3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;EAI1B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
2
+ // Threat-model US-5 AC-9 (extended to all tools as defense-in-depth):
3
+ // Reject model names with characters that could escape Odoo's expected dotted_snake_case.
4
+ const MODEL_NAME = z
5
+ .string()
6
+ .min(1)
7
+ .regex(/^[a-z][a-z0-9_.]*$/, 'model must match /^[a-z][a-z0-9_.]*$/');
8
+ // Reject method/action names with characters beyond safe snake_case identifiers.
9
+ const METHOD_NAME = z
10
+ .string()
11
+ .min(1)
12
+ .regex(/^[a-z_][a-z0-9_]*$/, 'method must match /^[a-z_][a-z0-9_]*$/');
13
+ const companyContext = {
14
+ allowed_company_ids: z.array(z.number().int().positive()).optional(),
15
+ active_company_id: z.number().int().positive().optional(),
16
+ };
17
+ export const searchReadSchema = z.object({
18
+ model: MODEL_NAME,
19
+ domain: z.array(z.unknown()).default([]),
20
+ fields: z.array(z.string()).default([]),
21
+ limit: z.number().int().positive().default(80),
22
+ offset: z.number().int().nonnegative().default(0),
23
+ order: z.string().optional(),
24
+ ...companyContext,
25
+ });
26
+ export const readSchema = z.object({
27
+ model: MODEL_NAME,
28
+ ids: z.array(z.number().int().positive()).min(1),
29
+ fields: z.array(z.string()).default([]),
30
+ ...companyContext,
31
+ });
32
+ export const createSchema = z.object({
33
+ model: MODEL_NAME,
34
+ values: z.union([z.record(z.unknown()), z.array(z.record(z.unknown()))]),
35
+ ...companyContext,
36
+ });
37
+ export const writeSchema = z.object({
38
+ model: MODEL_NAME,
39
+ ids: z.array(z.number().int().positive()).min(1),
40
+ values: z.record(z.unknown()),
41
+ ...companyContext,
42
+ });
43
+ export const unlinkSchema = z.object({
44
+ model: MODEL_NAME,
45
+ ids: z.array(z.number().int().positive()).min(1),
46
+ ...companyContext,
47
+ });
48
+ export const searchCountSchema = z.object({
49
+ model: MODEL_NAME,
50
+ domain: z.array(z.unknown()).default([]),
51
+ ...companyContext,
52
+ });
53
+ export const executeSchema = z.object({
54
+ model: MODEL_NAME,
55
+ method: METHOD_NAME,
56
+ args: z.array(z.unknown()).default([]),
57
+ kwargs: z.record(z.unknown()).default({}),
58
+ ...companyContext,
59
+ });
60
+ export const runReportSchema = z.object({
61
+ report_id: z.union([z.number().int().positive(), z.string().min(1)]),
62
+ doc_ids: z.array(z.number().int().positive()).min(1),
63
+ ...companyContext,
64
+ });
65
+ export const callActionSchema = z.object({
66
+ model: MODEL_NAME,
67
+ ids: z.array(z.number().int().positive()).min(1),
68
+ action_name: METHOD_NAME,
69
+ context: z.record(z.unknown()).optional(),
70
+ ...companyContext,
71
+ });
72
+ export const fieldsGetSchema = z.object({
73
+ model: MODEL_NAME,
74
+ attributes: z.array(z.string()).optional(),
75
+ ...companyContext,
76
+ });
77
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/tools/schemas.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@netlinksinc/odoo-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server exposing any Odoo 19 instance to Claude (Desktop, Code, Cowork) — generic-only tool surface, works on stock and customized Odoo",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "claude",
9
+ "anthropic",
10
+ "odoo",
11
+ "odoo19",
12
+ "erp",
13
+ "ai",
14
+ "agent"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/farshidghyasi/odoo-mcp.git",
19
+ "directory": "packages/odoo-mcp"
20
+ },
21
+ "homepage": "https://github.com/farshidghyasi/odoo-mcp#readme",
22
+ "bugs": "https://github.com/farshidghyasi/odoo-mcp/issues",
23
+ "author": "NETLINKS Inc",
24
+ "type": "module",
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "bin": {
28
+ "odoo-mcp": "./dist/bin.js"
29
+ },
30
+ "exports": {
31
+ ".": {
32
+ "import": "./dist/index.js",
33
+ "types": "./dist/index.d.ts"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=22"
42
+ },
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1",
45
+ "zod": "^3",
46
+ "@netlinksinc/odoo-client": "0.1.0"
47
+ },
48
+ "devDependencies": {
49
+ "typescript": "^5.7",
50
+ "vitest": "^3"
51
+ },
52
+ "scripts": {
53
+ "build": "tsc",
54
+ "test": "vitest run"
55
+ }
56
+ }