Sign In

@taskade/mcp-openapi-codegen

Package Overview
Dependencies
Maintainers
3
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@taskade/mcp-openapi-codegen - npm Package Compare versions

Comparing version
0.0.1
to
0.0.2
+6
-0
CHANGELOG.md
# @taskade/mcp-openapi-codegen
## 0.0.2
### Patch Changes
- [`6b1ba50`](https://github.com/taskade/mcp/commit/6b1ba50acd2a5a2c64c37863432fe1cd1ad08d68) Thanks [@prevwong](https://github.com/prevwong)! - Temporary fix for openapi codegen
## 0.0.1

@@ -4,0 +10,0 @@

+8
-1
{
"name": "@taskade/mcp-openapi-codegen",
"version": "0.0.1",
"version": "0.0.2",
"author": "Prev Wong",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/taskade/mcp.git"
},
"publishConfig": {
"access": "public"
},
"type": "module",

@@ -7,0 +14,0 @@ "exports": {

+4
-2

@@ -8,6 +8,6 @@ # @taskade/mcp-openapi-codegen

- Install `@taskade/mcp-openapi-codegen` package:
- Install `@taskade/mcp-openapi-codegen` and `@readme/openapi-parser` package:
```sh
npm install --dev @taskade/mcp-openapi-codegen
npm install --dev @taskade/mcp-openapi-codegen @readme/openapi-parser
```

@@ -32,2 +32,4 @@

Then run `npx tsx scripts/generate-openapi-tools.ts`
> This will generate a new `tools.generated.ts` file in the `src/` folder.

@@ -34,0 +36,0 @@

@@ -174,1 +174,113 @@ import type { JSONSchema7 as IJsonSchema } from 'json-schema';

};
/**
* Walks the schema and flattens `allOf` so it can be expressed as plain Zod.
*
* Why: Zod represents `allOf` as `z.intersection(...)`. When an `allOf` member
* contains an `anyOf`/`oneOf` whose branches use `additionalProperties: false`
* (i.e. `.strict()`), the intersection becomes unsatisfiable — sibling properties
* coming from the other `allOf` member are rejected as unknown by the strict
* branch, but are simultaneously required. We resolve this by distributing the
* other members into each branch so each branch knows about every sibling key.
*/
export const normalizeAllOf = (schema: IJsonSchema): IJsonSchema => {
if (!schema || typeof schema !== 'object') {
return schema;
}
const next: IJsonSchema = { ...schema };
if (next.properties) {
const props: Record<string, IJsonSchema> = {};
for (const [k, v] of Object.entries(next.properties)) {
props[k] = normalizeAllOf(v as IJsonSchema);
}
next.properties = props;
}
if (next.items) {
next.items = Array.isArray(next.items)
? next.items.map((i) => normalizeAllOf(i as IJsonSchema))
: normalizeAllOf(next.items as IJsonSchema);
}
if (Array.isArray(next.anyOf)) {
next.anyOf = next.anyOf.map((s) => normalizeAllOf(s as IJsonSchema));
}
if (Array.isArray(next.oneOf)) {
next.oneOf = next.oneOf.map((s) => normalizeAllOf(s as IJsonSchema));
}
if (Array.isArray(next.allOf)) {
next.allOf = next.allOf.map((s) => normalizeAllOf(s as IJsonSchema));
}
if (!Array.isArray(next.allOf) || next.allOf.length === 0) {
return next;
}
const members = next.allOf as IJsonSchema[];
// If any member has anyOf/oneOf, distribute the other members across each branch.
const branchIdx = members.findIndex((m) => Array.isArray(m.anyOf) || Array.isArray(m.oneOf));
if (branchIdx >= 0) {
const branchMember = members[branchIdx];
const branchKey: 'anyOf' | 'oneOf' = Array.isArray(branchMember.anyOf) ? 'anyOf' : 'oneOf';
const branches = branchMember[branchKey] as IJsonSchema[];
const others = members.filter((_, i) => i !== branchIdx);
const branchSiblings: IJsonSchema = { ...branchMember };
delete (branchSiblings as any)[branchKey];
const distributed = branches.map((b) =>
normalizeAllOf({ allOf: [...others, branchSiblings, b] }),
);
const result: IJsonSchema = { ...next };
delete result.allOf;
(result as any)[branchKey] = distributed;
return result;
}
// All members are plain — merge them into one object schema.
const merged = mergeObjectSchemas(members);
const result: IJsonSchema = { ...next, ...merged };
delete result.allOf;
return result;
};
const mergeObjectSchemas = (schemas: IJsonSchema[]): IJsonSchema => {
const properties: Record<string, IJsonSchema> = {};
const required = new Set<string>();
let additionalProperties: IJsonSchema['additionalProperties'] | undefined;
let type: IJsonSchema['type'] = 'object';
for (const s of schemas) {
if (s.properties) {
for (const [k, v] of Object.entries(s.properties)) {
properties[k] = v as IJsonSchema;
}
}
if (Array.isArray(s.required)) {
s.required.forEach((r) => required.add(r));
}
if (s.additionalProperties !== undefined) {
// false wins — if any branch is strict, the merged schema is strict.
if (s.additionalProperties === false || additionalProperties === false) {
additionalProperties = false;
} else {
additionalProperties = s.additionalProperties;
}
}
if (s.type && s.type !== 'object') {
type = s.type;
}
}
const result: IJsonSchema = { type, properties };
if (required.size > 0) {
result.required = Array.from(required);
}
if (additionalProperties !== undefined) {
result.additionalProperties = additionalProperties;
}
return result;
};

@@ -10,2 +10,3 @@ import type { JSONSchema7 as IJsonSchema } from 'json-schema';

isRequestBodyObject,
normalizeAllOf,
} from './openapi';

@@ -69,3 +70,5 @@

obj.properties![param.name] = convertOpenApiSchemaToJsonSchema(param.schema);
obj.properties![param.name] = normalizeAllOf(
convertOpenApiSchemaToJsonSchema(param.schema),
);

@@ -86,4 +89,6 @@ if (param.required) {

) {
const bodySchema = convertOpenApiSchemaToJsonSchema(
operation.requestBody.content['application/json'].schema,
const bodySchema = normalizeAllOf(
convertOpenApiSchemaToJsonSchema(
operation.requestBody.content['application/json'].schema,
),
);

@@ -95,2 +100,7 @@

}
if (Array.isArray(bodySchema.required) && bodySchema.required.length > 0) {
const merged = new Set([...(inputSchema.required ?? []), ...bodySchema.required]);
inputSchema.required = Array.from(merged);
}
}

@@ -97,0 +107,0 @@ }