mcp-insomnia 0.1.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 +125 -0
- package/dist/.claude/settings.local.json +9 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/resources.d.ts +11 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +449 -0
- package/dist/resources.js.map +1 -0
- package/dist/storage.d.ts +38 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +205 -0
- package/dist/storage.js.map +1 -0
- package/dist/tools.d.ts +10 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +698 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# MCP-Insomnia
|
|
2
|
+
|
|
3
|
+
MCP-Insomnia is an MCP (Model Context Protocol) server that enables AI agents to create and manage API collections in Insomnia-compatible format. This server provides tools and resources for managing collections, requests, and environments that can be exported to Insomnia.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Node.js 18+
|
|
10
|
+
- npm or yarn
|
|
11
|
+
|
|
12
|
+
### Install from NPM
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g mcp-insomnia
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Install from Source
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/anggasct/mcp-insomnia.git
|
|
22
|
+
cd mcp-insomnia
|
|
23
|
+
npm install
|
|
24
|
+
npm run build
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Add to MCP Configuration
|
|
28
|
+
|
|
29
|
+
Add to your MCP client configuration:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcpServers": {
|
|
34
|
+
"insomnia": {
|
|
35
|
+
"command": "mcp-insomnia"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or if installed from source:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"insomnia": {
|
|
47
|
+
"command": "node",
|
|
48
|
+
"args": ["/path/to/mcp-insomnia/dist/index.js"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Available Tools
|
|
55
|
+
|
|
56
|
+
### Collection Management
|
|
57
|
+
|
|
58
|
+
- `create_collection` - Create new collection/workspace
|
|
59
|
+
- `list_collections` - List all collections
|
|
60
|
+
- `export_collection` - Export collection to JSON format
|
|
61
|
+
- `import_from_insomnia_export` - Import collections from a standard Insomnia V4 export file
|
|
62
|
+
|
|
63
|
+
### Folder Management
|
|
64
|
+
|
|
65
|
+
- `create_folder` - Create folder within collection
|
|
66
|
+
|
|
67
|
+
### Request Management
|
|
68
|
+
|
|
69
|
+
- `create_request_in_collection` - Create new request
|
|
70
|
+
- `update_request` - Update existing request
|
|
71
|
+
- `delete_request` - Delete request
|
|
72
|
+
- `execute_request` - Execute request and view response
|
|
73
|
+
|
|
74
|
+
### Environment Management
|
|
75
|
+
|
|
76
|
+
- `set_environment_variable` - Set environment variable
|
|
77
|
+
- `get_environment_variables` - Get environment variables
|
|
78
|
+
|
|
79
|
+
## Available Resources
|
|
80
|
+
|
|
81
|
+
- `insomnia://collections` - List all collections
|
|
82
|
+
- `insomnia://requests` - List all requests. Can be filtered by `?collectionId={id}`.
|
|
83
|
+
- `insomnia://environments` - List environment variables. Can be filtered by `?collectionId={id}`.
|
|
84
|
+
- `insomnia://collection/{id}` - Specific collection details
|
|
85
|
+
- `insomnia://request/{id}` - Specific request details
|
|
86
|
+
- `insomnia://request/{id}/history` - Get the execution history for a specific request
|
|
87
|
+
- `insomnia://search?q={keyword}` - Search across all collections, folders, and requests.
|
|
88
|
+
- `insomnia://stats` - Global statistics
|
|
89
|
+
|
|
90
|
+
## Usage Examples
|
|
91
|
+
|
|
92
|
+
### Create Collection
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Create a new collection named "API Testing" for testing endpoints
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Add Request
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Add GET request to "API Testing" collection with:
|
|
102
|
+
- Name: Get Users
|
|
103
|
+
- URL: https://jsonplaceholder.typicode.com/users
|
|
104
|
+
- Headers: Content-Type: application/json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Set Environment Variable
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
Set environment variable "baseUrl" with value "https://api.example.com" for "API Testing" collection
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Execute Request
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
Execute "Get Users" request using the configured environment variables
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Data Storage
|
|
120
|
+
|
|
121
|
+
Data is stored in `~/.mcp-insomnia/collections.json` in JSON format.
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT License
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { createInsomniaTools } from './tools.js';
|
|
6
|
+
import { createInsomniaResources } from './resources.js';
|
|
7
|
+
const server = new Server({
|
|
8
|
+
name: 'mcp-insomnia',
|
|
9
|
+
version: '0.1.0',
|
|
10
|
+
}, {
|
|
11
|
+
capabilities: {
|
|
12
|
+
tools: {},
|
|
13
|
+
resources: {},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
const tools = createInsomniaTools();
|
|
17
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
18
|
+
return {
|
|
19
|
+
tools: tools.map(tool => ({
|
|
20
|
+
name: tool.name,
|
|
21
|
+
description: tool.description,
|
|
22
|
+
inputSchema: tool.inputSchema,
|
|
23
|
+
})),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
27
|
+
const { name } = request.params;
|
|
28
|
+
const tool = tools.find(t => t.name === name);
|
|
29
|
+
if (!tool) {
|
|
30
|
+
throw new Error(`Tool ${name} not found`);
|
|
31
|
+
}
|
|
32
|
+
return await tool.handler(request);
|
|
33
|
+
});
|
|
34
|
+
const resources = createInsomniaResources();
|
|
35
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
36
|
+
return {
|
|
37
|
+
resources: resources.map(resource => ({
|
|
38
|
+
uri: resource.uri,
|
|
39
|
+
name: resource.name,
|
|
40
|
+
description: resource.description,
|
|
41
|
+
mimeType: resource.mimeType,
|
|
42
|
+
})),
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
46
|
+
const { uri } = request.params;
|
|
47
|
+
const resource = resources.find(r => r.uri === uri || uri.startsWith(r.uri.replace('{id}', '')));
|
|
48
|
+
if (!resource) {
|
|
49
|
+
throw new Error(`Resource ${uri} not found`);
|
|
50
|
+
}
|
|
51
|
+
return await resource.handler(request);
|
|
52
|
+
});
|
|
53
|
+
async function main() {
|
|
54
|
+
const transport = new StdioServerTransport();
|
|
55
|
+
await server.connect(transport);
|
|
56
|
+
console.error('MCP Insomnia server running on stdio');
|
|
57
|
+
}
|
|
58
|
+
main().catch((error) => {
|
|
59
|
+
console.error('Server error:', error);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReadResourceRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
interface Resource {
|
|
3
|
+
uri: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
handler: (request: ReadResourceRequest) => Promise<any>;
|
|
8
|
+
}
|
|
9
|
+
export declare function createInsomniaResources(): Resource[];
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAIzE,UAAU,QAAQ;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACzD;AAED,wBAAgB,uBAAuB,IAAI,QAAQ,EAAE,CAuepD"}
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import { storage } from './storage.js';
|
|
2
|
+
export function createInsomniaResources() {
|
|
3
|
+
return [
|
|
4
|
+
{
|
|
5
|
+
uri: 'insomnia://collections',
|
|
6
|
+
name: 'Collections',
|
|
7
|
+
description: 'List all collections with folder structure',
|
|
8
|
+
mimeType: 'application/json',
|
|
9
|
+
handler: async () => {
|
|
10
|
+
const collections = storage.getAllCollections();
|
|
11
|
+
const result = Array.from(collections.entries()).map(([id, structure]) => ({
|
|
12
|
+
id,
|
|
13
|
+
name: structure.workspace.name,
|
|
14
|
+
description: structure.workspace.description,
|
|
15
|
+
scope: structure.workspace.scope,
|
|
16
|
+
created: new Date(structure.workspace.created).toISOString(),
|
|
17
|
+
modified: new Date(structure.workspace.modified).toISOString(),
|
|
18
|
+
folders: structure.folders.map(folder => ({
|
|
19
|
+
id: folder._id,
|
|
20
|
+
name: folder.name,
|
|
21
|
+
description: folder.description,
|
|
22
|
+
parentId: folder.parentId,
|
|
23
|
+
created: new Date(folder.created).toISOString(),
|
|
24
|
+
modified: new Date(folder.modified).toISOString(),
|
|
25
|
+
})),
|
|
26
|
+
requestCount: structure.requests.length,
|
|
27
|
+
environmentCount: structure.environments.length,
|
|
28
|
+
}));
|
|
29
|
+
return {
|
|
30
|
+
contents: [
|
|
31
|
+
{
|
|
32
|
+
type: 'text',
|
|
33
|
+
text: JSON.stringify(result, null, 2),
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
uri: 'insomnia://requests',
|
|
41
|
+
name: 'Requests',
|
|
42
|
+
description: 'List all requests in collections with metadata. Can be filtered with ?collectionId={id}',
|
|
43
|
+
mimeType: 'application/json',
|
|
44
|
+
handler: async (request) => {
|
|
45
|
+
const allRequests = [];
|
|
46
|
+
const uri = request.params.uri;
|
|
47
|
+
const url = new URL(uri);
|
|
48
|
+
const collectionIdFilter = url.searchParams.get('collectionId');
|
|
49
|
+
const collections = collectionIdFilter
|
|
50
|
+
? new Map([[collectionIdFilter, storage.getCollection(collectionIdFilter)]])
|
|
51
|
+
: storage.getAllCollections();
|
|
52
|
+
for (const [collectionId, structure] of collections.entries()) {
|
|
53
|
+
if (!structure)
|
|
54
|
+
continue; // Skip if a filtered collection is not found
|
|
55
|
+
const requests = structure.requests.map(request => ({
|
|
56
|
+
id: request._id,
|
|
57
|
+
collectionId,
|
|
58
|
+
collectionName: structure.workspace.name,
|
|
59
|
+
parentId: request.parentId,
|
|
60
|
+
parentName: structure.folders.find(f => f._id === request.parentId)?.name ?? 'Root',
|
|
61
|
+
name: request.name,
|
|
62
|
+
description: request.description,
|
|
63
|
+
method: request.method,
|
|
64
|
+
url: request.url,
|
|
65
|
+
hasAuthentication: !!request.authentication,
|
|
66
|
+
headerCount: request.headers?.length || 0,
|
|
67
|
+
parameterCount: request.parameters?.length || 0,
|
|
68
|
+
hasBody: !!request.body,
|
|
69
|
+
created: new Date(request.created).toISOString(),
|
|
70
|
+
modified: new Date(request.modified).toISOString(),
|
|
71
|
+
}));
|
|
72
|
+
allRequests.push(...requests);
|
|
73
|
+
}
|
|
74
|
+
allRequests.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
|
|
75
|
+
return {
|
|
76
|
+
contents: [
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: JSON.stringify(allRequests, null, 2),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
uri: 'insomnia://environments',
|
|
87
|
+
name: 'Environments',
|
|
88
|
+
description: 'List environment variables per collection. Can be filtered with ?collectionId={id}',
|
|
89
|
+
mimeType: 'application/json',
|
|
90
|
+
handler: async (request) => {
|
|
91
|
+
const allEnvironments = [];
|
|
92
|
+
const uri = request.params.uri;
|
|
93
|
+
const url = new URL(uri);
|
|
94
|
+
const collectionIdFilter = url.searchParams.get('collectionId');
|
|
95
|
+
const collections = collectionIdFilter
|
|
96
|
+
? new Map([[collectionIdFilter, storage.getCollection(collectionIdFilter)]])
|
|
97
|
+
: storage.getAllCollections();
|
|
98
|
+
for (const [collectionId, structure] of collections.entries()) {
|
|
99
|
+
if (!structure)
|
|
100
|
+
continue; // Skip if a filtered collection is not found
|
|
101
|
+
const environments = structure.environments.map(env => ({
|
|
102
|
+
id: env._id,
|
|
103
|
+
collectionId,
|
|
104
|
+
collectionName: structure.workspace.name,
|
|
105
|
+
name: env.name,
|
|
106
|
+
description: env.description,
|
|
107
|
+
variableCount: Object.keys(env.data || {}).length,
|
|
108
|
+
variables: Object.entries(env.data || {}).map(([key, value]) => ({
|
|
109
|
+
key,
|
|
110
|
+
value: typeof value === 'string' && value.length > 100 ? `${value.substring(0, 100)}...` : value,
|
|
111
|
+
type: typeof value,
|
|
112
|
+
})),
|
|
113
|
+
isPrivate: env.isPrivate || false,
|
|
114
|
+
created: new Date(env.created).toISOString(),
|
|
115
|
+
modified: new Date(env.modified).toISOString(),
|
|
116
|
+
}));
|
|
117
|
+
allEnvironments.push(...environments);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
contents: [
|
|
121
|
+
{
|
|
122
|
+
type: 'text',
|
|
123
|
+
text: JSON.stringify(allEnvironments, null, 2),
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
uri: 'insomnia://collection/{id}',
|
|
131
|
+
name: 'Collection Detail',
|
|
132
|
+
description: 'Full details of a specific collection',
|
|
133
|
+
mimeType: 'application/json',
|
|
134
|
+
handler: async (request) => {
|
|
135
|
+
const uri = request.params.uri;
|
|
136
|
+
const collectionId = uri.replace('insomnia://collection/', '');
|
|
137
|
+
const structure = storage.getCollection(collectionId);
|
|
138
|
+
if (!structure) {
|
|
139
|
+
throw new Error(`Collection with ID ${collectionId} not found`);
|
|
140
|
+
}
|
|
141
|
+
const result = {
|
|
142
|
+
workspace: {
|
|
143
|
+
id: structure.workspace._id,
|
|
144
|
+
name: structure.workspace.name,
|
|
145
|
+
description: structure.workspace.description,
|
|
146
|
+
scope: structure.workspace.scope,
|
|
147
|
+
created: new Date(structure.workspace.created).toISOString(),
|
|
148
|
+
modified: new Date(structure.workspace.modified).toISOString(),
|
|
149
|
+
},
|
|
150
|
+
structure: {
|
|
151
|
+
folders: structure.folders.map(folder => ({
|
|
152
|
+
id: folder._id,
|
|
153
|
+
name: folder.name,
|
|
154
|
+
description: folder.description,
|
|
155
|
+
parentId: folder.parentId,
|
|
156
|
+
requestCount: structure.requests.filter(r => r.parentId === folder._id).length,
|
|
157
|
+
})),
|
|
158
|
+
requests: structure.requests.map(request => ({
|
|
159
|
+
id: request._id,
|
|
160
|
+
name: request.name,
|
|
161
|
+
method: request.method,
|
|
162
|
+
url: request.url,
|
|
163
|
+
parentId: request.parentId,
|
|
164
|
+
parentName: request.parentId === collectionId
|
|
165
|
+
? 'Root'
|
|
166
|
+
: structure.folders.find(f => f._id === request.parentId)?.name ?? 'Unknown',
|
|
167
|
+
hasAuth: !!request.authentication,
|
|
168
|
+
authType: request.authentication?.type,
|
|
169
|
+
})),
|
|
170
|
+
environments: structure.environments.map(env => ({
|
|
171
|
+
id: env._id,
|
|
172
|
+
name: env.name,
|
|
173
|
+
variableCount: Object.keys(env.data || {}).length,
|
|
174
|
+
})),
|
|
175
|
+
},
|
|
176
|
+
statistics: {
|
|
177
|
+
totalRequests: structure.requests.length,
|
|
178
|
+
totalFolders: structure.folders.length,
|
|
179
|
+
totalEnvironments: structure.environments.length,
|
|
180
|
+
methodBreakdown: structure.requests.reduce((acc, req) => {
|
|
181
|
+
acc[req.method] = (acc[req.method] || 0) + 1;
|
|
182
|
+
return acc;
|
|
183
|
+
}, {}),
|
|
184
|
+
authenticationBreakdown: structure.requests.reduce((acc, req) => {
|
|
185
|
+
const authType = req.authentication?.type ?? 'none';
|
|
186
|
+
acc[authType] = (acc[authType] || 0) + 1;
|
|
187
|
+
return acc;
|
|
188
|
+
}, {}),
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
contents: [
|
|
193
|
+
{
|
|
194
|
+
type: 'text',
|
|
195
|
+
text: JSON.stringify(result, null, 2),
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
uri: 'insomnia://request/{id}',
|
|
203
|
+
name: 'Request Detail',
|
|
204
|
+
description: 'Full details of a specific request',
|
|
205
|
+
mimeType: 'application/json',
|
|
206
|
+
handler: async (request) => {
|
|
207
|
+
const uri = request.params.uri;
|
|
208
|
+
const requestId = uri.replace('insomnia://request/', '');
|
|
209
|
+
let targetRequest = null;
|
|
210
|
+
let collectionInfo = null;
|
|
211
|
+
const collections = storage.getAllCollections();
|
|
212
|
+
for (const [collectionId, structure] of collections.entries()) {
|
|
213
|
+
const foundRequest = structure.requests.find(r => r._id === requestId);
|
|
214
|
+
if (foundRequest) {
|
|
215
|
+
targetRequest = foundRequest;
|
|
216
|
+
collectionInfo = {
|
|
217
|
+
id: collectionId,
|
|
218
|
+
name: structure.workspace.name,
|
|
219
|
+
parentName: foundRequest.parentId === collectionId
|
|
220
|
+
? 'Root'
|
|
221
|
+
: structure.folders.find(f => f._id === foundRequest.parentId)?.name ?? 'Unknown',
|
|
222
|
+
};
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!targetRequest) {
|
|
227
|
+
throw new Error(`Request with ID ${requestId} not found`);
|
|
228
|
+
}
|
|
229
|
+
const result = {
|
|
230
|
+
id: targetRequest._id,
|
|
231
|
+
name: targetRequest.name,
|
|
232
|
+
description: targetRequest.description,
|
|
233
|
+
method: targetRequest.method,
|
|
234
|
+
url: targetRequest.url,
|
|
235
|
+
collection: collectionInfo,
|
|
236
|
+
headers: targetRequest.headers || [],
|
|
237
|
+
parameters: targetRequest.parameters || [],
|
|
238
|
+
body: targetRequest.body || null,
|
|
239
|
+
authentication: targetRequest.authentication ? {
|
|
240
|
+
type: targetRequest.authentication.type,
|
|
241
|
+
hasCredentials: !!(targetRequest.authentication.username ?? targetRequest.authentication.token),
|
|
242
|
+
} : null,
|
|
243
|
+
metadata: {
|
|
244
|
+
created: new Date(targetRequest.created).toISOString(),
|
|
245
|
+
modified: new Date(targetRequest.modified).toISOString(),
|
|
246
|
+
hasHeaders: (targetRequest.headers || []).length > 0,
|
|
247
|
+
hasParameters: (targetRequest.parameters || []).length > 0,
|
|
248
|
+
hasBody: !!targetRequest.body,
|
|
249
|
+
hasAuthentication: !!targetRequest.authentication,
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
return {
|
|
253
|
+
contents: [
|
|
254
|
+
{
|
|
255
|
+
type: 'text',
|
|
256
|
+
text: JSON.stringify(result, null, 2),
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
uri: 'insomnia://request/{id}/history',
|
|
264
|
+
name: 'Request Execution History',
|
|
265
|
+
description: 'Get the execution history of a specific request',
|
|
266
|
+
mimeType: 'application/json',
|
|
267
|
+
handler: async (request) => {
|
|
268
|
+
const uri = request.params.uri;
|
|
269
|
+
const requestId = uri.replace('insomnia://request/', '').replace('/history', '');
|
|
270
|
+
let targetRequest = null;
|
|
271
|
+
const collections = storage.getAllCollections();
|
|
272
|
+
for (const structure of collections.values()) {
|
|
273
|
+
const foundRequest = structure.requests.find(r => r._id === requestId);
|
|
274
|
+
if (foundRequest) {
|
|
275
|
+
targetRequest = foundRequest;
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (!targetRequest) {
|
|
280
|
+
throw new Error(`Request with ID ${requestId} not found`);
|
|
281
|
+
}
|
|
282
|
+
const history = (targetRequest.history || []).map(h => ({
|
|
283
|
+
id: h._id,
|
|
284
|
+
timestamp: new Date(h.timestamp).toISOString(),
|
|
285
|
+
response: {
|
|
286
|
+
statusCode: h.response.statusCode,
|
|
287
|
+
statusMessage: h.response.statusMessage,
|
|
288
|
+
duration: h.response.duration,
|
|
289
|
+
size: h.response.size,
|
|
290
|
+
headers: h.response.headers,
|
|
291
|
+
body: h.response.body,
|
|
292
|
+
},
|
|
293
|
+
error: h.error,
|
|
294
|
+
}));
|
|
295
|
+
return {
|
|
296
|
+
contents: [
|
|
297
|
+
{
|
|
298
|
+
type: 'text',
|
|
299
|
+
text: JSON.stringify(history, null, 2),
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
};
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
uri: 'insomnia://search',
|
|
307
|
+
name: 'Search',
|
|
308
|
+
description: 'Search for a keyword across all collections, folders, and requests. Use with ?q=keyword',
|
|
309
|
+
mimeType: 'application/json',
|
|
310
|
+
handler: async (request) => {
|
|
311
|
+
const uri = request.params.uri;
|
|
312
|
+
const url = new URL(uri);
|
|
313
|
+
const keyword = url.searchParams.get('q');
|
|
314
|
+
if (!keyword) {
|
|
315
|
+
throw new Error('Search keyword must be provided with ?q=');
|
|
316
|
+
}
|
|
317
|
+
const searchResults = [];
|
|
318
|
+
const collections = storage.getAllCollections();
|
|
319
|
+
const lowerCaseKeyword = keyword.toLowerCase();
|
|
320
|
+
for (const [collectionId, structure] of collections.entries()) {
|
|
321
|
+
// Search in workspace
|
|
322
|
+
if (structure.workspace.name.toLowerCase().includes(lowerCaseKeyword) ||
|
|
323
|
+
(structure.workspace.description || '').toLowerCase().includes(lowerCaseKeyword)) {
|
|
324
|
+
searchResults.push({
|
|
325
|
+
type: 'Collection',
|
|
326
|
+
id: collectionId,
|
|
327
|
+
name: structure.workspace.name,
|
|
328
|
+
match: 'Name or description',
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
// Search in folders
|
|
332
|
+
for (const folder of structure.folders) {
|
|
333
|
+
if (folder.name.toLowerCase().includes(lowerCaseKeyword) ||
|
|
334
|
+
(folder.description || '').toLowerCase().includes(lowerCaseKeyword)) {
|
|
335
|
+
searchResults.push({
|
|
336
|
+
type: 'Folder',
|
|
337
|
+
id: folder._id,
|
|
338
|
+
name: folder.name,
|
|
339
|
+
collection: { id: collectionId, name: structure.workspace.name },
|
|
340
|
+
match: 'Name or description',
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
// Search in requests
|
|
345
|
+
for (const req of structure.requests) {
|
|
346
|
+
let matchReason = '';
|
|
347
|
+
if (req.name.toLowerCase().includes(lowerCaseKeyword))
|
|
348
|
+
matchReason = 'Name';
|
|
349
|
+
else if ((req.description || '').toLowerCase().includes(lowerCaseKeyword))
|
|
350
|
+
matchReason = 'Description';
|
|
351
|
+
else if (req.url.toLowerCase().includes(lowerCaseKeyword))
|
|
352
|
+
matchReason = 'URL';
|
|
353
|
+
else if (req.method.toLowerCase().includes(lowerCaseKeyword))
|
|
354
|
+
matchReason = 'Method';
|
|
355
|
+
if (matchReason) {
|
|
356
|
+
searchResults.push({
|
|
357
|
+
type: 'Request',
|
|
358
|
+
id: req._id,
|
|
359
|
+
name: req.name,
|
|
360
|
+
collection: { id: collectionId, name: structure.workspace.name },
|
|
361
|
+
match: matchReason,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
contents: [
|
|
368
|
+
{
|
|
369
|
+
type: 'text',
|
|
370
|
+
text: JSON.stringify(searchResults, null, 2),
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
};
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
uri: 'insomnia://stats',
|
|
378
|
+
name: 'Statistics',
|
|
379
|
+
description: 'Global statistics of all collections',
|
|
380
|
+
mimeType: 'application/json',
|
|
381
|
+
handler: async () => {
|
|
382
|
+
const collections = storage.getAllCollections();
|
|
383
|
+
const totalCollections = collections.size;
|
|
384
|
+
let totalRequests = 0;
|
|
385
|
+
let totalFolders = 0;
|
|
386
|
+
let totalEnvironments = 0;
|
|
387
|
+
let totalEnvironmentVariables = 0;
|
|
388
|
+
const methodStats = {};
|
|
389
|
+
const authStats = {};
|
|
390
|
+
const recentActivity = [];
|
|
391
|
+
for (const [collectionId, structure] of collections.entries()) {
|
|
392
|
+
totalRequests += structure.requests.length;
|
|
393
|
+
totalFolders += structure.folders.length;
|
|
394
|
+
totalEnvironments += structure.environments.length;
|
|
395
|
+
structure.environments.forEach(env => {
|
|
396
|
+
totalEnvironmentVariables += Object.keys(env.data || {}).length;
|
|
397
|
+
});
|
|
398
|
+
structure.requests.forEach(request => {
|
|
399
|
+
methodStats[request.method] = (methodStats[request.method] || 0) + 1;
|
|
400
|
+
const authType = request.authentication?.type ?? 'none';
|
|
401
|
+
authStats[authType] = (authStats[authType] || 0) + 1;
|
|
402
|
+
recentActivity.push({
|
|
403
|
+
type: 'request',
|
|
404
|
+
id: request._id,
|
|
405
|
+
name: request.name,
|
|
406
|
+
collectionName: structure.workspace.name,
|
|
407
|
+
method: request.method,
|
|
408
|
+
modified: request.modified,
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
recentActivity.push({
|
|
412
|
+
type: 'collection',
|
|
413
|
+
id: collectionId,
|
|
414
|
+
name: structure.workspace.name,
|
|
415
|
+
requestCount: structure.requests.length,
|
|
416
|
+
modified: structure.workspace.modified,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
recentActivity.sort((a, b) => b.modified - a.modified);
|
|
420
|
+
const result = {
|
|
421
|
+
summary: {
|
|
422
|
+
totalCollections,
|
|
423
|
+
totalRequests,
|
|
424
|
+
totalFolders,
|
|
425
|
+
totalEnvironments,
|
|
426
|
+
totalEnvironmentVariables,
|
|
427
|
+
},
|
|
428
|
+
methodBreakdown: methodStats,
|
|
429
|
+
authenticationBreakdown: authStats,
|
|
430
|
+
recentActivity: recentActivity.slice(0, 20),
|
|
431
|
+
averages: {
|
|
432
|
+
requestsPerCollection: totalCollections > 0 ? Math.round(totalRequests / totalCollections * 100) / 100 : 0,
|
|
433
|
+
foldersPerCollection: totalCollections > 0 ? Math.round(totalFolders / totalCollections * 100) / 100 : 0,
|
|
434
|
+
environmentsPerCollection: totalCollections > 0 ? Math.round(totalEnvironments / totalCollections * 100) / 100 : 0,
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
contents: [
|
|
439
|
+
{
|
|
440
|
+
type: 'text',
|
|
441
|
+
text: JSON.stringify(result, null, 2),
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
};
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
];
|
|
448
|
+
}
|
|
449
|
+
//# sourceMappingURL=resources.js.map
|