@ampeco/public-api-mcp 0.2.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/LICENSE +21 -0
- package/README.md +734 -0
- package/dist/build/flattener.d.ts +39 -0
- package/dist/build/flattener.d.ts.map +1 -0
- package/dist/build/flattener.js +193 -0
- package/dist/build/flattener.js.map +1 -0
- package/dist/build/index.d.ts +13 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +175 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/optimizer.d.ts +32 -0
- package/dist/build/optimizer.d.ts.map +1 -0
- package/dist/build/optimizer.js +222 -0
- package/dist/build/optimizer.js.map +1 -0
- package/dist/build/parser.d.ts +35 -0
- package/dist/build/parser.d.ts.map +1 -0
- package/dist/build/parser.js +83 -0
- package/dist/build/parser.js.map +1 -0
- package/dist/build/types.d.ts +91 -0
- package/dist/build/types.d.ts.map +1 -0
- package/dist/build/types.js +5 -0
- package/dist/build/types.js.map +1 -0
- package/dist/build/zod-generator.d.ts +34 -0
- package/dist/build/zod-generator.d.ts.map +1 -0
- package/dist/build/zod-generator.js +317 -0
- package/dist/build/zod-generator.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/generated/build-stats.json +7 -0
- package/dist/generated/endpoints.json +32181 -0
- package/dist/generated/schemas.d.ts +8157 -0
- package/dist/generated/schemas.d.ts.map +1 -0
- package/dist/generated/schemas.js +2726 -0
- package/dist/generated/schemas.js.map +1 -0
- package/dist/generated/schemas.ts +3171 -0
- package/dist/server/factory.d.ts +11 -0
- package/dist/server/factory.d.ts.map +1 -0
- package/dist/server/factory.js +450 -0
- package/dist/server/factory.js.map +1 -0
- package/dist/server/factory.test.d.ts +5 -0
- package/dist/server/factory.test.d.ts.map +1 -0
- package/dist/server/factory.test.js +77 -0
- package/dist/server/factory.test.js.map +1 -0
- package/dist/server/http.d.ts +10 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +110 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1502 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/loader.d.ts +10 -0
- package/dist/server/loader.d.ts.map +1 -0
- package/dist/server/loader.js +19 -0
- package/dist/server/loader.js.map +1 -0
- package/dist/server/prompts.d.ts +6 -0
- package/dist/server/prompts.d.ts.map +1 -0
- package/dist/server/prompts.js +462 -0
- package/dist/server/prompts.js.map +1 -0
- package/dist/server/stdio.d.ts +10 -0
- package/dist/server/stdio.d.ts.map +1 -0
- package/dist/server/stdio.js +25 -0
- package/dist/server/stdio.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Factory
|
|
3
|
+
* Creates and configures MCP server instances with shared logic for resources, tools, and prompts
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
import type { BuildOutput } from '../build/types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create and configure the MCP server
|
|
9
|
+
*/
|
|
10
|
+
export declare function createServer(endpoints: BuildOutput, bearerToken: string, hostname: string): McpServer;
|
|
11
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAihBrG"}
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Factory
|
|
3
|
+
* Creates and configures MCP server instances with shared logic for resources, tools, and prompts
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import fetch from 'node-fetch';
|
|
9
|
+
import { getPromptContent } from './prompts.js';
|
|
10
|
+
/**
|
|
11
|
+
* Create and configure the MCP server
|
|
12
|
+
*/
|
|
13
|
+
export function createServer(endpoints, bearerToken, hostname) {
|
|
14
|
+
const server = new McpServer({
|
|
15
|
+
name: 'public-api-mcp',
|
|
16
|
+
version: '0.1.0',
|
|
17
|
+
}, {
|
|
18
|
+
capabilities: {
|
|
19
|
+
resources: {},
|
|
20
|
+
tools: {},
|
|
21
|
+
prompts: {},
|
|
22
|
+
logging: {},
|
|
23
|
+
},
|
|
24
|
+
instructions: `This server provides access to the ${endpoints.info.title} API (v${endpoints.info.version}).
|
|
25
|
+
|
|
26
|
+
It exposes ${endpoints.endpoints.filter(e => !e.deprecated).length} active API endpoints through a hierarchical resource structure (deprecated endpoints are automatically filtered out) and provides a tool for making authenticated HTTP requests.
|
|
27
|
+
|
|
28
|
+
Target API: ${hostname}
|
|
29
|
+
|
|
30
|
+
Resource Structure (3-tier hierarchy):
|
|
31
|
+
- Tier 1 (Discovery): List resources returns API tags (e.g., tag://Users, tag://ChargingSessions)
|
|
32
|
+
- Tier 2 (Navigation): Read a tag resource to see all endpoints within that tag
|
|
33
|
+
- Tier 3 (Details): Read an individual endpoint resource for full specification
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
1. List available resources to discover API tags (returns ~10-30 tags instead of 443 endpoints)
|
|
37
|
+
2. Read a tag resource (e.g., tag://Users) to see all endpoints within that tag
|
|
38
|
+
3. Read an endpoint resource (e.g., api://GET/users/{id}) to get detailed endpoint information
|
|
39
|
+
4. Use the 'api_request' tool to make HTTP calls to any endpoint
|
|
40
|
+
|
|
41
|
+
URI Formats:
|
|
42
|
+
- Tags: tag://{TagName} (e.g., tag://Users)
|
|
43
|
+
- Endpoints: api://{METHOD}{path} (e.g., api://GET/users/{id})
|
|
44
|
+
|
|
45
|
+
The server automatically proxies your Bearer token to all API requests to ${hostname}.
|
|
46
|
+
|
|
47
|
+
Note: Deprecated endpoints are not exposed as resources and cannot be accessed. This hierarchical structure reduces initial context consumption by ~95-97%.
|
|
48
|
+
|
|
49
|
+
## Available Prompts
|
|
50
|
+
|
|
51
|
+
This server provides helpful prompts for common workflows. Use these prompts to learn best practices:
|
|
52
|
+
|
|
53
|
+
- **charging_session_workflow**: Learn how to implement the complete charging session lifecycle: finding charge points, starting/stopping sessions, and retrieving session details
|
|
54
|
+
- **authentication_workflow**: Understand how authentication works with the AMPECO API and how to implement custom authentication in your backend
|
|
55
|
+
- **reservation_workflow**: Learn how to reserve charge points for immediate or future use
|
|
56
|
+
- **smart_charging_setup**: Guide for configuring smart charging modes including scheduled, solar, and dynamic pricing strategies
|
|
57
|
+
|
|
58
|
+
To use a prompt, simply reference it by name when you need guidance on these workflows.
|
|
59
|
+
|
|
60
|
+
## AMPECO API Resource Relationships
|
|
61
|
+
|
|
62
|
+
The AMPECO API has a hierarchical structure: **Locations** → **Charging Zones** → **Charge Points** → **EVSEs** → **Connectors**
|
|
63
|
+
|
|
64
|
+
Each resource can be listed independently. EVSEs contain the currentType field ("ac"/"dc") for determining charging type.
|
|
65
|
+
|
|
66
|
+
## Best Practices for Data Fetching
|
|
67
|
+
|
|
68
|
+
**Always prefer top-level listing endpoints over nested fetching:**
|
|
69
|
+
- ✅ Use \`GET /evses\` to get all EVSEs across all charge points (1 API call)
|
|
70
|
+
- ❌ Avoid fetching \`GET /charge-points/{id}/evses\` for each charge point (N API calls)
|
|
71
|
+
|
|
72
|
+
The top-level listing endpoints are more efficient and reduce API load. Use nested endpoints only when you specifically need resources for a single parent entity.
|
|
73
|
+
|
|
74
|
+
## Session State & Webhooks
|
|
75
|
+
|
|
76
|
+
The AMPECO API is event-driven and uses webhooks for real-time updates. When performing actions like starting/stopping charging sessions:
|
|
77
|
+
- Initial API responses return immediately with session IDs
|
|
78
|
+
- Actual state changes arrive via webhooks (SessionUpdateNotification, SessionMeterValuesNotification)
|
|
79
|
+
- Clients should implement webhook handlers to track session status changes from "pending" → "active" → "finished"
|
|
80
|
+
- Session details and final metrics are retrieved via GET requests after receiving webhook notifications
|
|
81
|
+
|
|
82
|
+
## Cursor Pagination Guide
|
|
83
|
+
|
|
84
|
+
Many list endpoints support cursor-based pagination, which is faster and more reliable than offset-based pagination. Here's how to use it:
|
|
85
|
+
|
|
86
|
+
**Initial Request** - Start with an empty cursor:
|
|
87
|
+
\`\`\`
|
|
88
|
+
api_request(endpoint: "/users", method: "GET", query_params: { limit: 100, cursor: "" })
|
|
89
|
+
\`\`\`
|
|
90
|
+
|
|
91
|
+
**Subsequent Requests** - Use the cursor from the previous response:
|
|
92
|
+
\`\`\`
|
|
93
|
+
api_request(endpoint: "/users", method: "GET", query_params: { limit: 100, cursor: "eyJpZCI6MTAwfQ==" })
|
|
94
|
+
\`\`\`
|
|
95
|
+
|
|
96
|
+
**Pagination Loop:**
|
|
97
|
+
1. Start with \`cursor=""\` (empty string)
|
|
98
|
+
2. Make request with current cursor
|
|
99
|
+
3. Collect items from response
|
|
100
|
+
4. If response contains a non-empty cursor, use it for next request
|
|
101
|
+
5. Stop when cursor is null/empty or data array is empty
|
|
102
|
+
|
|
103
|
+
**Key Points:**
|
|
104
|
+
- ✅ Always use \`cursor=""\` for first request
|
|
105
|
+
- ✅ Use exact cursor value from responses
|
|
106
|
+
- ✅ Check for null/empty cursor or empty data array to detect end
|
|
107
|
+
- ✅ Adjust limit based on data size (100-1000 typical)
|
|
108
|
+
- ❌ Don't use offset pagination when cursor is available`,
|
|
109
|
+
});
|
|
110
|
+
// Register resources/list handler - returns tags (Tier 1)
|
|
111
|
+
server.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
112
|
+
const startTime = Date.now();
|
|
113
|
+
console.error('[Resources List] Building tag-based resource list...');
|
|
114
|
+
// Filter out deprecated endpoints first
|
|
115
|
+
const activeEndpoints = endpoints.endpoints.filter(endpoint => !endpoint.deprecated);
|
|
116
|
+
// Extract unique tags from all active endpoints
|
|
117
|
+
const tagsSet = new Set();
|
|
118
|
+
let untaggedCount = 0;
|
|
119
|
+
for (const endpoint of activeEndpoints) {
|
|
120
|
+
if (endpoint.tags && endpoint.tags.length > 0) {
|
|
121
|
+
endpoint.tags.forEach(tag => tagsSet.add(tag));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
untaggedCount++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Convert to sorted array
|
|
128
|
+
const tags = Array.from(tagsSet).sort();
|
|
129
|
+
// Add "Untagged" category if there are untagged endpoints
|
|
130
|
+
if (untaggedCount > 0) {
|
|
131
|
+
tags.push('Untagged');
|
|
132
|
+
}
|
|
133
|
+
// Build resources list with tag URIs
|
|
134
|
+
const resources = tags.map(tag => {
|
|
135
|
+
const tagEndpoints = activeEndpoints.filter(e => tag === 'Untagged'
|
|
136
|
+
? !e.tags || e.tags.length === 0
|
|
137
|
+
: e.tags?.includes(tag));
|
|
138
|
+
return {
|
|
139
|
+
uri: `tag://${tag}`,
|
|
140
|
+
name: tag,
|
|
141
|
+
description: `${tagEndpoints.length} endpoint${tagEndpoints.length !== 1 ? 's' : ''} tagged with '${tag}'`,
|
|
142
|
+
mimeType: 'application/json',
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
const duration = Date.now() - startTime;
|
|
146
|
+
console.error(`[Resources List] Built ${resources.length} tag resources (filtered ${endpoints.endpoints.length - activeEndpoints.length} deprecated endpoints) in ${duration}ms`);
|
|
147
|
+
return { resources };
|
|
148
|
+
});
|
|
149
|
+
// Register resources/read handler - supports tag:// (Tier 2) and api:// (Tier 3) URIs
|
|
150
|
+
server.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
151
|
+
const uri = request.params.uri;
|
|
152
|
+
// Manual URI parsing to handle spaces and special characters in tag names
|
|
153
|
+
// Format: tag://{TagName} or api://{METHOD}{path}
|
|
154
|
+
const protocolMatch = uri.match(/^([^:]+):\/\/(.*)$/);
|
|
155
|
+
if (!protocolMatch) {
|
|
156
|
+
throw new Error(`Invalid URI format: ${uri}`);
|
|
157
|
+
}
|
|
158
|
+
const protocol = protocolMatch[1];
|
|
159
|
+
const remainder = protocolMatch[2];
|
|
160
|
+
// Tier 2: Handle tag:// URIs - return list of endpoints within the tag
|
|
161
|
+
if (protocol === 'tag') {
|
|
162
|
+
const tag = remainder;
|
|
163
|
+
// Filter active endpoints by tag
|
|
164
|
+
const activeEndpoints = endpoints.endpoints.filter(endpoint => !endpoint.deprecated);
|
|
165
|
+
const taggedEndpoints = activeEndpoints.filter(e => tag === 'Untagged'
|
|
166
|
+
? !e.tags || e.tags.length === 0
|
|
167
|
+
: e.tags?.includes(tag));
|
|
168
|
+
if (taggedEndpoints.length === 0) {
|
|
169
|
+
throw new Error(`No endpoints found for tag: ${tag}`);
|
|
170
|
+
}
|
|
171
|
+
// Build response with endpoint summaries
|
|
172
|
+
const tagResource = {
|
|
173
|
+
tag,
|
|
174
|
+
count: taggedEndpoints.length,
|
|
175
|
+
endpoints: taggedEndpoints.map(e => ({
|
|
176
|
+
uri: `api://${e.method.toUpperCase()}${e.path}`,
|
|
177
|
+
method: e.method.toUpperCase(),
|
|
178
|
+
path: e.path,
|
|
179
|
+
summary: e.summary || e.operationId || `${e.method} ${e.path}`,
|
|
180
|
+
operationId: e.operationId,
|
|
181
|
+
})),
|
|
182
|
+
};
|
|
183
|
+
return {
|
|
184
|
+
contents: [
|
|
185
|
+
{
|
|
186
|
+
uri,
|
|
187
|
+
mimeType: 'application/json',
|
|
188
|
+
text: JSON.stringify(tagResource, null, 2),
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// Tier 3: Handle api:// URIs - return individual endpoint details
|
|
194
|
+
if (protocol === 'api') {
|
|
195
|
+
// Parse URI format: api://METHOD/path
|
|
196
|
+
// Example: api://POST/users or api://GET/users/{id}
|
|
197
|
+
const match = remainder.match(/^([A-Z]+)(\/.*)/);
|
|
198
|
+
if (!match) {
|
|
199
|
+
throw new Error(`Invalid API URI format: ${uri}`);
|
|
200
|
+
}
|
|
201
|
+
const method = match[1];
|
|
202
|
+
const path = match[2];
|
|
203
|
+
// Find the matching endpoint
|
|
204
|
+
const endpoint = endpoints.endpoints.find((e) => e.path === path && e.method.toUpperCase() === method.toUpperCase());
|
|
205
|
+
if (!endpoint) {
|
|
206
|
+
throw new Error(`Endpoint not found: ${method} ${path}`);
|
|
207
|
+
}
|
|
208
|
+
// Reject deprecated endpoints
|
|
209
|
+
if (endpoint.deprecated) {
|
|
210
|
+
throw new Error(`Endpoint is deprecated: ${method} ${path}`);
|
|
211
|
+
}
|
|
212
|
+
// Return comprehensive endpoint information
|
|
213
|
+
return {
|
|
214
|
+
contents: [
|
|
215
|
+
{
|
|
216
|
+
uri,
|
|
217
|
+
mimeType: 'application/json',
|
|
218
|
+
text: JSON.stringify(endpoint, null, 2),
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// Unsupported protocol
|
|
224
|
+
throw new Error(`Unsupported URI protocol: ${protocol}. Expected 'tag' or 'api'`);
|
|
225
|
+
});
|
|
226
|
+
// Register the API request tool
|
|
227
|
+
server.tool('api_request', `Make an authenticated HTTP request to any active API endpoint from the OpenAPI specification. Deprecated endpoints cannot be called and will return an error. Authentication is handled automatically using the Bearer token from the MCP request. The target API hostname is: ${hostname}
|
|
228
|
+
|
|
229
|
+
IMPORTANT - Pagination: Always prefer cursor-based pagination when available. For list endpoints that support both offset and cursor pagination, you MUST use cursor pagination by including an empty "cursor" query parameter (cursor="") in your initial request to engage cursor-based pagination. Subsequent requests should use the cursor value returned in the response.`, {
|
|
230
|
+
endpoint: z.string().describe('The API endpoint path (e.g., "/users/{id}")'),
|
|
231
|
+
method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']).describe('HTTP method'),
|
|
232
|
+
path_params: z.preprocess((val) => (val === null || val === undefined || val === '' ? {} : val), z.record(z.any()).default({})).optional().describe('Path parameter values as key-value pairs (optional)'),
|
|
233
|
+
query_params: z.preprocess((val) => (val === null || val === undefined || val === '' ? {} : val), z.record(z.any()).default({})).optional().describe('Query string parameters as key-value pairs (optional)'),
|
|
234
|
+
body: z.preprocess((val) => (val === null || val === undefined || val === '' ? undefined : val), z.any()).optional().describe('Request body for POST/PUT/PATCH requests (optional)'),
|
|
235
|
+
headers: z.preprocess((val) => (val === null || val === undefined || val === '' ? {} : val), z.record(z.string()).default({})).optional().describe('Additional HTTP headers (optional)'),
|
|
236
|
+
}, async (args) => {
|
|
237
|
+
const { endpoint, method, path_params = {}, query_params = {}, body, headers = {}, } = args;
|
|
238
|
+
// Check if endpoint is deprecated
|
|
239
|
+
const endpointDef = endpoints.endpoints.find((e) => e.path === endpoint && e.method.toUpperCase() === method.toUpperCase());
|
|
240
|
+
if (endpointDef?.deprecated) {
|
|
241
|
+
return {
|
|
242
|
+
content: [
|
|
243
|
+
{
|
|
244
|
+
type: 'text',
|
|
245
|
+
text: JSON.stringify({
|
|
246
|
+
error: true,
|
|
247
|
+
message: `Endpoint is deprecated and cannot be called: ${method} ${endpoint}`,
|
|
248
|
+
}, null, 2),
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
isError: true,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
// Construct the full URL
|
|
255
|
+
let url = hostname.replace(/\/$/, '') + endpoint;
|
|
256
|
+
// Replace path parameters
|
|
257
|
+
for (const [key, value] of Object.entries(path_params)) {
|
|
258
|
+
url = url.replace(`{${key}}`, encodeURIComponent(String(value)));
|
|
259
|
+
}
|
|
260
|
+
// Add query parameters
|
|
261
|
+
const queryString = Object.entries(query_params)
|
|
262
|
+
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
|
|
263
|
+
.join('&');
|
|
264
|
+
if (queryString) {
|
|
265
|
+
url += `?${queryString}`;
|
|
266
|
+
}
|
|
267
|
+
// Prepare headers with proxied Bearer token
|
|
268
|
+
const requestHeaders = {
|
|
269
|
+
'Content-Type': 'application/json',
|
|
270
|
+
...headers,
|
|
271
|
+
};
|
|
272
|
+
// Add Authorization header if bearer token is available
|
|
273
|
+
if (bearerToken) {
|
|
274
|
+
requestHeaders['Authorization'] = `Bearer ${bearerToken}`;
|
|
275
|
+
}
|
|
276
|
+
// Log the request
|
|
277
|
+
console.error(`[API Request] ${method} ${url}`);
|
|
278
|
+
try {
|
|
279
|
+
// Prepare fetch options
|
|
280
|
+
const fetchOptions = {
|
|
281
|
+
method,
|
|
282
|
+
headers: requestHeaders,
|
|
283
|
+
};
|
|
284
|
+
// Only include body for methods that support it (not GET/HEAD)
|
|
285
|
+
if (body && !['GET', 'HEAD'].includes(method.toUpperCase())) {
|
|
286
|
+
fetchOptions.body = JSON.stringify(body);
|
|
287
|
+
}
|
|
288
|
+
// Make the HTTP request
|
|
289
|
+
const response = await fetch(url, fetchOptions);
|
|
290
|
+
// Parse response
|
|
291
|
+
const rawResponseText = await response.text();
|
|
292
|
+
let responseBody;
|
|
293
|
+
try {
|
|
294
|
+
responseBody = rawResponseText ? JSON.parse(rawResponseText) : null;
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
responseBody = rawResponseText;
|
|
298
|
+
}
|
|
299
|
+
// Log the response
|
|
300
|
+
console.error(`[API Response] ${response.status} ${response.statusText}`);
|
|
301
|
+
// Prepare structured response with truncation
|
|
302
|
+
const responseObject = {
|
|
303
|
+
status: response.status,
|
|
304
|
+
statusText: response.statusText,
|
|
305
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
306
|
+
body: responseBody,
|
|
307
|
+
};
|
|
308
|
+
let responseText = JSON.stringify(responseObject, null, 2);
|
|
309
|
+
// Truncate if response exceeds 20000 characters (leaving room for metadata)
|
|
310
|
+
const MAX_RESPONSE_LENGTH = 20000;
|
|
311
|
+
let wasTruncated = false;
|
|
312
|
+
if (responseText.length > MAX_RESPONSE_LENGTH) {
|
|
313
|
+
wasTruncated = true;
|
|
314
|
+
const originalLength = responseText.length;
|
|
315
|
+
responseText = responseText.substring(0, MAX_RESPONSE_LENGTH);
|
|
316
|
+
// Try to truncate at a reasonable boundary (end of a line)
|
|
317
|
+
const lastNewlineIndex = responseText.lastIndexOf('\n');
|
|
318
|
+
if (lastNewlineIndex > MAX_RESPONSE_LENGTH * 0.9) {
|
|
319
|
+
responseText = responseText.substring(0, lastNewlineIndex);
|
|
320
|
+
}
|
|
321
|
+
// Add truncation notice
|
|
322
|
+
responseText += `\n\n... [Response truncated - original size: ${originalLength} characters, showing first ${responseText.length} characters]\n\nNote: The response was too large to display in full. This is typically because the API returned detailed error information or a large dataset. Check the status code and the visible portion of the response for key information.`;
|
|
323
|
+
}
|
|
324
|
+
const toolResponse = {
|
|
325
|
+
content: [
|
|
326
|
+
{
|
|
327
|
+
type: 'text',
|
|
328
|
+
text: responseText,
|
|
329
|
+
},
|
|
330
|
+
],
|
|
331
|
+
};
|
|
332
|
+
console.error(`[Tool Response] Returning response with ${responseText.length} characters${wasTruncated ? ' (truncated)' : ''}`);
|
|
333
|
+
// Return structured response
|
|
334
|
+
return toolResponse;
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
338
|
+
console.error(`[API Error] ${errorMessage}`);
|
|
339
|
+
const errorObject = {
|
|
340
|
+
error: true,
|
|
341
|
+
message: errorMessage,
|
|
342
|
+
details: error instanceof Error ? error.stack : undefined,
|
|
343
|
+
};
|
|
344
|
+
let errorText = JSON.stringify(errorObject, null, 2);
|
|
345
|
+
// Truncate error responses too
|
|
346
|
+
const MAX_ERROR_LENGTH = 5000;
|
|
347
|
+
if (errorText.length > MAX_ERROR_LENGTH) {
|
|
348
|
+
errorText = errorText.substring(0, MAX_ERROR_LENGTH) + '\n\n... [Error message truncated]';
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
content: [
|
|
352
|
+
{
|
|
353
|
+
type: 'text',
|
|
354
|
+
text: errorText,
|
|
355
|
+
},
|
|
356
|
+
],
|
|
357
|
+
isError: true,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
// Register prompts - using shortened implementation for brevity
|
|
362
|
+
// (Full prompt implementations remain the same as in original server/index.ts)
|
|
363
|
+
server.server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
364
|
+
return {
|
|
365
|
+
prompts: [
|
|
366
|
+
{
|
|
367
|
+
name: 'charging_session_workflow',
|
|
368
|
+
description: 'Learn how to implement the complete charging session lifecycle: finding charge points, starting/stopping sessions, and retrieving session details',
|
|
369
|
+
arguments: [
|
|
370
|
+
{
|
|
371
|
+
name: 'evseId',
|
|
372
|
+
description: 'The EVSE network ID to start charging on (optional - if not provided, guidance will be generic)',
|
|
373
|
+
required: false,
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
name: 'sessionId',
|
|
377
|
+
description: 'The session ID to monitor or stop (optional - if not provided, guidance will be generic)',
|
|
378
|
+
required: false,
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: 'authentication_workflow',
|
|
384
|
+
description: 'Understand how authentication works with the AMPECO API and how to implement custom authentication in your backend',
|
|
385
|
+
arguments: [],
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
name: 'reservation_workflow',
|
|
389
|
+
description: 'Learn how to reserve charge points for immediate or future use',
|
|
390
|
+
arguments: [
|
|
391
|
+
{
|
|
392
|
+
name: 'chargePointId',
|
|
393
|
+
description: 'The charge point ID to reserve (optional)',
|
|
394
|
+
required: false,
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
name: 'evseNetworkId',
|
|
398
|
+
description: 'The EVSE network ID to reserve (optional)',
|
|
399
|
+
required: false,
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: 'userId',
|
|
403
|
+
description: 'The user ID making the reservation (optional)',
|
|
404
|
+
required: false,
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
name: 'reservationType',
|
|
408
|
+
description: 'Type of reservation: "immediate" or "future" (optional, defaults to immediate)',
|
|
409
|
+
required: false,
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: 'smart_charging_setup',
|
|
415
|
+
description: 'Guide for configuring smart charging modes including scheduled, solar, and dynamic pricing strategies',
|
|
416
|
+
arguments: [
|
|
417
|
+
{
|
|
418
|
+
name: 'chargePointId',
|
|
419
|
+
description: 'The charge point ID to configure (optional)',
|
|
420
|
+
required: false,
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: 'mode',
|
|
424
|
+
description: 'Smart charging mode to configure: "scheduled", "solar", "octopus_agile", "octopus_go", "nordpool", or "energi_elspot" (optional)',
|
|
425
|
+
required: false,
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
},
|
|
429
|
+
],
|
|
430
|
+
};
|
|
431
|
+
});
|
|
432
|
+
server.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
433
|
+
const promptName = request.params.name;
|
|
434
|
+
const args = request.params.arguments || {};
|
|
435
|
+
const promptText = getPromptContent(promptName, args);
|
|
436
|
+
return {
|
|
437
|
+
messages: [
|
|
438
|
+
{
|
|
439
|
+
role: 'user',
|
|
440
|
+
content: {
|
|
441
|
+
type: 'text',
|
|
442
|
+
text: promptText,
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
],
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
return server;
|
|
449
|
+
}
|
|
450
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.test.d.ts","sourceRoot":"","sources":["../../src/server/factory.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic sanity tests for server factory
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { createServer } from './factory.js';
|
|
6
|
+
describe('createServer', () => {
|
|
7
|
+
it('should create a server instance', () => {
|
|
8
|
+
const mockEndpoints = {
|
|
9
|
+
endpoints: [
|
|
10
|
+
{
|
|
11
|
+
path: '/test',
|
|
12
|
+
method: 'get',
|
|
13
|
+
operationId: 'getTest',
|
|
14
|
+
summary: 'Test endpoint',
|
|
15
|
+
tags: ['Test'],
|
|
16
|
+
deprecated: false,
|
|
17
|
+
parameters: [],
|
|
18
|
+
responses: {},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
info: {
|
|
22
|
+
title: 'Test API',
|
|
23
|
+
version: '1.0.0',
|
|
24
|
+
},
|
|
25
|
+
buildTimestamp: '2025-10-10T00:00:00Z',
|
|
26
|
+
stats: {
|
|
27
|
+
totalEndpoints: 1,
|
|
28
|
+
originalSize: 1000,
|
|
29
|
+
optimizedSize: 800,
|
|
30
|
+
reductionPercent: 20,
|
|
31
|
+
buildDuration: 100,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const server = createServer(mockEndpoints, 'test-token', 'http://test.example.com');
|
|
35
|
+
expect(server).toBeDefined();
|
|
36
|
+
expect(server.server).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
it('should handle empty endpoints array', () => {
|
|
39
|
+
const mockEndpoints = {
|
|
40
|
+
endpoints: [],
|
|
41
|
+
info: {
|
|
42
|
+
title: 'Empty API',
|
|
43
|
+
version: '1.0.0',
|
|
44
|
+
},
|
|
45
|
+
buildTimestamp: '2025-10-10T00:00:00Z',
|
|
46
|
+
stats: {
|
|
47
|
+
totalEndpoints: 0,
|
|
48
|
+
originalSize: 0,
|
|
49
|
+
optimizedSize: 0,
|
|
50
|
+
reductionPercent: 0,
|
|
51
|
+
buildDuration: 0,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
const server = createServer(mockEndpoints, 'test-token', 'http://test.example.com');
|
|
55
|
+
expect(server).toBeDefined();
|
|
56
|
+
});
|
|
57
|
+
it('should accept bearer token and hostname', () => {
|
|
58
|
+
const mockEndpoints = {
|
|
59
|
+
endpoints: [],
|
|
60
|
+
info: {
|
|
61
|
+
title: 'Test API',
|
|
62
|
+
version: '1.0.0',
|
|
63
|
+
},
|
|
64
|
+
buildTimestamp: '2025-10-10T00:00:00Z',
|
|
65
|
+
stats: {
|
|
66
|
+
totalEndpoints: 0,
|
|
67
|
+
originalSize: 0,
|
|
68
|
+
optimizedSize: 0,
|
|
69
|
+
reductionPercent: 0,
|
|
70
|
+
buildDuration: 0,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
const server = createServer(mockEndpoints, 'my-token', 'https://api.example.com');
|
|
74
|
+
expect(server).toBeDefined();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=factory.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.test.js","sourceRoot":"","sources":["../../src/server/factory.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,aAAa,GAAgB;YACjC,SAAS,EAAE;gBACT;oBACE,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,KAAK;oBACb,WAAW,EAAE,SAAS;oBACtB,OAAO,EAAE,eAAe;oBACxB,IAAI,EAAE,CAAC,MAAM,CAAC;oBACd,UAAU,EAAE,KAAK;oBACjB,UAAU,EAAE,EAAE;oBACd,SAAS,EAAE,EAAE;iBACd;aACF;YACD,IAAI,EAAE;gBACJ,KAAK,EAAE,UAAU;gBACjB,OAAO,EAAE,OAAO;aACjB;YACD,cAAc,EAAE,sBAAsB;YACtC,KAAK,EAAE;gBACL,cAAc,EAAE,CAAC;gBACjB,YAAY,EAAE,IAAI;gBAClB,aAAa,EAAE,GAAG;gBAClB,gBAAgB,EAAE,EAAE;gBACpB,aAAa,EAAE,GAAG;aACnB;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,EAAE,YAAY,EAAE,yBAAyB,CAAC,CAAC;QAEpF,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,aAAa,GAAgB;YACjC,SAAS,EAAE,EAAE;YACb,IAAI,EAAE;gBACJ,KAAK,EAAE,WAAW;gBAClB,OAAO,EAAE,OAAO;aACjB;YACD,cAAc,EAAE,sBAAsB;YACtC,KAAK,EAAE;gBACL,cAAc,EAAE,CAAC;gBACjB,YAAY,EAAE,CAAC;gBACf,aAAa,EAAE,CAAC;gBAChB,gBAAgB,EAAE,CAAC;gBACnB,aAAa,EAAE,CAAC;aACjB;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,EAAE,YAAY,EAAE,yBAAyB,CAAC,CAAC;QAEpF,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,aAAa,GAAgB;YACjC,SAAS,EAAE,EAAE;YACb,IAAI,EAAE;gBACJ,KAAK,EAAE,UAAU;gBACjB,OAAO,EAAE,OAAO;aACjB;YACD,cAAc,EAAE,sBAAsB;YACtC,KAAK,EAAE;gBACL,cAAc,EAAE,CAAC;gBACjB,YAAY,EAAE,CAAC;gBACf,aAAa,EAAE,CAAC;gBAChB,gBAAgB,EAAE,CAAC;gBACnB,aAAa,EAAE,CAAC;aACjB;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,EAAE,UAAU,EAAE,yBAAyB,CAAC,CAAC;QAElF,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP MCP Server
|
|
3
|
+
* Runs MCP server with HTTP Streamable transport for remote access
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Start MCP server in HTTP mode
|
|
7
|
+
* Creates Express server listening on specified port
|
|
8
|
+
*/
|
|
9
|
+
export declare function startHttpServer(port: number): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+GjE"}
|