@ttoss/http-server-mcp-openapi 0.2.14 → 0.3.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
@@ -31,12 +31,15 @@ registerOpenApiTools({
31
31
  server,
32
32
  spec: openApiDocument,
33
33
  // You own how the request is executed — base URL, auth, fetch impl.
34
- callApi: async ({ method, url, body }) => {
34
+ // `headers` is what createMcpRouter's `getApiHeaders` produced for this
35
+ // MCP request — typically the caller's credentials.
36
+ callApi: async ({ method, url, body, headers }) => {
35
37
  const res = await fetch(`https://api.example.com${url}`, {
36
38
  method,
37
- headers: { 'Content-Type': 'application/json' },
39
+ headers: { ...headers, 'Content-Type': 'application/json' },
38
40
  body: body ? JSON.stringify(body) : undefined,
39
41
  });
42
+ if (res.status === 204) return undefined;
40
43
  return res.json();
41
44
  },
42
45
  });
@@ -55,19 +58,25 @@ Each OpenAPI operation with an `operationId` and a supported HTTP method
55
58
  | OpenAPI | MCP tool |
56
59
  | ------------------------- | -------------------------------------------- |
57
60
  | `operationId: listAgents` | tool name `list-agents` (kebab-case) |
58
- | path/query/body params | a single camelCase `inputSchema` object |
61
+ | path/query/body params | a single `inputSchema` object |
59
62
  | `$ref`, `oneOf`, `anyOf` | dereferenced and merged into a flat schema |
60
- | snake_case body fields | camelCase tool inputs, mapped back on call |
63
+ | snake_case names | camelCase tool inputs, mapped back on call |
61
64
  | operation `description` | tool description (quotes/newlines sanitised) |
62
65
 
63
66
  Path params are always required strings. Query and body params carry their
64
- declared type and `required` flag. Array params keep their `items` schema.
67
+ declared type and `required` flag. Array params keep their `items` schema. A
68
+ body property declared as a single-entry `allOf` (usually `allOf: [{ $ref }]`
69
+ beside its own `description`) takes `type`, `nullable` and `items` from the
70
+ referenced schema; a multi-entry `allOf` is forwarded verbatim, and a property
71
+ with no declared type is advertised untyped so it accepts any value.
65
72
  Parameters declared at the **path-item level** (shared by every operation on a
66
73
  path) are merged into each operation; an operation-level parameter overrides a
67
74
  path-item one with the same `name`+`in`.
68
75
 
69
- Tool arguments are **camelCase** (`agentId`, `projectId`); the generated
70
- request path, query string, and body use the original **snake_case** names.
76
+ By default tool arguments are **camelCase** (`agentId`, `projectId`) and the
77
+ generated request path, query string, and body use the spec's original names.
78
+ Set `argumentNames: 'verbatim'` to use the spec's names as the arguments too,
79
+ so the MCP contract matches the REST contract exactly.
71
80
 
72
81
  Query params honour their declared `style` and `explode`. `form` (the default)
73
82
  repeats array values, `spaceDelimited`/`pipeDelimited` join them, and
@@ -76,13 +85,18 @@ repeats array values, `spaceDelimited`/`pipeDelimited` join them, and
76
85
 
77
86
  ## `registerOpenApiTools`
78
87
 
79
- | Field | Description |
80
- | ---------- | ------------------------------------------------------------------------------------------------------------- |
81
- | `server` | The `McpServer` to register tools on. |
82
- | `spec` | One OpenAPI document, or an array of them (tools are flattened). |
83
- | `callApi` | Runs the resolved `{ method, url, body, tool }` request and returns the raw data. |
84
- | `toText?` | Serialises the raw data into the tool's text payload. Defaults to pretty JSON; strings pass through verbatim. |
85
- | `options?` | See [Options](#options). |
88
+ | Field | Description |
89
+ | ------------------- | ------------------------------------------------------------------------------------------------------------- |
90
+ | `server` | The `McpServer` to register tools on. |
91
+ | `spec` | One OpenAPI document, or an array of them (tools are flattened). |
92
+ | `callApi` | Runs the resolved `{ method, url, body, tool, headers }` request and returns the raw data. |
93
+ | `toText?` | Serialises the raw data into the tool's text payload. Defaults to pretty JSON; strings pass through verbatim. |
94
+ | `serverParameters?` | Supplies server-managed path/query parameter values. See [Server-managed values](#server-managed-values). |
95
+ | `options?` | See [Options](#options). |
96
+
97
+ The default `toText` answers `NO_CONTENT_TEXT` (`Succeeded. The operation
98
+ returned no content.`) when `callApi` resolves `undefined` or `''`, so a `204`
99
+ reaches the client as a success.
86
100
 
87
101
  Returns the list of `ToolDefinition`s that were registered.
88
102
 
@@ -105,7 +119,7 @@ for (const tool of tools) {
105
119
 
106
120
  Each `ToolDefinition` exposes `name`, `description`, `inputSchema`, `method`,
107
121
  `pathTemplate`, `operationId`, the `path`/`query`/`body` builders,
108
- `acceptedBodyFields`, and `extensions`.
122
+ `acceptedBodyFields`, `extensions`, and `serverManagedParameters`.
109
123
 
110
124
  ## Options
111
125
 
@@ -116,17 +130,48 @@ registerOpenApiTools({
116
130
  callApi,
117
131
  options: {
118
132
  excludeExtension: 'x-mcp-exclude', // operations flagged truthy are skipped
119
- serverManagedExtension: 'x-mcp-server-managed', // body fields hidden from the input schema
133
+ serverManagedExtension: 'x-mcp-server-managed', // values hidden from the input schema
134
+ argumentNames: 'camelCase', // or 'verbatim'
135
+ documents: { './tags.yaml': tagsDocument }, // targets of cross-file $refs
120
136
  },
121
137
  });
122
138
  ```
123
139
 
124
140
  - **`excludeExtension`** (default `x-mcp-exclude`) — an operation with this
125
141
  extension set truthy is omitted from the tool surface.
126
- - **`serverManagedExtension`** (default `x-mcp-server-managed`) — a request-body
127
- property with this extension set truthy is hidden from the tool's
128
- `inputSchema` (the caller can't set it) but still appears in
129
- `acceptedBodyFields`.
142
+ - **`serverManagedExtension`** (default `x-mcp-server-managed`) — see
143
+ [Server-managed values](#server-managed-values).
144
+ - **`argumentNames`** (default `camelCase`) — `verbatim` keeps the spec's
145
+ parameter and property names as tool argument names.
146
+ - **`documents`** — sibling documents for `$ref`s with a file part, keyed by
147
+ that part as the spec writes it (a leading `./` is optional). In
148
+ `./tags.yaml#/components/schemas/Tag` the key is `./tags.yaml`; refs inside
149
+ a sibling resolve against that sibling. A ref to a file missing from the map
150
+ resolves to an empty schema, which accepts any value.
151
+
152
+ ### Server-managed values
153
+
154
+ A value flagged with `serverManagedExtension` is never offered to the model:
155
+
156
+ - A **request-body property** is hidden from `inputSchema` and never sent (the
157
+ API sets it itself). It still appears in `acceptedBodyFields`.
158
+ - A **path or query parameter** is hidden from `inputSchema` and listed in
159
+ `tool.serverManagedParameters`. `registerOpenApiTools` discards anything the
160
+ model sent for it and fills it from `serverParameters`, keyed by spec name:
161
+
162
+ ```typescript
163
+ registerOpenApiTools({
164
+ server,
165
+ spec,
166
+ callApi,
167
+ serverParameters: ({ tool, headers }) => ({
168
+ project_id: projectIdFromToken(headers.Authorization),
169
+ }),
170
+ });
171
+ ```
172
+
173
+ With `openApiToToolDefinitions`, set each entry's `argName` in the args before
174
+ calling `tool.path` / `tool.query`.
130
175
 
131
176
  ### Reading custom extensions
132
177