@sgpdirectory/mcp 1.0.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/README.md +70 -0
- package/index.js +56 -0
- package/package.json +23 -0
- package/scripts/smoke-test.js +93 -0
- package/server.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @sgpdirectory/mcp
|
|
2
|
+
|
|
3
|
+
Official local MCP (Model Context Protocol) wrapper for the `sgpdirectory` remote server.
|
|
4
|
+
|
|
5
|
+
This package provides a standard `stdio` interface compatible with local MCP clients (like Claude Desktop and Cursor), proxying requests securely to the remote HTTP streamable sgpdirectory server (`https://mcp.sgpdirectory.com/mcp`).
|
|
6
|
+
|
|
7
|
+
## Usage with Cursor
|
|
8
|
+
Run the following package directly using `npx`:
|
|
9
|
+
|
|
10
|
+
When configuring Cursor, set the MCP "Type" to `command` and use:
|
|
11
|
+
```bash
|
|
12
|
+
npx -y @sgpdirectory/mcp
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage with Claude Desktop
|
|
16
|
+
Add this to your `mcp-servers.json` configuration file:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"sgpdirectory": {
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["-y", "@sgpdirectory/mcp"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Authentication
|
|
30
|
+
|
|
31
|
+
If your proxy is behind an access token, you can pass it via `SGP_DIRECTORY_API_KEY` environment variable. The wrapper will automatically format it as an `Authorization: Bearer <TOKEN>` header and attach it to the `mcp-remote` connection.
|
|
32
|
+
|
|
33
|
+
### Example in Claude Desktop
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"sgpdirectory": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "@sgpdirectory/mcp"],
|
|
40
|
+
"env": {
|
|
41
|
+
"SGP_DIRECTORY_API_KEY": "your-secret-token"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Publishing to NPM
|
|
49
|
+
|
|
50
|
+
1. **Login to NPM**
|
|
51
|
+
Run the login command and follow the prompts. You need to be a part of the `@sgpdirectory` org.
|
|
52
|
+
```bash
|
|
53
|
+
npm login
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
2. **Publish the package**
|
|
57
|
+
Run the following inside your wrapper directory:
|
|
58
|
+
```bash
|
|
59
|
+
npm publish --access public
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Local Testing
|
|
63
|
+
If you have cloned the repository locally, you can run:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm install
|
|
67
|
+
npm start
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This will launch the proxy and wait for standard `stdio` JSON-RPC messages.
|
package/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @sgpdirectory/mcp
|
|
5
|
+
* A simple stdio proxy for the sgpdirectory remote Model Context Protocol (MCP) server.
|
|
6
|
+
* This executable connects to the remote HTTP streamable server.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const REMOTE_URL = 'https://mcp.sgpdirectory.com/mcp';
|
|
13
|
+
|
|
14
|
+
// Find the local mcp-remote executable within our own node_modules
|
|
15
|
+
// This ensures we run the pinned version we depend on.
|
|
16
|
+
const mcpRemoteBin = require.resolve('mcp-remote/dist/proxy.js'); // Standard resolution or fallback to npx
|
|
17
|
+
|
|
18
|
+
function startProxy() {
|
|
19
|
+
const args = ['mcp-remote', REMOTE_URL];
|
|
20
|
+
|
|
21
|
+
// If the user provided an API token via SGP_DIRECTORY_API_KEY environment variable,
|
|
22
|
+
// append it as an Authorization header to the mcp-remote call.
|
|
23
|
+
const token = process.env.SGP_DIRECTORY_API_KEY;
|
|
24
|
+
if (token) {
|
|
25
|
+
args.push('--header', `Authorization: Bearer ${token}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// We use npx mcp-remote because mcp-remote exposes its proxy utility.
|
|
29
|
+
// Instead of importing, we spawn the CLI directly to inherit its exact stdio behavior.
|
|
30
|
+
const child = spawn('npx', args, {
|
|
31
|
+
stdio: 'inherit',
|
|
32
|
+
env: {
|
|
33
|
+
...process.env,
|
|
34
|
+
// Pass any required env vars from the local client if necessary
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on('error', (err) => {
|
|
39
|
+
console.error(`[sgpdirectory-mcp] Failed to start underlying proxy: ${err.message}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
child.on('exit', (code, signal) => {
|
|
44
|
+
if (code !== null) {
|
|
45
|
+
process.exit(code);
|
|
46
|
+
} else {
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (require.main === module) {
|
|
53
|
+
startProxy();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = { startProxy };
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sgpdirectory/mcp",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "The official local MCP stdio package for sgpdirectory remote server",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node ./index.js",
|
|
8
|
+
"test": "node scripts/smoke-test.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"type": "commonjs",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"mcp-remote": "^0.1.38"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"sgpdirectory-mcp": "./index.js"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @sgpdirectory/mcp smoke test
|
|
4
|
+
* This script launches the MCP standard-io proxy and sends a JSON-RPC 'initialize' request
|
|
5
|
+
* to verify that the server starts up and responds correctly.
|
|
6
|
+
*/
|
|
7
|
+
const { spawn } = require('child_process');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const scriptPath = path.resolve(__dirname, '../index.js');
|
|
11
|
+
|
|
12
|
+
console.log('--- Starting SGP Directory MCP Smoke Test ---');
|
|
13
|
+
|
|
14
|
+
// We use 'pipe' for all stdio to capture and send data programmatically
|
|
15
|
+
const server = spawn('node', [scriptPath], {
|
|
16
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
17
|
+
env: {
|
|
18
|
+
...process.env,
|
|
19
|
+
// Add a test API key to ensure the logic for appending headers works
|
|
20
|
+
SGP_DIRECTORY_API_KEY: 'test-smoke-key'
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
let output = '';
|
|
25
|
+
let responseFound = false;
|
|
26
|
+
|
|
27
|
+
server.stdout.on('data', (data) => {
|
|
28
|
+
const str = data.toString();
|
|
29
|
+
output += str;
|
|
30
|
+
|
|
31
|
+
// Just log a snippet if too long
|
|
32
|
+
console.log(`[STDOUT snippet]: ${str.slice(0, 200).trim()}${str.length > 200 ? '...' : ''}`);
|
|
33
|
+
|
|
34
|
+
// Check for successful JSON-RPC initialization response
|
|
35
|
+
if (output.includes('"result":') || output.includes('"id":1')) {
|
|
36
|
+
responseFound = true;
|
|
37
|
+
// If we got the response, we can stop the test early
|
|
38
|
+
cleanup();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
server.stderr.on('data', (data) => {
|
|
43
|
+
console.error('[STDERR]:', data.toString().trim());
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const initializeRequest = JSON.stringify({
|
|
47
|
+
jsonrpc: '2.0',
|
|
48
|
+
id: 1,
|
|
49
|
+
method: 'initialize',
|
|
50
|
+
params: {
|
|
51
|
+
protocolVersion: '2024-11-05',
|
|
52
|
+
capabilities: {},
|
|
53
|
+
clientInfo: { name: 'smoke-test', version: '1.0.0' }
|
|
54
|
+
}
|
|
55
|
+
}) + '\n';
|
|
56
|
+
|
|
57
|
+
console.log('Sending initialize request to local proxy...');
|
|
58
|
+
server.stdin.write(initializeRequest);
|
|
59
|
+
|
|
60
|
+
let isCleanedUp = false;
|
|
61
|
+
function cleanup() {
|
|
62
|
+
if (isCleanedUp) return;
|
|
63
|
+
isCleanedUp = true;
|
|
64
|
+
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
server.kill();
|
|
67
|
+
|
|
68
|
+
if (responseFound) {
|
|
69
|
+
console.log('\n✅ SMOKE TEST PASSED: SGP Directory MCP proxy responded to initialize request.');
|
|
70
|
+
process.exit(0);
|
|
71
|
+
} else {
|
|
72
|
+
console.error('\n❌ SMOKE TEST FAILED: SGP Directory MCP proxy did not respond with a valid JSON-RPC result.');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Timeout after 15 seconds if no response
|
|
78
|
+
const timeout = setTimeout(() => {
|
|
79
|
+
console.log('\n--- Smoke Test Timeout (15s) ---');
|
|
80
|
+
cleanup();
|
|
81
|
+
}, 15000);
|
|
82
|
+
|
|
83
|
+
server.on('exit', (code, signal) => {
|
|
84
|
+
if (!isCleanedUp) {
|
|
85
|
+
console.log(`\n--- SGP Directory MCP exited unexpectedly (code: ${code}, signal: ${signal}) ---`);
|
|
86
|
+
cleanup();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
server.on('error', (err) => {
|
|
91
|
+
console.error('\n❌ Failed to launch SGP Directory MCP:', err.message);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
package/server.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
|
|
3
|
+
"name": "io.github.sgpdirectory/sgpdirectory-mcp",
|
|
4
|
+
"description": "Official local MCP wrapper for sgpdirectory remote server",
|
|
5
|
+
"status": "active",
|
|
6
|
+
"repository": {
|
|
7
|
+
"url": "https://github.com/sgpdirectory/sgpdirectory-mcp-package",
|
|
8
|
+
"source": "github"
|
|
9
|
+
},
|
|
10
|
+
"version": "1.0.0",
|
|
11
|
+
"remotes": [
|
|
12
|
+
{
|
|
13
|
+
"type": "streamable-http",
|
|
14
|
+
"url": "https://mcp.sgpdirectory.com/mcp",
|
|
15
|
+
"environment_variables": [
|
|
16
|
+
{
|
|
17
|
+
"name": "SGP_DIRECTORY_API_KEY",
|
|
18
|
+
"description": "Your API key for the service",
|
|
19
|
+
"is_required": false,
|
|
20
|
+
"format": "string",
|
|
21
|
+
"is_secret": true
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"packages": [
|
|
27
|
+
{
|
|
28
|
+
"registry_type": "npm",
|
|
29
|
+
"registry_base_url": "https://registry.npmjs.org",
|
|
30
|
+
"identifier": "@sgpdirectory/mcp",
|
|
31
|
+
"version": "1.0.0",
|
|
32
|
+
"transport": {
|
|
33
|
+
"type": "stdio"
|
|
34
|
+
},
|
|
35
|
+
"environment_variables": [
|
|
36
|
+
{
|
|
37
|
+
"name": "SGP_DIRECTORY_API_KEY",
|
|
38
|
+
"description": "Your API key for the service",
|
|
39
|
+
"is_required": false,
|
|
40
|
+
"format": "string",
|
|
41
|
+
"is_secret": true
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|