🔧 A tool for converting OpenApi/Swagger/Apifox into code.
50
stars
670
commits
TypeScript
primary language
Sep 7, 2026
updated
STC
STC (Swagger Transform Code) is a tool for converting OpenApi/Swagger/Apifox into code.

🚧 Encapsulate the "shared" directory.
axios, wx.request, fetch.
xhr/ajax、ofetchplanned
dio.download by system:
1.Install the @lonu/stc npm package.
pnpm add @lonu/stc -D
2.Open the project's package.json file and add the following command to scripts:
{
"scripts": {
"api": "stc --url=http://127.0.0.1:4523/export/openapi/2?version=3.1"
}
}
⚠️ Note: deno will not parse the ~ character as the user's home directory.
stc --url=https://petstore3.swagger.io/api/v3/openapi.json --outDir=out


Assume a project directory is:
.
├── src
│ └── apis # Copy the shared directory here.
│ └── shared
│ └── xxx.ts # Other files.
Find the directory of outDir, copy the entire shared directory to the directory of the axios module you encapsulated.
Open the shared > axios > index.ts file, copy the request method, and add it to the axios module you encapsulated. If it is not encapsulated, copy the index.ts file as a new file to avoid the problem of modification being overwritten.
Taking Vue as an example, add the following code to the main.ts file:
import { createApiClient } from './apis/shared/fetchRuntime';
createApiClient({
baseURL: 'https://api.xxx.com'
// onError(msg) {
// // 处理错误信息
// }
})
Find the directory of outDir, copy the entire directory of shared to the directory of the wechat module you encapsulated.
Open the shared > wechat > index.ts file, copy the request method, and add it to the wx.request code file you encapsulated. If it is not encapsulated, copy the index.ts file as a new file to avoid the problem of modification being overwritten.
Add the following code to the app.ts file:
import { createApiClient } from './apis/shared/fetchRuntime';
// import Notify from './miniprogram_npm/@vant/weapp/notify/notify';
App<IAppOption>({
onLaunch() {
createApiClient({
baseURL: 'https://api.xxx.com,
onError(msg) {
// Notify({ type: 'danger', message: msg, selector: '#v-notify'})
}
})
}
});
STC does not generate authentication code. For the axios client, inject a token into every request via onRequestInterceptor:
import { createApiClient } from './apis/shared/fetchRuntime';
createApiClient({
baseURL: 'https://api.xxx.com',
onRequestInterceptor(config) {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
},
onLogin() {
// Triggered when the response status is 401, e.g. redirect to the login page
}
})
For the
fetchorconfigargument of each generated method instead, e.g.getPetById(petId, { headers: { Authorization: 'Bearer xxx' } }).
| Option | Alias | Type | Default | Description |
|---|---|---|---|---|
| url | string | Swagger/OpenApi/Apifox document address, or local path (JSON or YAML). | ||
| outDir | o | string | ./stc_out | Output Directory. |
| client | string | axios | http request client. When lang is ts/js, the possible values are: axios, wechat, fetch. | |
| lang | l | string | ts | Language, used for output file suffix. |
| tag | number | Specify the tag from the interface url. By default, the first tag is read for the file name. | ||
| filter | f | string[] | Filter interfaces. Interfaces that meet the filter conditions will be generated. Example: --filter "/pet*", generate an interface for /pet, and support multiple --filter. For more usage information, please refer to micromatch | |
| conjunction | c | string | By | The method's connector, the default value is By. |
| actionIndex | number | -1 | The method name index, the default value is -1. | |
| shared | boolean | true | Whether to generate the shared directory. [default: true]. | |
| clean | boolean | true | Whether to clean the output directory before generating. [default: true]. | |
| globalHeader | gh | string[] | Global header key configuration, multiple can be set. When a single API has the same key, it will not appear as a parameter. | |
| version | v | boolean | Output version information. | |
| help | h | boolean | Output help information. |
Use --mcp to generate mcp-tools.json. The file contains the standard MCP tool fields (name, description, inputSchema) and an x-stc-http extension with the original HTTP method and path, so an MCP server can expose the tools and connect them to a generic HTTP executor.
stc --url=./openapi.yaml --mcp --outDir=./generated
The generated JSON is intentionally limited to tool discovery. Authentication, base URL selection, and HTTP execution remain in the MCP server/runtime that consumes the catalog.
For convenience, STC can not only develop plugins in Deno, but also provides @lonu/stc npm library, which can develop plugins in Node environment.
⚠️ Prepare the Deno environment.
Create a myPlugin.ts file:
// 引用模块
// import { start } from 'https://deno.land/x/stc@2.17.0/mod.ts'
import { start } from 'jsr:@lonu/stc@^2.17.0'
// Defining plugins
const myPlugin: IPlugin = {
name: 'stc:MyPlugin',
lang: 'ts',
setup(context: IPluginContext) {
// type map
return {
}
},
onTransform(def, action) {
// definition
const defContent: string = parserDefinition(
def
)
// action
const actionContent: Map<string, string> = parserAction(
action
)
return {
definition: {
filename: '_types.ts',
content: defContent,
},
action: actionContent // Here actionContent is of type Map<string, string>, key is the file name, value is the converted code.
}
},
onEnd() {
console.log('end')
}
}
// use plugin
start({
// ...other options
plugins: [myPlugin]
})
Create a myPlugin.ts file.
Add the @lonu/stc reference and use the start method:
import { start } from '@lonu/stc'
definition and action into the target language in the plugin's onTransform hook function.export const myPlugin: IPlugin = {
name: 'stc:MyPlugin',
lang: 'ts',
setup(context: IPluginContext) {
// type map
return {
}
},
onTransform(def, action) {
// definition
const defContent: string = parserDefinition(
def
)
// action
const actionContent: Map<string, string> = parserAction(
action
)
return {
definition: defContent,
action: actionContent
}
},
onEnd() {
console.log('end')
}
}
4.In the start method, add plugins:
start({
// ...other options
plugins: [myPlugin]
})
TypeScript
93.5%
Swift
4.2%
Dart
2.3%
🔧 A tool for converting OpenApi/Swagger/Apifox into code.
50
stars
670
commits
TypeScript
primary language
Sep 7, 2026
updated
STC
STC (Swagger Transform Code) is a tool for converting OpenApi/Swagger/Apifox into code.

