api-spec-cli 0.2.3 → 0.2.5
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 +390 -282
- package/package.json +55 -41
- package/src/cli.js +338 -172
- package/src/commands/add.js +163 -78
- package/src/commands/auth.js +32 -0
- package/src/commands/call.js +224 -207
- package/src/commands/fetch.js +63 -27
- package/src/commands/grep.js +14 -11
- package/src/commands/list.js +89 -80
- package/src/commands/show.js +16 -7
- package/src/commands/skill.js +40 -0
- package/src/commands/specs.js +22 -9
- package/src/commands/types.js +6 -2
- package/src/commands/usage.js +15 -0
- package/src/commands/validate.js +33 -7
- package/src/dotenv.js +38 -0
- package/src/glob.js +6 -1
- package/src/mcp-client.js +91 -63
- package/src/oauth/auth-flow.js +59 -0
- package/src/oauth/provider.js +191 -0
- package/src/oauth/tokens.js +59 -0
- package/src/output.js +65 -61
- package/src/registry.js +36 -10
- package/src/resolve.js +66 -65
- package/src/secrets.js +46 -0
- package/src/skill/SKILL.md +112 -0
- package/src/usage.js +62 -0
package/README.md
CHANGED
|
@@ -1,282 +1,390 @@
|
|
|
1
|
-
# api-spec-cli
|
|
2
|
-
|
|
3
|
-
CLI for AI agents to explore and call OpenAPI, GraphQL, and MCP APIs. Output is JSON by default — compact, parseable, token-efficient.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g api-spec-cli
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Works with Node.js 18+. No other dependencies.
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
# Or run without installing
|
|
15
|
-
npx api-spec-cli <command>
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## How It Works
|
|
19
|
-
|
|
20
|
-
Every command is stateless — you specify the spec source on each call. Two paths:
|
|
21
|
-
|
|
22
|
-
| Path | When to use |
|
|
23
|
-
|---|---|
|
|
24
|
-
| `--spec <name>` | Registered spec — auto-fetches and caches on first use |
|
|
25
|
-
| Inline flags | Ad-hoc — no registration, fetched each call |
|
|
26
|
-
|
|
27
|
-
### Register once, use everywhere
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
spec add petstore --openapi https://petstore3.swagger.io/api/v3/openapi.json \
|
|
31
|
-
--base-url https://petstore3.swagger.io/api/v3 \
|
|
32
|
-
--description "Petstore example"
|
|
33
|
-
|
|
34
|
-
spec add hashnode --graphql https://gql.hashnode.com --auth YOUR_TOKEN
|
|
35
|
-
|
|
36
|
-
spec add agno --mcp-http https://docs.agno.com/mcp --description "Agno docs"
|
|
37
|
-
|
|
38
|
-
spec add fs --mcp-stdio "npx -y @modelcontextprotocol/server-filesystem /tmp"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Registration is instant — does not connect. Connection happens on first `list`/`show`/`call` and the result is cached at `~/spec-cli-config/cache/<name>.json`.
|
|
42
|
-
|
|
43
|
-
### Or use inline (no registration)
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
spec list --openapi https://petstore3.swagger.io/api/v3/openapi.json
|
|
47
|
-
spec list --graphql https://gql.hashnode.com
|
|
48
|
-
spec list --mcp-http https://docs.agno.com/mcp
|
|
49
|
-
spec list --mcp-sse http://localhost:3000/sse
|
|
50
|
-
spec list --mcp-stdio "npx -y @modelcontextprotocol/server-filesystem /tmp"
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Inline fetches every call, nothing cached.
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Discovery
|
|
58
|
-
|
|
59
|
-
### Search across specs
|
|
60
|
-
|
|
61
|
-
`grep` searches operation/tool names and descriptions across all registered specs.
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
spec grep search # Substring match across all specs
|
|
65
|
-
spec grep "get*" # Glob: anything starting with "get"
|
|
66
|
-
spec grep "*list*" # Glob: anything containing "list"
|
|
67
|
-
spec grep search --spec agno # Limit to one spec
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Matches on name and description. Case-insensitive. Plain text = substring, `*`/`?` = glob.
|
|
71
|
-
|
|
72
|
-
### List all specs in the registry
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
spec specs # Compact: name, type, enabled
|
|
76
|
-
spec specs --compact false # Full: includes source, config
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### List operations / tools
|
|
80
|
-
|
|
81
|
-
`list` is compact by default — just IDs, no schemas. Use `--filter`, `--tag`, `--limit` to narrow down.
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
spec list --spec agno # Registered spec (uses cache)
|
|
85
|
-
spec list --spec petstore --filter pet # Search by keyword
|
|
86
|
-
spec list --spec petstore --tag pets # OpenAPI: filter by tag
|
|
87
|
-
spec list --spec hashnode --tag mutation # GraphQL: filter by kind
|
|
88
|
-
spec list --spec petstore --limit 10 # First 10 only
|
|
89
|
-
spec list --spec petstore --limit 10 --offset 10 # Next 10
|
|
90
|
-
spec list --mcp-http https://docs.agno.com/mcp # Inline: no registration needed
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Compact output:
|
|
94
|
-
```json
|
|
95
|
-
{
|
|
96
|
-
"type": "mcp",
|
|
97
|
-
"total": 1,
|
|
98
|
-
"showing": 1,
|
|
99
|
-
"operations": [
|
|
100
|
-
{ "id": "search_agno", "description": "Search across the Agno knowledge base..." }
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Use `--compact false` for full details including `inputSchema` for MCP tools.
|
|
106
|
-
|
|
107
|
-
### Inspect one operation or tool
|
|
108
|
-
|
|
109
|
-
`show` gives you everything to make a call — params, body schema, response schemas, related types — in one call.
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
spec show --spec petstore getPetById # OpenAPI: by operationId
|
|
113
|
-
spec show --spec petstore /pet/{petId} # OpenAPI: by path
|
|
114
|
-
spec show --spec petstore "GET /pet/{petId}" # OpenAPI: by method + path
|
|
115
|
-
spec show --spec hashnode publishPost # GraphQL: by operation name
|
|
116
|
-
spec show --spec agno search_agno # MCP: by tool name
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
MCP output includes the full `inputSchema` so you know exactly what arguments to pass.
|
|
120
|
-
|
|
121
|
-
### Drill into types (OpenAPI/GraphQL only)
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
spec types --spec petstore # List all schema names
|
|
125
|
-
spec types --spec petstore Pet # Inspect one schema
|
|
126
|
-
spec types --spec hashnode PublishPostInput # GraphQL input type
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Calling APIs
|
|
132
|
-
|
|
133
|
-
```bash
|
|
134
|
-
# OpenAPI
|
|
135
|
-
spec call --spec petstore getPetById --var petId=1
|
|
136
|
-
spec call --spec petstore findPetsByStatus --query status=available
|
|
137
|
-
spec call --spec petstore addPet --data '{"name":"Rex","photoUrls":[]}'
|
|
138
|
-
|
|
139
|
-
# GraphQL (auto-generates query from schema)
|
|
140
|
-
spec call --spec hashnode me
|
|
141
|
-
spec call --spec hashnode publication --var host=blog.hashnode.dev
|
|
142
|
-
|
|
143
|
-
# MCP
|
|
144
|
-
spec call --spec agno search_agno --var query="how to create an agent"
|
|
145
|
-
spec call --spec agno search_agno --data '{"query":"agents"}'
|
|
146
|
-
|
|
147
|
-
# Read body from stdin (explicit --data -)
|
|
148
|
-
echo '{"query":"agents"}' | spec call --spec agno search_agno --data -
|
|
149
|
-
cat body.json | spec call --spec petstore addPet --data -
|
|
150
|
-
|
|
151
|
-
# Inline (no registration)
|
|
152
|
-
spec call --openapi https://petstore3.swagger.io/api/v3/openapi.json \
|
|
153
|
-
getPetById --var petId=1 --base-url https://petstore3.swagger.io/api/v3
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### Per-call overrides
|
|
157
|
-
|
|
158
|
-
Flags passed at call time win over registry entry config, which wins over `.spec-cli/config.json`.
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
spec call --spec agno search_agno --var query="foo" --header X-Tenant=acme
|
|
162
|
-
spec call --spec petstore getPetById --var petId=1 --auth staging-token
|
|
163
|
-
spec list --spec petstore --base-url https://staging.api.example.com
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Registry Management
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
spec remove <name> # Delete entry and remove cache
|
|
172
|
-
spec enable <name> # Re-enable a disabled spec
|
|
173
|
-
spec disable <name> # Disable without removing
|
|
174
|
-
spec refresh <name> # Force re-fetch and update cache
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
##
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
spec
|
|
185
|
-
spec
|
|
186
|
-
spec
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
spec add
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
spec
|
|
206
|
-
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
spec
|
|
226
|
-
spec
|
|
227
|
-
spec
|
|
228
|
-
spec
|
|
229
|
-
spec
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
spec
|
|
236
|
-
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
spec
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
-
|
|
256
|
-
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
1
|
+
# api-spec-cli
|
|
2
|
+
|
|
3
|
+
CLI for AI agents to explore and call OpenAPI, GraphQL, and MCP APIs. Output is JSON by default — compact, parseable, token-efficient.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g api-spec-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Works with Node.js 18+. No other dependencies.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Or run without installing
|
|
15
|
+
npx api-spec-cli <command>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
Every command is stateless — you specify the spec source on each call. Two paths:
|
|
21
|
+
|
|
22
|
+
| Path | When to use |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `--spec <name>` | Registered spec — auto-fetches and caches on first use |
|
|
25
|
+
| Inline flags | Ad-hoc — no registration, fetched each call |
|
|
26
|
+
|
|
27
|
+
### Register once, use everywhere
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
spec add petstore --openapi https://petstore3.swagger.io/api/v3/openapi.json \
|
|
31
|
+
--base-url https://petstore3.swagger.io/api/v3 \
|
|
32
|
+
--description "Petstore example"
|
|
33
|
+
|
|
34
|
+
spec add hashnode --graphql https://gql.hashnode.com --auth YOUR_TOKEN
|
|
35
|
+
|
|
36
|
+
spec add agno --mcp-http https://docs.agno.com/mcp --description "Agno docs"
|
|
37
|
+
|
|
38
|
+
spec add fs --mcp-stdio "npx -y @modelcontextprotocol/server-filesystem /tmp"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Registration is instant — does not connect. Connection happens on first `list`/`show`/`call` and the result is cached at `~/spec-cli-config/cache/<name>.json`.
|
|
42
|
+
|
|
43
|
+
### Or use inline (no registration)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
spec list --openapi https://petstore3.swagger.io/api/v3/openapi.json
|
|
47
|
+
spec list --graphql https://gql.hashnode.com
|
|
48
|
+
spec list --mcp-http https://docs.agno.com/mcp
|
|
49
|
+
spec list --mcp-sse http://localhost:3000/sse
|
|
50
|
+
spec list --mcp-stdio "npx -y @modelcontextprotocol/server-filesystem /tmp"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Inline fetches every call, nothing cached.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Discovery
|
|
58
|
+
|
|
59
|
+
### Search across specs
|
|
60
|
+
|
|
61
|
+
`grep` searches operation/tool names and descriptions across all registered specs.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
spec grep search # Substring match across all specs
|
|
65
|
+
spec grep "get*" # Glob: anything starting with "get"
|
|
66
|
+
spec grep "*list*" # Glob: anything containing "list"
|
|
67
|
+
spec grep search --spec agno # Limit to one spec
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Matches on name and description. Case-insensitive. Plain text = substring, `*`/`?` = glob.
|
|
71
|
+
|
|
72
|
+
### List all specs in the registry
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
spec specs # Compact: name, type, enabled
|
|
76
|
+
spec specs --compact false # Full: includes source, config
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### List operations / tools
|
|
80
|
+
|
|
81
|
+
`list` is compact by default — just IDs, no schemas. Use `--filter`, `--tag`, `--limit` to narrow down.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
spec list --spec agno # Registered spec (uses cache)
|
|
85
|
+
spec list --spec petstore --filter pet # Search by keyword
|
|
86
|
+
spec list --spec petstore --tag pets # OpenAPI: filter by tag
|
|
87
|
+
spec list --spec hashnode --tag mutation # GraphQL: filter by kind
|
|
88
|
+
spec list --spec petstore --limit 10 # First 10 only
|
|
89
|
+
spec list --spec petstore --limit 10 --offset 10 # Next 10
|
|
90
|
+
spec list --mcp-http https://docs.agno.com/mcp # Inline: no registration needed
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Compact output:
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"type": "mcp",
|
|
97
|
+
"total": 1,
|
|
98
|
+
"showing": 1,
|
|
99
|
+
"operations": [
|
|
100
|
+
{ "id": "search_agno", "description": "Search across the Agno knowledge base..." }
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use `--compact false` for full details including `inputSchema` for MCP tools.
|
|
106
|
+
|
|
107
|
+
### Inspect one operation or tool
|
|
108
|
+
|
|
109
|
+
`show` gives you everything to make a call — params, body schema, response schemas, related types — in one call.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
spec show --spec petstore getPetById # OpenAPI: by operationId
|
|
113
|
+
spec show --spec petstore /pet/{petId} # OpenAPI: by path
|
|
114
|
+
spec show --spec petstore "GET /pet/{petId}" # OpenAPI: by method + path
|
|
115
|
+
spec show --spec hashnode publishPost # GraphQL: by operation name
|
|
116
|
+
spec show --spec agno search_agno # MCP: by tool name
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
MCP output includes the full `inputSchema` so you know exactly what arguments to pass.
|
|
120
|
+
|
|
121
|
+
### Drill into types (OpenAPI/GraphQL only)
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
spec types --spec petstore # List all schema names
|
|
125
|
+
spec types --spec petstore Pet # Inspect one schema
|
|
126
|
+
spec types --spec hashnode PublishPostInput # GraphQL input type
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Calling APIs
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# OpenAPI
|
|
135
|
+
spec call --spec petstore getPetById --var petId=1
|
|
136
|
+
spec call --spec petstore findPetsByStatus --query status=available
|
|
137
|
+
spec call --spec petstore addPet --data '{"name":"Rex","photoUrls":[]}'
|
|
138
|
+
|
|
139
|
+
# GraphQL (auto-generates query from schema)
|
|
140
|
+
spec call --spec hashnode me
|
|
141
|
+
spec call --spec hashnode publication --var host=blog.hashnode.dev
|
|
142
|
+
|
|
143
|
+
# MCP
|
|
144
|
+
spec call --spec agno search_agno --var query="how to create an agent"
|
|
145
|
+
spec call --spec agno search_agno --data '{"query":"agents"}'
|
|
146
|
+
|
|
147
|
+
# Read body from stdin (explicit --data -)
|
|
148
|
+
echo '{"query":"agents"}' | spec call --spec agno search_agno --data -
|
|
149
|
+
cat body.json | spec call --spec petstore addPet --data -
|
|
150
|
+
|
|
151
|
+
# Inline (no registration)
|
|
152
|
+
spec call --openapi https://petstore3.swagger.io/api/v3/openapi.json \
|
|
153
|
+
getPetById --var petId=1 --base-url https://petstore3.swagger.io/api/v3
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Per-call overrides
|
|
157
|
+
|
|
158
|
+
Flags passed at call time win over registry entry config, which wins over `.spec-cli/config.json`.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
spec call --spec agno search_agno --var query="foo" --header X-Tenant=acme
|
|
162
|
+
spec call --spec petstore getPetById --var petId=1 --auth staging-token
|
|
163
|
+
spec list --spec petstore --base-url https://staging.api.example.com
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Registry Management
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
spec remove <name> # Delete entry and remove cache
|
|
172
|
+
spec enable <name> # Re-enable a disabled spec
|
|
173
|
+
spec disable <name> # Disable without removing
|
|
174
|
+
spec refresh <name> # Force re-fetch and update cache
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`spec add` is an upsert — re-adding an existing name overwrites the entry (and clears its stale cache), since there's no separate `update` command. The response includes `"overwritten": true` when an existing entry was replaced.
|
|
178
|
+
|
|
179
|
+
## Usage Ranking
|
|
180
|
+
|
|
181
|
+
`spec` records which operations/tools you call so agents can surface the ones that matter:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
spec list --spec petstore --top 5 # the 5 most-called operations first
|
|
185
|
+
spec usage # recorded usage across all specs
|
|
186
|
+
spec usage petstore # ranked operations for one spec
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Counts are stored locally in `~/spec-cli-config/usage.json`. `--top` applies after `--filter`/`--tag` and overrides `--limit`. Set `SPEC_NO_USAGE=1` to disable tracking.
|
|
190
|
+
|
|
191
|
+
## Secrets & Environment Overrides
|
|
192
|
+
|
|
193
|
+
Stored values can reference environment variables instead of holding raw secrets. Use `${VAR}` in `--auth` or header values — it's expanded from the environment at call time, never stored expanded:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
spec add gh --mcp-http https://api.example.com/mcp --header "Authorization=Bearer ${GH_TOKEN}"
|
|
197
|
+
spec config set auth '${API_TOKEN}'
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
A `.env` file in the working directory is auto-loaded on startup (real environment variables take precedence; set `SPEC_NO_DOTENV=1` to disable).
|
|
201
|
+
|
|
202
|
+
Two environment variables override a registered spec's connection per call — useful in CI:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
SPEC_URL=https://staging.example.com/mcp spec call --spec gh some_tool # override MCP/GraphQL endpoint
|
|
206
|
+
SPEC_HEADER_X_TENANT=acme spec list --spec gh # add/override a header
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`SPEC_HEADER_<NAME>` maps underscores to dashes (`SPEC_HEADER_X_TENANT` → `X-Tenant`). Precedence: call-time flags > env override > registry entry > project config.
|
|
210
|
+
|
|
211
|
+
## Agent Skill
|
|
212
|
+
|
|
213
|
+
Install a ready-made skill that teaches an agent the explore-then-call workflow:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
spec skill install # copy SKILL.md into ~/.claude/skills/api-spec-cli/
|
|
217
|
+
spec skill path # print the bundled SKILL.md location
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## spec add options
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
spec add <name> --openapi <url-or-file> [--base-url <url>] [--auth <token>] [--header k=v]
|
|
226
|
+
spec add <name> --graphql <url> [--auth <token>] [--header k=v]
|
|
227
|
+
spec add <name> --mcp-http <url> [--auth <token>] [--header k=v]
|
|
228
|
+
spec add <name> --mcp-sse <url> [--auth <token>] [--header k=v]
|
|
229
|
+
spec add <name> --mcp-stdio "<cmd args>" [--env KEY=VAL] [--cwd <path>]
|
|
230
|
+
[--description <text>] (all types)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
All options are repeatable where it makes sense (`--header`, `--env`). `--auth` adds `Authorization: Bearer <token>` unless the header is already set.
|
|
234
|
+
|
|
235
|
+
Operation filtering works for all spec types — MCP, OpenAPI, and GraphQL:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# MCP: allow only read/list tools
|
|
239
|
+
spec add <name> --mcp-http <url> \
|
|
240
|
+
--allow-tool "read_*" --allow-tool "list_*" \
|
|
241
|
+
--disable-tool "delete_*"
|
|
242
|
+
|
|
243
|
+
# OpenAPI: allow only GET operations (by operationId)
|
|
244
|
+
spec add <name> --openapi <url> \
|
|
245
|
+
--allow-tool "get*" --allow-tool "find*"
|
|
246
|
+
|
|
247
|
+
# GraphQL: allow specific operations by exact name
|
|
248
|
+
spec add <name> --graphql <url> \
|
|
249
|
+
--allow-tool "me" --allow-tool "publication"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`--allow-tool` keeps only matching operations. `--disable-tool` removes matching operations (applied after allow). Both are repeatable.
|
|
253
|
+
|
|
254
|
+
**Matching rules:**
|
|
255
|
+
- Plain text → **exact match** (case-insensitive): `"me"` matches only `me`
|
|
256
|
+
- Glob patterns → anchored match: `"get*"` matches `getPetById`, `"*post*"` matches `createPost`
|
|
257
|
+
|
|
258
|
+
Use `grep` for search (substring) — `--allow-tool` / `--disable-tool` for precise whitelists (exact or glob).
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## OAuth / Authentication
|
|
263
|
+
|
|
264
|
+
MCP HTTP and SSE servers that require OAuth 2.1 are handled automatically. spec-cli detects the 401 on `spec add` and runs the flow before returning.
|
|
265
|
+
|
|
266
|
+
Two modes depending on whether the server supports Dynamic Client Registration (DCR):
|
|
267
|
+
|
|
268
|
+
- **DCR-enabled servers** (e.g. self-hosted with Cloudflare workers-oauth-provider, Stytch, Curity) — no flags needed, browser opens automatically
|
|
269
|
+
- **Pre-registered-only servers** (e.g. GitHub) — pass `--oauth-client-id` with your app's client ID
|
|
270
|
+
|
|
271
|
+
### Interactive (browser) — default
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# DCR-enabled server: fully automatic
|
|
275
|
+
spec add myserver --mcp-http https://...
|
|
276
|
+
|
|
277
|
+
# GitHub (no DCR) — create an OAuth App at github.com/settings/developers first
|
|
278
|
+
# Set callback URL to http://127.0.0.1:8090/callback
|
|
279
|
+
spec add github --mcp-http https://api.githubcopilot.com/mcp/ \
|
|
280
|
+
--oauth-client-id <your-github-app-client-id> \
|
|
281
|
+
--oauth-callback-port 8090
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Headless / device flow
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
spec add myserver --mcp-http https://... --oauth-flow device
|
|
288
|
+
# Prints a URL to stderr — open in any browser to authorize
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Machine / CI (client credentials)
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
spec add myserver --mcp-http https://... \
|
|
295
|
+
--oauth-client-id <id> --oauth-client-secret <secret>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Re-authenticate
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
spec auth myserver # Re-run the OAuth flow
|
|
302
|
+
spec auth myserver --revoke # Clear stored token only
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Tokens are stored in `~/spec-cli-config/tokens/<name>.json` — separate from the cache, not touched by `spec refresh`. Access tokens are refreshed automatically: when a stored token expires, the refresh token is used and the rotated tokens are persisted, so the next command picks them up without re-authenticating.
|
|
306
|
+
|
|
307
|
+
### OAuth flags
|
|
308
|
+
|
|
309
|
+
| Flag | Description |
|
|
310
|
+
| --- | --- |
|
|
311
|
+
| `--oauth-client-id <id>` | Skip DCR — use a pre-registered OAuth app client ID |
|
|
312
|
+
| `--oauth-client-secret <secret>` | Use client credentials flow (machine/CI) |
|
|
313
|
+
| `--oauth-callback-port <port>` | Fixed callback port (required for apps with exact redirect URL match, e.g. GitHub) |
|
|
314
|
+
| `--oauth-flow device` | Force device authorization flow (headless/SSH) |
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Config
|
|
319
|
+
|
|
320
|
+
Persistent config stored in `.spec-cli/config.json` (lowest priority — overridden by registry entry config and call-time flags).
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
spec config set baseUrl https://api.example.com
|
|
324
|
+
spec config set auth my-token # Auto-adds "Bearer " prefix
|
|
325
|
+
spec config set auth "Basic dXNlcjpwYXNz" # Or explicit scheme
|
|
326
|
+
spec config set headers.X-API-Key abc123 # Custom header (dot notation)
|
|
327
|
+
spec config get
|
|
328
|
+
spec config unset auth
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Validate
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
spec validate https://api.example.com/openapi.json
|
|
335
|
+
spec validate ./openapi.yaml
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Reports broken `$ref` references, missing required fields, duplicate operationIds, invalid schema types, and more.
|
|
339
|
+
|
|
340
|
+
## Output Format
|
|
341
|
+
|
|
342
|
+
JSON by default. Errors go to stderr as `{"error": "message"}` with a non-zero exit code.
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
spec list --spec petstore --format text
|
|
346
|
+
spec show --spec petstore getPetById --format yaml
|
|
347
|
+
spec list --spec petstore --format toon # Token-Oriented Object Notation (densest)
|
|
348
|
+
spec list --spec petstore --format=json # equals syntax also works
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
`toon` ([Token-Oriented Object Notation](https://github.com/toon-format/spec)) is the most token-efficient format for tabular/list output — the best choice when feeding results back into a model. Errors are always JSON regardless of format.
|
|
352
|
+
|
|
353
|
+
## Token Efficiency
|
|
354
|
+
|
|
355
|
+
- `list` returns only IDs by default — no schemas
|
|
356
|
+
- `show` resolves `$ref` compactly — nested refs show as names, not explosions
|
|
357
|
+
- `types` lets you inspect one schema at a time
|
|
358
|
+
- `--limit` / `--offset` paginate large APIs
|
|
359
|
+
- `--filter` and `--tag` narrow results before output
|
|
360
|
+
|
|
361
|
+
## MCP Options
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
# Retry on connection failure (useful for stdio servers that take time to start)
|
|
365
|
+
MCP_MAX_RETRIES=3 # Attempts (default: 3)
|
|
366
|
+
MCP_RETRY_DELAY=1000 # Base delay in ms, doubles each attempt, capped at 5s (default: 1000)
|
|
367
|
+
|
|
368
|
+
# HTTP timeout for OpenAPI/GraphQL calls
|
|
369
|
+
SPEC_HTTP_TIMEOUT=30000 # ms (default: 30000)
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Stdio env vars support `${VAR}` expansion from the host environment:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
spec add fs --mcp-stdio "npx -y server /tmp" --env "TOKEN=${MY_SECRET}"
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Storage
|
|
379
|
+
|
|
380
|
+
| Path | Purpose |
|
|
381
|
+
|---|---|
|
|
382
|
+
| `~/spec-cli-config/registry.json` | Global named registry |
|
|
383
|
+
| `~/spec-cli-config/cache/<name>.json` | Cached spec per registered entry |
|
|
384
|
+
| `~/spec-cli-config/tokens/<name>.json` | OAuth tokens per MCP entry |
|
|
385
|
+
| `~/spec-cli-config/usage.json` | Operation/tool call counts for `--top` and `spec usage` |
|
|
386
|
+
| `.spec-cli/config.json` | Project-local config (baseUrl, auth, headers) |
|
|
387
|
+
|
|
388
|
+
## Planned
|
|
389
|
+
|
|
390
|
+
- `spec import <file>` — bulk import servers from VS Code `mcp.json` or Claude Desktop config format
|