@ttoss/http-server-mcp-openapi 0.5.7 → 0.7.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 +106 -8
- package/dist/index.cjs +293 -33
- package/dist/index.d.cts +156 -4
- package/dist/index.d.mts +156 -4
- package/dist/index.mjs +289 -33
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
import { dispatchInProcess } from "@ttoss/http-server";
|
|
2
3
|
import { getApiHeaders, registerToolFromSchema } from "@ttoss/http-server-mcp";
|
|
3
4
|
|
|
4
5
|
//#region src/schema.ts
|
|
5
|
-
var isRecord = value => {
|
|
6
|
+
var isRecord$1 = value => {
|
|
6
7
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
8
|
};
|
|
8
9
|
var getAlternativeSchemas = schema => {
|
|
@@ -39,7 +40,7 @@ var followPointer = args => {
|
|
|
39
40
|
const tokens = args.pointer.split("/").slice(1);
|
|
40
41
|
let current = args.root;
|
|
41
42
|
for (const rawToken of tokens) {
|
|
42
|
-
if (!isRecord(current) && !Array.isArray(current)) return void 0;
|
|
43
|
+
if (!isRecord$1(current) && !Array.isArray(current)) return void 0;
|
|
43
44
|
const token = decodeURIComponent(rawToken).replace(/~1/g, "/").replace(/~0/g, "~");
|
|
44
45
|
current = current[token];
|
|
45
46
|
}
|
|
@@ -98,7 +99,7 @@ var dereferenceValue = args => {
|
|
|
98
99
|
seenRefs
|
|
99
100
|
});
|
|
100
101
|
});
|
|
101
|
-
if (isRecord(value)) {
|
|
102
|
+
if (isRecord$1(value)) {
|
|
102
103
|
if (typeof value.$ref === "string") {
|
|
103
104
|
const target = resolveRef({
|
|
104
105
|
ref: value.$ref,
|
|
@@ -178,7 +179,7 @@ var resolveParameter = (param, spec, documents) => {
|
|
|
178
179
|
documents
|
|
179
180
|
}
|
|
180
181
|
});
|
|
181
|
-
return isRecord(target?.value) ? target.value : {};
|
|
182
|
+
return isRecord$1(target?.value) ? target.value : {};
|
|
182
183
|
}
|
|
183
184
|
return param;
|
|
184
185
|
};
|
|
@@ -217,7 +218,7 @@ var appendDeepObject = args => {
|
|
|
217
218
|
});
|
|
218
219
|
return;
|
|
219
220
|
}
|
|
220
|
-
if (isRecord(args.value)) {
|
|
221
|
+
if (isRecord$1(args.value)) {
|
|
221
222
|
for (const [property, propertyValue] of Object.entries(args.value)) appendDeepObject({
|
|
222
223
|
search: args.search,
|
|
223
224
|
key: `${args.key}[${property}]`,
|
|
@@ -269,7 +270,7 @@ var appendQueryValue = args => {
|
|
|
269
270
|
});
|
|
270
271
|
return;
|
|
271
272
|
}
|
|
272
|
-
if (isRecord(args.value)) {
|
|
273
|
+
if (isRecord$1(args.value)) {
|
|
273
274
|
appendObjectValue({
|
|
274
275
|
...serialization,
|
|
275
276
|
value: args.value
|
|
@@ -498,6 +499,8 @@ var extractPathParams = args => {
|
|
|
498
499
|
return {
|
|
499
500
|
name: p.name || "",
|
|
500
501
|
argName: toArgName(p.name || ""),
|
|
502
|
+
description: p.description,
|
|
503
|
+
schema: dereferenceSchema(p.schema, args.spec, args.documents),
|
|
501
504
|
...managedFields(readServerManaged({
|
|
502
505
|
node: p,
|
|
503
506
|
extension: flag
|
|
@@ -519,6 +522,7 @@ var extractQueryParams = args => {
|
|
|
519
522
|
description: p.description || "",
|
|
520
523
|
required: p.required || false,
|
|
521
524
|
type: p.schema?.type || "string",
|
|
525
|
+
schema: dereferenceSchema(p.schema, args.spec, args.documents),
|
|
522
526
|
style: p.style,
|
|
523
527
|
explode: p.explode,
|
|
524
528
|
...managedFields(readServerManaged({
|
|
@@ -611,7 +615,8 @@ var extractBodyProps = args => {
|
|
|
611
615
|
nullable: val.nullable === true,
|
|
612
616
|
oneOf: Array.isArray(val.oneOf) ? val.oneOf : void 0,
|
|
613
617
|
anyOf: Array.isArray(val.anyOf) ? val.anyOf : void 0,
|
|
614
|
-
allOf: Array.isArray(val.allOf) ? val.allOf : void 0
|
|
618
|
+
allOf: Array.isArray(val.allOf) ? val.allOf : void 0,
|
|
619
|
+
schema: value
|
|
615
620
|
};
|
|
616
621
|
});
|
|
617
622
|
};
|
|
@@ -641,6 +646,209 @@ var extractPinnedBody = args => {
|
|
|
641
646
|
return pinned;
|
|
642
647
|
};
|
|
643
648
|
|
|
649
|
+
//#endregion
|
|
650
|
+
//#region src/fullSchema.ts
|
|
651
|
+
var isRecord = value => {
|
|
652
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
653
|
+
};
|
|
654
|
+
var OPENAPI_ONLY_KEYWORDS = new Set(["discriminator", "example", "externalDocs", "xml"]);
|
|
655
|
+
var SCHEMA_MAPS = new Set(["$defs", "definitions", "dependentSchemas", "patternProperties", "properties"]);
|
|
656
|
+
var SCHEMA_VALUES = new Set(["additionalProperties", "contains", "else", "if", "items", "not", "propertyNames", "then", "unevaluatedItems", "unevaluatedProperties"]);
|
|
657
|
+
var SCHEMA_LISTS = new Set(["anyOf", "oneOf", "prefixItems"]);
|
|
658
|
+
/**
|
|
659
|
+
* OpenAPI 3.0's `nullable: true` in JSON Schema: `'null'` joins the `type`,
|
|
660
|
+
* and `null` joins an `enum`, which would otherwise still refuse it.
|
|
661
|
+
*/
|
|
662
|
+
var withNull = schema => {
|
|
663
|
+
const result = {
|
|
664
|
+
...schema
|
|
665
|
+
};
|
|
666
|
+
if (typeof result.type === "string") result.type = [result.type, "null"];else if (Array.isArray(result.type) && !result.type.includes("null")) result.type = [...result.type, "null"];
|
|
667
|
+
if (Array.isArray(result.enum) && !result.enum.includes(null)) result.enum = [...result.enum, null];
|
|
668
|
+
return result;
|
|
669
|
+
};
|
|
670
|
+
/**
|
|
671
|
+
* Merges an `allOf` into one schema, the shape a tool argument needs.
|
|
672
|
+
*
|
|
673
|
+
* Members that declare `properties` are an object composition — a write body
|
|
674
|
+
* that is a patch plus two fields — and merge their properties and `required`.
|
|
675
|
+
* Otherwise the `allOf` only wraps a referenced scalar so it can carry its own
|
|
676
|
+
* `description` (the one way OpenAPI 3.0 allows beside a `$ref`), and the
|
|
677
|
+
* members are merged as they are. Sibling keys win in both, because the
|
|
678
|
+
* wrapper exists to say something the referenced schema does not.
|
|
679
|
+
*/
|
|
680
|
+
var mergeAllOf = args => {
|
|
681
|
+
const {
|
|
682
|
+
members,
|
|
683
|
+
siblings
|
|
684
|
+
} = args;
|
|
685
|
+
if (!members.some(member => {
|
|
686
|
+
return member.properties !== void 0;
|
|
687
|
+
})) return Object.assign({}, ...members, siblings);
|
|
688
|
+
const properties = {};
|
|
689
|
+
const required = [];
|
|
690
|
+
for (const member of members) {
|
|
691
|
+
Object.assign(properties, member.properties);
|
|
692
|
+
if (Array.isArray(member.required)) required.push(...member.required);
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
...siblings,
|
|
696
|
+
type: "object",
|
|
697
|
+
properties,
|
|
698
|
+
...(required.length > 0 ? {
|
|
699
|
+
required: [...new Set(required)]
|
|
700
|
+
} : {})
|
|
701
|
+
};
|
|
702
|
+
};
|
|
703
|
+
var normalizeChildren = args => {
|
|
704
|
+
const {
|
|
705
|
+
schema,
|
|
706
|
+
next
|
|
707
|
+
} = args;
|
|
708
|
+
const result = {};
|
|
709
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
710
|
+
if (OPENAPI_ONLY_KEYWORDS.has(key) || key.startsWith("x-")) continue;
|
|
711
|
+
if (SCHEMA_MAPS.has(key) && isRecord(value)) result[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => {
|
|
712
|
+
return [name, next(child)];
|
|
713
|
+
}));else if (SCHEMA_VALUES.has(key) && isRecord(value)) result[key] = next(value);else if (SCHEMA_LISTS.has(key) && Array.isArray(value)) result[key] = value.map(next);else result[key] = value;
|
|
714
|
+
}
|
|
715
|
+
return result;
|
|
716
|
+
};
|
|
717
|
+
/**
|
|
718
|
+
* Turns an already-dereferenced OpenAPI schema into the JSON Schema a tool
|
|
719
|
+
* argument carries, keeping every constraint it declares — `enum`, `format`,
|
|
720
|
+
* `pattern`, `minimum`, `default`, nested `properties` and `required`,
|
|
721
|
+
* `oneOf` — and changing only what JSON Schema cannot express: `allOf` is
|
|
722
|
+
* merged, `nullable` becomes a `'null'` type, and OpenAPI-only keywords and
|
|
723
|
+
* `x-` extensions are dropped. Descriptions are kept verbatim.
|
|
724
|
+
*/
|
|
725
|
+
var toToolSchema = value => {
|
|
726
|
+
if (!isRecord(value)) return value;
|
|
727
|
+
const {
|
|
728
|
+
allOf,
|
|
729
|
+
nullable,
|
|
730
|
+
...rest
|
|
731
|
+
} = value;
|
|
732
|
+
const own = normalizeChildren({
|
|
733
|
+
schema: rest,
|
|
734
|
+
next: toToolSchema
|
|
735
|
+
});
|
|
736
|
+
const merged = Array.isArray(allOf) ? mergeAllOf({
|
|
737
|
+
members: allOf.filter(isRecord).map(member => {
|
|
738
|
+
return toToolSchema(member);
|
|
739
|
+
}),
|
|
740
|
+
siblings: own
|
|
741
|
+
}) : own;
|
|
742
|
+
return nullable === true ? withNull(merged) : merged;
|
|
743
|
+
};
|
|
744
|
+
/** A path or query parameter's schema, with the parameter's own description. */
|
|
745
|
+
var paramProperty = param => {
|
|
746
|
+
return {
|
|
747
|
+
...(toToolSchema(param.schema) ?? {}),
|
|
748
|
+
...(param.description ? {
|
|
749
|
+
description: param.description
|
|
750
|
+
} : {})
|
|
751
|
+
};
|
|
752
|
+
};
|
|
753
|
+
/**
|
|
754
|
+
* The `inputSchema` of a tool under `schemaDetail: 'full'`: every parameter
|
|
755
|
+
* and body property with its whole schema. `properties` is always present,
|
|
756
|
+
* even when empty, because some clients refuse an object schema without it.
|
|
757
|
+
*/
|
|
758
|
+
var buildFullInputSchema = args => {
|
|
759
|
+
const params = [...args.pathParams, ...args.queryParams].filter(param => {
|
|
760
|
+
return !param.serverManaged;
|
|
761
|
+
});
|
|
762
|
+
const properties = {};
|
|
763
|
+
const required = [];
|
|
764
|
+
for (const param of params) {
|
|
765
|
+
properties[param.argName] = paramProperty(param);
|
|
766
|
+
if (param.required) required.push(param.argName);
|
|
767
|
+
}
|
|
768
|
+
for (const prop of args.bodyProps) {
|
|
769
|
+
properties[prop.argName] = toToolSchema(prop.schema);
|
|
770
|
+
if (prop.required) required.push(prop.argName);
|
|
771
|
+
}
|
|
772
|
+
return {
|
|
773
|
+
type: "object",
|
|
774
|
+
properties,
|
|
775
|
+
...(required.length > 0 ? {
|
|
776
|
+
required: [...new Set(required)]
|
|
777
|
+
} : {})
|
|
778
|
+
};
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
//#endregion
|
|
782
|
+
//#region src/inProcessCallApi.ts
|
|
783
|
+
var nestedMessageOf = error => {
|
|
784
|
+
if (!error || typeof error !== "object") return null;
|
|
785
|
+
const {
|
|
786
|
+
code,
|
|
787
|
+
message
|
|
788
|
+
} = error;
|
|
789
|
+
if (typeof message !== "string") return null;
|
|
790
|
+
return typeof code === "string" ? `${code}: ${message}` : message;
|
|
791
|
+
};
|
|
792
|
+
/**
|
|
793
|
+
* The message an error response carries, read from the envelopes REST APIs
|
|
794
|
+
* commonly answer with: a plain string, `{ error: '…' }`,
|
|
795
|
+
* `{ error: { code, message } }` (as `code: message`) or `{ message: '…' }`.
|
|
796
|
+
* `null` when the body is none of them.
|
|
797
|
+
*/
|
|
798
|
+
var errorMessageOf = body => {
|
|
799
|
+
if (typeof body === "string") return body || null;
|
|
800
|
+
if (!body || typeof body !== "object") return null;
|
|
801
|
+
const {
|
|
802
|
+
error,
|
|
803
|
+
message
|
|
804
|
+
} = body;
|
|
805
|
+
if (typeof error === "string") return error;
|
|
806
|
+
return nestedMessageOf(error) ?? (typeof message === "string" ? message : null);
|
|
807
|
+
};
|
|
808
|
+
var defaultToError = response => {
|
|
809
|
+
return new Error(errorMessageOf(response.body) ?? `HTTP ${response.status}`);
|
|
810
|
+
};
|
|
811
|
+
/**
|
|
812
|
+
* A `callApi` for {@link registerOpenApiTools} that serves each tool call
|
|
813
|
+
* against the REST app in this same process, with no socket: validation,
|
|
814
|
+
* authorization and error handling run once, in the routes, for both
|
|
815
|
+
* surfaces.
|
|
816
|
+
*
|
|
817
|
+
* The MCP request's headers (what `createMcpRouter`'s `getApiHeaders`
|
|
818
|
+
* produced — typically the caller's `Authorization`) are forwarded onto the
|
|
819
|
+
* dispatched request. A 2xx answers its body; anything else throws, so the
|
|
820
|
+
* client sees a tool error rather than an error body rendered as a result.
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
* ```typescript
|
|
824
|
+
* registerOpenApiTools({
|
|
825
|
+
* server,
|
|
826
|
+
* spec,
|
|
827
|
+
* callApi: createInProcessCallApi({ app }),
|
|
828
|
+
* });
|
|
829
|
+
* ```
|
|
830
|
+
*/
|
|
831
|
+
var createInProcessCallApi = ({
|
|
832
|
+
app,
|
|
833
|
+
headers,
|
|
834
|
+
toError = defaultToError
|
|
835
|
+
}) => {
|
|
836
|
+
return async request => {
|
|
837
|
+
const response = await dispatchInProcess({
|
|
838
|
+
app: typeof app === "function" ? await app() : app,
|
|
839
|
+
method: request.method,
|
|
840
|
+
path: request.url,
|
|
841
|
+
headers: {
|
|
842
|
+
...request.headers,
|
|
843
|
+
...headers?.(request)
|
|
844
|
+
},
|
|
845
|
+
body: request.body
|
|
846
|
+
});
|
|
847
|
+
if (response.status < 200 || response.status >= 300) throw toError(response, request);
|
|
848
|
+
return response.body;
|
|
849
|
+
};
|
|
850
|
+
};
|
|
851
|
+
|
|
644
852
|
//#endregion
|
|
645
853
|
//#region src/toolDefinitions.ts
|
|
646
854
|
/** Converts a camelCase `operationId` to a kebab-case tool name. */
|
|
@@ -657,6 +865,11 @@ var getJsonSchemaType = schemaType => {
|
|
|
657
865
|
var sanitizeDescription = description => {
|
|
658
866
|
return (description || "").replace(/'/g, "\\'").replace(/\n/g, " ").trim();
|
|
659
867
|
};
|
|
868
|
+
var defaultDescribe = ({
|
|
869
|
+
operation
|
|
870
|
+
}) => {
|
|
871
|
+
return sanitizeDescription(operation.description);
|
|
872
|
+
};
|
|
660
873
|
/**
|
|
661
874
|
* Forwards a property's `oneOf` / `anyOf` / multi-entry `allOf` verbatim, or
|
|
662
875
|
* returns `undefined` when it declares none.
|
|
@@ -713,8 +926,7 @@ var buildInputSchema = (pathParams, queryParams, bodyProps) => {
|
|
|
713
926
|
const modelQueryParams = queryParams.filter(p => {
|
|
714
927
|
return !p.serverManaged;
|
|
715
928
|
});
|
|
716
|
-
|
|
717
|
-
if (allParams.length === 0) return {
|
|
929
|
+
if ([...modelPathParams, ...modelQueryParams, ...bodyProps].length === 0) return {
|
|
718
930
|
type: "object"
|
|
719
931
|
};
|
|
720
932
|
const requiredFields = [...modelPathParams.map(p => {
|
|
@@ -729,10 +941,11 @@ var buildInputSchema = (pathParams, queryParams, bodyProps) => {
|
|
|
729
941
|
return p.argName;
|
|
730
942
|
})];
|
|
731
943
|
const properties = {};
|
|
732
|
-
for (const param of
|
|
944
|
+
for (const param of modelPathParams) properties[param.argName] = {
|
|
733
945
|
type: "string",
|
|
734
946
|
description: ""
|
|
735
947
|
};
|
|
948
|
+
for (const param of [...modelQueryParams, ...bodyProps]) properties[param.argName] = normalizeNullable(buildTypedProperty(param));
|
|
736
949
|
return {
|
|
737
950
|
type: "object",
|
|
738
951
|
properties,
|
|
@@ -741,6 +954,35 @@ var buildInputSchema = (pathParams, queryParams, bodyProps) => {
|
|
|
741
954
|
} : {})
|
|
742
955
|
};
|
|
743
956
|
};
|
|
957
|
+
var SUPPORTED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
958
|
+
/** The tool description, from `options.describe` or the default. */
|
|
959
|
+
var describeOperation = args => {
|
|
960
|
+
const {
|
|
961
|
+
options,
|
|
962
|
+
operation,
|
|
963
|
+
method,
|
|
964
|
+
pathTemplate
|
|
965
|
+
} = args;
|
|
966
|
+
return (options.describe ?? defaultDescribe)({
|
|
967
|
+
operation,
|
|
968
|
+
method,
|
|
969
|
+
pathTemplate
|
|
970
|
+
});
|
|
971
|
+
};
|
|
972
|
+
/** The `inputSchema` at the detail {@link OpenApiToToolsOptions.schemaDetail} asks for. */
|
|
973
|
+
var selectInputSchema = args => {
|
|
974
|
+
if (args.schemaDetail !== "full") return buildInputSchema(args.pathParams, args.queryParams, args.bodyProps);
|
|
975
|
+
return buildFullInputSchema({
|
|
976
|
+
pathParams: args.pathParams.map(param => {
|
|
977
|
+
return {
|
|
978
|
+
...param,
|
|
979
|
+
required: true
|
|
980
|
+
};
|
|
981
|
+
}),
|
|
982
|
+
queryParams: args.queryParams,
|
|
983
|
+
bodyProps: args.bodyProps
|
|
984
|
+
});
|
|
985
|
+
};
|
|
744
986
|
/** Collects every `x-` prefixed extension declared on the operation. */
|
|
745
987
|
var extractExtensions = operation => {
|
|
746
988
|
const extensions = {};
|
|
@@ -749,9 +991,7 @@ var extractExtensions = operation => {
|
|
|
749
991
|
};
|
|
750
992
|
var processOperation = args => {
|
|
751
993
|
const httpMethod = args.method.toUpperCase();
|
|
752
|
-
if (!
|
|
753
|
-
if (!args.operation.operationId) return null;
|
|
754
|
-
if (args.operation[args.options.excludeExtension]) return null;
|
|
994
|
+
if (!SUPPORTED_METHODS.includes(httpMethod) || !args.operation.operationId || args.operation[args.options.excludeExtension]) return null;
|
|
755
995
|
const toolName = operationIdToToolName(args.operation.operationId);
|
|
756
996
|
const parameters = [...(args.pathItemParameters ?? []), ...(args.operation.parameters ?? [])];
|
|
757
997
|
const {
|
|
@@ -759,20 +999,15 @@ var processOperation = args => {
|
|
|
759
999
|
serverManagedExtension
|
|
760
1000
|
} = args.options;
|
|
761
1001
|
const toArgName = argNameMapper(args.options.argumentNames);
|
|
762
|
-
const
|
|
1002
|
+
const paramArgs = {
|
|
763
1003
|
parameters,
|
|
764
1004
|
spec: args.spec,
|
|
765
1005
|
documents,
|
|
766
1006
|
toArgName,
|
|
767
1007
|
serverManagedExtension
|
|
768
|
-
}
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
spec: args.spec,
|
|
772
|
-
documents,
|
|
773
|
-
toArgName,
|
|
774
|
-
serverManagedExtension
|
|
775
|
-
});
|
|
1008
|
+
};
|
|
1009
|
+
const pathParams = extractPathParams(paramArgs);
|
|
1010
|
+
const queryParams = extractQueryParams(paramArgs);
|
|
776
1011
|
const bodyArgs = {
|
|
777
1012
|
requestBody: args.operation.requestBody,
|
|
778
1013
|
spec: args.spec,
|
|
@@ -783,7 +1018,12 @@ var processOperation = args => {
|
|
|
783
1018
|
...bodyArgs,
|
|
784
1019
|
toArgName
|
|
785
1020
|
});
|
|
786
|
-
const inputSchema =
|
|
1021
|
+
const inputSchema = selectInputSchema({
|
|
1022
|
+
schemaDetail: args.options.schemaDetail,
|
|
1023
|
+
pathParams,
|
|
1024
|
+
queryParams,
|
|
1025
|
+
bodyProps
|
|
1026
|
+
});
|
|
787
1027
|
const serverManagedParameters = collectServerManagedParameters({
|
|
788
1028
|
pathParams,
|
|
789
1029
|
queryParams
|
|
@@ -791,7 +1031,10 @@ var processOperation = args => {
|
|
|
791
1031
|
const pinned = pinnedArgs(serverManagedParameters);
|
|
792
1032
|
return {
|
|
793
1033
|
name: toolName,
|
|
794
|
-
description:
|
|
1034
|
+
description: describeOperation({
|
|
1035
|
+
...args,
|
|
1036
|
+
method: httpMethod
|
|
1037
|
+
}),
|
|
795
1038
|
inputSchema,
|
|
796
1039
|
method: httpMethod,
|
|
797
1040
|
pathTemplate: args.pathTemplate,
|
|
@@ -840,6 +1083,8 @@ var resolveOptions = (options = {}) => {
|
|
|
840
1083
|
excludeExtension: options.excludeExtension ?? "x-mcp-exclude",
|
|
841
1084
|
serverManagedExtension: options.serverManagedExtension ?? "x-mcp-server-managed",
|
|
842
1085
|
argumentNames: options.argumentNames ?? "camelCase",
|
|
1086
|
+
schemaDetail: options.schemaDetail,
|
|
1087
|
+
describe: options.describe,
|
|
843
1088
|
documents: options.documents
|
|
844
1089
|
};
|
|
845
1090
|
};
|
|
@@ -935,6 +1180,9 @@ var registerOpenApiTools = args => {
|
|
|
935
1180
|
name: tool.name,
|
|
936
1181
|
description: tool.description,
|
|
937
1182
|
inputSchema: tool.inputSchema,
|
|
1183
|
+
_meta: args.toolMeta?.({
|
|
1184
|
+
tool
|
|
1185
|
+
}),
|
|
938
1186
|
handler: async rawArgs => {
|
|
939
1187
|
const headers = getApiHeaders();
|
|
940
1188
|
const handlerArgs = await applyServerParameters({
|
|
@@ -944,17 +1192,25 @@ var registerOpenApiTools = args => {
|
|
|
944
1192
|
serverParameters: args.serverParameters
|
|
945
1193
|
});
|
|
946
1194
|
const url = tool.path(handlerArgs) + (tool.query ? tool.query(handlerArgs) : "");
|
|
1195
|
+
const data = await args.callApi({
|
|
1196
|
+
method: tool.method,
|
|
1197
|
+
url,
|
|
1198
|
+
body: tool.body ? tool.body(handlerArgs) : void 0,
|
|
1199
|
+
tool,
|
|
1200
|
+
headers
|
|
1201
|
+
});
|
|
1202
|
+
const structuredContent = args.toStructuredContent?.({
|
|
1203
|
+
data,
|
|
1204
|
+
tool
|
|
1205
|
+
});
|
|
947
1206
|
return {
|
|
948
1207
|
content: [{
|
|
949
1208
|
type: "text",
|
|
950
|
-
text: toText(
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
headers
|
|
956
|
-
}))
|
|
957
|
-
}]
|
|
1209
|
+
text: toText(data)
|
|
1210
|
+
}],
|
|
1211
|
+
...(structuredContent === void 0 ? {} : {
|
|
1212
|
+
structuredContent
|
|
1213
|
+
})
|
|
958
1214
|
};
|
|
959
1215
|
}
|
|
960
1216
|
});
|
|
@@ -962,4 +1218,4 @@ var registerOpenApiTools = args => {
|
|
|
962
1218
|
};
|
|
963
1219
|
|
|
964
1220
|
//#endregion
|
|
965
|
-
export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, NO_CONTENT_TEXT, buildBodyFn, buildInputSchema, buildPathFn, buildQueryFn, dereferenceSchema, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel };
|
|
1221
|
+
export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, NO_CONTENT_TEXT, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/http-server-mcp-openapi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Generate Model Context Protocol (MCP) tools from an OpenAPI specification for @ttoss/http-server-mcp",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -35,15 +35,15 @@
|
|
|
35
35
|
"dist"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ttoss/http-server
|
|
38
|
+
"@ttoss/http-server": "^0.11.0",
|
|
39
|
+
"@ttoss/http-server-mcp": "^0.32.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
42
43
|
"jest": "^30.4.2",
|
|
43
44
|
"supertest": "^7.2.2",
|
|
44
45
|
"tsdown": "^0.22.2",
|
|
45
|
-
"@ttoss/
|
|
46
|
-
"@ttoss/config": "^1.39.1"
|
|
46
|
+
"@ttoss/config": "^1.40.0"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|
|
49
49
|
"access": "public",
|