@sgpdirectory/mcp 1.3.0 → 1.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/.mise.toml ADDED
@@ -0,0 +1,3 @@
1
+ [tools]
2
+ node = "22.16.0"
3
+ pnpm = "10.10.0"
package/README.md CHANGED
@@ -50,21 +50,21 @@ If your proxy is behind an access token, you can pass it via `SGP_DIRECTORY_API_
50
50
  1. **Login to NPM**
51
51
  Run the login command and follow the prompts. You need to be a part of the `@sgpdirectory` org.
52
52
  ```bash
53
- npm login
53
+ pnpm login
54
54
  ```
55
55
 
56
56
  2. **Publish the package**
57
57
  Run the following inside your wrapper directory:
58
58
  ```bash
59
- npm publish --access public
59
+ pnpm publish --access public
60
60
  ```
61
61
 
62
62
  ## Local Testing
63
63
  If you have cloned the repository locally, you can run:
64
64
 
65
65
  ```bash
66
- npm install
67
- npm start
66
+ pnpm install
67
+ pnpm start
68
68
  ```
69
69
 
70
70
  This will launch the proxy and wait for standard `stdio` JSON-RPC messages.
package/package.json CHANGED
@@ -1,14 +1,8 @@
1
1
  {
2
2
  "name": "@sgpdirectory/mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Singapore business directory. Search companies, UENs, and SSIC industry classifications.",
5
5
  "main": "index.js",
6
- "scripts": {
7
- "start": "node ./index.js",
8
- "test": "node scripts/smoke-test.js",
9
- "version": "node scripts/sync-version.js",
10
- "deploy": "sh scripts/3-login-dns.sh && sh scripts/4-publish.sh"
11
- },
12
6
  "keywords": [
13
7
  "mcp",
14
8
  "mcp-server",
@@ -31,5 +25,16 @@
31
25
  "publishConfig": {
32
26
  "access": "public"
33
27
  },
34
- "mcpName": "com.sgpdirectory/mcp"
28
+ "mcpName": "com.sgpdirectory/mcp",
29
+ "devDependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.27.1"
31
+ },
32
+ "scripts": {
33
+ "start": "node ./index.js",
34
+ "version": "node scripts/sync-version.js",
35
+ "deploy:npm": "pnpm login && pnpm publish --access public --no-git-checks",
36
+ "deploy:mcp": "sh scripts/3-publish-mcp.sh",
37
+ "test:integration": "node scripts/integration-test.js",
38
+ "test:smoke": "node scripts/smoke-test.js"
39
+ }
35
40
  }
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # Install the latest mcp-publisher tool from modelcontextprotocol/registry
3
+ set -e
4
+
5
+ # Detect OS and architecture
6
+ OS=$(uname -s | tr '[:upper:]' '[:lower:]')
7
+ ARCH=$(uname -m)
8
+
9
+ if [ "$ARCH" = "x86_64" ]; then
10
+ ARCH="amd64"
11
+ elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
12
+ ARCH="arm64"
13
+ else
14
+ echo "Unsupported architecture: $ARCH"
15
+ exit 1
16
+ fi
17
+
18
+ TAR_GZ_NAME="mcp-publisher_${OS}_${ARCH}.tar.gz"
19
+ DOWNLOAD_URL="https://github.com/modelcontextprotocol/registry/releases/latest/download/$TAR_GZ_NAME"
20
+
21
+ echo "Downloading $TAR_GZ_NAME..."
22
+ TMP_DIR=$(mktemp -d)
23
+ curl -sL -o "$TMP_DIR/$TAR_GZ_NAME" "$DOWNLOAD_URL"
24
+
25
+ echo "Extracting..."
26
+ tar -xzf "$TMP_DIR/$TAR_GZ_NAME" -C "$TMP_DIR"
27
+
28
+ INSTALL_DIR="$HOME/.local/bin"
29
+ mkdir -p "$INSTALL_DIR"
30
+ echo "Installing mcp-publisher to $INSTALL_DIR..."
31
+ mv "$TMP_DIR/mcp-publisher" "$INSTALL_DIR/"
32
+ chmod +x "$INSTALL_DIR/mcp-publisher"
33
+
34
+ # Cleanup
35
+ rm -rf "$TMP_DIR"
36
+
37
+ echo "mcp-publisher has been installed."
38
+ if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
39
+ echo ""
40
+ echo "WARNING: $INSTALL_DIR is not in your PATH."
41
+ echo "To use the mcp-publisher command globally, please add the following line to your shell profile (~/.bashrc, ~/.zshrc, etc.):"
42
+ echo ""
43
+ echo "export PATH=\"\$PATH:$INSTALL_DIR\""
44
+ fi
File without changes
File without changes
@@ -5,8 +5,13 @@ KEY_FILE="/tmp/sgpdirectory-mcp-dns-key.pem"
5
5
  # Generate keypair
6
6
  #openssl genpkey -algorithm Ed25519 -out $KEY_FILE
7
7
 
8
- # Get public key for DNS record
8
+ # Get public key for DNS record, add to your DNS provider
9
9
  #echo "$DOMAIN. IN TXT \"v=MCPv1; k=ed25519; p=$(openssl pkey -in $KEY_FILE -pubout -outform DER | tail -c 32 | base64)\""
10
10
 
11
- # Add the TXT record to your DNS, then login
11
+ # Login to MCP Registry
12
12
  mcp-publisher login dns --domain $DOMAIN --private-key $(openssl pkey -in $KEY_FILE -noout -text | grep -A3 "priv:" | tail -n +2 | tr -d ' :\n')
13
+
14
+ # Publish to MCP Registry
15
+ echo "Publishing to registry.modelcontextprotocol.io..."
16
+ # mcp-publisher publish uses the server.json file to update the MCP registry
17
+ mcp-publisher publish
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @sgpdirectory/mcp integration test
4
+ * Uses the official MCP SDK to verify the local server functionality.
5
+ */
6
+ const { Client } = require("@modelcontextprotocol/sdk/client/index.js");
7
+ const { StdioClientTransport } = require("@modelcontextprotocol/sdk/client/stdio.js");
8
+ const path = require('path');
9
+
10
+ async function runIntegrationTest() {
11
+ const scriptPath = path.resolve(__dirname, '../index.js');
12
+
13
+ console.log('--- Starting SGP Directory MCP Integration Test (SDK Mode) ---');
14
+
15
+ const transport = new StdioClientTransport({
16
+ command: "node",
17
+ args: [scriptPath],
18
+ env: {
19
+ ...process.env,
20
+ SGP_DIRECTORY_API_KEY: process.env.SGP_DIRECTORY_API_KEY || 'test-integration-key'
21
+ }
22
+ });
23
+
24
+ const client = new Client({
25
+ name: "integration-test-client",
26
+ version: "1.3.1"
27
+ }, {
28
+ capabilities: {}
29
+ });
30
+
31
+ try {
32
+ console.log("1. Connecting to local MCP server...");
33
+ await client.connect(transport);
34
+ console.log("✅ Connected");
35
+
36
+ console.log("2. Listing tools...");
37
+ const toolsRes = await client.listTools();
38
+ const tools = toolsRes.tools || [];
39
+ console.log(`✅ Found ${tools.length} tools: ${tools.map(t => t.name).join(', ')}`);
40
+
41
+ if (tools.length === 0) throw new Error("No tools found!");
42
+
43
+ console.log('3. Calling "search_entities" with query "Google"...');
44
+ const result = await client.callTool({
45
+ name: "search_entities",
46
+ arguments: { query: "Google", limit: 1 }
47
+ });
48
+
49
+ if (result.isError) {
50
+ throw new Error(`Tool call returned error: ${JSON.stringify(result.content)}`);
51
+ }
52
+
53
+ console.log('✅ Search call responded successfully');
54
+
55
+ console.log('\n✨ ALL INTEGRATION TESTS PASSED');
56
+ await client.close();
57
+ process.exit(0);
58
+
59
+ } catch (err) {
60
+ console.error(`\n❌ INTEGRATION TEST FAILED: ${err.message}`);
61
+ process.exit(1);
62
+ }
63
+ }
64
+
65
+ runIntegrationTest();
@@ -1,93 +1,75 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
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.
4
+ * Uses the official MCP SDK to verify the published package.
6
5
  */
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'
6
+ const { Client } = require("@modelcontextprotocol/sdk/client/index.js");
7
+ const { StdioClientTransport } = require("@modelcontextprotocol/sdk/client/stdio.js");
8
+ const pkg = require('../package.json');
9
+
10
+ async function runSmokeTest() {
11
+ // 1. Determine version (arg or package.json)
12
+ const specifiedVersion = process.argv[2];
13
+ const version = specifiedVersion || pkg.version;
14
+ const packageName = pkg.name;
15
+
16
+ console.log(`--- Starting SGP Directory MCP Smoke Test (SDK Mode) ---`);
17
+ console.log(`Testing package: ${packageName}@${version}`);
18
+
19
+ // We use the canonical way to run a binary when it doesn't match the package name:
20
+ // npx -y --package @scope/pkg@version -- binary-name
21
+ const transport = new StdioClientTransport({
22
+ command: "npx",
23
+ args: [
24
+ "-y",
25
+ "--package", `${packageName}@${version}`,
26
+ "--",
27
+ "sgpdirectory-mcp"
28
+ ],
29
+ env: {
30
+ ...process.env,
31
+ SGP_DIRECTORY_API_KEY: 'test-smoke-key'
32
+ }
33
+ });
34
+
35
+ if (process.env.DEBUG) {
36
+ transport.onmessage = (msg) => console.log(`[Transport JSON-RPC]: ${JSON.stringify(msg)}`);
21
37
  }
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
38
 
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
- });
39
+ const client = new Client({
40
+ name: "smoke-test-client",
41
+ version: "1.0.0"
42
+ }, {
43
+ capabilities: {}
44
+ });
41
45
 
42
- server.stderr.on('data', (data) => {
43
- console.error('[STDERR]:', data.toString().trim());
44
- });
46
+ try {
47
+ console.log("Connecting to MCP server via npx...");
45
48
 
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.1' }
54
- }
55
- }) + '\n';
49
+ // Timeout for the whole connection process
50
+ const timeout = setTimeout(() => {
51
+ console.error("❌ Error: Smoke test timed out after 15s");
52
+ process.exit(1);
53
+ }, 15000);
56
54
 
57
- console.log('Sending initialize request to local proxy...');
58
- server.stdin.write(initializeRequest);
55
+ await client.connect(transport);
56
+ clearTimeout(timeout);
59
57
 
60
- let isCleanedUp = false;
61
- function cleanup() {
62
- if (isCleanedUp) return;
63
- isCleanedUp = true;
58
+ console.log("✅ Successfully connected and initialized");
64
59
 
65
- clearTimeout(timeout);
66
- server.kill();
60
+ // Verify we can at least list tools (standard health check)
61
+ const tools = await client.listTools();
62
+ console.log(`✅ Server reported ${tools.tools.length} available tools`);
67
63
 
68
- if (responseFound) {
69
- console.log('\n✅ SMOKE TEST PASSED: SGP Directory MCP proxy responded to initialize request.');
64
+ console.log("\n✨ SMOKE TEST PASSED: Package is functional on the registry.");
65
+ await client.close();
70
66
  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.');
67
+
68
+ } catch (error) {
69
+ console.error("\n❌ SMOKE TEST FAILED");
70
+ console.error(error.message);
73
71
  process.exit(1);
74
72
  }
75
73
  }
76
74
 
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
- });
75
+ runSmokeTest();
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "com.sgpdirectory/mcp",
4
4
  "description": "Singapore business directory. Search companies, UENs, and SSIC industry classifications.",
5
5
  "title": "Singapore Business Directory",
6
- "version": "1.3.0",
6
+ "version": "1.3.1",
7
7
  "websiteUrl": "https://sgpdirectory.com",
8
8
  "icons": [
9
9
  {
@@ -35,7 +35,7 @@
35
35
  "registryType": "npm",
36
36
  "registryBaseUrl": "https://registry.npmjs.org",
37
37
  "identifier": "@sgpdirectory/mcp",
38
- "version": "1.3.0",
38
+ "version": "1.3.1",
39
39
  "transport": {
40
40
  "type": "stdio"
41
41
  },
@@ -1,13 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Ensure we're in the project root
4
- cd "$(dirname "$0")/.."
5
-
6
- # Publish to NPM
7
- echo "📦 Publishing to npmjs.com..."
8
- npm publish --access public
9
-
10
- # Publish to MCP Registry
11
- echo "🚀 Publishing to registry.modelcontextprotocol.io..."
12
- # mcp-publisher publish uses the server.json file to update the MCP registry
13
- mcp-publisher publish server.json