@myatkyawthu/mcp-connect 0.3.1 → 0.3.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,82 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@myatkyawthu/mcp-connect` are documented here.
4
+
5
+ ---
6
+
7
+ ## [0.3.3] — 2026-07-22
8
+
9
+ ### Bug Fixes
10
+
11
+ - **Fixed double-validation bug wiping tool schemas at runtime**
12
+ When a config file exported the result of `defineMCP()`, the CLI was executing `defineMCP()` a second time. This second invocation parsed the normalized tools and wiped out the `schema` metadata because it was already converted to `inputSchema` in the first run, rendering runtime schema validation inactive.
13
+ - Added early return guard (`_isMCPConfig` flag) in `defineMCP` to prevent double processing.
14
+ - Added fallback check to parse `inputSchema` keys if already normalized.
15
+
16
+ ---
17
+
18
+ ## [0.3.2] — 2026-07-22
19
+
20
+ ### Bug Fixes
21
+
22
+ - **Config validation: destructured args no longer falsely error**
23
+ Tools with handlers like `async ({ id, content }) => ...` were incorrectly reported as having multiple parameters. The validator now detects destructured arguments (`{...}` or `[...]`) and counts them as a single parameter. ([`configValidation.js`](src/utils/configValidation.js))
24
+
25
+ - **Config validation: `confirm` no longer warns as unknown property**
26
+ Tools with `confirm: true` were emitting a spurious _"Unknown properties: confirm"_ warning. `confirm` is now a recognised property in the validator. ([`configValidation.js`](src/utils/configValidation.js))
27
+
28
+ ### New Features
29
+
30
+ - **Runtime schema validation against tool input schemas**
31
+ Tool arguments are now validated against the tool's declared JSON Schema before the handler is called. Required fields that are missing and properties with the wrong type both return a clear error to the AI client instead of silently crashing.
32
+ - No new dependencies — uses the existing `required` and `properties.*.type` fields you already define.
33
+ - Example error: `Missing required argument: "message"` or `Argument "limit" must be of type number, got string`
34
+ ([`validation.js`](src/utils/validation.js), [`mcpServer.js`](src/server/mcpServer.js))
35
+
36
+ ---
37
+
38
+ ## [0.3.1] — 2026-07-21
39
+
40
+ ### Patch
41
+
42
+ - Re-publish to fix `bin` field packaging issue in 0.3.0 that caused the `mcp-connect` CLI command not to register on some npm versions.
43
+
44
+ ---
45
+
46
+ ## [0.3.0] — 2026-07-21
47
+
48
+ ### Breaking Changes
49
+
50
+ - **Removed Resources and Prompts support** — the framework is now strictly tool-centric. If you were using `resources` or `prompts` in your config, remove them. This makes the API surface smaller and the codebase ~40% leaner (YAGNI).
51
+
52
+ ### New Features
53
+
54
+ - **SSE / HTTP transport** (`--port` flag) — expose your MCP server over HTTP to any web client, IDE, or AI tool that supports SSE transport (Cursor, Cline, Windsurf, Claude.ai web, etc.)
55
+ - **Tunnel / relay transport** (`--tunnel` flag) — NAT-bypassing outbound tunnel so your laptop can serve remote AI clients without an open port. Includes a self-hostable `MCPRelayServer`.
56
+ - **Inspector Dashboard** — live browser UI at `GET /` showing real-time tool call logs and a mock tool executor for debugging without an AI client.
57
+ - **Bearer token auth** — protect all endpoints via `MCP_TUNNEL_TOKEN` env var or `server.tunnel.token` config.
58
+ - **CORS origin allowlist** — lock down which origins can connect via `server.cors.origins`.
59
+ - **Confirm gate** — mark any tool `confirm: true` to require a `y/N` prompt in the terminal before execution. Uses `/dev/tty` directly so it doesn't interfere with the STDIO JSON-RPC pipe.
60
+ - **AES-256-GCM end-to-end encryption** — tunnel payloads can be encrypted before leaving your machine via `server.tunnel.encryptionKey`.
61
+
62
+ ### Built-in Protections (always on)
63
+
64
+ - Rate limiting: 100 requests/minute
65
+ - Tool timeout: 30 seconds
66
+ - Response size cap: 1MB
67
+ - Error sanitization: stack traces stripped before returning to AI clients
68
+ - Circular reference guard on JSON serialisation
69
+
70
+ ### Upgraded
71
+
72
+ - `@modelcontextprotocol/sdk` upgraded from `^0.5.x` to `^1.29.0`
73
+
74
+ ---
75
+
76
+ ## [0.2.0] — Earlier
77
+
78
+ - Added basic SSE transport and dashboard prototype.
79
+
80
+ ## [0.1.0] — Initial release
81
+
82
+ - STDIO-only MCP wrapper with `defineMCP()` config API.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myatkyawthu/mcp-connect",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Dead simple MCP (Model Context Protocol) server for exposing your app functions to AI agents",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -13,6 +13,7 @@
13
13
  "files": [
14
14
  "src",
15
15
  "README.md",
16
+ "CHANGELOG.md",
16
17
  "LICENSE"
17
18
  ],
18
19
  "scripts": {
package/src/defineMCP.js CHANGED
@@ -2,6 +2,10 @@ import { formatValidationErrors, validateConfig } from './utils/configValidation
2
2
  import { logger } from './utils/logger.js';
3
3
 
4
4
  export function defineMCP(config) {
5
+ if (config && config._isMCPConfig) {
6
+ return config;
7
+ }
8
+
5
9
  const validationResult = validateConfig(config);
6
10
 
7
11
  if (!validationResult.isValid) {
@@ -33,11 +37,11 @@ export function defineMCP(config) {
33
37
  handler,
34
38
  };
35
39
  } else {
36
- const { name, handler, description, schema, confirm } = tool;
40
+ const { name, handler, description, schema, inputSchema, confirm } = tool;
37
41
  return {
38
42
  name: name.trim(),
39
43
  description: description || `Tool: ${name}`,
40
- inputSchema: schema || {
44
+ inputSchema: schema || inputSchema || {
41
45
  type: 'object',
42
46
  properties: {},
43
47
  additionalProperties: true,
@@ -54,5 +58,6 @@ export function defineMCP(config) {
54
58
  description: config.description,
55
59
  server: config.server || {},
56
60
  tools: mcpTools,
61
+ _isMCPConfig: true,
57
62
  };
58
63
  }
@@ -8,7 +8,7 @@ import {
8
8
  import { createServer } from 'node:http';
9
9
  import { decrypt, encrypt } from '../utils/crypto.js';
10
10
  import { logger } from '../utils/logger.js';
11
- import { sanitizeErrorMessage, validateToolArguments } from '../utils/validation.js';
11
+ import { sanitizeErrorMessage, validateArgsAgainstSchema, validateToolArguments } from '../utils/validation.js';
12
12
  import { getDashboardHTML } from './dashboard.js';
13
13
 
14
14
  const DEFAULT_TOOL_TIMEOUT = 30000;
@@ -150,6 +150,7 @@ export class MCPConnectServer {
150
150
  }
151
151
  }
152
152
  const validatedArgs = validateToolArguments(args);
153
+ validateArgsAgainstSchema(validatedArgs, tool.inputSchema);
153
154
 
154
155
  const toolPromise = Promise.resolve(tool.handler(validatedArgs));
155
156
  const result = await logger.timeAsync(
@@ -211,7 +211,7 @@ export class ConfigValidator {
211
211
  this.validateToolDescription(tool.description, `${fieldPrefix}.description`);
212
212
  this.validateToolSchema(tool.schema, `${fieldPrefix}.schema`);
213
213
 
214
- const knownProps = ['name', 'handler', 'description', 'schema'];
214
+ const knownProps = ['name', 'handler', 'description', 'schema', 'confirm'];
215
215
  const unknownProps = Object.keys(tool).filter((prop) => !knownProps.includes(prop));
216
216
  if (unknownProps.length > 0) {
217
217
  this.addWarning(
@@ -290,7 +290,8 @@ export class ConfigValidator {
290
290
  if (paramMatch) {
291
291
  const params = paramMatch[1].trim();
292
292
  if (params) {
293
- const paramCount = params.split(',').filter(p => p.trim()).length;
293
+ const isDestructured = params.startsWith('{') || params.startsWith('[');
294
+ const paramCount = isDestructured ? 1 : params.split(',').filter((p) => p.trim()).length;
294
295
  if (paramCount > 1) {
295
296
  this.addError(
296
297
  fieldPath,
@@ -36,6 +36,40 @@ export function validateToolArguments(args) {
36
36
  return args;
37
37
  }
38
38
 
39
+ /**
40
+ * Validate args against a JSON Schema definition (subset: required + type).
41
+ * No external deps — covers the common cases without pulling in ajv.
42
+ * @param {object} args
43
+ * @param {object} schema - the tool's inputSchema
44
+ */
45
+ export function validateArgsAgainstSchema(args, schema) {
46
+ if (!schema || typeof schema !== 'object') return;
47
+
48
+ // Check required fields
49
+ if (Array.isArray(schema.required)) {
50
+ for (const field of schema.required) {
51
+ if (args[field] === undefined || args[field] === null) {
52
+ throw new Error(`Missing required argument: "${field}"`);
53
+ }
54
+ }
55
+ }
56
+
57
+ // Check declared property types
58
+ if (schema.properties && typeof schema.properties === 'object') {
59
+ for (const [key, def] of Object.entries(schema.properties)) {
60
+ if (args[key] === undefined) continue; // optional — already handled above
61
+ if (!def || typeof def.type !== 'string') continue;
62
+
63
+ const actual = Array.isArray(args[key]) ? 'array' : typeof args[key];
64
+ if (actual !== def.type) {
65
+ throw new Error(
66
+ `Argument "${key}" must be of type ${def.type}, got ${actual}`
67
+ );
68
+ }
69
+ }
70
+ }
71
+ }
72
+
39
73
  export function sanitizeErrorMessage(error) {
40
74
  if (error instanceof Error) {
41
75
  // Remove sensitive information from stack traces