🚧 Encapsulate the "shared" directory.
axios, wx.request, fetch.
xhr/ajax、ofetchplanned
dio.download by system:
1.Install the @lonu/stc npm package.
pnpm add @lonu/stc -D
2.Open the project's package.json file and add the following command to scripts:
{
"scripts": {
"api": "stc --url=http://127.0.0.1:4523/export/openapi/2?version=3.1"
}
}
⚠️ Note: deno will not parse the ~ character as the user's home directory.
stc --url=https://petstore3.swagger.io/api/v3/openapi.json --outDir=out


Assume a project directory is:
.
├── src
│ └── apis # Copy the shared directory here.
│ └── shared
│ └── xxx.ts # Other files.
Find the directory of outDir, copy the entire shared directory to the directory of the axios module you encapsulated.
Open the shared > axios > index.ts file, copy the request method, and add it to the axios module you encapsulated. If it is not encapsulated, copy the index.ts file as a new file to avoid the problem of modification being overwritten.
Taking Vue as an example, add the following code to the main.ts file:
import { createApiClient } from './apis/shared/fetchRuntime';
createApiClient({
baseURL: 'https://api.xxx.com'
// onError(msg) {
// // 处理错误信息
// }
})
Find the directory of outDir, copy the entire directory of shared to the directory of the wechat module you encapsulated.
Open the shared > wechat > index.ts file, copy the request method, and add it to the wx.request code file you encapsulated. If it is not encapsulated, copy the index.ts file as a new file to avoid the problem of modification being overwritten.
Add the following code to the app.ts file:
import { createApiClient } from './apis/shared/fetchRuntime';
// import Notify from './miniprogram_npm/@vant/weapp/notify/notify';
App<IAppOption>({
onLaunch() {
createApiClient({
baseURL: 'https://api.xxx.com,
onError(msg) {
// Notify({ type: 'danger', message: msg, selector: '#v-notify'})
}
})
}
});
STC does not generate authentication code. For the axios client, inject a token into every request via onRequestInterceptor:
import { createApiClient } from './apis/shared/fetchRuntime';
createApiClient({
baseURL: 'https://api.xxx.com',
onRequestInterceptor(config) {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
},
onLogin() {
// Triggered when the response status is 401, e.g. redirect to the login page
}
})
For the
fetchorconfigargument of each generated method instead, e.g.getPetById(petId, { headers: { Authorization: 'Bearer xxx' } }).
| Option | Alias | Type | Default | Description |
|---|---|---|---|---|
| url | string | Swagger/OpenApi/Apifox document address, or local path (JSON or YAML). | ||
| outDir | o | string | ./stc_out | Output Directory. |
| client | string | axios | http request client. When lang is ts/js, the possible values are: axios, wechat, fetch. | |
| lang | l | string | ts | Language, used for output file suffix. |
| tag | number | Specify the tag from the interface url. By default, the first tag is read for the file name. | ||
| filter | f | string[] | Filter interfaces. Interfaces that meet the filter conditions will be generated. Example: --filter "/pet*", generate an interface for /pet, and support multiple --filter. For more usage information, please refer to micromatch | |
| conjunction | c | string | By | The method's connector, the default value is By. |
| actionIndex | number | -1 | The method name index, the default value is -1. | |
| shared | boolean | true | Whether to generate the shared directory. [default: true]. | |
| clean | boolean | true | Whether to clean the output directory before generating. [default: true]. | |
| globalHeader | gh | string[] | Global header key configuration, multiple can be set. When a single API has the same key, it will not appear as a parameter. | |
| version | v | boolean | Output version information. | |
| help | h | boolean | Output help information. |
Use --mcp to generate mcp-tools.json. The file contains the standard MCP tool fields (name, description, inputSchema) and an x-stc-http extension with the original HTTP method and path, so an MCP server can expose the tools and connect them to a generic HTTP executor.
stc --url=./openapi.yaml --mcp --outDir=./generated
The generated JSON is intentionally limited to tool discovery. Authentication, base URL selection, and HTTP execution remain in the MCP server/runtime that consumes the catalog.
For convenience, STC can not only develop plugins in Deno, but also provides @lonu/stc npm library, which can develop plugins in Node environment.
⚠️ Prepare the Deno environment.
Create a myPlugin.ts file:
// 引用模块
// import { start } from 'https://deno.land/x/stc@2.17.0/mod.ts'
import { start } from 'jsr:@lonu/stc@^2.17.0'
// Defining plugins
const myPlugin: IPlugin = {
name: 'stc:MyPlugin',
lang: 'ts',
setup(context: IPluginContext) {
// type map
return {
}
},
onTransform(def, action) {
// definition
const defContent: string = parserDefinition(
def
)
// action
const actionContent: Map<string, string> = parserAction(
action
)
return {
definition: {
filename: '_types.ts',
content: defContent,
},
action: actionContent // Here actionContent is of type Map<string, string>, key is the file name, value is the converted code.
}
},
onEnd() {
console.log('end')
}
}
// use plugin
start({
// ...other options
plugins: [myPlugin]
})
Create a myPlugin.ts file.
Add the @lonu/stc reference and use the start method:
import { start } from '@lonu/stc'
definition and action into the target language in the plugin's onTransform hook function.export const myPlugin: IPlugin = {
name: 'stc:MyPlugin',
lang: 'ts',
setup(context: IPluginContext) {
// type map
return {
}
},
onTransform(def, action) {
// definition
const defContent: string = parserDefinition(
def
)
// action
const actionContent: Map<string, string> = parserAction(
action
)
return {
definition: defContent,
action: actionContent
}
},
onEnd() {
console.log('end')
}
}
4.In the start method, add plugins:
start({
// ...other options
plugins: [myPlugin]
})
TypeScript
93.5%
Swift
4.2%
Dart
2.3%