@access-mcp/shared 0.2.3 → 0.3.1
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/dist/base-server.d.ts +22 -2
- package/dist/base-server.js +118 -4
- package/package.json +5 -1
package/dist/base-server.d.ts
CHANGED
|
@@ -8,12 +8,32 @@ export declare abstract class BaseAccessServer {
|
|
|
8
8
|
protected server: Server;
|
|
9
9
|
protected transport: StdioServerTransport;
|
|
10
10
|
private _httpClient?;
|
|
11
|
+
private _httpServer?;
|
|
12
|
+
private _httpPort?;
|
|
11
13
|
constructor(serverName: string, version: string, baseURL?: string);
|
|
12
14
|
protected get httpClient(): AxiosInstance;
|
|
13
15
|
private setupHandlers;
|
|
14
16
|
protected abstract getTools(): any[];
|
|
15
17
|
protected abstract getResources(): any[];
|
|
16
18
|
protected abstract handleToolCall(request: any): Promise<any>;
|
|
17
|
-
protected
|
|
18
|
-
|
|
19
|
+
protected handleResourceRead(request: any): Promise<any>;
|
|
20
|
+
/**
|
|
21
|
+
* Start the MCP server with optional HTTP service layer for inter-server communication
|
|
22
|
+
*/
|
|
23
|
+
start(options?: {
|
|
24
|
+
httpPort?: number;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Start HTTP service layer for inter-server communication
|
|
28
|
+
*/
|
|
29
|
+
private startHttpService;
|
|
30
|
+
/**
|
|
31
|
+
* Call a tool on another ACCESS-CI MCP server via HTTP
|
|
32
|
+
*/
|
|
33
|
+
protected callRemoteServer(serviceName: string, toolName: string, args?: Record<string, any>): Promise<any>;
|
|
34
|
+
/**
|
|
35
|
+
* Get service endpoint from environment configuration
|
|
36
|
+
* Expected format: ACCESS_MCP_SERVICES=nsf-awards=http://localhost:3001,xdmod-metrics=http://localhost:3002
|
|
37
|
+
*/
|
|
38
|
+
private getServiceEndpoint;
|
|
19
39
|
}
|
package/dist/base-server.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import axios from "axios";
|
|
5
|
+
import express from "express";
|
|
5
6
|
export class BaseAccessServer {
|
|
6
7
|
serverName;
|
|
7
8
|
version;
|
|
@@ -9,6 +10,8 @@ export class BaseAccessServer {
|
|
|
9
10
|
server;
|
|
10
11
|
transport;
|
|
11
12
|
_httpClient;
|
|
13
|
+
_httpServer;
|
|
14
|
+
_httpPort;
|
|
12
15
|
constructor(serverName, version, baseURL = "https://support.access-ci.org/api") {
|
|
13
16
|
this.serverName = serverName;
|
|
14
17
|
this.version = version;
|
|
@@ -99,9 +102,120 @@ export class BaseAccessServer {
|
|
|
99
102
|
}
|
|
100
103
|
});
|
|
101
104
|
}
|
|
102
|
-
async
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
async handleResourceRead(request) {
|
|
106
|
+
throw new Error("Resource reading not supported by this server");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Start the MCP server with optional HTTP service layer for inter-server communication
|
|
110
|
+
*/
|
|
111
|
+
async start(options) {
|
|
112
|
+
// Start HTTP service layer if port is specified
|
|
113
|
+
if (options?.httpPort) {
|
|
114
|
+
this._httpPort = options.httpPort;
|
|
115
|
+
await this.startHttpService();
|
|
116
|
+
console.log(`${this.serverName} HTTP server running on port ${this._httpPort}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Only connect stdio transport when NOT in HTTP mode
|
|
120
|
+
await this.server.connect(this.transport);
|
|
121
|
+
// MCP servers should not output anything to stderr/stdout when running
|
|
122
|
+
// as it interferes with JSON-RPC communication
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Start HTTP service layer for inter-server communication
|
|
127
|
+
*/
|
|
128
|
+
async startHttpService() {
|
|
129
|
+
if (!this._httpPort)
|
|
130
|
+
return;
|
|
131
|
+
this._httpServer = express();
|
|
132
|
+
this._httpServer.use(express.json());
|
|
133
|
+
// Health check endpoint
|
|
134
|
+
this._httpServer.get('/health', (req, res) => {
|
|
135
|
+
res.json({
|
|
136
|
+
server: this.serverName,
|
|
137
|
+
version: this.version,
|
|
138
|
+
status: 'healthy',
|
|
139
|
+
timestamp: new Date().toISOString()
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
// List available tools endpoint
|
|
143
|
+
this._httpServer.get('/tools', (req, res) => {
|
|
144
|
+
try {
|
|
145
|
+
const tools = this.getTools();
|
|
146
|
+
res.json({ tools });
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
res.status(500).json({ error: 'Failed to list tools' });
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
// Tool execution endpoint
|
|
153
|
+
this._httpServer.post('/tools/:toolName', async (req, res) => {
|
|
154
|
+
try {
|
|
155
|
+
const { toolName } = req.params;
|
|
156
|
+
const { arguments: args = {} } = req.body;
|
|
157
|
+
// Validate that the tool exists
|
|
158
|
+
const tools = this.getTools();
|
|
159
|
+
const tool = tools.find(t => t.name === toolName);
|
|
160
|
+
if (!tool) {
|
|
161
|
+
return res.status(404).json({ error: `Tool '${toolName}' not found` });
|
|
162
|
+
}
|
|
163
|
+
// Execute the tool
|
|
164
|
+
const request = {
|
|
165
|
+
params: {
|
|
166
|
+
name: toolName,
|
|
167
|
+
arguments: args
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const result = await this.handleToolCall(request);
|
|
171
|
+
res.json(result);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
175
|
+
res.status(500).json({ error: errorMessage });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
// Start HTTP server
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
this._httpServer.listen(this._httpPort, '0.0.0.0', () => {
|
|
181
|
+
resolve();
|
|
182
|
+
}).on('error', reject);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Call a tool on another ACCESS-CI MCP server via HTTP
|
|
187
|
+
*/
|
|
188
|
+
async callRemoteServer(serviceName, toolName, args = {}) {
|
|
189
|
+
const serviceUrl = this.getServiceEndpoint(serviceName);
|
|
190
|
+
if (!serviceUrl) {
|
|
191
|
+
throw new Error(`Service '${serviceName}' not found. Check ACCESS_MCP_SERVICES environment variable.`);
|
|
192
|
+
}
|
|
193
|
+
const response = await axios.post(`${serviceUrl}/tools/${toolName}`, {
|
|
194
|
+
arguments: args
|
|
195
|
+
}, {
|
|
196
|
+
timeout: 30000,
|
|
197
|
+
validateStatus: () => true
|
|
198
|
+
});
|
|
199
|
+
if (response.status !== 200) {
|
|
200
|
+
throw new Error(`Remote server call failed: ${response.status} ${response.data?.error || response.statusText}`);
|
|
201
|
+
}
|
|
202
|
+
return response.data;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get service endpoint from environment configuration
|
|
206
|
+
* Expected format: ACCESS_MCP_SERVICES=nsf-awards=http://localhost:3001,xdmod-metrics=http://localhost:3002
|
|
207
|
+
*/
|
|
208
|
+
getServiceEndpoint(serviceName) {
|
|
209
|
+
const services = process.env.ACCESS_MCP_SERVICES;
|
|
210
|
+
if (!services)
|
|
211
|
+
return null;
|
|
212
|
+
const serviceMap = {};
|
|
213
|
+
services.split(',').forEach(service => {
|
|
214
|
+
const [name, url] = service.split('=');
|
|
215
|
+
if (name && url) {
|
|
216
|
+
serviceMap[name.trim()] = url.trim();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return serviceMap[serviceName] || null;
|
|
106
220
|
}
|
|
107
221
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@access-mcp/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Shared utilities for ACCESS-CI MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.16.0",
|
|
36
36
|
"axios": "^1.6.0",
|
|
37
|
+
"express": "^5.1.0",
|
|
37
38
|
"zod": "^3.22.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/express": "^5.0.0"
|
|
38
42
|
}
|
|
39
43
|
}
|